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

Side by Side Diff: third_party/WebKit/Source/core/input/PointerEventManager.cpp

Issue 2147263003: Send got/lostpointercapture immediately if possible (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Apply comments Created 4 years, 5 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 | « third_party/WebKit/Source/core/input/PointerEventManager.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "core/input/PointerEventManager.h" 5 #include "core/input/PointerEventManager.h"
6 6
7 #include "core/dom/ElementTraversal.h" 7 #include "core/dom/ElementTraversal.h"
8 #include "core/dom/ExecutionContextTask.h"
8 #include "core/dom/shadow/FlatTreeTraversal.h" 9 #include "core/dom/shadow/FlatTreeTraversal.h"
9 #include "core/events/MouseEvent.h" 10 #include "core/events/MouseEvent.h"
10 #include "core/frame/FrameView.h" 11 #include "core/frame/FrameView.h"
11 #include "core/frame/UseCounter.h" 12 #include "core/frame/UseCounter.h"
12 #include "core/html/HTMLCanvasElement.h" 13 #include "core/html/HTMLCanvasElement.h"
13 #include "core/input/EventHandler.h" 14 #include "core/input/EventHandler.h"
14 #include "core/input/TouchActionUtil.h" 15 #include "core/input/TouchActionUtil.h"
15 #include "core/page/ChromeClient.h" 16 #include "core/page/ChromeClient.h"
16 #include "core/page/Page.h" 17 #include "core/page/Page.h"
17 #include "platform/PlatformTouchEvent.h" 18 #include "platform/PlatformTouchEvent.h"
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 360
360 processCaptureAndPositionOfPointerEvent(pointerEvent, target); 361 processCaptureAndPositionOfPointerEvent(pointerEvent, target);
361 362
362 // TODO(nzolghadr): This event follows implicit TE capture. The actual t arget 363 // TODO(nzolghadr): This event follows implicit TE capture. The actual t arget
363 // would depend on PE capturing. Perhaps need to split TE/PE event path upstream? 364 // would depend on PE capturing. Perhaps need to split TE/PE event path upstream?
364 // crbug.com/579553. 365 // crbug.com/579553.
365 dispatchPointerEvent( 366 dispatchPointerEvent(
366 getEffectiveTargetForPointerEvent(target, pointerEvent->pointerId()) , 367 getEffectiveTargetForPointerEvent(target, pointerEvent->pointerId()) ,
367 pointerEvent); 368 pointerEvent);
368 369
369 releasePointerCapture(pointerEvent->pointerId()); 370 modifyPendingPointerCapture(pointerEvent->pointerId(), nullptr);
370 371
371 // Sending the leave/out events and lostpointercapture 372 // Sending the leave/out events and lostpointercapture
372 // because the next touch event will have a different id. So delayed 373 // because the next touch event will have a different id. So delayed
373 // sending of lostpointercapture won't work here. 374 // sending of lostpointercapture won't work here.
374 processCaptureAndPositionOfPointerEvent(pointerEvent, nullptr); 375 processCaptureAndPositionOfPointerEvent(pointerEvent, nullptr);
375 376
376 removePointer(pointerEvent); 377 removePointer(pointerEvent);
377 } 378 }
378 } 379 }
379 380
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 // Setting the implicit capture for touch 506 // Setting the implicit capture for touch
506 if (pointerEvent->type() == EventTypeNames::pointerdown) 507 if (pointerEvent->type() == EventTypeNames::pointerdown)
507 setPointerCapture(pointerEvent->pointerId(), target); 508 setPointerCapture(pointerEvent->pointerId(), target);
508 509
509 WebInputEventResult result = dispatchPointerEvent( 510 WebInputEventResult result = dispatchPointerEvent(
510 getEffectiveTargetForPointerEvent(target, pointerEvent->pointerId()), 511 getEffectiveTargetForPointerEvent(target, pointerEvent->pointerId()),
511 pointerEvent); 512 pointerEvent);
512 513
513 if (pointerEvent->type() == EventTypeNames::pointerup 514 if (pointerEvent->type() == EventTypeNames::pointerup
514 || pointerEvent->type() == EventTypeNames::pointercancel) { 515 || pointerEvent->type() == EventTypeNames::pointercancel) {
515 releasePointerCapture(pointerEvent->pointerId()); 516 modifyPendingPointerCapture(pointerEvent->pointerId(), nullptr);
516 517
517 // Sending the leave/out events and lostpointercapture 518 // Sending the leave/out events and lostpointercapture
518 // because the next touch event will have a different id. So delayed 519 // because the next touch event will have a different id. So delayed
519 // sending of lostpointercapture won't work here. 520 // sending of lostpointercapture won't work here.
520 processCaptureAndPositionOfPointerEvent(pointerEvent, nullptr); 521 processCaptureAndPositionOfPointerEvent(pointerEvent, nullptr);
521 522
522 removePointer(pointerEvent); 523 removePointer(pointerEvent);
523 } 524 }
524 525
525 return result; 526 return result;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 break; 572 break;
572 } 573 }
573 } 574 }
574 } 575 }
575 result = EventHandler::mergeEventResult(result, 576 result = EventHandler::mergeEventResult(result,
576 dispatchMouseEvent(mouseTarget, mouseEventType, mouseEvent, 577 dispatchMouseEvent(mouseTarget, mouseEventType, mouseEvent,
577 nullptr, clickCount)); 578 nullptr, clickCount));
578 } 579 }
579 580
580 if (pointerEvent->buttons() == 0) { 581 if (pointerEvent->buttons() == 0) {
581 releasePointerCapture(pointerEvent->pointerId()); 582 modifyPendingPointerCapture(pointerEvent->pointerId(), nullptr);
582 if (pointerEvent->isPrimary()) { 583 if (pointerEvent->isPrimary()) {
583 m_preventMouseEventForPointerType[toPointerTypeIndex( 584 m_preventMouseEventForPointerType[toPointerTypeIndex(
584 mouseEvent.pointerProperties().pointerType)] = false; 585 mouseEvent.pointerProperties().pointerType)] = false;
585 } 586 }
586 } 587 }
587 588
588 return result; 589 return result;
589 } 590 }
590 591
591 PointerEventManager::PointerEventManager(LocalFrame* frame) 592 PointerEventManager::PointerEventManager(LocalFrame* frame)
(...skipping 13 matching lines...) Expand all
605 entry = false; 606 entry = false;
606 m_touchEventManager.clear(); 607 m_touchEventManager.clear();
607 m_inCanceledStateForPointerTypeTouch = false; 608 m_inCanceledStateForPointerTypeTouch = false;
608 m_pointerEventFactory.clear(); 609 m_pointerEventFactory.clear();
609 m_touchIdsForCanceledPointerdowns.clear(); 610 m_touchIdsForCanceledPointerdowns.clear();
610 m_nodeUnderPointer.clear(); 611 m_nodeUnderPointer.clear();
611 m_pointerCaptureTarget.clear(); 612 m_pointerCaptureTarget.clear();
612 m_pendingPointerCaptureTarget.clear(); 613 m_pendingPointerCaptureTarget.clear();
613 } 614 }
614 615
616 bool PointerEventManager::getPointerCaptureState(int pointerId,
617 EventTarget** pointerCaptureTarget,
618 EventTarget** pendingPointerCaptureTarget)
619 {
620 PointerCapturingMap::iterator it;
621
622 it = m_pointerCaptureTarget.find(pointerId);
623 EventTarget* pointercaptureTargetTemp = (it != m_pointerCaptureTarget.end()) ? it->value : nullptr;
624 it = m_pendingPointerCaptureTarget.find(pointerId);
625 EventTarget* pendingPointercaptureTargetTemp = (it != m_pendingPointerCaptur eTarget.end()) ? it->value : nullptr;
626
627 if (pointerCaptureTarget)
628 *pointerCaptureTarget = pointercaptureTargetTemp;
629 if (pendingPointerCaptureTarget)
630 *pendingPointerCaptureTarget = pendingPointercaptureTargetTemp;
631
632 return pointercaptureTargetTemp != pendingPointercaptureTargetTemp;
633 }
634
615 void PointerEventManager::processCaptureAndPositionOfPointerEvent( 635 void PointerEventManager::processCaptureAndPositionOfPointerEvent(
616 PointerEvent* pointerEvent, 636 PointerEvent* pointerEvent,
617 EventTarget* hitTestTarget, 637 EventTarget* hitTestTarget,
618 EventTarget* lastNodeUnderMouse, 638 EventTarget* lastNodeUnderMouse,
619 const PlatformMouseEvent& mouseEvent, 639 const PlatformMouseEvent& mouseEvent,
620 bool sendMouseEvent, bool setPointerPosition) 640 bool sendMouseEvent, bool setPointerPosition)
621 { 641 {
622 bool isCaptureChanged = false; 642 bool isCaptureChanged = false;
623 643
624 if (setPointerPosition) { 644 if (setPointerPosition) {
625 isCaptureChanged = processPendingPointerCapture(pointerEvent, 645 isCaptureChanged = processPendingPointerCapture(pointerEvent,
626 hitTestTarget, mouseEvent, sendMouseEvent); 646 hitTestTarget, mouseEvent, sendMouseEvent);
627 // If there was a change in capturing processPendingPointerCapture has 647 // If there was a change in capturing processPendingPointerCapture has
628 // already taken care of transition events. So we don't need to send the 648 // already taken care of transition events. So we don't need to send the
629 // transition events here. 649 // transition events here.
630 setNodeUnderPointer(pointerEvent, hitTestTarget, !isCaptureChanged); 650 setNodeUnderPointer(pointerEvent, hitTestTarget, !isCaptureChanged);
631 } 651 }
632 if (sendMouseEvent && !isCaptureChanged) { 652 if (sendMouseEvent && !isCaptureChanged) {
633 // lastNodeUnderMouse is needed here because it is still stored in Event Handler. 653 // lastNodeUnderMouse is needed here because it is still stored in Event Handler.
634 sendBoundaryEvents(lastNodeUnderMouse, hitTestTarget, 654 sendBoundaryEvents(lastNodeUnderMouse, hitTestTarget,
635 pointerEvent, mouseEvent, true); 655 pointerEvent, mouseEvent, true);
636 } 656 }
637 } 657 }
638 658
659 void PointerEventManager::immediatelyProcessPendingPointerCapture(int pointerId)
660 {
661 EventTarget* pointerCaptureTarget;
662 EventTarget* pendingPointerCaptureTarget;
663 const bool isCaptureChanged = getPointerCaptureState(pointerId,
664 &pointerCaptureTarget, &pendingPointerCaptureTarget);
665
666 if (!isCaptureChanged)
667 return;
668
669 if (pointerCaptureTarget) {
670 // Re-target lostpointercapture to the document when the element is
671 // no longer participating in the tree.
672 EventTarget* target = pointerCaptureTarget;
673 if (target->toNode()
674 && !target->toNode()->isConnected()) {
675 target = target->toNode()->ownerDocument();
676 }
677 dispatchPointerEvent(target,
678 m_pointerEventFactory.createPointerCaptureEvent(
679 pointerId, EventTypeNames::lostpointercapture));
680 }
681 dispatchPointerEvent(pendingPointerCaptureTarget,
682 m_pointerEventFactory.createPointerCaptureEvent(
683 pointerId, EventTypeNames::gotpointercapture));
684
685 // Setting |m_pointerCaptureTarget| comes at the end to prevent the infinite
686 // loop if js calls set/releasepointercapture in got/lostpointercapture
687 // handlers.
688 if (pendingPointerCaptureTarget)
689 m_pointerCaptureTarget.set(pointerId, pendingPointerCaptureTarget);
690 else
691 m_pointerCaptureTarget.remove(pointerId);
692 }
693
694 // TODO(crbug.com/629921): This function should be merged with |immediatelyProce ssPendingPointerCapture|
695 // when we stop hit-testing while a pointer is captured.
639 bool PointerEventManager::processPendingPointerCapture( 696 bool PointerEventManager::processPendingPointerCapture(
640 PointerEvent* pointerEvent, 697 PointerEvent* pointerEvent,
641 EventTarget* hitTestTarget, 698 EventTarget* hitTestTarget,
642 const PlatformMouseEvent& mouseEvent, bool sendMouseEvent) 699 const PlatformMouseEvent& mouseEvent, bool sendMouseEvent)
643 { 700 {
644 int pointerId = pointerEvent->pointerId(); 701 int pointerId = pointerEvent->pointerId();
645 EventTarget* pointerCaptureTarget = 702 EventTarget* pointerCaptureTarget;
646 m_pointerCaptureTarget.contains(pointerId) 703 EventTarget* pendingPointerCaptureTarget;
647 ? m_pointerCaptureTarget.get(pointerId) : nullptr; 704 const bool isCaptureChanged = getPointerCaptureState(pointerId,
648 EventTarget* pendingPointerCaptureTarget = 705 &pointerCaptureTarget, &pendingPointerCaptureTarget);
649 m_pendingPointerCaptureTarget.contains(pointerId)
650 ? m_pendingPointerCaptureTarget.get(pointerId) : nullptr;
651 const EventTargetAttributes &nodeUnderPointerAtt = 706 const EventTargetAttributes &nodeUnderPointerAtt =
652 m_nodeUnderPointer.contains(pointerId) 707 m_nodeUnderPointer.contains(pointerId)
653 ? m_nodeUnderPointer.get(pointerId) : EventTargetAttributes(); 708 ? m_nodeUnderPointer.get(pointerId) : EventTargetAttributes();
654 const bool isCaptureChanged =
655 pointerCaptureTarget != pendingPointerCaptureTarget;
656 709
657 if (isCaptureChanged) { 710 if (isCaptureChanged) {
658 if ((hitTestTarget != nodeUnderPointerAtt.target 711 if ((hitTestTarget != nodeUnderPointerAtt.target
659 || (pendingPointerCaptureTarget 712 || (pendingPointerCaptureTarget
660 && pendingPointerCaptureTarget != nodeUnderPointerAtt.target)) 713 && pendingPointerCaptureTarget != nodeUnderPointerAtt.target))
661 && nodeUnderPointerAtt.hasRecievedOverEvent) { 714 && nodeUnderPointerAtt.hasRecievedOverEvent) {
662 if (sendMouseEvent) { 715 if (sendMouseEvent) {
663 // Send pointer event transitions as the line after this if 716 // Send pointer event transitions as the line after this if
664 // block sends the mouse events 717 // block sends the mouse events
665 sendBoundaryEvents(nodeUnderPointerAtt.target, nullptr, 718 sendBoundaryEvents(nodeUnderPointerAtt.target, nullptr,
666 pointerEvent); 719 pointerEvent);
667 } 720 }
668 sendBoundaryEvents(nodeUnderPointerAtt.target, nullptr, 721 sendBoundaryEvents(nodeUnderPointerAtt.target, nullptr,
669 pointerEvent, mouseEvent, sendMouseEvent); 722 pointerEvent, mouseEvent, sendMouseEvent);
670 } 723 }
671 if (pointerCaptureTarget) { 724 if (pointerCaptureTarget) {
672 // Re-target lostpointercapture to the document when the element is 725 // Re-target lostpointercapture to the document when the element is
673 // no longer participating in the tree. 726 // no longer participating in the tree.
674 EventTarget* target = pointerCaptureTarget; 727 EventTarget* target = pointerCaptureTarget;
675 if (target->toNode() 728 if (target->toNode()
676 && !target->toNode()->isConnected()) { 729 && !target->toNode()->isConnected()) {
677 target = target->toNode()->ownerDocument(); 730 target = target->toNode()->ownerDocument();
678 } 731 }
679 dispatchPointerEvent(target, 732 dispatchPointerEvent(target,
680 m_pointerEventFactory.createPointerCaptureEvent( 733 m_pointerEventFactory.createPointerCaptureEvent(
681 pointerEvent, EventTypeNames::lostpointercapture)); 734 pointerId, EventTypeNames::lostpointercapture));
682 } 735 }
683 } 736 }
684 737
685 // Set pointerCaptureTarget from pendingPointerCaptureTarget. This does 738 // Set pointerCaptureTarget from pendingPointerCaptureTarget. This does
686 // affect the behavior of sendBoundaryEvents function. So the 739 // affect the behavior of sendBoundaryEvents function. So the
687 // ordering of the surrounding blocks of code for sending transition events 740 // ordering of the surrounding blocks of code for sending transition events
688 // are important. 741 // are important.
689 if (pendingPointerCaptureTarget) 742 if (pendingPointerCaptureTarget)
690 m_pointerCaptureTarget.set(pointerId, pendingPointerCaptureTarget); 743 m_pointerCaptureTarget.set(pointerId, pendingPointerCaptureTarget);
691 else 744 else
692 m_pointerCaptureTarget.remove(pointerId); 745 m_pointerCaptureTarget.remove(pointerId);
693 746
694 if (isCaptureChanged) { 747 if (isCaptureChanged) {
695 dispatchPointerEvent(pendingPointerCaptureTarget, 748 dispatchPointerEvent(pendingPointerCaptureTarget,
696 m_pointerEventFactory.createPointerCaptureEvent( 749 m_pointerEventFactory.createPointerCaptureEvent(
697 pointerEvent, EventTypeNames::gotpointercapture)); 750 pointerId, EventTypeNames::gotpointercapture));
698 if ((pendingPointerCaptureTarget == hitTestTarget 751 if ((pendingPointerCaptureTarget == hitTestTarget
699 || !pendingPointerCaptureTarget) 752 || !pendingPointerCaptureTarget)
700 && (nodeUnderPointerAtt.target != hitTestTarget 753 && (nodeUnderPointerAtt.target != hitTestTarget
701 || !nodeUnderPointerAtt.hasRecievedOverEvent)) { 754 || !nodeUnderPointerAtt.hasRecievedOverEvent)) {
702 if (sendMouseEvent) { 755 if (sendMouseEvent) {
703 // Send pointer event transitions as the line after this if 756 // Send pointer event transitions as the line after this if
704 // block sends the mouse events 757 // block sends the mouse events
705 sendBoundaryEvents(nullptr, hitTestTarget, pointerEvent); 758 sendBoundaryEvents(nullptr, hitTestTarget, pointerEvent);
706 } 759 }
707 sendBoundaryEvents(nullptr, hitTestTarget, pointerEvent, 760 sendBoundaryEvents(nullptr, hitTestTarget, pointerEvent,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
744 } 797 }
745 798
746 void PointerEventManager::elementRemoved(EventTarget* target) 799 void PointerEventManager::elementRemoved(EventTarget* target)
747 { 800 {
748 removeTargetFromPointerCapturingMapping(m_pendingPointerCaptureTarget, targe t); 801 removeTargetFromPointerCapturingMapping(m_pendingPointerCaptureTarget, targe t);
749 } 802 }
750 803
751 void PointerEventManager::setPointerCapture(int pointerId, EventTarget* target) 804 void PointerEventManager::setPointerCapture(int pointerId, EventTarget* target)
752 { 805 {
753 UseCounter::count(m_frame->document(), UseCounter::PointerEventSetCapture); 806 UseCounter::count(m_frame->document(), UseCounter::PointerEventSetCapture);
754 if (m_pointerEventFactory.isActiveButtonsState(pointerId)) 807 if (m_pointerEventFactory.isActiveButtonsState(pointerId)) {
755 m_pendingPointerCaptureTarget.set(pointerId, target); 808 modifyPendingPointerCapture(pointerId, target);
809 }
756 } 810 }
757 811
758 void PointerEventManager::releasePointerCapture(int pointerId, EventTarget* targ et) 812 void PointerEventManager::releasePointerCapture(int pointerId, EventTarget* targ et)
759 { 813 {
760 // Only the element that is going to get the next pointer event can release 814 // Only the element that is going to get the next pointer event can release
761 // the capture. Note that this might be different from 815 // the capture. Note that this might be different from
762 // |m_pointercaptureTarget|. |m_pointercaptureTarget| holds the element 816 // |m_pointercaptureTarget|. |m_pointercaptureTarget| holds the element
763 // that had the capture until now and has been receiving the pointerevents 817 // that had the capture until now and has been receiving the pointerevents
764 // but |m_pendingPointerCaptureTarget| indicated the element that gets the 818 // but |m_pendingPointerCaptureTarget| indicated the element that gets the
765 // very next pointer event. They will be the same if there was no change in 819 // very next pointer event. They will be the same if there was no change in
766 // capturing of a particular |pointerId|. See crbug.com/614481. 820 // capturing of a particular |pointerId|. See crbug.com/614481.
767 if (m_pendingPointerCaptureTarget.get(pointerId) == target) 821 if (m_pendingPointerCaptureTarget.get(pointerId) == target)
768 releasePointerCapture(pointerId); 822 modifyPendingPointerCapture(pointerId, nullptr);
769 } 823 }
770 824
771 void PointerEventManager::releasePointerCapture(int pointerId) 825 void PointerEventManager::modifyPendingPointerCapture(
826 int pointerId, EventTarget* target)
772 { 827 {
773 m_pendingPointerCaptureTarget.remove(pointerId); 828 bool wasCaptureStationary = !getPointerCaptureState(pointerId, nullptr, null ptr);
829
830 if (target)
831 m_pendingPointerCaptureTarget.set(pointerId, target);
832 else
833 m_pendingPointerCaptureTarget.remove(pointerId);
834
835 // Only queue the processing pending pointer capture if the pending
836 // capture target and capture target were the same to prevent infinite
837 // got/lostpointercapture event sequence.
838 // See https://github.com/w3c/pointerevents/issues/32.
839 if (wasCaptureStationary) {
840 m_frame->document()->postTask(
841 BLINK_FROM_HERE,
842 createSameThreadTask(
843 &EventHandler::immediatelyProcessPendingPointerCapture,
844 wrapWeakPersistent(&m_frame->eventHandler()), pointerId));
845 }
774 } 846 }
775 847
776 bool PointerEventManager::isActive(const int pointerId) const 848 bool PointerEventManager::isActive(const int pointerId) const
777 { 849 {
778 return m_pointerEventFactory.isActive(pointerId); 850 return m_pointerEventFactory.isActive(pointerId);
779 } 851 }
780 852
781 bool PointerEventManager::isAnyTouchActive() const 853 bool PointerEventManager::isAnyTouchActive() const
782 { 854 {
783 return m_touchEventManager.isAnyTouchActive(); 855 return m_touchEventManager.isAnyTouchActive();
(...skipping 19 matching lines...) Expand all
803 { 875 {
804 visitor->trace(m_frame); 876 visitor->trace(m_frame);
805 visitor->trace(m_nodeUnderPointer); 877 visitor->trace(m_nodeUnderPointer);
806 visitor->trace(m_pointerCaptureTarget); 878 visitor->trace(m_pointerCaptureTarget);
807 visitor->trace(m_pendingPointerCaptureTarget); 879 visitor->trace(m_pendingPointerCaptureTarget);
808 visitor->trace(m_touchEventManager); 880 visitor->trace(m_touchEventManager);
809 } 881 }
810 882
811 883
812 } // namespace blink 884 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/input/PointerEventManager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698