1 // Copyright (c) 2013 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_TARGETER_H_
6 #define UI_AURA_WINDOW_TARGETER_H_
7 
8 #include <memory>
9 #include <vector>
10 
11 #include "base/macros.h"
12 #include "ui/aura/aura_export.h"
13 #include "ui/events/event_targeter.h"
14 #include "ui/gfx/geometry/insets.h"
15 
16 namespace gfx {
17 class Rect;
18 }
19 
20 namespace ui {
21 class LocatedEvent;
22 }  // namespace ui
23 
24 namespace aura {
25 
26 class Window;
27 
28 class AURA_EXPORT WindowTargeter : public ui::EventTargeter {
29  public:
30   WindowTargeter();
31   ~WindowTargeter() override;
32 
33   using HitTestRects = std::vector<gfx::Rect>;
34 
35   // Returns true if |window| or one of its descendants can be a target of
36   // |event|. This requires that |window| and its descendants are not
37   // prohibited from accepting the event, and that the event is within an
38   // actionable region of the target's bounds. Note that the location etc. of
39   // |event| is in |window|'s parent's coordinate system.
40   virtual bool SubtreeShouldBeExploredForEvent(Window* window,
41                                                const ui::LocatedEvent& event);
42 
43   // Returns true if the |target| is accepting LocatedEvents, false otherwise.
44   // |hit_test_rect_mouse| and |hit_test_rect_touch| must be not null and return
45   // the bounds that can be used for hit testing. The default implementation
46   // extends the |target|'s |bounds()| by insets provided with SetInsets().
47   // This can be used to extend the hit-test area for touch events and make
48   // targeting windows with imprecise input devices easier.
49   // Returned rectangles are in |target|'s parent's coordinates.
50   virtual bool GetHitTestRects(Window* target,
51                                gfx::Rect* hit_test_rect_mouse,
52                                gfx::Rect* hit_test_rect_touch) const;
53 
54   // Returns additional hit-test areas or nullptr when there are none. Used when
55   // a window needs a complex shape hit-test area. This additional area is
56   // clipped to |hit_test_rect_mouse| returned by GetHitTestRects or the window
57   // bounds when GetHitTestRects is not overridden.
58   // Returned rectangles are in |target|'s coordinates.
59   virtual std::unique_ptr<HitTestRects> GetExtraHitTestShapeRects(
60       Window* target) const;
61 
62   // Sets additional mouse and touch insets that are factored into the hit-test
63   // regions returned by GetHitTestRects.
64   void SetInsets(const gfx::Insets& mouse_and_touch_extend);
65   void SetInsets(const gfx::Insets& mouse_extend,
66                  const gfx::Insets& touch_extend);
67 
68   // If there is a target that takes priority over normal WindowTargeter (such
69   // as a capture window) this returns it.
70   Window* GetPriorityTargetInRootWindow(Window* root_window,
71                                         const ui::LocatedEvent& event);
72 
73   Window* FindTargetInRootWindow(Window* root_window,
74                                  const ui::LocatedEvent& event);
75 
76   // If |target| is not a child of |root_window|, then converts |event| to
77   // be relative to |root_window| and dispatches the event to |root_window|.
78   // Returns false if the |target| is a child of |root_window|.
79   bool ProcessEventIfTargetsDifferentRootWindow(Window* root_window,
80                                                 Window* target,
81                                                 ui::Event* event);
82 
83   // ui::EventTargeter:
84   ui::EventTarget* FindTargetForEvent(ui::EventTarget* root,
85                                       ui::Event* event) override;
86   ui::EventTarget* FindNextBestTarget(ui::EventTarget* previous_target,
87                                       ui::Event* event) override;
88 
89   Window* FindTargetForKeyEvent(Window* root_window);
90 
91  protected:
window()92   aura::Window* window() { return window_; }
window()93   const aura::Window* window() const { return window_; }
94 
95   // This is called by Window when the targeter is set on a window.
96   virtual void OnInstalled(Window* window);
97 
98   // Same as FindTargetForEvent(), but used for positional events. The location
99   // etc. of |event| are in |window|'s coordinate system. When finding the
100   // target for the event, the targeter can mutate the |event| (e.g. change the
101   // coordinate to be in the returned target's coordinate system) so that it can
102   // be dispatched to the target without any further modification.
103   virtual Window* FindTargetForLocatedEvent(Window* window,
104                                             ui::LocatedEvent* event);
105 
106   // Returns false if neither |window| nor any of its descendants are allowed
107   // to accept |event| for reasons unrelated to the event's location or the
108   // target's bounds. For example, overrides of this function may consider
109   // attributes such as the visibility or enabledness of |window|. Note that
110   // the location etc. of |event| is in |window|'s parent's coordinate system.
111   virtual bool SubtreeCanAcceptEvent(Window* window,
112                                      const ui::LocatedEvent& event) const;
113 
114   // Returns whether the location of the event is in an actionable region of the
115   // target. Note that the location etc. of |event| is in the |window|'s
116   // parent's coordinate system.
117   // Deprecated. As an alternative, override GetHitTestRects.
118   // TODO(varkha): Make this non-overridable.
119   virtual bool EventLocationInsideBounds(Window* target,
120                                          const ui::LocatedEvent& event) const;
121 
122   // Returns true if the hit testing (GetHitTestRects()) should use the
123   // extended bounds.
124   virtual bool ShouldUseExtendedBounds(const aura::Window* w) const;
125 
mouse_extend()126   const gfx::Insets& mouse_extend() const { return mouse_extend_; }
touch_extend()127   const gfx::Insets& touch_extend() const { return touch_extend_; }
128 
129  private:
130   // To call OnInstalled().
131   friend class Window;
132 
133   Window* FindTargetForNonKeyEvent(Window* root_window, ui::Event* event);
134   Window* FindTargetForLocatedEventRecursively(Window* root_window,
135                                                ui::LocatedEvent* event);
136 
137   // The Window this WindowTargeter is installed on. Null if not attached to a
138   // Window.
139   aura::Window* window_ = nullptr;
140 
141   gfx::Insets mouse_extend_;
142   gfx::Insets touch_extend_;
143 
144   DISALLOW_COPY_AND_ASSIGN(WindowTargeter);
145 };
146 
147 }  // namespace aura
148 
149 #endif  // UI_AURA_WINDOW_TARGETER_H_
150