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

Side by Side Diff: services/ui/ws/event_dispatcher.cc

Issue 2884463002: Make event-targeting asynchronous in window server. (Closed)
Patch Set: cache; by value Created 3 years, 6 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
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 "services/ui/ws/event_dispatcher.h" 5 #include "services/ui/ws/event_dispatcher.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/memory/ptr_util.h" 9 #include "base/memory/ptr_util.h"
10 #include "base/time/time.h" 10 #include "base/time/time.h"
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 const ClientSpecificId target_client_id = delegate_->GetEventTargetClientId( 217 const ClientSpecificId target_client_id = delegate_->GetEventTargetClientId(
218 mouse_cursor_source_window_, mouse_cursor_in_non_client_area_); 218 mouse_cursor_source_window_, mouse_cursor_in_non_client_area_);
219 const ServerWindow* window = mouse_cursor_source_window_; 219 const ServerWindow* window = mouse_cursor_source_window_;
220 while (window && window->id().client_id == target_client_id) 220 while (window && window->id().client_id == target_client_id)
221 window = window->parent(); 221 window = window->parent();
222 return window; 222 return window;
223 } 223 }
224 224
225 void EventDispatcher::UpdateNonClientAreaForCurrentWindow() { 225 void EventDispatcher::UpdateNonClientAreaForCurrentWindow() {
226 if (mouse_cursor_source_window_) { 226 if (mouse_cursor_source_window_) {
227 DeepestWindow deepest_window = 227 event_targeter_->FindDeepestVisibleWindowForEvents(
sky 2017/05/31 23:36:34 Can all the calls to async code DCHECK if there is
riajiang 2017/06/01 18:22:11 In EventTargeter::FindDeepestVisibleWindowForEvent
sky 2017/06/01 21:12:58 My question is how do we end up in EventTargeter::
riajiang 2017/06/01 22:00:21 EventTargeter::FindDeepestVisibleWindowForEvents()
228 event_targeter_->FindDeepestVisibleWindowForEvents( 228 mouse_pointer_last_location_, mouse_pointer_display_id_,
229 &mouse_pointer_last_location_, &mouse_pointer_display_id_); 229 base::BindOnce(
230 if (deepest_window.window == mouse_cursor_source_window_) { 230 &EventDispatcher::UpdateNonClientAreaForCurrentWindowOnFoundWindow,
231 mouse_cursor_in_non_client_area_ = mouse_cursor_source_window_ 231 base::Unretained(this)));
232 ? deepest_window.in_non_client_area
233 : false;
234 }
235 } 232 }
236 } 233 }
237 234
238 void EventDispatcher::UpdateCursorProviderByLastKnownLocation() { 235 void EventDispatcher::UpdateCursorProviderByLastKnownLocation() {
239 if (!mouse_button_down_) { 236 if (!mouse_button_down_) {
240 DeepestWindow deepest_window = 237 event_targeter_->FindDeepestVisibleWindowForEvents(
241 event_targeter_->FindDeepestVisibleWindowForEvents( 238 mouse_pointer_last_location_, mouse_pointer_display_id_,
242 &mouse_pointer_last_location_, &mouse_pointer_display_id_); 239 base::BindOnce(&EventDispatcher::
243 SetMouseCursorSourceWindow(deepest_window.window); 240 UpdateCursorProviderByLastKnownLocationOnFoundWindow,
244 if (mouse_cursor_source_window_) { 241 base::Unretained(this)));
245 mouse_cursor_in_non_client_area_ = deepest_window.in_non_client_area;
246 } else {
247 SetMouseCursorSourceWindow(delegate_->GetRootWindowContaining(
248 &mouse_pointer_last_location_, &mouse_pointer_display_id_));
249 mouse_cursor_in_non_client_area_ = true;
250 }
251 } 242 }
252 } 243 }
253 244
254 bool EventDispatcher::AddAccelerator(uint32_t id, 245 bool EventDispatcher::AddAccelerator(uint32_t id,
255 mojom::EventMatcherPtr event_matcher) { 246 mojom::EventMatcherPtr event_matcher) {
256 std::unique_ptr<Accelerator> accelerator(new Accelerator(id, *event_matcher)); 247 std::unique_ptr<Accelerator> accelerator(new Accelerator(id, *event_matcher));
257 // If an accelerator with the same id or matcher already exists, then abort. 248 // If an accelerator with the same id or matcher already exists, then abort.
258 for (const auto& pair : accelerators_) { 249 for (const auto& pair : accelerators_) {
259 if (pair.first == id) { 250 if (pair.first == id) {
260 DVLOG(1) << "duplicate accelerator. Accelerator id=" << accelerator->id() 251 DVLOG(1) << "duplicate accelerator. Accelerator id=" << accelerator->id()
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 if (mouse_cursor_source_window_ == window) 312 if (mouse_cursor_source_window_ == window)
322 return; 313 return;
323 314
324 if (mouse_cursor_source_window_) 315 if (mouse_cursor_source_window_)
325 UnobserveWindow(mouse_cursor_source_window_); 316 UnobserveWindow(mouse_cursor_source_window_);
326 mouse_cursor_source_window_ = window; 317 mouse_cursor_source_window_ = window;
327 if (mouse_cursor_source_window_) 318 if (mouse_cursor_source_window_)
328 ObserveWindow(mouse_cursor_source_window_); 319 ObserveWindow(mouse_cursor_source_window_);
329 } 320 }
330 321
322 void EventDispatcher::UpdateMousePointerLocation(
323 const gfx::Point& new_mouse_location,
324 const int64_t new_mouse_display_id) {
325 if (new_mouse_location != mouse_pointer_last_location_)
sky 2017/05/31 23:36:34 Is there a reason not to set the values all the ti
riajiang 2017/06/01 18:22:11 Removed if. I was thinking that we don't have to s
326 mouse_pointer_last_location_ = new_mouse_location;
327 if (new_mouse_display_id != mouse_pointer_display_id_)
328 mouse_pointer_display_id_ = new_mouse_display_id;
329 }
330
331 void EventDispatcher::ProcessKeyEvent(const ui::KeyEvent& event, 331 void EventDispatcher::ProcessKeyEvent(const ui::KeyEvent& event,
332 AcceleratorMatchPhase match_phase) { 332 AcceleratorMatchPhase match_phase) {
333 Accelerator* post_target = 333 Accelerator* post_target =
334 FindAccelerator(event, ui::mojom::AcceleratorPhase::POST_TARGET); 334 FindAccelerator(event, ui::mojom::AcceleratorPhase::POST_TARGET);
335 if (drag_controller_ && event.type() == ui::ET_KEY_PRESSED && 335 if (drag_controller_ && event.type() == ui::ET_KEY_PRESSED &&
336 event.key_code() == ui::VKEY_ESCAPE) { 336 event.key_code() == ui::VKEY_ESCAPE) {
337 drag_controller_->Cancel(); 337 drag_controller_->Cancel();
338 return; 338 return;
339 } 339 }
340 ServerWindow* focused_window = 340 ServerWindow* focused_window =
341 delegate_->GetFocusedWindowForEventDispatcher(event_display_id_); 341 delegate_->GetFocusedWindowForEventDispatcher(event_display_id_);
342 if (focused_window) { 342 if (focused_window) {
343 // Assume key events are for the client area. 343 // Assume key events are for the client area.
344 const bool in_nonclient_area = false; 344 const bool in_nonclient_area = false;
345 const ClientSpecificId client_id = 345 const ClientSpecificId client_id =
346 delegate_->GetEventTargetClientId(focused_window, in_nonclient_area); 346 delegate_->GetEventTargetClientId(focused_window, in_nonclient_area);
347 delegate_->DispatchInputEventToWindow( 347 delegate_->DispatchInputEventToWindow(
348 focused_window, client_id, event_display_id_, event, post_target); 348 focused_window, client_id, event_display_id_, event, post_target);
349 return; 349 return;
350 } 350 }
351 delegate_->OnEventTargetNotFound(event, event_display_id_); 351 delegate_->OnEventTargetNotFound(event, event_display_id_);
352 if (post_target) 352 if (post_target)
353 delegate_->OnAccelerator(post_target->id(), event_display_id_, event, 353 delegate_->OnAccelerator(post_target->id(), event_display_id_, event,
354 EventDispatcherDelegate::AcceleratorPhase::POST); 354 EventDispatcherDelegate::AcceleratorPhase::POST);
355 } 355 }
356 356
357 void EventDispatcher::ProcessPointerEvent(const ui::PointerEvent& event) { 357 void EventDispatcher::ProcessPointerEvent(const ui::PointerEvent& event) {
358 DCHECK(event.IsPointerEvent()); 358 DCHECK(event.IsPointerEvent());
359 event_targeter_->PointerTargetForEvent(
sky 2017/05/31 23:36:34 As this is a single line now (albeit a long single
riajiang 2017/06/01 18:22:11 True, moved to ProcessEvent.
360 event, event_display_id_,
361 base::BindOnce(&EventDispatcher::ProcessPointerEventOnFoundTarget,
362 base::Unretained(this), event));
363 }
364
365 void EventDispatcher::ProcessPointerEventOnFoundTarget(
366 const ui::PointerEvent& event,
367 const PointerTarget& pointer_target_found,
368 const DeepestWindow& deepest_window,
369 const gfx::Point& new_location,
370 const int64_t new_display_id) {
371 event_targeter_->ProcessNextHittesetRequestFromQueue();
372
373 std::unique_ptr<ui::Event> cloned_event = ui::Event::Clone(event);
374 if (new_display_id != event_display_id_) {
375 event_display_id_ = new_display_id;
376 cloned_event->AsLocatedEvent()->set_root_location(new_location);
377 }
378
359 const bool is_mouse_event = event.IsMousePointerEvent(); 379 const bool is_mouse_event = event.IsMousePointerEvent();
360 380
361 if (is_mouse_event) { 381 if (is_mouse_event) {
362 mouse_pointer_last_location_ = event.root_location(); 382 UpdateMousePointerLocation(new_location, new_display_id);
363 mouse_pointer_display_id_ = event_display_id_; 383 delegate_->OnMouseCursorLocationChanged(new_location, new_display_id);
364 delegate_->OnMouseCursorLocationChanged(event.root_location(),
365 event_display_id_);
366 } 384 }
367 385
368 // Release capture on pointer up. For mouse we only release if there are 386 // Release capture on pointer up. For mouse we only release if there are
369 // no buttons down. 387 // no buttons down.
370 const bool is_pointer_going_up = 388 const bool is_pointer_going_up =
371 (event.type() == ui::ET_POINTER_UP || 389 (event.type() == ui::ET_POINTER_UP ||
372 event.type() == ui::ET_POINTER_CANCELLED) && 390 event.type() == ui::ET_POINTER_CANCELLED) &&
373 (!is_mouse_event || IsOnlyOneMouseButtonDown(event.flags())); 391 (!is_mouse_event || IsOnlyOneMouseButtonDown(event.flags()));
374 392
375 // Update mouse down state upon events which change it. 393 // Update mouse down state upon events which change it.
376 if (is_mouse_event) { 394 if (is_mouse_event) {
377 if (event.type() == ui::ET_POINTER_DOWN) 395 if (event.type() == ui::ET_POINTER_DOWN)
378 mouse_button_down_ = true; 396 mouse_button_down_ = true;
379 else if (is_pointer_going_up) 397 else if (is_pointer_going_up)
380 mouse_button_down_ = false; 398 mouse_button_down_ = false;
381 } 399 }
382 400
383 if (drag_controller_) { 401 if (drag_controller_) {
384 const PointerTarget target = 402 if (drag_controller_->DispatchPointerEvent(*cloned_event->AsPointerEvent(),
385 event_targeter_->PointerTargetForEvent(event, &event_display_id_); 403 pointer_target_found.window))
386 if (drag_controller_->DispatchPointerEvent(event, target.window))
387 return; 404 return;
388 } 405 }
389 406
390 if (capture_window_) { 407 if (capture_window_) {
391 SetMouseCursorSourceWindow(capture_window_); 408 SetMouseCursorSourceWindow(capture_window_);
392 DispatchToClient(capture_window_, capture_window_client_id_, event); 409 DispatchToClient(capture_window_, capture_window_client_id_,
410 *cloned_event->AsPointerEvent());
393 return; 411 return;
394 } 412 }
395 413
396 const int32_t pointer_id = event.pointer_details().id; 414 const int32_t pointer_id = event.pointer_details().id;
397 if (!IsTrackingPointer(pointer_id) || 415 if (!IsTrackingPointer(pointer_id) ||
398 !pointer_targets_[pointer_id].is_pointer_down) { 416 !pointer_targets_[pointer_id].is_pointer_down) {
399 const bool any_pointers_down = AreAnyPointersDown(); 417 const bool any_pointers_down = AreAnyPointersDown();
400 UpdateTargetForPointer(pointer_id, event); 418 UpdateTargetForPointer(pointer_id, *cloned_event->AsPointerEvent(),
419 pointer_target_found);
401 if (is_mouse_event) 420 if (is_mouse_event)
402 SetMouseCursorSourceWindow(pointer_targets_[pointer_id].window); 421 SetMouseCursorSourceWindow(pointer_targets_[pointer_id].window);
403 422
404 PointerTarget& pointer_target = pointer_targets_[pointer_id]; 423 PointerTarget& pointer_target = pointer_targets_[pointer_id];
405 if (pointer_target.is_pointer_down) { 424 if (pointer_target.is_pointer_down) {
406 if (is_mouse_event) 425 if (is_mouse_event)
407 SetMouseCursorSourceWindow(pointer_target.window); 426 SetMouseCursorSourceWindow(pointer_target.window);
408 if (!any_pointers_down) { 427 if (!any_pointers_down) {
409 if (pointer_target.window) 428 if (pointer_target.window)
410 delegate_->SetFocusedWindowFromEventDispatcher(pointer_target.window); 429 delegate_->SetFocusedWindowFromEventDispatcher(pointer_target.window);
411 ServerWindow* capture_window = pointer_target.window; 430 ServerWindow* capture_window = pointer_target.window;
412 if (!capture_window) { 431 if (!capture_window) {
413 gfx::Point event_location = event.root_location(); 432 gfx::Point event_location =
433 cloned_event->AsPointerEvent()->root_location();
414 int64_t event_display_id = event_display_id_; 434 int64_t event_display_id = event_display_id_;
415 capture_window = delegate_->GetRootWindowContaining( 435 capture_window = delegate_->GetRootWindowContaining(
416 &event_location, &event_display_id); 436 &event_location, &event_display_id);
417 } 437 }
418 delegate_->SetNativeCapture(capture_window); 438 delegate_->SetNativeCapture(capture_window);
419 } 439 }
420 } 440 }
421 } 441 }
422 442
423 // When we release the mouse button, we want the cursor to be sourced from 443 // When we release the mouse button, we want the cursor to be sourced from
424 // the window under the mouse pointer, even though we're sending the button 444 // the window under the mouse pointer, even though we're sending the button
425 // up event to the window that had implicit capture. We have to set this 445 // up event to the window that had implicit capture. We have to set this
426 // before we perform dispatch because the Delegate is going to read this 446 // before we perform dispatch because the Delegate is going to read this
427 // information from us. 447 // information from us.
428 if (is_pointer_going_up && is_mouse_event) 448 if (is_pointer_going_up && is_mouse_event) {
429 UpdateCursorProviderByLastKnownLocation(); 449 UpdateCursorProviderByLastKnownLocationWithWindow(
450 deepest_window, new_location, new_display_id);
451 }
430 452
431 DispatchToPointerTarget(pointer_targets_[pointer_id], event); 453 DispatchToPointerTarget(pointer_targets_[pointer_id],
454 *cloned_event->AsPointerEvent());
432 455
433 if (is_pointer_going_up) { 456 if (is_pointer_going_up) {
434 if (is_mouse_event) 457 if (is_mouse_event)
435 pointer_targets_[pointer_id].is_pointer_down = false; 458 pointer_targets_[pointer_id].is_pointer_down = false;
436 else 459 else
437 StopTrackingPointer(pointer_id); 460 StopTrackingPointer(pointer_id);
438 if (!AreAnyPointersDown()) 461 if (!AreAnyPointersDown())
439 delegate_->ReleaseNativeCapture(); 462 delegate_->ReleaseNativeCapture();
440 } 463 }
441 } 464 }
442 465
443 void EventDispatcher::StartTrackingPointer( 466 void EventDispatcher::StartTrackingPointer(
444 int32_t pointer_id, 467 int32_t pointer_id,
445 const PointerTarget& pointer_target) { 468 const PointerTarget& pointer_target) {
446 DCHECK(!IsTrackingPointer(pointer_id)); 469 DCHECK(!IsTrackingPointer(pointer_id));
447 if (pointer_target.window) 470 if (pointer_target.window)
448 ObserveWindow(pointer_target.window); 471 ObserveWindow(pointer_target.window);
449 pointer_targets_[pointer_id] = pointer_target; 472 pointer_targets_[pointer_id] = pointer_target;
450 } 473 }
451 474
452 void EventDispatcher::StopTrackingPointer(int32_t pointer_id) { 475 void EventDispatcher::StopTrackingPointer(int32_t pointer_id) {
453 DCHECK(IsTrackingPointer(pointer_id)); 476 DCHECK(IsTrackingPointer(pointer_id));
454 ServerWindow* window = pointer_targets_[pointer_id].window; 477 ServerWindow* window = pointer_targets_[pointer_id].window;
455 pointer_targets_.erase(pointer_id); 478 pointer_targets_.erase(pointer_id);
456 if (window) 479 if (window)
457 UnobserveWindow(window); 480 UnobserveWindow(window);
458 } 481 }
459 482
460 void EventDispatcher::UpdateTargetForPointer(int32_t pointer_id, 483 void EventDispatcher::UpdateTargetForPointer(
461 const ui::LocatedEvent& event) { 484 int32_t pointer_id,
485 const ui::PointerEvent& event,
486 const PointerTarget& pointer_target_found) {
462 if (!IsTrackingPointer(pointer_id)) { 487 if (!IsTrackingPointer(pointer_id)) {
463 StartTrackingPointer(pointer_id, event_targeter_->PointerTargetForEvent( 488 StartTrackingPointer(pointer_id, pointer_target_found);
464 event, &event_display_id_));
465 return; 489 return;
466 } 490 }
467 491
468 const PointerTarget pointer_target = 492 if (pointer_target_found.window == pointer_targets_[pointer_id].window &&
469 event_targeter_->PointerTargetForEvent(event, &event_display_id_); 493 pointer_target_found.in_nonclient_area ==
470 if (pointer_target.window == pointer_targets_[pointer_id].window &&
471 pointer_target.in_nonclient_area ==
472 pointer_targets_[pointer_id].in_nonclient_area) { 494 pointer_targets_[pointer_id].in_nonclient_area) {
473 // The targets are the same, only set the down state to true if necessary. 495 // The targets are the same, only set the down state to true if necessary.
474 // Down going to up is handled by ProcessLocatedEvent(). 496 // Down going to up is handled by ProcessLocatedEvent().
475 if (pointer_target.is_pointer_down) 497 if (pointer_target_found.is_pointer_down)
476 pointer_targets_[pointer_id].is_pointer_down = true; 498 pointer_targets_[pointer_id].is_pointer_down = true;
477 return; 499 return;
478 } 500 }
479 501
480 // The targets are changing. Send an exit if appropriate. 502 // The targets are changing. Send an exit if appropriate.
481 if (event.IsMousePointerEvent()) { 503 if (event.IsMousePointerEvent()) {
482 ui::PointerEvent exit_event( 504 ui::PointerEvent exit_event(
483 ui::ET_POINTER_EXITED, event.location(), event.root_location(), 505 ui::ET_POINTER_EXITED, event.location(), event.root_location(),
484 event.flags(), 0 /* changed_button_flags */, 506 event.flags(), 0 /* changed_button_flags */,
485 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 507 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE,
486 ui::MouseEvent::kMousePointerId), 508 ui::MouseEvent::kMousePointerId),
487 event.time_stamp()); 509 event.time_stamp());
488 DispatchToPointerTarget(pointer_targets_[pointer_id], exit_event); 510 DispatchToPointerTarget(pointer_targets_[pointer_id], exit_event);
489 } 511 }
490 512
491 // Technically we're updating in place, but calling start then stop makes for 513 // Technically we're updating in place, but calling start then stop makes for
492 // simpler code. 514 // simpler code.
493 StopTrackingPointer(pointer_id); 515 StopTrackingPointer(pointer_id);
494 StartTrackingPointer(pointer_id, pointer_target); 516 StartTrackingPointer(pointer_id, pointer_target_found);
517 }
518
519 void EventDispatcher::UpdateNonClientAreaForCurrentWindowOnFoundWindow(
520 const DeepestWindow& deepest_window,
521 const gfx::Point& new_location,
522 const int64_t new_display_id) {
523 event_targeter_->ProcessNextHittesetRequestFromQueue();
524
525 if (deepest_window.window == mouse_cursor_source_window_) {
526 mouse_cursor_in_non_client_area_ =
527 mouse_cursor_source_window_ ? deepest_window.in_non_client_area : false;
528 }
529 UpdateMousePointerLocation(new_location, new_display_id);
530 delegate_->UpdateNativeCursorFromDispatcher();
531 }
532
533 void EventDispatcher::UpdateCursorProviderByLastKnownLocationOnFoundWindow(
534 const DeepestWindow& deepest_window,
535 const gfx::Point& new_location,
536 const int64_t new_display_id) {
537 event_targeter_->ProcessNextHittesetRequestFromQueue();
538 UpdateCursorProviderByLastKnownLocationWithWindow(
539 deepest_window, new_location, new_display_id);
540 }
541
542 void EventDispatcher::UpdateCursorProviderByLastKnownLocationWithWindow(
543 const DeepestWindow& deepest_window,
544 const gfx::Point& new_location,
545 const int64_t new_display_id) {
546 SetMouseCursorSourceWindow(deepest_window.window);
547 if (mouse_cursor_source_window_) {
548 mouse_cursor_in_non_client_area_ = deepest_window.in_non_client_area;
549 } else {
550 SetMouseCursorSourceWindow(delegate_->GetRootWindowContaining(
551 &mouse_pointer_last_location_, &mouse_pointer_display_id_));
552 mouse_cursor_in_non_client_area_ = true;
553 }
554 UpdateMousePointerLocation(new_location, new_display_id);
555 delegate_->UpdateNativeCursorFromDispatcher();
495 } 556 }
496 557
497 bool EventDispatcher::AreAnyPointersDown() const { 558 bool EventDispatcher::AreAnyPointersDown() const {
498 for (const auto& pair : pointer_targets_) { 559 for (const auto& pair : pointer_targets_) {
499 if (pair.second.is_pointer_down) 560 if (pair.second.is_pointer_down)
500 return true; 561 return true;
501 } 562 }
502 return false; 563 return false;
503 } 564 }
504 565
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 if (mouse_cursor_source_window_ == window) 706 if (mouse_cursor_source_window_ == window)
646 SetMouseCursorSourceWindow(nullptr); 707 SetMouseCursorSourceWindow(nullptr);
647 } 708 }
648 709
649 void EventDispatcher::OnDragCursorUpdated() { 710 void EventDispatcher::OnDragCursorUpdated() {
650 delegate_->UpdateNativeCursorFromDispatcher(); 711 delegate_->UpdateNativeCursorFromDispatcher();
651 } 712 }
652 713
653 } // namespace ws 714 } // namespace ws
654 } // namespace ui 715 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698