window_event_dispatcher.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
12da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// Copyright 2014 The Chromium Authors. All rights reserved. 22da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// Use of this source code is governed by a BSD-style license that can be 32da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// found in the LICENSE file. 42da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 52da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/aura/window_event_dispatcher.h" 62da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 72da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "base/bind.h" 82da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "base/debug/trace_event.h" 92da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "base/logging.h" 102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "base/message_loop/message_loop.h" 112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/aura/client/capture_client.h" 122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/aura/client/cursor_client.h" 132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/aura/client/event_client.h" 142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/aura/client/focus_client.h" 152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/aura/client/screen_position_client.h" 162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/aura/env.h" 172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/aura/window.h" 182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/aura/window_delegate.h" 192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/aura/window_targeter.h" 202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/aura/window_tracker.h" 212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/aura/window_tree_host.h" 222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/base/hit_test.h" 232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/compositor/dip_util.h" 242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/events/event.h" 252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/events/gestures/gesture_recognizer.h" 262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#include "ui/events/gestures/gesture_types.h" 272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 282da489cd246702bee5938545b18a6f710ed214bcJamie Gennistypedef ui::EventDispatchDetails DispatchDetails; 292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 302da489cd246702bee5938545b18a6f710ed214bcJamie Gennisnamespace aura { 312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 322da489cd246702bee5938545b18a6f710ed214bcJamie Gennisnamespace { 332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// Returns true if |target| has a non-client (frame) component at |location|, 352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// in window coordinates. 362da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbool IsNonClientLocation(Window* target, const gfx::Point& location) { 372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!target->delegate()) 382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return false; 392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis int hit_test_code = target->delegate()->GetNonClientComponent(location); 402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE; 412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 432da489cd246702bee5938545b18a6f710ed214bcJamie GennisWindow* ConsumerToWindow(ui::GestureConsumer* consumer) { 442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return consumer ? static_cast<Window*>(consumer) : NULL; 452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 472da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid SetLastMouseLocation(const Window* root_window, 482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis const gfx::Point& location_in_root) { 492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis client::ScreenPositionClient* client = 502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis client::GetScreenPositionClient(root_window); 512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (client) { 522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis gfx::Point location_in_screen = location_in_root; 532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis client->ConvertPointToScreen(root_window, &location_in_screen); 542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Env::GetInstance()->set_last_mouse_location(location_in_screen); 552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } else { 562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Env::GetInstance()->set_last_mouse_location(location_in_root); 572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 602da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbool IsEventCandidateForHold(const ui::Event& event) { 612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (event.type() == ui::ET_TOUCH_MOVED) 622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return true; 632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (event.type() == ui::ET_MOUSE_DRAGGED) 642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return true; 652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (event.IsMouseEvent() && (event.flags() & ui::EF_IS_SYNTHESIZED)) 662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return true; 672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return false; 682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} // namespace 712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis//////////////////////////////////////////////////////////////////////////////// 732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// WindowEventDispatcher, public: 742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 752da489cd246702bee5938545b18a6f710ed214bcJamie GennisWindowEventDispatcher::WindowEventDispatcher(WindowTreeHost* host) 762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis : host_(host), 772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis touch_ids_down_(0), 782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis mouse_pressed_handler_(NULL), 792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis mouse_moved_handler_(NULL), 802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis event_dispatch_target_(NULL), 812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis old_dispatch_target_(NULL), 822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis synthesize_mouse_move_(false), 832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis move_hold_count_(0), 842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis dispatching_held_event_(false), 852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis observer_manager_(this), 862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis repost_event_factory_(this), 872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis held_event_factory_(this) { 882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::GestureRecognizer::Get()->AddGestureEventHelper(this); 892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Env::GetInstance()->AddObserver(this); 902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 922da489cd246702bee5938545b18a6f710ed214bcJamie GennisWindowEventDispatcher::~WindowEventDispatcher() { 932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis TRACE_EVENT0("shutdown", "WindowEventDispatcher::Destructor"); 942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Env::GetInstance()->RemoveObserver(this); 952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::GestureRecognizer::Get()->RemoveGestureEventHelper(this); 962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 982da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::RepostEvent(const ui::LocatedEvent& event) { 992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis DCHECK(event.type() == ui::ET_MOUSE_PRESSED || 1002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis event.type() == ui::ET_GESTURE_TAP_DOWN); 1012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // We allow for only one outstanding repostable event. This is used 1022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // in exiting context menus. A dropped repost request is allowed. 1032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (event.type() == ui::ET_MOUSE_PRESSED) { 1042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis held_repostable_event_.reset( 1052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis new ui::MouseEvent( 1062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis static_cast<const ui::MouseEvent&>(event), 1072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis static_cast<aura::Window*>(event.target()), 1082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis window())); 1092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis base::MessageLoop::current()->PostNonNestableTask( 1102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis FROM_HERE, base::Bind( 1112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis base::IgnoreResult(&WindowEventDispatcher::DispatchHeldEvents), 1122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis repost_event_factory_.GetWeakPtr())); 1132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } else { 1142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis DCHECK(event.type() == ui::ET_GESTURE_TAP_DOWN); 1152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis held_repostable_event_.reset(); 1162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // TODO(rbyers): Reposing of gestures is tricky to get 1172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // right, so it's not yet supported. crbug.com/170987. 1182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 1202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1212da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::OnMouseEventsEnableStateChanged(bool enabled) { 1222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Send entered / exited so that visual state can be updated to match 1232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // mouse events state. 1242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis PostSynthesizeMouseMove(); 1252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // TODO(mazda): Add code to disable mouse events when |enabled| == false. 1262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 1272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1282da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::DispatchCancelModeEvent() { 1292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::CancelModeEvent event; 1302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Window* focused_window = client::GetFocusClient(window())->GetFocusedWindow(); 1312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (focused_window && !window()->Contains(focused_window)) 1322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis focused_window = NULL; 1332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis DispatchDetails details = 1342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis DispatchEvent(focused_window ? focused_window : window(), &event); 1352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (details.dispatcher_destroyed) 1362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 1372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 1382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1392da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::DispatchGestureEvent(ui::GestureEvent* event) { 1402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis DispatchDetails details = DispatchHeldEvents(); 1412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (details.dispatcher_destroyed) 1422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 1432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Window* target = GetGestureTarget(event); 1442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (target) { 1452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis event->ConvertLocationToTarget(window(), target); 1462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis DispatchDetails details = DispatchEvent(target, event); 1472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (details.dispatcher_destroyed) 1482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 1492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 1512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1522da489cd246702bee5938545b18a6f710ed214bcJamie GennisDispatchDetails WindowEventDispatcher::DispatchMouseExitAtPoint( 1532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis const gfx::Point& point) { 1542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::MouseEvent event(ui::ET_MOUSE_EXITED, point, point, ui::EF_NONE, 1552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::EF_NONE); 1562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return DispatchMouseEnterOrExit(event, ui::ET_MOUSE_EXITED); 1572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 1582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1592da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::ProcessedTouchEvent(ui::TouchEvent* event, 1602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Window* window, 1612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::EventResult result) { 1622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // TODO(tdresser): Move this to PreDispatchTouchEvent, to enable eager 1632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // gesture detection. See crbug.com/410280. 1642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!ui::GestureRecognizer::Get() 1652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ->ProcessTouchEventPreDispatch(*event, window)) { 1662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 1672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Once we've fully migrated to the eager gesture detector, we won't need to 1702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // pass an event here. 1712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis scoped_ptr<ui::GestureRecognizer::Gestures> gestures( 1722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::GestureRecognizer::Get()->ProcessTouchEventOnAsyncAck( 1732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis *event, result, window)); 1742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis DispatchDetails details = ProcessGestures(gestures.get()); 1752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (details.dispatcher_destroyed) 1762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 1772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 1782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1792da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::HoldPointerMoves() { 1802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!move_hold_count_) 1812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis held_event_factory_.InvalidateWeakPtrs(); 1822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ++move_hold_count_; 1832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis TRACE_EVENT_ASYNC_BEGIN0("ui", "WindowEventDispatcher::HoldPointerMoves", 1842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this); 1852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 1862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1872da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::ReleasePointerMoves() { 1882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis --move_hold_count_; 1892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis DCHECK_GE(move_hold_count_, 0); 1902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!move_hold_count_ && held_move_event_) { 1912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // We don't want to call DispatchHeldEvents directly, because this might be 1922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // called from a deep stack while another event, in which case dispatching 1932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // another one may not be safe/expected. Instead we post a task, that we 1942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // may cancel if HoldPointerMoves is called again before it executes. 1952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis base::MessageLoop::current()->PostNonNestableTask( 1962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis FROM_HERE, base::Bind( 1972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis base::IgnoreResult(&WindowEventDispatcher::DispatchHeldEvents), 1982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis held_event_factory_.GetWeakPtr())); 1992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 2002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis TRACE_EVENT_ASYNC_END0("ui", "WindowEventDispatcher::HoldPointerMoves", this); 2012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 2022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2032da489cd246702bee5938545b18a6f710ed214bcJamie Gennisgfx::Point WindowEventDispatcher::GetLastMouseLocationInRoot() const { 2042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis gfx::Point location = Env::GetInstance()->last_mouse_location(); 2052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis client::ScreenPositionClient* client = 2062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis client::GetScreenPositionClient(window()); 2072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (client) 2082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis client->ConvertPointFromScreen(window(), &location); 2092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return location; 2102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 2112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2122da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::OnHostLostMouseGrab() { 2132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis mouse_pressed_handler_ = NULL; 2142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis mouse_moved_handler_ = NULL; 2152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 2162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2172da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::OnCursorMovedToRootLocation( 2182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis const gfx::Point& root_location) { 2192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis SetLastMouseLocation(window(), root_location); 2202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis synthesize_mouse_move_ = false; 2212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 2222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2232da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::OnPostNotifiedWindowDestroying(Window* window) { 2242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis OnWindowHidden(window, WINDOW_DESTROYED); 2252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 2262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis//////////////////////////////////////////////////////////////////////////////// 2282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// WindowEventDispatcher, private: 2292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2302da489cd246702bee5938545b18a6f710ed214bcJamie GennisWindow* WindowEventDispatcher::window() { 2312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return host_->window(); 2322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 2332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2342da489cd246702bee5938545b18a6f710ed214bcJamie Gennisconst Window* WindowEventDispatcher::window() const { 2352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return host_->window(); 2362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 2372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2382da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::TransformEventForDeviceScaleFactor( 2392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::LocatedEvent* event) { 2402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis event->UpdateForRootTransform(host_->GetInverseRootTransform()); 2412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 2422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2432da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::DispatchMouseExitToHidingWindow(Window* window) { 2442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // The mouse capture is intentionally ignored. Think that a mouse enters 2452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // to a window, the window sets the capture, the mouse exits the window, 2462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // and then it releases the capture. In that case OnMouseExited won't 2472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // be called. So it is natural not to emit OnMouseExited even though 2482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // |window| is the capture window. 2492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis gfx::Point last_mouse_location = GetLastMouseLocationInRoot(); 2502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (window->Contains(mouse_moved_handler_) && 2512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis window->ContainsPointInRoot(last_mouse_location)) { 2522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis DispatchDetails details = DispatchMouseExitAtPoint(last_mouse_location); 2532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (details.dispatcher_destroyed) 2542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 2552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 2562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 2572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2582da489cd246702bee5938545b18a6f710ed214bcJamie Gennisui::EventDispatchDetails WindowEventDispatcher::DispatchMouseEnterOrExit( 2592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis const ui::MouseEvent& event, 2602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::EventType type) { 2612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (event.type() != ui::ET_MOUSE_CAPTURE_CHANGED && 2622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis !(event.flags() & ui::EF_IS_SYNTHESIZED)) { 2632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis SetLastMouseLocation(window(), event.root_location()); 2642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 2652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!mouse_moved_handler_ || !mouse_moved_handler_->delegate() || 2672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis !window()->Contains(mouse_moved_handler_)) 2682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return DispatchDetails(); 2692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // |event| may be an event in the process of being dispatched to a target (in 2712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // which case its locations will be in the event's target's coordinate 2722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // system), or a synthetic event created in root-window (in which case, the 2732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // event's target will be NULL, and the event will be in the root-window's 2742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // coordinate system. 2752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis aura::Window* target = static_cast<Window*>(event.target()); 2762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!target) 2772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis target = window(); 2782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::MouseEvent translated_event(event, 2792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis target, 2802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis mouse_moved_handler_, 2812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis type, 2822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis event.flags() | ui::EF_IS_SYNTHESIZED); 2832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return DispatchEvent(mouse_moved_handler_, &translated_event); 2842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 2852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2862da489cd246702bee5938545b18a6f710ed214bcJamie Gennisui::EventDispatchDetails WindowEventDispatcher::ProcessGestures( 2872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::GestureRecognizer::Gestures* gestures) { 2882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis DispatchDetails details; 2892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!gestures || gestures->empty()) 2902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return details; 2912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Window* target = GetGestureTarget(gestures->get().at(0)); 2932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!target) 2942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return details; 2952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for (size_t i = 0; i < gestures->size(); ++i) { 2972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::GestureEvent* event = gestures->get().at(i); 2982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis event->ConvertLocationToTarget(window(), target); 2992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis details = DispatchEvent(target, event); 3002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (details.dispatcher_destroyed || details.target_destroyed) 3012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 3022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return details; 3042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 3052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3062da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::OnWindowHidden(Window* invisible, 3072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis WindowHiddenReason reason) { 3082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // If the window the mouse was pressed in becomes invisible, it should no 3092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // longer receive mouse events. 3102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (invisible->Contains(mouse_pressed_handler_)) 3112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis mouse_pressed_handler_ = NULL; 3122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (invisible->Contains(mouse_moved_handler_)) 3132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis mouse_moved_handler_ = NULL; 3142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // If events are being dispatched from a nested message-loop, and the target 3162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // of the outer loop is hidden or moved to another dispatcher during 3172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // dispatching events in the inner loop, then reset the target for the outer 3182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // loop. 3192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (invisible->Contains(old_dispatch_target_)) 3202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis old_dispatch_target_ = NULL; 3212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis invisible->CleanupGestureState(); 3232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Do not clear the capture, and the |event_dispatch_target_| if the 3252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // window is moving across hosts, because the target itself is actually still 3262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // visible and clearing them stops further event processing, which can cause 3272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // unexpected behaviors. See crbug.com/157583 3282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (reason != WINDOW_MOVING) { 3292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // We don't ask |invisible| here, because invisible may have been removed 3302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // from the window hierarchy already by the time this function is called 3312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // (OnWindowDestroyed). 3322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis client::CaptureClient* capture_client = 3332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis client::GetCaptureClient(host_->window()); 3342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Window* capture_window = 3352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis capture_client ? capture_client->GetCaptureWindow() : NULL; 3362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (invisible->Contains(event_dispatch_target_)) 3382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis event_dispatch_target_ = NULL; 3392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // If the ancestor of the capture window is hidden, release the capture. 3412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Note that this may delete the window so do not use capture_window 3422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // after this. 3432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (invisible->Contains(capture_window) && invisible != window()) 3442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis capture_window->ReleaseCapture(); 3452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 3472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3482da489cd246702bee5938545b18a6f710ed214bcJamie GennisWindow* WindowEventDispatcher::GetGestureTarget(ui::GestureEvent* event) { 3492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Window* target = NULL; 3502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!event->IsEndingEvent()) { 3512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // The window that received the start event (e.g. scroll begin) needs to 3522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // receive the end event (e.g. scroll end). 3532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis target = client::GetCaptureWindow(window()); 3542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!target) { 3562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis target = ConsumerToWindow( 3572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::GestureRecognizer::Get()->GetTargetForGestureEvent(*event)); 3582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return target; 3612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 3622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis//////////////////////////////////////////////////////////////////////////////// 3642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// WindowEventDispatcher, aura::client::CaptureDelegate implementation: 3652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3662da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::UpdateCapture(Window* old_capture, 3672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Window* new_capture) { 3682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // |mouse_moved_handler_| may have been set to a Window in a different root 3692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // (see below). Clear it here to ensure we don't end up referencing a stale 3702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Window. 3712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (mouse_moved_handler_ && !window()->Contains(mouse_moved_handler_)) 3722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis mouse_moved_handler_ = NULL; 3732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (old_capture && old_capture->GetRootWindow() == window() && 3752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis old_capture->delegate()) { 3762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Send a capture changed event with bogus location data. 3772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::MouseEvent event(ui::ET_MOUSE_CAPTURE_CHANGED, gfx::Point(), 3782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis gfx::Point(), 0, 0); 3792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis DispatchDetails details = DispatchEvent(old_capture, &event); 3812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (details.dispatcher_destroyed) 3822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 3832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis old_capture->delegate()->OnCaptureLost(); 3852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (new_capture) { 3882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Make all subsequent mouse events go to the capture window. We shouldn't 3892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // need to send an event here as OnCaptureLost() should take care of that. 3902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (mouse_moved_handler_ || Env::GetInstance()->IsMouseButtonDown()) 3912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis mouse_moved_handler_ = new_capture; 3922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } else { 3932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Make sure mouse_moved_handler gets updated. 3942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis DispatchDetails details = SynthesizeMouseMoveEvent(); 3952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (details.dispatcher_destroyed) 3962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 3972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis mouse_pressed_handler_ = NULL; 3992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 4002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4012da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::OnOtherRootGotCapture() { 4022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Windows provides the TrackMouseEvents API which allows us to rely on the 4032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // OS to send us the mouse exit events (WM_MOUSELEAVE). Additionally on 4042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // desktop Windows, every top level window could potentially have its own 4052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // root window, in which case this function will get called whenever those 4062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // windows grab mouse capture. Sending mouse exit messages in these cases 4072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // causes subtle bugs like (crbug.com/394672). 4082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#if !defined(OS_WIN) 4092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (mouse_moved_handler_) { 4102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Dispatch a mouse exit to reset any state associated with hover. This is 4112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // important when going from no window having capture to a window having 4122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // capture because we do not dispatch ET_MOUSE_CAPTURE_CHANGED in this case. 4132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis DispatchDetails details = DispatchMouseExitAtPoint( 4142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis GetLastMouseLocationInRoot()); 4152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (details.dispatcher_destroyed) 4162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 4172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 4182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#endif 4192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis mouse_moved_handler_ = NULL; 4212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis mouse_pressed_handler_ = NULL; 4222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 4232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4242da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::SetNativeCapture() { 4252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis host_->SetCapture(); 4262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 4272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4282da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::ReleaseNativeCapture() { 4292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis host_->ReleaseCapture(); 4302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 4312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis//////////////////////////////////////////////////////////////////////////////// 4332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// WindowEventDispatcher, ui::EventProcessor implementation: 4342da489cd246702bee5938545b18a6f710ed214bcJamie Gennisui::EventTarget* WindowEventDispatcher::GetRootTarget() { 4352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return window(); 4362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 4372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4382da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::PrepareEventForDispatch(ui::Event* event) { 4392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (dispatching_held_event_) { 4402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // The held events are already in |window()|'s coordinate system. So it is 4412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // not necessary to apply the transform to convert from the host's 4422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // coordinate system to |window()|'s coordinate system. 4432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 4442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 4452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (event->IsLocatedEvent()) { 4462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis TransformEventForDeviceScaleFactor(static_cast<ui::LocatedEvent*>(event)); 4472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 4482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 4492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis//////////////////////////////////////////////////////////////////////////////// 4512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// WindowEventDispatcher, ui::EventDispatcherDelegate implementation: 4522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4532da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbool WindowEventDispatcher::CanDispatchToTarget(ui::EventTarget* target) { 4542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return event_dispatch_target_ == target; 4552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 4562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4572da489cd246702bee5938545b18a6f710ed214bcJamie Gennisui::EventDispatchDetails WindowEventDispatcher::PreDispatchEvent( 4582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::EventTarget* target, 4592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::Event* event) { 4602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Window* target_window = static_cast<Window*>(target); 4612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis CHECK(window()->Contains(target_window)); 4622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!dispatching_held_event_) { 4642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis bool can_be_held = IsEventCandidateForHold(*event); 4652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!move_hold_count_ || !can_be_held) { 4662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (can_be_held) 4672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis held_move_event_.reset(); 4682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis DispatchDetails details = DispatchHeldEvents(); 4692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (details.dispatcher_destroyed || details.target_destroyed) 4702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return details; 4712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 4722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 4732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (event->IsMouseEvent()) { 4752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis PreDispatchMouseEvent(target_window, static_cast<ui::MouseEvent*>(event)); 4762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } else if (event->IsScrollEvent()) { 4772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis PreDispatchLocatedEvent(target_window, 4782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis static_cast<ui::ScrollEvent*>(event)); 4792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } else if (event->IsTouchEvent()) { 4802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis PreDispatchTouchEvent(target_window, static_cast<ui::TouchEvent*>(event)); 4812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 4822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis old_dispatch_target_ = event_dispatch_target_; 4832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis event_dispatch_target_ = static_cast<Window*>(target); 4842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return DispatchDetails(); 4852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 4862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4872da489cd246702bee5938545b18a6f710ed214bcJamie Gennisui::EventDispatchDetails WindowEventDispatcher::PostDispatchEvent( 4882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::EventTarget* target, 4892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis const ui::Event& event) { 4902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis DispatchDetails details; 4912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!target || target != event_dispatch_target_) 4922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis details.target_destroyed = true; 4932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis event_dispatch_target_ = old_dispatch_target_; 4942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis old_dispatch_target_ = NULL; 4952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#ifndef NDEBUG 4962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis DCHECK(!event_dispatch_target_ || window()->Contains(event_dispatch_target_)); 4972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis#endif 4982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (event.IsTouchEvent() && !details.target_destroyed) { 5002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Do not let 'held' touch events contribute to any gestures unless it is 5012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // being dispatched. 5022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (dispatching_held_event_ || !held_move_event_ || 5032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis !held_move_event_->IsTouchEvent()) { 5042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Once we've fully migrated to the eager gesture detector, we won't 5062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // need to pass an event here. 5072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::TouchEvent orig_event(static_cast<const ui::TouchEvent&>(event), 5082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis static_cast<Window*>(event.target()), 5092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis window()); 5102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (event.result() & ui::ER_CONSUMED) 5122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis orig_event.StopPropagation(); 5132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // TODO(tdresser): Move this to PreDispatchTouchEvent, to enable eager 5152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // gesture detection. See crbug.com/410280. 5162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!ui::GestureRecognizer::Get() 5172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ->ProcessTouchEventPreDispatch(orig_event, 5182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis static_cast<Window*>(target))) { 5192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return details; 5202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 5212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis scoped_ptr<ui::GestureRecognizer::Gestures> gestures; 5232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis gestures.reset( 5252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::GestureRecognizer::Get()->ProcessTouchEventPostDispatch( 5262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis orig_event, event.result(), static_cast<Window*>(target))); 5272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return ProcessGestures(gestures.get()); 5292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 5302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 5312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return details; 5332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 5342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis//////////////////////////////////////////////////////////////////////////////// 5362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// WindowEventDispatcher, ui::GestureEventHelper implementation: 5372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5382da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbool WindowEventDispatcher::CanDispatchToConsumer( 5392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ui::GestureConsumer* consumer) { 5402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Window* consumer_window = ConsumerToWindow(consumer); 5412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return (consumer_window && consumer_window->GetRootWindow() == window()); 5422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis} 5432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5442da489cd246702bee5938545b18a6f710ed214bcJamie Gennisvoid WindowEventDispatcher::DispatchCancelTouchEvent(ui::TouchEvent* event) { 545 // The touchcancel event's location is based on the last known location of 546 // the pointer, in dips. OnEventFromSource expects events with co-ordinates 547 // in raw pixels, so we convert back to raw pixels here. 548 event->UpdateForRootTransform(host_->GetRootTransform()); 549 DispatchDetails details = OnEventFromSource(event); 550 if (details.dispatcher_destroyed) 551 return; 552} 553 554//////////////////////////////////////////////////////////////////////////////// 555// WindowEventDispatcher, WindowObserver implementation: 556 557void WindowEventDispatcher::OnWindowDestroying(Window* window) { 558 if (!host_->window()->Contains(window)) 559 return; 560 561 DispatchMouseExitToHidingWindow(window); 562 SynthesizeMouseMoveAfterChangeToWindow(window); 563} 564 565void WindowEventDispatcher::OnWindowDestroyed(Window* window) { 566 // We observe all windows regardless of what root Window (if any) they're 567 // attached to. 568 observer_manager_.Remove(window); 569} 570 571void WindowEventDispatcher::OnWindowAddedToRootWindow(Window* attached) { 572 if (!observer_manager_.IsObserving(attached)) 573 observer_manager_.Add(attached); 574 575 if (!host_->window()->Contains(attached)) 576 return; 577 578 SynthesizeMouseMoveAfterChangeToWindow(attached); 579} 580 581void WindowEventDispatcher::OnWindowRemovingFromRootWindow(Window* detached, 582 Window* new_root) { 583 if (!host_->window()->Contains(detached)) 584 return; 585 586 DCHECK(client::GetCaptureWindow(window()) != window()); 587 588 DispatchMouseExitToHidingWindow(detached); 589 SynthesizeMouseMoveAfterChangeToWindow(detached); 590 591 // Hiding the window releases capture which can implicitly destroy the window 592 // so the window may no longer be valid after this call. 593 OnWindowHidden(detached, new_root ? WINDOW_MOVING : WINDOW_HIDDEN); 594} 595 596void WindowEventDispatcher::OnWindowVisibilityChanging(Window* window, 597 bool visible) { 598 if (!host_->window()->Contains(window)) 599 return; 600 601 DispatchMouseExitToHidingWindow(window); 602} 603 604void WindowEventDispatcher::OnWindowVisibilityChanged(Window* window, 605 bool visible) { 606 if (!host_->window()->Contains(window)) 607 return; 608 609 if (window->ContainsPointInRoot(GetLastMouseLocationInRoot())) 610 PostSynthesizeMouseMove(); 611 612 // Hiding the window releases capture which can implicitly destroy the window 613 // so the window may no longer be valid after this call. 614 if (!visible) 615 OnWindowHidden(window, WINDOW_HIDDEN); 616} 617 618void WindowEventDispatcher::OnWindowBoundsChanged(Window* window, 619 const gfx::Rect& old_bounds, 620 const gfx::Rect& new_bounds) { 621 if (!host_->window()->Contains(window)) 622 return; 623 624 if (window == host_->window()) { 625 TRACE_EVENT1("ui", "WindowEventDispatcher::OnWindowBoundsChanged(root)", 626 "size", new_bounds.size().ToString()); 627 628 DispatchDetails details = DispatchHeldEvents(); 629 if (details.dispatcher_destroyed) 630 return; 631 632 synthesize_mouse_move_ = false; 633 } 634 635 if (window->IsVisible() && !window->ignore_events()) { 636 gfx::Rect old_bounds_in_root = old_bounds, new_bounds_in_root = new_bounds; 637 Window::ConvertRectToTarget(window->parent(), host_->window(), 638 &old_bounds_in_root); 639 Window::ConvertRectToTarget(window->parent(), host_->window(), 640 &new_bounds_in_root); 641 gfx::Point last_mouse_location = GetLastMouseLocationInRoot(); 642 if (old_bounds_in_root.Contains(last_mouse_location) != 643 new_bounds_in_root.Contains(last_mouse_location)) { 644 PostSynthesizeMouseMove(); 645 } 646 } 647} 648 649void WindowEventDispatcher::OnWindowTransforming(Window* window) { 650 if (!host_->window()->Contains(window)) 651 return; 652 653 SynthesizeMouseMoveAfterChangeToWindow(window); 654} 655 656void WindowEventDispatcher::OnWindowTransformed(Window* window) { 657 if (!host_->window()->Contains(window)) 658 return; 659 660 SynthesizeMouseMoveAfterChangeToWindow(window); 661} 662 663/////////////////////////////////////////////////////////////////////////////// 664// WindowEventDispatcher, EnvObserver implementation: 665 666void WindowEventDispatcher::OnWindowInitialized(Window* window) { 667 observer_manager_.Add(window); 668} 669 670//////////////////////////////////////////////////////////////////////////////// 671// WindowEventDispatcher, private: 672 673ui::EventDispatchDetails WindowEventDispatcher::DispatchHeldEvents() { 674 if (!held_repostable_event_ && !held_move_event_) 675 return DispatchDetails(); 676 677 CHECK(!dispatching_held_event_); 678 dispatching_held_event_ = true; 679 680 DispatchDetails dispatch_details; 681 if (held_repostable_event_) { 682 if (held_repostable_event_->type() == ui::ET_MOUSE_PRESSED) { 683 scoped_ptr<ui::MouseEvent> mouse_event( 684 static_cast<ui::MouseEvent*>(held_repostable_event_.release())); 685 dispatch_details = OnEventFromSource(mouse_event.get()); 686 } else { 687 // TODO(rbyers): GESTURE_TAP_DOWN not yet supported: crbug.com/170987. 688 NOTREACHED(); 689 } 690 if (dispatch_details.dispatcher_destroyed) 691 return dispatch_details; 692 } 693 694 if (held_move_event_) { 695 // If a mouse move has been synthesized, the target location is suspect, 696 // so drop the held mouse event. 697 if (held_move_event_->IsTouchEvent() || 698 (held_move_event_->IsMouseEvent() && !synthesize_mouse_move_)) { 699 dispatch_details = OnEventFromSource(held_move_event_.get()); 700 } 701 if (!dispatch_details.dispatcher_destroyed) 702 held_move_event_.reset(); 703 } 704 705 if (!dispatch_details.dispatcher_destroyed) 706 dispatching_held_event_ = false; 707 return dispatch_details; 708} 709 710void WindowEventDispatcher::PostSynthesizeMouseMove() { 711 if (synthesize_mouse_move_) 712 return; 713 synthesize_mouse_move_ = true; 714 base::MessageLoop::current()->PostNonNestableTask( 715 FROM_HERE, 716 base::Bind(base::IgnoreResult( 717 &WindowEventDispatcher::SynthesizeMouseMoveEvent), 718 held_event_factory_.GetWeakPtr())); 719} 720 721void WindowEventDispatcher::SynthesizeMouseMoveAfterChangeToWindow( 722 Window* window) { 723 if (window->IsVisible() && 724 window->ContainsPointInRoot(GetLastMouseLocationInRoot())) { 725 PostSynthesizeMouseMove(); 726 } 727} 728 729ui::EventDispatchDetails WindowEventDispatcher::SynthesizeMouseMoveEvent() { 730 DispatchDetails details; 731 if (!synthesize_mouse_move_) 732 return details; 733 synthesize_mouse_move_ = false; 734 735 // If one of the mouse buttons is currently down, then do not synthesize a 736 // mouse-move event. In such cases, aura could synthesize a DRAGGED event 737 // instead of a MOVED event, but in multi-display/multi-host scenarios, the 738 // DRAGGED event can be synthesized in the incorrect host. So avoid 739 // synthesizing any events at all. 740 if (Env::GetInstance()->mouse_button_flags()) 741 return details; 742 743 gfx::Point root_mouse_location = GetLastMouseLocationInRoot(); 744 if (!window()->bounds().Contains(root_mouse_location)) 745 return details; 746 gfx::Point host_mouse_location = root_mouse_location; 747 host_->ConvertPointToHost(&host_mouse_location); 748 ui::MouseEvent event(ui::ET_MOUSE_MOVED, 749 host_mouse_location, 750 host_mouse_location, 751 ui::EF_IS_SYNTHESIZED, 752 0); 753 return OnEventFromSource(&event); 754} 755 756void WindowEventDispatcher::PreDispatchLocatedEvent(Window* target, 757 ui::LocatedEvent* event) { 758 int flags = event->flags(); 759 if (IsNonClientLocation(target, event->location())) 760 flags |= ui::EF_IS_NON_CLIENT; 761 event->set_flags(flags); 762 763 if (!dispatching_held_event_ && 764 (event->IsMouseEvent() || event->IsScrollEvent()) && 765 !(event->flags() & ui::EF_IS_SYNTHESIZED)) { 766 if (event->type() != ui::ET_MOUSE_CAPTURE_CHANGED) 767 SetLastMouseLocation(window(), event->root_location()); 768 synthesize_mouse_move_ = false; 769 } 770} 771 772void WindowEventDispatcher::PreDispatchMouseEvent(Window* target, 773 ui::MouseEvent* event) { 774 client::CursorClient* cursor_client = client::GetCursorClient(window()); 775 // We allow synthesized mouse exit events through even if mouse events are 776 // disabled. This ensures that hover state, etc on controls like buttons is 777 // cleared. 778 if (cursor_client && 779 !cursor_client->IsMouseEventsEnabled() && 780 (event->flags() & ui::EF_IS_SYNTHESIZED) && 781 (event->type() != ui::ET_MOUSE_EXITED)) { 782 event->SetHandled(); 783 return; 784 } 785 786 if (IsEventCandidateForHold(*event) && !dispatching_held_event_) { 787 if (move_hold_count_) { 788 if (!(event->flags() & ui::EF_IS_SYNTHESIZED) && 789 event->type() != ui::ET_MOUSE_CAPTURE_CHANGED) { 790 SetLastMouseLocation(window(), event->root_location()); 791 } 792 held_move_event_.reset(new ui::MouseEvent(*event, target, window())); 793 event->SetHandled(); 794 return; 795 } else { 796 // We may have a held event for a period between the time move_hold_count_ 797 // fell to 0 and the DispatchHeldEvents executes. Since we're going to 798 // dispatch the new event directly below, we can reset the old one. 799 held_move_event_.reset(); 800 } 801 } 802 803 const int kMouseButtonFlagMask = ui::EF_LEFT_MOUSE_BUTTON | 804 ui::EF_MIDDLE_MOUSE_BUTTON | 805 ui::EF_RIGHT_MOUSE_BUTTON; 806 switch (event->type()) { 807 case ui::ET_MOUSE_EXITED: 808 if (!target || target == window()) { 809 DispatchDetails details = 810 DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED); 811 if (details.dispatcher_destroyed) { 812 event->SetHandled(); 813 return; 814 } 815 mouse_moved_handler_ = NULL; 816 } 817 break; 818 case ui::ET_MOUSE_MOVED: 819 // Send an exit to the current |mouse_moved_handler_| and an enter to 820 // |target|. Take care that both us and |target| aren't destroyed during 821 // dispatch. 822 if (target != mouse_moved_handler_) { 823 aura::Window* old_mouse_moved_handler = mouse_moved_handler_; 824 WindowTracker live_window; 825 live_window.Add(target); 826 DispatchDetails details = 827 DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED); 828 if (details.dispatcher_destroyed) { 829 event->SetHandled(); 830 return; 831 } 832 // If the |mouse_moved_handler_| changes out from under us, assume a 833 // nested message loop ran and we don't need to do anything. 834 if (mouse_moved_handler_ != old_mouse_moved_handler) { 835 event->SetHandled(); 836 return; 837 } 838 if (!live_window.Contains(target) || details.target_destroyed) { 839 mouse_moved_handler_ = NULL; 840 event->SetHandled(); 841 return; 842 } 843 live_window.Remove(target); 844 845 mouse_moved_handler_ = target; 846 details = DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_ENTERED); 847 if (details.dispatcher_destroyed || details.target_destroyed) { 848 event->SetHandled(); 849 return; 850 } 851 } 852 break; 853 case ui::ET_MOUSE_PRESSED: 854 // Don't set the mouse pressed handler for non client mouse down events. 855 // These are only sent by Windows and are not always followed with non 856 // client mouse up events which causes subsequent mouse events to be 857 // sent to the wrong target. 858 if (!(event->flags() & ui::EF_IS_NON_CLIENT) && !mouse_pressed_handler_) 859 mouse_pressed_handler_ = target; 860 Env::GetInstance()->set_mouse_button_flags( 861 event->flags() & kMouseButtonFlagMask); 862 break; 863 case ui::ET_MOUSE_RELEASED: 864 mouse_pressed_handler_ = NULL; 865 Env::GetInstance()->set_mouse_button_flags(event->flags() & 866 kMouseButtonFlagMask & ~event->changed_button_flags()); 867 break; 868 default: 869 break; 870 } 871 872 PreDispatchLocatedEvent(target, event); 873} 874 875void WindowEventDispatcher::PreDispatchTouchEvent(Window* target, 876 ui::TouchEvent* event) { 877 switch (event->type()) { 878 case ui::ET_TOUCH_PRESSED: 879 touch_ids_down_ |= (1 << event->touch_id()); 880 Env::GetInstance()->set_touch_down(touch_ids_down_ != 0); 881 break; 882 883 // Handle ET_TOUCH_CANCELLED only if it has a native event. 884 case ui::ET_TOUCH_CANCELLED: 885 if (!event->HasNativeEvent()) 886 break; 887 // fallthrough 888 case ui::ET_TOUCH_RELEASED: 889 touch_ids_down_ = (touch_ids_down_ | (1 << event->touch_id())) ^ 890 (1 << event->touch_id()); 891 Env::GetInstance()->set_touch_down(touch_ids_down_ != 0); 892 break; 893 894 case ui::ET_TOUCH_MOVED: 895 if (move_hold_count_ && !dispatching_held_event_) { 896 held_move_event_.reset(new ui::TouchEvent(*event, target, window())); 897 event->SetHandled(); 898 return; 899 } 900 break; 901 902 default: 903 NOTREACHED(); 904 break; 905 } 906 907 PreDispatchLocatedEvent(target, event); 908} 909 910} // namespace aura 911