OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 COMPONENTS_MUS_WS_EVENT_DISPATCHER_H_ | |
6 #define COMPONENTS_MUS_WS_EVENT_DISPATCHER_H_ | |
7 | |
8 #include <stdint.h> | |
9 | |
10 #include <map> | |
11 #include <memory> | |
12 #include <utility> | |
13 | |
14 #include "base/macros.h" | |
15 #include "components/mus/common/types.h" | |
16 #include "components/mus/public/interfaces/event_matcher.mojom.h" | |
17 #include "components/mus/ws/modal_window_controller.h" | |
18 #include "components/mus/ws/server_window_observer.h" | |
19 #include "ui/gfx/geometry/rect_f.h" | |
20 | |
21 namespace ui { | |
22 class Event; | |
23 class KeyEvent; | |
24 class LocatedEvent; | |
25 } | |
26 | |
27 namespace mus { | |
28 namespace ws { | |
29 | |
30 class Accelerator; | |
31 class EventDispatcherDelegate; | |
32 class ServerWindow; | |
33 | |
34 namespace test { | |
35 class EventDispatcherTestApi; | |
36 } | |
37 | |
38 // Handles dispatching events to the right location as well as updating focus. | |
39 class EventDispatcher : public ServerWindowObserver { | |
40 public: | |
41 explicit EventDispatcher(EventDispatcherDelegate* delegate); | |
42 ~EventDispatcher() override; | |
43 | |
44 // Cancels capture and stops tracking any pointer events. This does not send | |
45 // any events to the delegate. | |
46 void Reset(); | |
47 | |
48 void SetMousePointerScreenLocation(const gfx::Point& screen_location); | |
49 const gfx::Point& mouse_pointer_last_location() const { | |
50 return mouse_pointer_last_location_; | |
51 } | |
52 | |
53 // If we still have the window of the last mouse move, returns true and sets | |
54 // the current cursor to use to |cursor_out|. | |
55 bool GetCurrentMouseCursor(int32_t* cursor_out); | |
56 | |
57 // |capture_window_| will receive all input. See window_tree.mojom for | |
58 // details. | |
59 ServerWindow* capture_window() { return capture_window_; } | |
60 const ServerWindow* capture_window() const { return capture_window_; } | |
61 // Setting capture can fail if the window is blocked by a modal window | |
62 // (indicated by returning |false|). | |
63 bool SetCaptureWindow(ServerWindow* capture_window, | |
64 ClientSpecificId client_id); | |
65 | |
66 // Id of the client that capture events are sent to. | |
67 ClientSpecificId capture_window_client_id() const { | |
68 return capture_window_client_id_; | |
69 } | |
70 | |
71 // Adds a system modal window. The window remains modal to system until it is | |
72 // destroyed. There can exist multiple system modal windows, in which case the | |
73 // one that is visible and added most recently or shown most recently would be | |
74 // the active one. | |
75 void AddSystemModalWindow(ServerWindow* window); | |
76 | |
77 // Checks if |modal_window| is a visible modal window that blocks current | |
78 // capture window and if that's the case, releases the capture. | |
79 void ReleaseCaptureBlockedByModalWindow(const ServerWindow* modal_window); | |
80 | |
81 // Checks if the current capture window is blocked by any visible modal window | |
82 // and if that's the case, releases the capture. | |
83 void ReleaseCaptureBlockedByAnyModalWindow(); | |
84 | |
85 // Retrieves the ServerWindow of the last mouse move. | |
86 ServerWindow* mouse_cursor_source_window() const { | |
87 return mouse_cursor_source_window_; | |
88 } | |
89 | |
90 // If the mouse cursor is still over |mouse_cursor_source_window_|, updates | |
91 // whether we are in the non-client area. Used when | |
92 // |mouse_cursor_source_window_| has changed its properties. | |
93 void UpdateNonClientAreaForCurrentWindow(); | |
94 | |
95 // Possibly updates the cursor. If we aren't in an implicit capture, we take | |
96 // the last known location of the mouse pointer, and look for the | |
97 // ServerWindow* under it. | |
98 void UpdateCursorProviderByLastKnownLocation(); | |
99 | |
100 // Adds an accelerator with the given id and event-matcher. If an accelerator | |
101 // already exists with the same id or the same matcher, then the accelerator | |
102 // is not added. Returns whether adding the accelerator was successful or not. | |
103 bool AddAccelerator(uint32_t id, mojom::EventMatcherPtr event_matcher); | |
104 void RemoveAccelerator(uint32_t id); | |
105 | |
106 // Processes the supplied event, informing the delegate as approriate. This | |
107 // may result in generating any number of events. | |
108 void ProcessEvent(const ui::Event& event); | |
109 | |
110 private: | |
111 friend class test::EventDispatcherTestApi; | |
112 | |
113 // Keeps track of state associated with an active pointer. | |
114 struct PointerTarget { | |
115 PointerTarget() | |
116 : window(nullptr), | |
117 is_mouse_event(false), | |
118 in_nonclient_area(false), | |
119 is_pointer_down(false) {} | |
120 | |
121 // NOTE: this is set to null if the window is destroyed before a | |
122 // corresponding release/cancel. | |
123 ServerWindow* window; | |
124 | |
125 bool is_mouse_event; | |
126 | |
127 // Did the pointer event start in the non-client area. | |
128 bool in_nonclient_area; | |
129 | |
130 bool is_pointer_down; | |
131 }; | |
132 | |
133 void ProcessKeyEvent(const ui::KeyEvent& event); | |
134 | |
135 bool IsTrackingPointer(int32_t pointer_id) const { | |
136 return pointer_targets_.count(pointer_id) > 0; | |
137 } | |
138 | |
139 // EventDispatcher provides the following logic for pointer events: | |
140 // . wheel events go to the current target of the associated pointer. If | |
141 // there is no target, they go to the deepest window. | |
142 // . move (not drag) events go to the deepest window. | |
143 // . when a pointer goes down all events until the corresponding up or | |
144 // cancel go to the deepest target. For mouse events the up only occurs | |
145 // when no buttons on the mouse are down. | |
146 // This also generates exit events as appropriate. For example, if the mouse | |
147 // moves between one window to another an exit is generated on the first. | |
148 void ProcessLocatedEvent(const ui::LocatedEvent& event); | |
149 | |
150 // Adds |pointer_target| to |pointer_targets_|. | |
151 void StartTrackingPointer(int32_t pointer_id, | |
152 const PointerTarget& pointer_target); | |
153 | |
154 // Removes a PointerTarget from |pointer_targets_|. | |
155 void StopTrackingPointer(int32_t pointer_id); | |
156 | |
157 // Starts tracking the pointer for |event|, or if already tracking the | |
158 // pointer sends the appropriate event to the delegate and updates the | |
159 // currently tracked PointerTarget appropriately. | |
160 void UpdateTargetForPointer(int32_t pointer_id, | |
161 const ui::LocatedEvent& event); | |
162 | |
163 // Returns a PointerTarget from the supplied event. | |
164 PointerTarget PointerTargetForEvent(const ui::LocatedEvent& event); | |
165 | |
166 // Returns true if any pointers are in the pressed/down state. | |
167 bool AreAnyPointersDown() const; | |
168 | |
169 // If |target->window| is valid, then passes the event to the delegate. | |
170 void DispatchToPointerTarget(const PointerTarget& target, | |
171 const ui::LocatedEvent& event); | |
172 | |
173 // Dispatch |event| to the delegate. | |
174 void DispatchToClient(ServerWindow* window, | |
175 ClientSpecificId client_id, | |
176 const ui::LocatedEvent& event); | |
177 | |
178 // Stops sending pointer events to |window|. This does not remove the entry | |
179 // for |window| from |pointer_targets_|, rather it nulls out the window. This | |
180 // way we continue to eat events until the up/cancel is received. | |
181 void CancelPointerEventsToTarget(ServerWindow* window); | |
182 | |
183 // Used to observe a window. Can be called multiple times on a window. To | |
184 // unobserve a window, UnobserveWindow() should be called the same number of | |
185 // times. | |
186 void ObserveWindow(ServerWindow* winodw); | |
187 void UnobserveWindow(ServerWindow* winodw); | |
188 | |
189 // Returns an Accelerator bound to the specified code/flags, and of the | |
190 // matching |phase|. Otherwise returns null. | |
191 Accelerator* FindAccelerator(const ui::KeyEvent& event, | |
192 const ui::mojom::AcceleratorPhase phase); | |
193 | |
194 ServerWindow* FindDeepestVisibleWindowForEvents(gfx::Point* location); | |
195 | |
196 // ServerWindowObserver: | |
197 void OnWillChangeWindowHierarchy(ServerWindow* window, | |
198 ServerWindow* new_parent, | |
199 ServerWindow* old_parent) override; | |
200 void OnWindowVisibilityChanged(ServerWindow* window) override; | |
201 void OnWindowDestroyed(ServerWindow* window) override; | |
202 | |
203 EventDispatcherDelegate* delegate_; | |
204 | |
205 ServerWindow* capture_window_; | |
206 ClientSpecificId capture_window_client_id_; | |
207 | |
208 ModalWindowController modal_window_controller_; | |
209 | |
210 bool mouse_button_down_; | |
211 ServerWindow* mouse_cursor_source_window_; | |
212 bool mouse_cursor_in_non_client_area_; | |
213 | |
214 // The on screen location of the mouse pointer. This can be outside the | |
215 // bounds of |mouse_cursor_source_window_|, which can capture the cursor. | |
216 gfx::Point mouse_pointer_last_location_; | |
217 | |
218 std::map<uint32_t, std::unique_ptr<Accelerator>> accelerators_; | |
219 | |
220 using PointerIdToTargetMap = std::map<int32_t, PointerTarget>; | |
221 // |pointer_targets_| contains the active pointers. For a mouse based pointer | |
222 // a PointerTarget is always active (and present in |pointer_targets_|). For | |
223 // touch based pointers the pointer is active while down and removed on | |
224 // cancel or up. | |
225 PointerIdToTargetMap pointer_targets_; | |
226 | |
227 // Keeps track of number of observe requests for each observed window. | |
228 std::map<const ServerWindow*, uint8_t> observed_windows_; | |
229 | |
230 DISALLOW_COPY_AND_ASSIGN(EventDispatcher); | |
231 }; | |
232 | |
233 } // namespace ws | |
234 } // namespace mus | |
235 | |
236 #endif // COMPONENTS_MUS_WS_EVENT_DISPATCHER_H_ | |
OLD | NEW |