Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |