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

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: Rebased 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
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 587 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 EventTarget* pct = m_pointerCaptureTarget.contains(pointerId)
Rick Byers 2016/07/15 17:35:32 nit: HashMap::find is the efficient way to do cont
Navid Zolghadr 2016/07/15 20:41:01 Done.
621 ? m_pointerCaptureTarget.get(pointerId)
622 : nullptr;
623 EventTarget* ppct = m_pendingPointerCaptureTarget.contains(pointerId)
624 ? m_pendingPointerCaptureTarget.get(pointerId)
625 : nullptr;
626
627 if (pointerCaptureTarget)
628 *pointerCaptureTarget = pct;
629 if (pendingPointerCaptureTarget)
630 *pendingPointerCaptureTarget = ppct;
631
632 return pct != ppct;
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::immediateProcessPendingPointerCapture(int pointerId)
mustaq 2016/07/15 19:35:43 Nit: s/immediate/immediately/
Navid Zolghadr 2016/07/15 20:41:01 Done.
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
Rick Byers 2016/07/15 17:35:32 is this behavior specified somewhere? It seems re
Navid Zolghadr 2016/07/15 20:41:01 Yes. It is here the second paragraph. https://w3c.
671 // no longer participating in the tree.
672 EventTarget* target = pointerCaptureTarget;
673 if (target->toNode()
674 && !target->toNode()->inShadowIncludingDocument()) {
675 target = target->toNode()->ownerDocument();
676 }
677 dispatchPointerEvent(target,
678 m_pointerEventFactory.createPointerCaptureEvent(
679 pointerId, EventTypeNames::lostpointercapture));
680 }
681 dispatchPointerEvent(pendingPointerCaptureTarget,
Rick Byers 2016/07/15 17:35:32 Don't you need to check for null here too - eg. fo
mustaq 2016/07/15 19:35:43 Yes, pendingPointerCaptureTarget would be null aft
Navid Zolghadr 2016/07/15 20:41:01 Since there was a lot of those checks around every
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
639 bool PointerEventManager::processPendingPointerCapture( 694 bool PointerEventManager::processPendingPointerCapture(
Rick Byers 2016/07/15 17:35:31 once we make the other changes here (eg. not firin
Navid Zolghadr 2016/07/15 20:41:01 That is correct. I added the TODO.
mustaq 2016/07/15 21:06:14 "Not firing the boundary events": we still need to
640 PointerEvent* pointerEvent, 695 PointerEvent* pointerEvent,
641 EventTarget* hitTestTarget, 696 EventTarget* hitTestTarget,
642 const PlatformMouseEvent& mouseEvent, bool sendMouseEvent) 697 const PlatformMouseEvent& mouseEvent, bool sendMouseEvent)
643 { 698 {
644 int pointerId = pointerEvent->pointerId(); 699 int pointerId = pointerEvent->pointerId();
645 EventTarget* pointerCaptureTarget = 700 EventTarget* pointerCaptureTarget;
646 m_pointerCaptureTarget.contains(pointerId) 701 EventTarget* pendingPointerCaptureTarget;
647 ? m_pointerCaptureTarget.get(pointerId) : nullptr; 702 const bool isCaptureChanged = getPointerCaptureState(pointerId,
648 EventTarget* pendingPointerCaptureTarget = 703 &pointerCaptureTarget, &pendingPointerCaptureTarget);
649 m_pendingPointerCaptureTarget.contains(pointerId)
650 ? m_pendingPointerCaptureTarget.get(pointerId) : nullptr;
651 const EventTargetAttributes &nodeUnderPointerAtt = 704 const EventTargetAttributes &nodeUnderPointerAtt =
652 m_nodeUnderPointer.contains(pointerId) 705 m_nodeUnderPointer.contains(pointerId)
653 ? m_nodeUnderPointer.get(pointerId) : EventTargetAttributes(); 706 ? m_nodeUnderPointer.get(pointerId) : EventTargetAttributes();
654 const bool isCaptureChanged =
655 pointerCaptureTarget != pendingPointerCaptureTarget;
656 707
657 if (isCaptureChanged) { 708 if (isCaptureChanged) {
658 if ((hitTestTarget != nodeUnderPointerAtt.target 709 if ((hitTestTarget != nodeUnderPointerAtt.target
659 || (pendingPointerCaptureTarget 710 || (pendingPointerCaptureTarget
660 && pendingPointerCaptureTarget != nodeUnderPointerAtt.target)) 711 && pendingPointerCaptureTarget != nodeUnderPointerAtt.target))
661 && nodeUnderPointerAtt.hasRecievedOverEvent) { 712 && nodeUnderPointerAtt.hasRecievedOverEvent) {
662 if (sendMouseEvent) { 713 if (sendMouseEvent) {
663 // Send pointer event transitions as the line after this if 714 // Send pointer event transitions as the line after this if
664 // block sends the mouse events 715 // block sends the mouse events
665 sendBoundaryEvents(nodeUnderPointerAtt.target, nullptr, 716 sendBoundaryEvents(nodeUnderPointerAtt.target, nullptr,
666 pointerEvent); 717 pointerEvent);
667 } 718 }
668 sendBoundaryEvents(nodeUnderPointerAtt.target, nullptr, 719 sendBoundaryEvents(nodeUnderPointerAtt.target, nullptr,
669 pointerEvent, mouseEvent, sendMouseEvent); 720 pointerEvent, mouseEvent, sendMouseEvent);
670 } 721 }
671 if (pointerCaptureTarget) { 722 if (pointerCaptureTarget) {
672 // Re-target lostpointercapture to the document when the element is 723 // Re-target lostpointercapture to the document when the element is
673 // no longer participating in the tree. 724 // no longer participating in the tree.
674 EventTarget* target = pointerCaptureTarget; 725 EventTarget* target = pointerCaptureTarget;
675 if (target->toNode() 726 if (target->toNode()
676 && !target->toNode()->isConnected()) { 727 && !target->toNode()->isConnected()) {
677 target = target->toNode()->ownerDocument(); 728 target = target->toNode()->ownerDocument();
678 } 729 }
679 dispatchPointerEvent(target, 730 dispatchPointerEvent(target,
680 m_pointerEventFactory.createPointerCaptureEvent( 731 m_pointerEventFactory.createPointerCaptureEvent(
681 pointerEvent, EventTypeNames::lostpointercapture)); 732 pointerId, EventTypeNames::lostpointercapture));
682 } 733 }
683 } 734 }
684 735
685 // Set pointerCaptureTarget from pendingPointerCaptureTarget. This does 736 // Set pointerCaptureTarget from pendingPointerCaptureTarget. This does
686 // affect the behavior of sendBoundaryEvents function. So the 737 // affect the behavior of sendBoundaryEvents function. So the
mustaq 2016/07/15 19:35:43 Does that mean the boundary event firing is incons
Navid Zolghadr 2016/07/15 20:41:01 I believe yes. But I saw none of the tests failing
mustaq 2016/07/15 21:06:14 Here is the catch for not sending boundary events
687 // ordering of the surrounding blocks of code for sending transition events 738 // ordering of the surrounding blocks of code for sending transition events
688 // are important. 739 // are important.
689 if (pendingPointerCaptureTarget) 740 if (pendingPointerCaptureTarget)
690 m_pointerCaptureTarget.set(pointerId, pendingPointerCaptureTarget); 741 m_pointerCaptureTarget.set(pointerId, pendingPointerCaptureTarget);
691 else 742 else
692 m_pointerCaptureTarget.remove(pointerId); 743 m_pointerCaptureTarget.remove(pointerId);
693 744
694 if (isCaptureChanged) { 745 if (isCaptureChanged) {
695 dispatchPointerEvent(pendingPointerCaptureTarget, 746 dispatchPointerEvent(pendingPointerCaptureTarget,
696 m_pointerEventFactory.createPointerCaptureEvent( 747 m_pointerEventFactory.createPointerCaptureEvent(
697 pointerEvent, EventTypeNames::gotpointercapture)); 748 pointerId, EventTypeNames::gotpointercapture));
698 if ((pendingPointerCaptureTarget == hitTestTarget 749 if ((pendingPointerCaptureTarget == hitTestTarget
699 || !pendingPointerCaptureTarget) 750 || !pendingPointerCaptureTarget)
700 && (nodeUnderPointerAtt.target != hitTestTarget 751 && (nodeUnderPointerAtt.target != hitTestTarget
701 || !nodeUnderPointerAtt.hasRecievedOverEvent)) { 752 || !nodeUnderPointerAtt.hasRecievedOverEvent)) {
702 if (sendMouseEvent) { 753 if (sendMouseEvent) {
703 // Send pointer event transitions as the line after this if 754 // Send pointer event transitions as the line after this if
704 // block sends the mouse events 755 // block sends the mouse events
705 sendBoundaryEvents(nullptr, hitTestTarget, pointerEvent); 756 sendBoundaryEvents(nullptr, hitTestTarget, pointerEvent);
706 } 757 }
707 sendBoundaryEvents(nullptr, hitTestTarget, pointerEvent, 758 sendBoundaryEvents(nullptr, hitTestTarget, pointerEvent,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 m_pointerCaptureTarget.remove(pointerId); 792 m_pointerCaptureTarget.remove(pointerId);
742 m_nodeUnderPointer.remove(pointerId); 793 m_nodeUnderPointer.remove(pointerId);
743 } 794 }
744 } 795 }
745 796
746 void PointerEventManager::elementRemoved(EventTarget* target) 797 void PointerEventManager::elementRemoved(EventTarget* target)
747 { 798 {
748 removeTargetFromPointerCapturingMapping(m_pendingPointerCaptureTarget, targe t); 799 removeTargetFromPointerCapturingMapping(m_pendingPointerCaptureTarget, targe t);
749 } 800 }
750 801
751 void PointerEventManager::setPointerCapture(int pointerId, EventTarget* target) 802 void PointerEventManager::setPointerCapture(int pointerId, EventTarget* target)
mustaq 2016/07/15 19:35:43 It's not clear to me what happens in case of a jan
Navid Zolghadr 2016/07/15 20:41:01 Nothing I guess. Actually before we fire every poi
752 { 803 {
753 UseCounter::count(m_frame->document(), UseCounter::PointerEventSetCapture); 804 UseCounter::count(m_frame->document(), UseCounter::PointerEventSetCapture);
754 if (m_pointerEventFactory.isActiveButtonsState(pointerId)) 805 if (m_pointerEventFactory.isActiveButtonsState(pointerId)) {
806 bool wasCaptureStationary = !getPointerCaptureState(pointerId, nullptr, nullptr);
755 m_pendingPointerCaptureTarget.set(pointerId, target); 807 m_pendingPointerCaptureTarget.set(pointerId, target);
808 // Only queue the processing pending pointer capture if the pending
Rick Byers 2016/07/15 17:35:32 nit: Add a comment referencing the github issue wh
Navid Zolghadr 2016/07/15 20:41:01 Done.
809 // capture target and capture target were the same to prevent infinite
810 // got/lostpointercapture event sequence.
811 if (wasCaptureStationary) {
812 m_frame->document()->getExecutionContext()->postTask(
Rick Byers 2016/07/15 17:35:31 Looking at this more, I think you probably should
Navid Zolghadr 2016/07/15 20:41:01 Done.
813 BLINK_FROM_HERE,
814 createSameThreadTask(
815 &PointerEventManager::immediateProcessPendingPointerCapture,
816 WTF::unretained(this), pointerId));
817 }
818 }
756 } 819 }
757 820
758 void PointerEventManager::releasePointerCapture(int pointerId, EventTarget* targ et) 821 void PointerEventManager::releasePointerCapture(int pointerId, EventTarget* targ et)
759 { 822 {
760 // Only the element that is going to get the next pointer event can release 823 // Only the element that is going to get the next pointer event can release
761 // the capture. Note that this might be different from 824 // the capture. Note that this might be different from
762 // |m_pointercaptureTarget|. |m_pointercaptureTarget| holds the element 825 // |m_pointercaptureTarget|. |m_pointercaptureTarget| holds the element
763 // that had the capture until now and has been receiving the pointerevents 826 // that had the capture until now and has been receiving the pointerevents
764 // but |m_pendingPointerCaptureTarget| indicated the element that gets the 827 // 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 828 // 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. 829 // capturing of a particular |pointerId|. See crbug.com/614481.
767 if (m_pendingPointerCaptureTarget.get(pointerId) == target) 830 if (m_pendingPointerCaptureTarget.get(pointerId) == target)
768 releasePointerCapture(pointerId); 831 releasePointerCapture(pointerId);
769 } 832 }
770 833
771 void PointerEventManager::releasePointerCapture(int pointerId) 834 void PointerEventManager::releasePointerCapture(int pointerId)
772 { 835 {
836 bool wasCaptureStationary = !getPointerCaptureState(pointerId, nullptr, null ptr);
773 m_pendingPointerCaptureTarget.remove(pointerId); 837 m_pendingPointerCaptureTarget.remove(pointerId);
838 // Only queue the processing pending pointer capture if the pending
Rick Byers 2016/07/15 17:35:32 please avoid copy/paste - share this code
Navid Zolghadr 2016/07/15 20:41:01 Done.
839 // capture target and capture target were the same to prevent infinite
840 // got/lostpointercapture event sequence.
841 if (wasCaptureStationary) {
842 m_frame->document()->getExecutionContext()->postTask(
843 BLINK_FROM_HERE,
844 createSameThreadTask(
845 &PointerEventManager::immediateProcessPendingPointerCapture,
846 WTF::unretained(this), pointerId));
847 }
774 } 848 }
775 849
776 bool PointerEventManager::isActive(const int pointerId) const 850 bool PointerEventManager::isActive(const int pointerId) const
777 { 851 {
778 return m_pointerEventFactory.isActive(pointerId); 852 return m_pointerEventFactory.isActive(pointerId);
779 } 853 }
780 854
781 bool PointerEventManager::isAnyTouchActive() const 855 bool PointerEventManager::isAnyTouchActive() const
782 { 856 {
783 return m_touchEventManager.isAnyTouchActive(); 857 return m_touchEventManager.isAnyTouchActive();
(...skipping 19 matching lines...) Expand all
803 { 877 {
804 visitor->trace(m_frame); 878 visitor->trace(m_frame);
805 visitor->trace(m_nodeUnderPointer); 879 visitor->trace(m_nodeUnderPointer);
806 visitor->trace(m_pointerCaptureTarget); 880 visitor->trace(m_pointerCaptureTarget);
807 visitor->trace(m_pendingPointerCaptureTarget); 881 visitor->trace(m_pendingPointerCaptureTarget);
808 visitor->trace(m_touchEventManager); 882 visitor->trace(m_touchEventManager);
809 } 883 }
810 884
811 885
812 } // namespace blink 886 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698