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

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

Issue 1677513002: mus Window Server: implement event capture (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 months 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_delegate.h » ('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> 7 #include <set>
8 8
9 #include "base/time/time.h"
9 #include "cc/surfaces/surface_hittest.h" 10 #include "cc/surfaces/surface_hittest.h"
10 #include "components/mus/surfaces/surfaces_state.h" 11 #include "components/mus/surfaces/surfaces_state.h"
11 #include "components/mus/ws/event_dispatcher_delegate.h" 12 #include "components/mus/ws/event_dispatcher_delegate.h"
12 #include "components/mus/ws/server_window.h" 13 #include "components/mus/ws/server_window.h"
13 #include "components/mus/ws/server_window_delegate.h" 14 #include "components/mus/ws/server_window_delegate.h"
14 #include "components/mus/ws/window_coordinate_conversions.h" 15 #include "components/mus/ws/window_coordinate_conversions.h"
15 #include "components/mus/ws/window_finder.h" 16 #include "components/mus/ws/window_finder.h"
16 #include "components/mus/ws/window_tree_host_impl.h" 17 #include "components/mus/ws/window_tree_host_impl.h"
17 #include "mojo/converters/geometry/geometry_type_converters.h" 18 #include "mojo/converters/geometry/geometry_type_converters.h"
18 #include "ui/gfx/geometry/point.h" 19 #include "ui/gfx/geometry/point.h"
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 mojom::KeyboardCode keyboard_code_; 151 mojom::KeyboardCode keyboard_code_;
151 mojom::PointerKind pointer_kind_; 152 mojom::PointerKind pointer_kind_;
152 gfx::RectF pointer_region_; 153 gfx::RectF pointer_region_;
153 }; 154 };
154 155
155 //////////////////////////////////////////////////////////////////////////////// 156 ////////////////////////////////////////////////////////////////////////////////
156 157
157 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate) 158 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate)
158 : delegate_(delegate), 159 : delegate_(delegate),
159 root_(nullptr), 160 root_(nullptr),
161 capture_window_(nullptr),
162 capture_window_in_nonclient_area_(false),
160 mouse_button_down_(false), 163 mouse_button_down_(false),
161 mouse_cursor_source_window_(nullptr) {} 164 mouse_cursor_source_window_(nullptr) {}
162 165
163 EventDispatcher::~EventDispatcher() { 166 EventDispatcher::~EventDispatcher() {
164 std::set<ServerWindow*> pointer_targets; 167 std::set<ServerWindow*> pointer_targets;
168 if (capture_window_) {
169 pointer_targets.insert(capture_window_);
170 capture_window_->RemoveObserver(this);
171 capture_window_ = nullptr;
172 }
165 for (const auto& pair : pointer_targets_) { 173 for (const auto& pair : pointer_targets_) {
166 if (pair.second.window && 174 if (pair.second.window &&
167 pointer_targets.insert(pair.second.window).second) { 175 pointer_targets.insert(pair.second.window).second) {
168 pair.second.window->RemoveObserver(this); 176 pair.second.window->RemoveObserver(this);
169 } 177 }
170 } 178 }
179 pointer_targets_.clear();
180 }
181
182 void EventDispatcher::SetCaptureWindow(ServerWindow* window,
183 bool in_nonclient_area) {
184 if (window == capture_window_)
185 return;
186
187 if (capture_window_) {
188 // Stop observing old capture window. |pointer_targets_| are cleared on
189 // intial setting of a capture window.
190 delegate_->OnServerWindowCaptureLost(capture_window_);
191 capture_window_->RemoveObserver(this);
192 } else {
193 // Cancel implicit capture to all other windows.
194 std::set<ServerWindow*> unobserved_windows;
195 for (const auto& pair : pointer_targets_) {
196 ServerWindow* target = pair.second.window;
197 if (!target)
198 continue;
199 if (unobserved_windows.insert(target).second)
200 target->RemoveObserver(this);
201 if (target == window)
202 continue;
203 mojom::EventPtr cancel_event = mojom::Event::New();
204 cancel_event->action = mojom::EventType::POINTER_CANCEL;
205 cancel_event->flags = mojom::kEventFlagNone;
206 cancel_event->time_stamp = base::TimeTicks::Now().ToInternalValue();
207 cancel_event->pointer_data = mojom::PointerData::New();
208 // TODO(jonross): Track previous location in PointerTarget for sending
209 // cancels
210 cancel_event->pointer_data->location = mojom::LocationData::New();
211 cancel_event->pointer_data->pointer_id = pair.first;
212 DispatchToPointerTarget(pair.second, std::move(cancel_event));
213 }
214 pointer_targets_.clear();
215 }
216
217 // Begin tracking the capture window if it is not yet being observed.
218 if (window) {
219 window->AddObserver(this);
220 if (!capture_window_)
221 delegate_->SetNativeCapture();
222 } else {
223 delegate_->ReleaseNativeCapture();
224 if (!mouse_button_down_)
225 UpdateCursorProviderByLastKnownLocation();
226 }
227
228 capture_window_ = window;
229 capture_window_in_nonclient_area_ = in_nonclient_area;
171 } 230 }
172 231
173 void EventDispatcher::UpdateCursorProviderByLastKnownLocation() { 232 void EventDispatcher::UpdateCursorProviderByLastKnownLocation() {
174 if (!mouse_button_down_) { 233 if (!mouse_button_down_) {
175 gfx::Point location = mouse_pointer_last_location_; 234 gfx::Point location = mouse_pointer_last_location_;
176 mouse_cursor_source_window_ = 235 mouse_cursor_source_window_ =
177 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location); 236 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location);
178 } 237 }
179 } 238 }
180 239
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 std::move(event)); 289 std::move(event));
231 } 290 }
232 291
233 void EventDispatcher::ProcessPointerEvent(mojom::EventPtr event) { 292 void EventDispatcher::ProcessPointerEvent(mojom::EventPtr event) {
234 const bool is_mouse_event = event->pointer_data && 293 const bool is_mouse_event = event->pointer_data &&
235 event->pointer_data->kind == mojom::PointerKind::MOUSE; 294 event->pointer_data->kind == mojom::PointerKind::MOUSE;
236 295
237 if (is_mouse_event) 296 if (is_mouse_event)
238 mouse_pointer_last_location_ = EventLocationToPoint(*event); 297 mouse_pointer_last_location_ = EventLocationToPoint(*event);
239 298
299 // Release capture on pointer up. For mouse we only release if there are
300 // no buttons down.
301 const bool is_pointer_going_up =
302 (event->action == mojom::EventType::POINTER_UP ||
303 event->action == mojom::EventType::POINTER_CANCEL) &&
304 (event->pointer_data->kind != mojom::PointerKind::MOUSE ||
305 IsOnlyOneMouseButtonDown(event->flags));
306
307 // Update mouse down state upon events which change it.
308 if (is_mouse_event) {
309 if (event->action == mojom::EventType::POINTER_DOWN)
310 mouse_button_down_ = true;
311 else if (is_pointer_going_up)
312 mouse_button_down_ = false;
313 }
314
315 if (capture_window_) {
316 mouse_cursor_source_window_ = capture_window_;
317 PointerTarget pointer_target;
318 pointer_target.window = capture_window_;
319 pointer_target.in_nonclient_area = capture_window_in_nonclient_area_;
320 DispatchToPointerTarget(pointer_target, std::move(event));
321 return;
322 }
323
240 const int32_t pointer_id = event->pointer_data->pointer_id; 324 const int32_t pointer_id = event->pointer_data->pointer_id;
241 if (!IsTrackingPointer(pointer_id) || 325 if (!IsTrackingPointer(pointer_id) ||
242 !pointer_targets_[pointer_id].is_pointer_down) { 326 !pointer_targets_[pointer_id].is_pointer_down) {
243 const bool any_pointers_down = AreAnyPointersDown(); 327 const bool any_pointers_down = AreAnyPointersDown();
244 UpdateTargetForPointer(*event); 328 UpdateTargetForPointer(*event);
245 if (is_mouse_event) 329 if (is_mouse_event)
246 mouse_cursor_source_window_ = pointer_targets_[pointer_id].window; 330 mouse_cursor_source_window_ = pointer_targets_[pointer_id].window;
247 331
248 PointerTarget& pointer_target = pointer_targets_[pointer_id]; 332 PointerTarget& pointer_target = pointer_targets_[pointer_id];
249 if (pointer_target.is_pointer_down) { 333 if (pointer_target.is_pointer_down) {
250 if (is_mouse_event) { 334 if (is_mouse_event)
251 mouse_button_down_ = true;
252 mouse_cursor_source_window_ = pointer_target.window; 335 mouse_cursor_source_window_ = pointer_target.window;
336 if (!any_pointers_down) {
337 delegate_->SetFocusedWindowFromEventDispatcher(pointer_target.window);
338 delegate_->SetNativeCapture();
253 } 339 }
254 if (!any_pointers_down)
255 delegate_->SetFocusedWindowFromEventDispatcher(pointer_target.window);
256 } 340 }
257 } 341 }
258 342
259 // Release capture on pointer up. For mouse we only release if there are 343 // When we release the mouse button, we want the cursor to be sourced from
260 // no buttons down. 344 // the window under the mouse pointer, even though we're sending the button
261 const bool is_pointer_going_up = 345 // up event to the window that had implicit capture. We have to set this
262 (event->action == mojom::EventType::POINTER_UP || 346 // before we perform dispatch because the Delegate is going to read this
263 event->action == mojom::EventType::POINTER_CANCEL) && 347 // information from us.
264 (event->pointer_data->kind != mojom::PointerKind::MOUSE || 348 if (is_pointer_going_up && is_mouse_event)
265 IsOnlyOneMouseButtonDown(event->flags)); 349 UpdateCursorProviderByLastKnownLocation();
266
267 if (is_pointer_going_up && is_mouse_event) {
268 // When we release the mouse button, we want the cursor to be sourced from
269 // the window under the mouse pointer, even though we're sending the button
270 // up event to the window that had implicit capture. We have to set this
271 // before we perform dispatch because the Delegate is going to read this
272 // information from us.
273 mouse_button_down_ = false;
274 gfx::Point location(EventLocationToPoint(*event));
275 mouse_cursor_source_window_ =
276 FindDeepestVisibleWindowForEvents(root_, surface_id_, &location);
277 }
278 350
279 DispatchToPointerTarget(pointer_targets_[pointer_id], std::move(event)); 351 DispatchToPointerTarget(pointer_targets_[pointer_id], std::move(event));
280 352
281 if (is_pointer_going_up) { 353 if (is_pointer_going_up) {
282 if (is_mouse_event) 354 if (is_mouse_event)
283 pointer_targets_[pointer_id].is_pointer_down = false; 355 pointer_targets_[pointer_id].is_pointer_down = false;
284 else 356 else
285 StopTrackingPointer(pointer_id); 357 StopTrackingPointer(pointer_id);
358 if (!AreAnyPointersDown())
359 delegate_->ReleaseNativeCapture();
286 } 360 }
287 } 361 }
288 362
289 void EventDispatcher::StartTrackingPointer( 363 void EventDispatcher::StartTrackingPointer(
290 int32_t pointer_id, 364 int32_t pointer_id,
291 const PointerTarget& pointer_target) { 365 const PointerTarget& pointer_target) {
292 DCHECK(!IsTrackingPointer(pointer_id)); 366 DCHECK(!IsTrackingPointer(pointer_id));
293 if (!IsObservingWindow(pointer_target.window)) 367 if (!IsObservingWindow(pointer_target.window))
294 pointer_target.window->AddObserver(this); 368 pointer_target.window->AddObserver(this);
295 pointer_targets_[pointer_id] = pointer_target; 369 pointer_targets_[pointer_id] = pointer_target;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 transform.TransformPoint(&location); 447 transform.TransformPoint(&location);
374 event->pointer_data->location->x = location.x(); 448 event->pointer_data->location->x = location.x();
375 event->pointer_data->location->y = location.y(); 449 event->pointer_data->location->y = location.y();
376 delegate_->DispatchInputEventToWindow(target.window, target.in_nonclient_area, 450 delegate_->DispatchInputEventToWindow(target.window, target.in_nonclient_area,
377 std::move(event)); 451 std::move(event));
378 } 452 }
379 453
380 void EventDispatcher::CancelPointerEventsToTarget(ServerWindow* window) { 454 void EventDispatcher::CancelPointerEventsToTarget(ServerWindow* window) {
381 window->RemoveObserver(this); 455 window->RemoveObserver(this);
382 456
457 if (capture_window_ == window) {
458 capture_window_ = nullptr;
459 mouse_button_down_ = false;
460 // A window only cares to be informed that it lost capture if it explicitly
461 // requested capture. A window can lose capture if another window gains
462 // explicit capture.
463 delegate_->OnServerWindowCaptureLost(window);
464 delegate_->ReleaseNativeCapture();
465 UpdateCursorProviderByLastKnownLocation();
466 return;
467 }
468
383 for (auto& pair : pointer_targets_) { 469 for (auto& pair : pointer_targets_) {
384 if (pair.second.window == window) 470 if (pair.second.window == window)
385 pair.second.window = nullptr; 471 pair.second.window = nullptr;
386 } 472 }
387 } 473 }
388 474
389 bool EventDispatcher::IsObservingWindow(ServerWindow* window) { 475 bool EventDispatcher::IsObservingWindow(ServerWindow* window) {
390 for (const auto& pair : pointer_targets_) { 476 for (const auto& pair : pointer_targets_) {
391 if (pair.second.window == window) 477 if (pair.second.window == window)
392 return true; 478 return true;
(...skipping 25 matching lines...) Expand all
418 504
419 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) { 505 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) {
420 CancelPointerEventsToTarget(window); 506 CancelPointerEventsToTarget(window);
421 507
422 if (mouse_cursor_source_window_ == window) 508 if (mouse_cursor_source_window_ == window)
423 mouse_cursor_source_window_ = nullptr; 509 mouse_cursor_source_window_ = nullptr;
424 } 510 }
425 511
426 } // namespace ws 512 } // namespace ws
427 } // namespace mus 513 } // namespace mus
OLDNEW
« no previous file with comments | « components/mus/ws/event_dispatcher.h ('k') | components/mus/ws/event_dispatcher_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698