Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(452)

Side by Side Diff: components/mus/ws/event_dispatcher.cc

Issue 1425123002: Makes event dispatch implicitly target specific window until release (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: merge 2 trunk Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/mus/ws/event_dispatcher.h ('k') | components/mus/ws/event_dispatcher_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/mus/ws/event_dispatcher.h" 5 #include "components/mus/ws/event_dispatcher.h"
6 6
7 #include <set>
8
7 #include "cc/surfaces/surface_hittest.h" 9 #include "cc/surfaces/surface_hittest.h"
8 #include "components/mus/surfaces/surfaces_state.h" 10 #include "components/mus/surfaces/surfaces_state.h"
9 #include "components/mus/ws/event_dispatcher_delegate.h" 11 #include "components/mus/ws/event_dispatcher_delegate.h"
10 #include "components/mus/ws/server_window.h" 12 #include "components/mus/ws/server_window.h"
11 #include "components/mus/ws/server_window_delegate.h" 13 #include "components/mus/ws/server_window_delegate.h"
12 #include "components/mus/ws/window_coordinate_conversions.h" 14 #include "components/mus/ws/window_coordinate_conversions.h"
13 #include "components/mus/ws/window_finder.h" 15 #include "components/mus/ws/window_finder.h"
14 #include "components/mus/ws/window_tree_host_impl.h" 16 #include "components/mus/ws/window_tree_host_impl.h"
15 #include "mojo/converters/geometry/geometry_type_converters.h" 17 #include "mojo/converters/geometry/geometry_type_converters.h"
16 #include "ui/gfx/geometry/point.h" 18 #include "ui/gfx/geometry/point.h"
17 #include "ui/gfx/geometry/point_conversions.h" 19 #include "ui/gfx/geometry/point_conversions.h"
18 20
19 namespace mus { 21 namespace mus {
20 namespace ws { 22 namespace ws {
21 namespace { 23 namespace {
22 24
23 bool IsMouseEventFlag(int32_t event_flags) {
24 return !!(event_flags & (mojom::EVENT_FLAGS_LEFT_MOUSE_BUTTON |
25 mojom::EVENT_FLAGS_MIDDLE_MOUSE_BUTTON |
26 mojom::EVENT_FLAGS_RIGHT_MOUSE_BUTTON));
27 }
28
29 bool IsOnlyOneMouseButtonDown(mojom::EventFlags flags) { 25 bool IsOnlyOneMouseButtonDown(mojom::EventFlags flags) {
30 const uint32_t mouse_only_flags = 26 const uint32_t mouse_only_flags =
31 flags & (mojom::EVENT_FLAGS_LEFT_MOUSE_BUTTON | 27 flags & (mojom::EVENT_FLAGS_LEFT_MOUSE_BUTTON |
32 mojom::EVENT_FLAGS_MIDDLE_MOUSE_BUTTON | 28 mojom::EVENT_FLAGS_MIDDLE_MOUSE_BUTTON |
33 mojom::EVENT_FLAGS_RIGHT_MOUSE_BUTTON); 29 mojom::EVENT_FLAGS_RIGHT_MOUSE_BUTTON);
34 return mouse_only_flags == mojom::EVENT_FLAGS_LEFT_MOUSE_BUTTON || 30 return mouse_only_flags == mojom::EVENT_FLAGS_LEFT_MOUSE_BUTTON ||
35 mouse_only_flags == mojom::EVENT_FLAGS_MIDDLE_MOUSE_BUTTON || 31 mouse_only_flags == mojom::EVENT_FLAGS_MIDDLE_MOUSE_BUTTON ||
36 mouse_only_flags == mojom::EVENT_FLAGS_RIGHT_MOUSE_BUTTON; 32 mouse_only_flags == mojom::EVENT_FLAGS_RIGHT_MOUSE_BUTTON;
37 } 33 }
38 34
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 mojom::EventType event_type_; 130 mojom::EventType event_type_;
135 mojom::EventFlags event_flags_; 131 mojom::EventFlags event_flags_;
136 mojom::KeyboardCode keyboard_code_; 132 mojom::KeyboardCode keyboard_code_;
137 mojom::PointerKind pointer_kind_; 133 mojom::PointerKind pointer_kind_;
138 gfx::RectF pointer_region_; 134 gfx::RectF pointer_region_;
139 }; 135 };
140 136
141 //////////////////////////////////////////////////////////////////////////////// 137 ////////////////////////////////////////////////////////////////////////////////
142 138
143 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate) 139 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate)
144 : delegate_(delegate), 140 : delegate_(delegate), root_(nullptr) {}
145 root_(nullptr),
146 capture_window_(nullptr),
147 capture_in_nonclient_area_(false) {}
148 141
149 EventDispatcher::~EventDispatcher() {} 142 EventDispatcher::~EventDispatcher() {
143 std::set<ServerWindow*> pointer_targets;
144 for (const auto& pair : pointer_targets_) {
145 if (pair.second.window &&
146 pointer_targets.insert(pair.second.window).second) {
147 pair.second.window->RemoveObserver(this);
148 }
149 }
150 }
150 151
151 void EventDispatcher::AddAccelerator(uint32_t id, 152 void EventDispatcher::AddAccelerator(uint32_t id,
152 mojom::EventMatcherPtr event_matcher) { 153 mojom::EventMatcherPtr event_matcher) {
153 EventMatcher matcher(*event_matcher); 154 EventMatcher matcher(*event_matcher);
154 #if !defined(NDEBUG) 155 #if !defined(NDEBUG)
155 for (const auto& pair : accelerators_) { 156 for (const auto& pair : accelerators_) {
156 DCHECK_NE(pair.first, id); 157 DCHECK_NE(pair.first, id);
157 DCHECK(!matcher.Equals(pair.second)); 158 DCHECK(!matcher.Equals(pair.second));
158 } 159 }
159 #endif 160 #endif
(...skipping 12 matching lines...) Expand all
172 173
173 if (event->action == mojom::EVENT_TYPE_KEY_PRESSED && 174 if (event->action == mojom::EVENT_TYPE_KEY_PRESSED &&
174 !event->key_data->is_char) { 175 !event->key_data->is_char) {
175 uint32_t accelerator = 0u; 176 uint32_t accelerator = 0u;
176 if (FindAccelerator(*event, &accelerator)) { 177 if (FindAccelerator(*event, &accelerator)) {
177 delegate_->OnAccelerator(accelerator, event.Pass()); 178 delegate_->OnAccelerator(accelerator, event.Pass());
178 return; 179 return;
179 } 180 }
180 } 181 }
181 182
182 ServerWindow* target = FindEventTarget(event.get()); 183 if (event->key_data) {
183 bool in_nonclient_area = false; 184 ProcessKeyEvent(event.Pass());
184 185 return;
185 if (IsMouseEventFlag(event->flags)) {
186 if (!capture_window_ && target &&
187 (event->action == mojom::EVENT_TYPE_POINTER_DOWN)) {
188 // TODO(sky): |capture_window_| needs to be reset when window removed
189 // from hierarchy.
190 capture_window_ = target;
191 // TODO(sky): this needs to happen for pointer down events too.
192 capture_in_nonclient_area_ =
193 IsLocationInNonclientArea(target, EventLocationToPoint(*event));
194 in_nonclient_area = capture_in_nonclient_area_;
195 } else if (event->action == mojom::EVENT_TYPE_POINTER_UP &&
196 IsOnlyOneMouseButtonDown(event->flags)) {
197 capture_window_ = nullptr;
198 }
199 in_nonclient_area = capture_in_nonclient_area_;
200 } 186 }
201 187
202 if (target) { 188 if (event->pointer_data.get()) {
203 if (event->action == mojom::EVENT_TYPE_POINTER_DOWN) 189 ProcessPointerEvent(event.Pass());
190 return;
191 }
192
193 NOTREACHED();
194 }
195
196 void EventDispatcher::ProcessKeyEvent(mojom::EventPtr event) {
197 ServerWindow* focused_window =
198 delegate_->GetFocusedWindowForEventDispatcher();
199 if (focused_window)
200 delegate_->DispatchInputEventToWindow(focused_window, false, event.Pass());
201 }
202
203 void EventDispatcher::ProcessPointerEvent(mojom::EventPtr event) {
204 const int32_t pointer_id = event->pointer_data->pointer_id;
205 if (event->action == mojom::EVENT_TYPE_WHEEL ||
206 (event->action == mojom::EVENT_TYPE_POINTER_MOVE &&
207 pointer_targets_.count(pointer_id) == 0)) {
208 PointerTarget pointer_target;
209 if (pointer_targets_.count(pointer_id) != 0) {
210 pointer_target = pointer_targets_[pointer_id];
211 } else {
212 gfx::Point location(EventLocationToPoint(*event));
213 pointer_target.window =
214 FindDeepestVisibleWindow(root_, surface_id_, &location);
215 }
216 DispatchToPointerTarget(pointer_target, event.Pass());
217 return;
218 }
219
220 // Pointer down implicitly captures.
221 if (pointer_targets_.count(pointer_id) == 0) {
222 DCHECK(event->action == mojom::EVENT_TYPE_POINTER_DOWN);
223 const bool is_first_pointer_down = pointer_targets_.empty();
224 gfx::Point location(EventLocationToPoint(*event));
225 ServerWindow* target =
226 FindDeepestVisibleWindow(root_, surface_id_, &location);
227 DCHECK(target);
228 if (!IsObservingWindow(target))
229 target->AddObserver(this);
230
231 pointer_targets_[pointer_id].window = target;
232 pointer_targets_[pointer_id].in_nonclient_area =
233 IsLocationInNonclientArea(target, location);
234
235 if (is_first_pointer_down)
204 delegate_->SetFocusedWindowFromEventDispatcher(target); 236 delegate_->SetFocusedWindowFromEventDispatcher(target);
237 }
205 238
206 delegate_->DispatchInputEventToWindow(target, in_nonclient_area, 239 // Release capture on pointer up. For mouse we only release if there are
207 event.Pass()); 240 // no buttons down.
241 const bool should_reset_target =
242 (event->action == mojom::EVENT_TYPE_POINTER_UP ||
243 event->action == mojom::EVENT_TYPE_POINTER_CANCEL) &&
244 (event->pointer_data->kind != mojom::POINTER_KIND_MOUSE ||
245 IsOnlyOneMouseButtonDown(event->flags));
246
247 DispatchToPointerTarget(pointer_targets_[pointer_id], event.Pass());
248
249 if (should_reset_target) {
250 ServerWindow* target = pointer_targets_[pointer_id].window;
251 pointer_targets_.erase(pointer_id);
252 if (target && !IsObservingWindow(target))
253 target->RemoveObserver(this);
208 } 254 }
209 } 255 }
210 256
257 void EventDispatcher::DispatchToPointerTarget(const PointerTarget& target,
258 mojom::EventPtr event) {
259 if (!target.window)
260 return;
261
262 gfx::Point location(EventLocationToPoint(*event));
263 gfx::Transform transform(GetTransformToWindow(surface_id_, target.window));
264 transform.TransformPoint(&location);
265 event->pointer_data->location->x = location.x();
266 event->pointer_data->location->y = location.y();
267 delegate_->DispatchInputEventToWindow(target.window, target.in_nonclient_area,
268 event.Pass());
269 }
270
271 void EventDispatcher::CancelPointerEventsToTarget(ServerWindow* window) {
272 window->RemoveObserver(this);
273
274 for (auto& pair : pointer_targets_) {
275 if (pair.second.window == window)
276 pair.second.window = nullptr;
277 }
278 }
279
280 bool EventDispatcher::IsObservingWindow(ServerWindow* window) {
281 for (const auto& pair : pointer_targets_) {
282 if (pair.second.window == window)
283 return true;
284 }
285 return false;
286 }
287
211 bool EventDispatcher::FindAccelerator(const mojom::Event& event, 288 bool EventDispatcher::FindAccelerator(const mojom::Event& event,
212 uint32_t* accelerator_id) { 289 uint32_t* accelerator_id) {
213 DCHECK(event.key_data); 290 DCHECK(event.key_data);
214 for (const auto& pair : accelerators_) { 291 for (const auto& pair : accelerators_) {
215 if (pair.second.MatchesEvent(event)) { 292 if (pair.second.MatchesEvent(event)) {
216 *accelerator_id = pair.first; 293 *accelerator_id = pair.first;
217 return true; 294 return true;
218 } 295 }
219 } 296 }
220 return false; 297 return false;
221 } 298 }
222 299
223 ServerWindow* EventDispatcher::FindEventTarget(mojom::Event* event) { 300 void EventDispatcher::OnWillChangeWindowHierarchy(ServerWindow* window,
224 ServerWindow* focused_window = 301 ServerWindow* new_parent,
225 delegate_->GetFocusedWindowForEventDispatcher(); 302 ServerWindow* old_parent) {
226 if (event->key_data) 303 CancelPointerEventsToTarget(window);
227 return focused_window; 304 }
228 305
229 DCHECK(event->pointer_data) << "Unknown event type: " << event->action; 306 void EventDispatcher::OnWindowVisibilityChanged(ServerWindow* window) {
230 mojom::LocationData* event_location = event->pointer_data->location.get(); 307 CancelPointerEventsToTarget(window);
231 DCHECK(event_location); 308 }
232 gfx::Point location(static_cast<int>(event_location->x),
233 static_cast<int>(event_location->y));
234 309
235 ServerWindow* target = capture_window_; 310 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) {
236 311 CancelPointerEventsToTarget(window);
237 if (!target) {
238 target = FindDeepestVisibleWindow(root_, surface_id_, &location);
239 } else {
240 gfx::Transform transform(GetTransformToWindow(surface_id_, target));
241 transform.TransformPoint(&location);
242 }
243
244 event_location->x = location.x();
245 event_location->y = location.y();
246
247 return target;
248 } 312 }
249 313
250 } // namespace ws 314 } // namespace ws
251 } // namespace mus 315 } // namespace mus
OLDNEW
« no previous file with comments | « components/mus/ws/event_dispatcher.h ('k') | components/mus/ws/event_dispatcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698