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