1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
|
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_UI_WS_EVENT_DISPATCHER_H_
#define SERVICES_UI_WS_EVENT_DISPATCHER_H_
#include <stdint.h>
#include <map>
#include <memory>
#include <utility>
#include "base/macros.h"
#include "services/ui/common/types.h"
#include "services/ui/public/interfaces/cursor/cursor.mojom.h"
#include "services/ui/public/interfaces/window_manager.mojom.h"
#include "services/ui/ws/drag_cursor_updater.h"
#include "services/ui/ws/modal_window_controller.h"
#include "services/ui/ws/server_window_observer.h"
#include "ui/gfx/geometry/rect_f.h"
namespace ui {
class Event;
class KeyEvent;
class LocatedEvent;
class PointerEvent;
namespace ws {
class Accelerator;
struct DeepestWindow;
class DragController;
class DragSource;
class DragTargetConnection;
class EventDispatcherDelegate;
class ServerWindow;
namespace test {
class EventDispatcherTestApi;
}
// Handles dispatching events to the right location as well as updating focus.
class EventDispatcher : public ServerWindowObserver, public DragCursorUpdater {
public:
enum class AcceleratorMatchPhase {
// Both pre and post should be considered.
ANY,
// PRE_TARGETs are not considered, only the actual target and any
// accelerators registered with POST_TARGET.
POST_ONLY,
};
explicit EventDispatcher(EventDispatcherDelegate* delegate);
~EventDispatcher() override;
// Cancels capture and stops tracking any pointer events. This does not send
// any events to the delegate.
void Reset();
void SetMousePointerScreenLocation(const gfx::Point& screen_location);
const gfx::Point& mouse_pointer_last_location() const {
return mouse_pointer_last_location_;
}
// Returns the cursor for the current target, or POINTER if the mouse is not
// over a valid target.
ui::CursorData GetCurrentMouseCursor() const;
// |capture_window_| will receive all input. See window_tree.mojom for
// details.
ServerWindow* capture_window() { return capture_window_; }
const ServerWindow* capture_window() const { return capture_window_; }
// Setting capture can fail if the window is blocked by a modal window
// (indicated by returning |false|).
bool SetCaptureWindow(ServerWindow* capture_window,
ClientSpecificId client_id);
// Id of the client that capture events are sent to.
ClientSpecificId capture_window_client_id() const {
return capture_window_client_id_;
}
void SetDragDropSourceWindow(
DragSource* drag_source,
ServerWindow* window,
DragTargetConnection* source_connection,
int32_t drag_pointer,
const std::unordered_map<std::string, std::vector<uint8_t>>& mime_data,
uint32_t drag_operations);
void CancelDragDrop();
void EndDragDrop();
void OnWillDestroyDragTargetConnection(DragTargetConnection* connection);
// Adds a system modal window. The window remains modal to system until it is
// destroyed. There can exist multiple system modal windows, in which case the
// one that is visible and added most recently or shown most recently would be
// the active one.
void AddSystemModalWindow(ServerWindow* window);
// Checks if |modal_window| is a visible modal window that blocks current
// capture window and if that's the case, releases the capture.
void ReleaseCaptureBlockedByModalWindow(const ServerWindow* modal_window);
// Checks if the current capture window is blocked by any visible modal window
// and if that's the case, releases the capture.
void ReleaseCaptureBlockedByAnyModalWindow();
// Retrieves the ServerWindow of the last mouse move. If there is no valid
// window event target this falls back to the root of the display. In general
// this is not null, but may be null during shutdown.
ServerWindow* mouse_cursor_source_window() const {
return mouse_cursor_source_window_;
}
// Returns the window the mouse cursor is taken from. This does not take
// into account drags. In other words if there is a drag on going the mouse
// comes comes from a different window.
const ServerWindow* GetWindowForMouseCursor() const;
// If the mouse cursor is still over |mouse_cursor_source_window_|, updates
// whether we are in the non-client area. Used when
// |mouse_cursor_source_window_| has changed its properties.
void UpdateNonClientAreaForCurrentWindow();
// Possibly updates the cursor. If we aren't in an implicit capture, we take
// the last known location of the mouse pointer, and look for the
// ServerWindow* under it.
void UpdateCursorProviderByLastKnownLocation();
// Adds an accelerator with the given id and event-matcher. If an accelerator
// already exists with the same id or the same matcher, then the accelerator
// is not added. Returns whether adding the accelerator was successful or not.
bool AddAccelerator(uint32_t id, mojom::EventMatcherPtr event_matcher);
void RemoveAccelerator(uint32_t id);
// Processes the supplied event, informing the delegate as approriate. This
// may result in generating any number of events. If |match_phase| is
// ANY and there is a matching accelerator with PRE_TARGET found, than only
// OnAccelerator() is called. The expectation is after the PRE_TARGET has been
// handled this is again called with an AcceleratorMatchPhase of POST_ONLY.
void ProcessEvent(const ui::Event& event, AcceleratorMatchPhase match_phase);
private:
friend class test::EventDispatcherTestApi;
// Keeps track of state associated with an active pointer.
struct PointerTarget {
PointerTarget()
: window(nullptr),
is_mouse_event(false),
in_nonclient_area(false),
is_pointer_down(false) {}
// The target window, which may be null. null is used in two situations:
// when there is no valid window target, or there was a target but the
// window is destroyed before a corresponding release/cancel.
ServerWindow* window;
bool is_mouse_event;
// Did the pointer event start in the non-client area.
bool in_nonclient_area;
bool is_pointer_down;
};
void SetMouseCursorSourceWindow(ServerWindow* window);
void ProcessKeyEvent(const ui::KeyEvent& event,
AcceleratorMatchPhase match_phase);
bool IsTrackingPointer(int32_t pointer_id) const {
return pointer_targets_.count(pointer_id) > 0;
}
// EventDispatcher provides the following logic for pointer events:
// . wheel events go to the current target of the associated pointer. If
// there is no target, they go to the deepest window.
// . move (not drag) events go to the deepest window.
// . when a pointer goes down all events until the corresponding up or
// cancel go to the deepest target. For mouse events the up only occurs
// when no buttons on the mouse are down.
// This also generates exit events as appropriate. For example, if the mouse
// moves between one window to another an exit is generated on the first.
void ProcessPointerEvent(const ui::PointerEvent& event);
// Adds |pointer_target| to |pointer_targets_|.
void StartTrackingPointer(int32_t pointer_id,
const PointerTarget& pointer_target);
// Removes a PointerTarget from |pointer_targets_|.
void StopTrackingPointer(int32_t pointer_id);
// Starts tracking the pointer for |event|, or if already tracking the
// pointer sends the appropriate event to the delegate and updates the
// currently tracked PointerTarget appropriately.
void UpdateTargetForPointer(int32_t pointer_id,
const ui::LocatedEvent& event);
// Returns a PointerTarget for the supplied event. If there is no valid
// event target for the specified location |window| in the returned value is
// null.
PointerTarget PointerTargetForEvent(const ui::LocatedEvent& event);
// Returns true if any pointers are in the pressed/down state.
bool AreAnyPointersDown() const;
// If |target->window| is valid, then passes the event to the delegate.
void DispatchToPointerTarget(const PointerTarget& target,
const ui::LocatedEvent& event);
// Dispatch |event| to the delegate.
void DispatchToClient(ServerWindow* window,
ClientSpecificId client_id,
const ui::LocatedEvent& event);
// Stops sending pointer events to |window|. This does not remove the entry
// for |window| from |pointer_targets_|, rather it nulls out the window. This
// way we continue to eat events until the up/cancel is received.
void CancelPointerEventsToTarget(ServerWindow* window);
// Used to observe a window. Can be called multiple times on a window. To
// unobserve a window, UnobserveWindow() should be called the same number of
// times.
void ObserveWindow(ServerWindow* winodw);
void UnobserveWindow(ServerWindow* winodw);
// Returns an Accelerator bound to the specified code/flags, and of the
// matching |phase|. Otherwise returns null.
Accelerator* FindAccelerator(const ui::KeyEvent& event,
const ui::mojom::AcceleratorPhase phase);
DeepestWindow FindDeepestVisibleWindowForEvents(const gfx::Point& location);
// Clears the implicit captures in |pointer_targets_|, with the exception of
// |window|. |window| may be null. |client_id| is the target client of
// |window|.
void CancelImplicitCaptureExcept(ServerWindow* window,
ClientSpecificId client_id);
// ServerWindowObserver:
void OnWillChangeWindowHierarchy(ServerWindow* window,
ServerWindow* new_parent,
ServerWindow* old_parent) override;
void OnWindowVisibilityChanged(ServerWindow* window) override;
void OnWindowDestroyed(ServerWindow* window) override;
// DragCursorUpdater:
void OnDragCursorUpdated() override;
EventDispatcherDelegate* delegate_;
ServerWindow* capture_window_;
ClientSpecificId capture_window_client_id_;
std::unique_ptr<DragController> drag_controller_;
ModalWindowController modal_window_controller_;
bool mouse_button_down_;
ServerWindow* mouse_cursor_source_window_;
bool mouse_cursor_in_non_client_area_;
// The on screen location of the mouse pointer. This can be outside the
// bounds of |mouse_cursor_source_window_|, which can capture the cursor.
gfx::Point mouse_pointer_last_location_;
std::map<uint32_t, std::unique_ptr<Accelerator>> accelerators_;
using PointerIdToTargetMap = std::map<int32_t, PointerTarget>;
// |pointer_targets_| contains the active pointers. For a mouse based pointer
// a PointerTarget is always active (and present in |pointer_targets_|). For
// touch based pointers the pointer is active while down and removed on
// cancel or up.
PointerIdToTargetMap pointer_targets_;
// Keeps track of number of observe requests for each observed window.
std::map<const ServerWindow*, uint8_t> observed_windows_;
#if !defined(NDEBUG)
std::unique_ptr<ui::Event> previous_event_;
AcceleratorMatchPhase previous_accelerator_match_phase_ =
AcceleratorMatchPhase::ANY;
#endif
DISALLOW_COPY_AND_ASSIGN(EventDispatcher);
};
} // namespace ws
} // namespace ui
#endif // SERVICES_UI_WS_EVENT_DISPATCHER_H_
|