Home | History | Annotate | Download | only in aura
      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 
     66   Window* mouse_pressed_handler() { return mouse_pressed_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