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