1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef UI_AURA_WINDOW_EVENT_DISPATCHER_H_ 6 #define UI_AURA_WINDOW_EVENT_DISPATCHER_H_ 7 8 #include <vector> 9 10 #include "base/basictypes.h" 11 #include "base/gtest_prod_util.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/weak_ptr.h" 15 #include "base/message_loop/message_loop.h" 16 #include "base/scoped_observer.h" 17 #include "ui/aura/aura_export.h" 18 #include "ui/aura/client/capture_delegate.h" 19 #include "ui/aura/env_observer.h" 20 #include "ui/aura/window_observer.h" 21 #include "ui/base/cursor/cursor.h" 22 #include "ui/events/event_constants.h" 23 #include "ui/events/event_processor.h" 24 #include "ui/events/event_targeter.h" 25 #include "ui/events/gestures/gesture_recognizer.h" 26 #include "ui/events/gestures/gesture_types.h" 27 #include "ui/gfx/native_widget_types.h" 28 #include "ui/gfx/point.h" 29 30 namespace gfx { 31 class Size; 32 class Transform; 33 } 34 35 namespace ui { 36 class GestureEvent; 37 class GestureRecognizer; 38 class KeyEvent; 39 class MouseEvent; 40 class ScrollEvent; 41 class TouchEvent; 42 } 43 44 namespace aura { 45 class TestScreen; 46 class WindowTargeter; 47 class WindowTreeHost; 48 49 namespace test { 50 class WindowEventDispatcherTestApi; 51 } 52 53 // WindowEventDispatcher orchestrates event dispatch within a window tree 54 // owned by WindowTreeHost. WTH also owns the WED. 55 // TODO(beng): In progress, remove functionality not directly related to 56 // event dispatch. 57 class AURA_EXPORT WindowEventDispatcher : public ui::EventProcessor, 58 public ui::GestureEventHelper, 59 public client::CaptureDelegate, 60 public WindowObserver, 61 public EnvObserver { 62 public: 63 explicit WindowEventDispatcher(WindowTreeHost* host); 64 virtual ~WindowEventDispatcher(); 65 mouse_pressed_handler()66 Window* mouse_pressed_handler() { return mouse_pressed_handler_; } mouse_moved_handler()67 Window* mouse_moved_handler() { return mouse_moved_handler_; } 68 69 // Repost event for re-processing. Used when exiting context menus. 70 // We only support the ET_MOUSE_PRESSED and ET_GESTURE_TAP_DOWN event 71 // types (although the latter is currently a no-op). 72 void RepostEvent(const ui::LocatedEvent& event); 73 74 // Invoked when the mouse events get enabled or disabled. 75 void OnMouseEventsEnableStateChanged(bool enabled); 76 77 void DispatchCancelModeEvent(); 78 79 // Dispatches a ui::ET_MOUSE_EXITED event at |point|. 80 // TODO(beng): needed only for WTH::OnCursorVisibilityChanged(). 81 ui::EventDispatchDetails DispatchMouseExitAtPoint( 82 const gfx::Point& point) WARN_UNUSED_RESULT; 83 84 // Gesture Recognition ------------------------------------------------------- 85 86 // When a touch event is dispatched to a Window, it may want to process the 87 // touch event asynchronously. In such cases, the window should consume the 88 // event during the event dispatch. Once the event is properly processed, the 89 // window should let the WindowEventDispatcher know about the result of the 90 // event processing, so that gesture events can be properly created and 91 // dispatched. |event|'s location should be in the dispatcher's coordinate 92 // space, in DIPs. 93 void ProcessedTouchEvent(ui::TouchEvent* event, 94 Window* window, 95 ui::EventResult result); 96 97 // These methods are used to defer the processing of mouse/touch events 98 // related to resize. A client (typically a RenderWidgetHostViewAura) can call 99 // HoldPointerMoves when an resize is initiated and then ReleasePointerMoves 100 // once the resize is completed. 101 // 102 // More than one hold can be invoked and each hold must be cancelled by a 103 // release before we resume normal operation. 104 void HoldPointerMoves(); 105 void ReleasePointerMoves(); 106 107 // Gets the last location seen in a mouse event in this root window's 108 // coordinates. This may return a point outside the root window's bounds. 109 gfx::Point GetLastMouseLocationInRoot() const; 110 111 void OnHostLostMouseGrab(); 112 void OnCursorMovedToRootLocation(const gfx::Point& root_location); 113 114 // TODO(beng): This is only needed because this cleanup needs to happen after 115 // all other observers are notified of OnWindowDestroying() but 116 // before OnWindowDestroyed() is sent (i.e. while the window 117 // hierarchy is still intact). This didn't seem worth adding a 118 // generic notification for as only this class needs to implement 119 // it. I would however like to find a way to do this via an 120 // observer. 121 void OnPostNotifiedWindowDestroying(Window* window); 122 123 private: 124 FRIEND_TEST_ALL_PREFIXES(WindowEventDispatcherTest, 125 KeepTranslatedEventInRoot); 126 127 friend class test::WindowEventDispatcherTestApi; 128 friend class Window; 129 friend class TestScreen; 130 131 // The parameter for OnWindowHidden() to specify why window is hidden. 132 enum WindowHiddenReason { 133 WINDOW_DESTROYED, // Window is destroyed. 134 WINDOW_HIDDEN, // Window is hidden. 135 WINDOW_MOVING, // Window is temporarily marked as hidden due to move 136 // across root windows. 137 }; 138 139 Window* window(); 140 const Window* window() const; 141 142 // Updates the event with the appropriate transform for the device scale 143 // factor. The WindowEventDispatcher dispatches events in the physical pixel 144 // coordinate. But the event processing from WindowEventDispatcher onwards 145 // happen in device-independent pixel coordinate. So it is necessary to update 146 // the event received from the host. 147 void TransformEventForDeviceScaleFactor(ui::LocatedEvent* event); 148 149 // Dispatches OnMouseExited to the |window| which is hiding if necessary. 150 void DispatchMouseExitToHidingWindow(Window* window); 151 152 // Dispatches the specified event type (intended for enter/exit) to the 153 // |mouse_moved_handler_|. 154 ui::EventDispatchDetails DispatchMouseEnterOrExit( 155 const ui::MouseEvent& event, 156 ui::EventType type) WARN_UNUSED_RESULT; 157 ui::EventDispatchDetails ProcessGestures( 158 ui::GestureRecognizer::Gestures* gestures) WARN_UNUSED_RESULT; 159 160 // Called when a window becomes invisible, either by being removed 161 // from root window hierarchy, via SetVisible(false) or being destroyed. 162 // |reason| specifies what triggered the hiding. Note that becoming invisible 163 // will cause a window to lose capture and some windows may destroy themselves 164 // on capture (like DragDropTracker). 165 void OnWindowHidden(Window* invisible, WindowHiddenReason reason); 166 167 // Returns a target window for the given gesture event. 168 Window* GetGestureTarget(ui::GestureEvent* event); 169 170 // Overridden from aura::client::CaptureDelegate: 171 virtual void UpdateCapture(Window* old_capture, Window* new_capture) OVERRIDE; 172 virtual void OnOtherRootGotCapture() OVERRIDE; 173 virtual void SetNativeCapture() OVERRIDE; 174 virtual void ReleaseNativeCapture() OVERRIDE; 175 176 // Overridden from ui::EventProcessor: 177 virtual ui::EventTarget* GetRootTarget() OVERRIDE; 178 virtual void PrepareEventForDispatch(ui::Event* event) OVERRIDE; 179 180 // Overridden from ui::EventDispatcherDelegate. 181 virtual bool CanDispatchToTarget(ui::EventTarget* target) OVERRIDE; 182 virtual ui::EventDispatchDetails PreDispatchEvent(ui::EventTarget* target, 183 ui::Event* event) OVERRIDE; 184 virtual ui::EventDispatchDetails PostDispatchEvent( 185 ui::EventTarget* target, const ui::Event& event) OVERRIDE; 186 187 // Overridden from ui::GestureEventHelper. 188 virtual bool CanDispatchToConsumer(ui::GestureConsumer* consumer) OVERRIDE; 189 virtual void DispatchGestureEvent(ui::GestureEvent* event) OVERRIDE; 190 virtual void DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE; 191 192 // Overridden from WindowObserver: 193 virtual void OnWindowDestroying(Window* window) OVERRIDE; 194 virtual void OnWindowDestroyed(Window* window) OVERRIDE; 195 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE; 196 virtual void OnWindowRemovingFromRootWindow(Window* window, 197 Window* new_root) OVERRIDE; 198 virtual void OnWindowVisibilityChanging(Window* window, 199 bool visible) OVERRIDE; 200 virtual void OnWindowVisibilityChanged(Window* window, bool visible) OVERRIDE; 201 virtual void OnWindowBoundsChanged(Window* window, 202 const gfx::Rect& old_bounds, 203 const gfx::Rect& new_bounds) OVERRIDE; 204 virtual void OnWindowTransforming(Window* window) OVERRIDE; 205 virtual void OnWindowTransformed(Window* window) OVERRIDE; 206 207 // Overridden from EnvObserver: 208 virtual void OnWindowInitialized(Window* window) OVERRIDE; 209 210 // We hold and aggregate mouse drags and touch moves as a way of throttling 211 // resizes when HoldMouseMoves() is called. The following methods are used to 212 // dispatch held and newly incoming mouse and touch events, typically when an 213 // event other than one of these needs dispatching or a matching 214 // ReleaseMouseMoves()/ReleaseTouchMoves() is called. NOTE: because these 215 // methods dispatch events from WindowTreeHost the coordinates are in terms of 216 // the root. 217 ui::EventDispatchDetails DispatchHeldEvents() WARN_UNUSED_RESULT; 218 219 // Posts a task to send synthesized mouse move event if there is no a pending 220 // task. 221 void PostSynthesizeMouseMove(); 222 223 // Creates and dispatches synthesized mouse move event using the current mouse 224 // location. 225 ui::EventDispatchDetails SynthesizeMouseMoveEvent() WARN_UNUSED_RESULT; 226 227 // Calls SynthesizeMouseMove() if |window| is currently visible and contains 228 // the mouse cursor. 229 void SynthesizeMouseMoveAfterChangeToWindow(Window* window); 230 231 void PreDispatchLocatedEvent(Window* target, ui::LocatedEvent* event); 232 void PreDispatchMouseEvent(Window* target, ui::MouseEvent* event); 233 void PreDispatchTouchEvent(Window* target, ui::TouchEvent* event); 234 235 WindowTreeHost* host_; 236 237 // Touch ids that are currently down. 238 uint32 touch_ids_down_; 239 240 Window* mouse_pressed_handler_; 241 Window* mouse_moved_handler_; 242 Window* event_dispatch_target_; 243 Window* old_dispatch_target_; 244 245 bool synthesize_mouse_move_; 246 247 // How many move holds are outstanding. We try to defer dispatching 248 // touch/mouse moves while the count is > 0. 249 int move_hold_count_; 250 // The location of |held_move_event_| is in |window_|'s coordinate. 251 scoped_ptr<ui::LocatedEvent> held_move_event_; 252 253 // Allowing for reposting of events. Used when exiting context menus. 254 scoped_ptr<ui::LocatedEvent> held_repostable_event_; 255 256 // Set when dispatching a held event. 257 bool dispatching_held_event_; 258 259 ScopedObserver<aura::Window, aura::WindowObserver> observer_manager_; 260 261 // Used to schedule reposting an event. 262 base::WeakPtrFactory<WindowEventDispatcher> repost_event_factory_; 263 264 // Used to schedule DispatchHeldEvents() when |move_hold_count_| goes to 0. 265 base::WeakPtrFactory<WindowEventDispatcher> held_event_factory_; 266 267 DISALLOW_COPY_AND_ASSIGN(WindowEventDispatcher); 268 }; 269 270 } // namespace aura 271 272 #endif // UI_AURA_WINDOW_EVENT_DISPATCHER_H_ 273