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

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: Make PointerEventManager a GC object 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* pct =
624 (it != m_pointerCaptureTarget.end()) ? it->value : nullptr;
625 it = m_pendingPointerCaptureTarget.find(pointerId);
626 EventTarget* ppct =
627 (it != m_pendingPointerCaptureTarget.end()) ? it->value : nullptr;
628
629 if (pointerCaptureTarget)
630 *pointerCaptureTarget = pct;
631 if (pendingPointerCaptureTarget)
632 *pendingPointerCaptureTarget = ppct;
633
634 return pct != ppct;
635 }
636
615 void PointerEventManager::processCaptureAndPositionOfPointerEvent( 637 void PointerEventManager::processCaptureAndPositionOfPointerEvent(
616 PointerEvent* pointerEvent, 638 PointerEvent* pointerEvent,
617 EventTarget* hitTestTarget, 639 EventTarget* hitTestTarget,
618 EventTarget* lastNodeUnderMouse, 640 EventTarget* lastNodeUnderMouse,
619 const PlatformMouseEvent& mouseEvent, 641 const PlatformMouseEvent& mouseEvent,
620 bool sendMouseEvent, bool setPointerPosition) 642 bool sendMouseEvent, bool setPointerPosition)
621 { 643 {
622 bool isCaptureChanged = false; 644 bool isCaptureChanged = false;
623 645
624 if (setPointerPosition) { 646 if (setPointerPosition) {
625 isCaptureChanged = processPendingPointerCapture(pointerEvent, 647 isCaptureChanged = processPendingPointerCapture(pointerEvent,
626 hitTestTarget, mouseEvent, sendMouseEvent); 648 hitTestTarget, mouseEvent, sendMouseEvent);
627 // If there was a change in capturing processPendingPointerCapture has 649 // If there was a change in capturing processPendingPointerCapture has
628 // already taken care of transition events. So we don't need to send the 650 // already taken care of transition events. So we don't need to send the
629 // transition events here. 651 // transition events here.
630 setNodeUnderPointer(pointerEvent, hitTestTarget, !isCaptureChanged); 652 setNodeUnderPointer(pointerEvent, hitTestTarget, !isCaptureChanged);
631 } 653 }
632 if (sendMouseEvent && !isCaptureChanged) { 654 if (sendMouseEvent && !isCaptureChanged) {
633 // lastNodeUnderMouse is needed here because it is still stored in Event Handler. 655 // lastNodeUnderMouse is needed here because it is still stored in Event Handler.
634 sendBoundaryEvents(lastNodeUnderMouse, hitTestTarget, 656 sendBoundaryEvents(lastNodeUnderMouse, hitTestTarget,
635 pointerEvent, mouseEvent, true); 657 pointerEvent, mouseEvent, true);
636 } 658 }
637 } 659 }
638 660
661 void PointerEventManager::immediatelyProcessPendingPointerCapture(int pointerId)
662 {
663 EventTarget* pointerCaptureTarget;
664 EventTarget* pendingPointerCaptureTarget;
665 const bool isCaptureChanged = getPointerCaptureState(pointerId,
666 &pointerCaptureTarget, &pendingPointerCaptureTarget);
667
668 if (!isCaptureChanged)
669 return;
670
671 if (pointerCaptureTarget) {
672 // Re-target lostpointercapture to the document when the element is
673 // no longer participating in the tree.
674 EventTarget* target = pointerCaptureTarget;
675 if (target->toNode()
676 && !target->toNode()->isConnected()) {
677 target = target->toNode()->ownerDocument();
678 }
679 dispatchPointerEvent(target,
680 m_pointerEventFactory.createPointerCaptureEvent(
681 pointerId, EventTypeNames::lostpointercapture));
682 }
683 dispatchPointerEvent(pendingPointerCaptureTarget,
684 m_pointerEventFactory.createPointerCaptureEvent(
685 pointerId, EventTypeNames::gotpointercapture));
686
687 // Setting |m_pointerCaptureTarget| comes at the end to prevent the infinite
688 // loop if js calls set/releasepointercapture in got/lostpointercapture
689 // handlers.
690 if (pendingPointerCaptureTarget)
691 m_pointerCaptureTarget.set(pointerId, pendingPointerCaptureTarget);
692 else
693 m_pointerCaptureTarget.remove(pointerId);
694 }
695
696 // TODO(nzolghadr): This function should be merged with |immediatelyProcessPendi ngPointerCapture|
697 // when we stop hit-testing while a pointer is captured.
mustaq 2016/07/18 20:31:40 Please add in the TODO comment that firing of boun
639 bool PointerEventManager::processPendingPointerCapture( 698 bool PointerEventManager::processPendingPointerCapture(
640 PointerEvent* pointerEvent, 699 PointerEvent* pointerEvent,
641 EventTarget* hitTestTarget, 700 EventTarget* hitTestTarget,
642 const PlatformMouseEvent& mouseEvent, bool sendMouseEvent) 701 const PlatformMouseEvent& mouseEvent, bool sendMouseEvent)
643 { 702 {
644 int pointerId = pointerEvent->pointerId(); 703 int pointerId = pointerEvent->pointerId();
645 EventTarget* pointerCaptureTarget = 704 EventTarget* pointerCaptureTarget;
646 m_pointerCaptureTarget.contains(pointerId) 705 EventTarget* pendingPointerCaptureTarget;
647 ? m_pointerCaptureTarget.get(pointerId) : nullptr; 706 const bool isCaptureChanged = getPointerCaptureState(pointerId,
648 EventTarget* pendingPointerCaptureTarget = 707 &pointerCaptureTarget, &pendingPointerCaptureTarget);
649 m_pendingPointerCaptureTarget.contains(pointerId)
650 ? m_pendingPointerCaptureTarget.get(pointerId) : nullptr;
651 const EventTargetAttributes &nodeUnderPointerAtt = 708 const EventTargetAttributes &nodeUnderPointerAtt =
652 m_nodeUnderPointer.contains(pointerId) 709 m_nodeUnderPointer.contains(pointerId)
653 ? m_nodeUnderPointer.get(pointerId) : EventTargetAttributes(); 710 ? m_nodeUnderPointer.get(pointerId) : EventTargetAttributes();
654 const bool isCaptureChanged =
655 pointerCaptureTarget != pendingPointerCaptureTarget;
656 711
657 if (isCaptureChanged) { 712 if (isCaptureChanged) {
658 if ((hitTestTarget != nodeUnderPointerAtt.target 713 if ((hitTestTarget != nodeUnderPointerAtt.target
659 || (pendingPointerCaptureTarget 714 || (pendingPointerCaptureTarget
660 && pendingPointerCaptureTarget != nodeUnderPointerAtt.target)) 715 && pendingPointerCaptureTarget != nodeUnderPointerAtt.target))
661 && nodeUnderPointerAtt.hasRecievedOverEvent) { 716 && nodeUnderPointerAtt.hasRecievedOverEvent) {
662 if (sendMouseEvent) { 717 if (sendMouseEvent) {
663 // Send pointer event transitions as the line after this if 718 // Send pointer event transitions as the line after this if
664 // block sends the mouse events 719 // block sends the mouse events
665 sendBoundaryEvents(nodeUnderPointerAtt.target, nullptr, 720 sendBoundaryEvents(nodeUnderPointerAtt.target, nullptr,
666 pointerEvent); 721 pointerEvent);
667 } 722 }
668 sendBoundaryEvents(nodeUnderPointerAtt.target, nullptr, 723 sendBoundaryEvents(nodeUnderPointerAtt.target, nullptr,
669 pointerEvent, mouseEvent, sendMouseEvent); 724 pointerEvent, mouseEvent, sendMouseEvent);
670 } 725 }
671 if (pointerCaptureTarget) { 726 if (pointerCaptureTarget) {
672 // Re-target lostpointercapture to the document when the element is 727 // Re-target lostpointercapture to the document when the element is
673 // no longer participating in the tree. 728 // no longer participating in the tree.
674 EventTarget* target = pointerCaptureTarget; 729 EventTarget* target = pointerCaptureTarget;
675 if (target->toNode() 730 if (target->toNode()
676 && !target->toNode()->isConnected()) { 731 && !target->toNode()->isConnected()) {
677 target = target->toNode()->ownerDocument(); 732 target = target->toNode()->ownerDocument();
678 } 733 }
679 dispatchPointerEvent(target, 734 dispatchPointerEvent(target,
680 m_pointerEventFactory.createPointerCaptureEvent( 735 m_pointerEventFactory.createPointerCaptureEvent(
681 pointerEvent, EventTypeNames::lostpointercapture)); 736 pointerId, EventTypeNames::lostpointercapture));
682 } 737 }
683 } 738 }
684 739
685 // Set pointerCaptureTarget from pendingPointerCaptureTarget. This does 740 // Set pointerCaptureTarget from pendingPointerCaptureTarget. This does
686 // affect the behavior of sendBoundaryEvents function. So the 741 // affect the behavior of sendBoundaryEvents function. So the
687 // ordering of the surrounding blocks of code for sending transition events 742 // ordering of the surrounding blocks of code for sending transition events
688 // are important. 743 // are important.
689 if (pendingPointerCaptureTarget) 744 if (pendingPointerCaptureTarget)
690 m_pointerCaptureTarget.set(pointerId, pendingPointerCaptureTarget); 745 m_pointerCaptureTarget.set(pointerId, pendingPointerCaptureTarget);
691 else 746 else
692 m_pointerCaptureTarget.remove(pointerId); 747 m_pointerCaptureTarget.remove(pointerId);
693 748
694 if (isCaptureChanged) { 749 if (isCaptureChanged) {
695 dispatchPointerEvent(pendingPointerCaptureTarget, 750 dispatchPointerEvent(pendingPointerCaptureTarget,
696 m_pointerEventFactory.createPointerCaptureEvent( 751 m_pointerEventFactory.createPointerCaptureEvent(
697 pointerEvent, EventTypeNames::gotpointercapture)); 752 pointerId, EventTypeNames::gotpointercapture));
698 if ((pendingPointerCaptureTarget == hitTestTarget 753 if ((pendingPointerCaptureTarget == hitTestTarget
699 || !pendingPointerCaptureTarget) 754 || !pendingPointerCaptureTarget)
700 && (nodeUnderPointerAtt.target != hitTestTarget 755 && (nodeUnderPointerAtt.target != hitTestTarget
701 || !nodeUnderPointerAtt.hasRecievedOverEvent)) { 756 || !nodeUnderPointerAtt.hasRecievedOverEvent)) {
702 if (sendMouseEvent) { 757 if (sendMouseEvent) {
703 // Send pointer event transitions as the line after this if 758 // Send pointer event transitions as the line after this if
704 // block sends the mouse events 759 // block sends the mouse events
705 sendBoundaryEvents(nullptr, hitTestTarget, pointerEvent); 760 sendBoundaryEvents(nullptr, hitTestTarget, pointerEvent);
706 } 761 }
707 sendBoundaryEvents(nullptr, hitTestTarget, pointerEvent, 762 sendBoundaryEvents(nullptr, hitTestTarget, pointerEvent,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
744 } 799 }
745 800
746 void PointerEventManager::elementRemoved(EventTarget* target) 801 void PointerEventManager::elementRemoved(EventTarget* target)
747 { 802 {
748 removeTargetFromPointerCapturingMapping(m_pendingPointerCaptureTarget, targe t); 803 removeTargetFromPointerCapturingMapping(m_pendingPointerCaptureTarget, targe t);
749 } 804 }
750 805
751 void PointerEventManager::setPointerCapture(int pointerId, EventTarget* target) 806 void PointerEventManager::setPointerCapture(int pointerId, EventTarget* target)
752 { 807 {
753 UseCounter::count(m_frame->document(), UseCounter::PointerEventSetCapture); 808 UseCounter::count(m_frame->document(), UseCounter::PointerEventSetCapture);
754 if (m_pointerEventFactory.isActiveButtonsState(pointerId)) 809 if (m_pointerEventFactory.isActiveButtonsState(pointerId)) {
755 m_pendingPointerCaptureTarget.set(pointerId, target); 810 modifyPendingPointerCapture(pointerId, target);
811 }
756 } 812 }
757 813
758 void PointerEventManager::releasePointerCapture(int pointerId, EventTarget* targ et) 814 void PointerEventManager::releasePointerCapture(int pointerId, EventTarget* targ et)
759 { 815 {
760 // Only the element that is going to get the next pointer event can release 816 // Only the element that is going to get the next pointer event can release
761 // the capture. Note that this might be different from 817 // the capture. Note that this might be different from
762 // |m_pointercaptureTarget|. |m_pointercaptureTarget| holds the element 818 // |m_pointercaptureTarget|. |m_pointercaptureTarget| holds the element
763 // that had the capture until now and has been receiving the pointerevents 819 // that had the capture until now and has been receiving the pointerevents
764 // but |m_pendingPointerCaptureTarget| indicated the element that gets the 820 // 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 821 // 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. 822 // capturing of a particular |pointerId|. See crbug.com/614481.
767 if (m_pendingPointerCaptureTarget.get(pointerId) == target) 823 if (m_pendingPointerCaptureTarget.get(pointerId) == target)
768 releasePointerCapture(pointerId); 824 modifyPendingPointerCapture(pointerId, nullptr);
769 } 825 }
770 826
771 void PointerEventManager::releasePointerCapture(int pointerId) 827 void PointerEventManager::modifyPendingPointerCapture(
828 int pointerId, EventTarget* target)
772 { 829 {
773 m_pendingPointerCaptureTarget.remove(pointerId); 830 bool wasCaptureStationary = !getPointerCaptureState(pointerId, nullptr, null ptr);
831
832 if (target)
833 m_pendingPointerCaptureTarget.set(pointerId, target);
834 else
835 m_pendingPointerCaptureTarget.remove(pointerId);
836
837 // Only queue the processing pending pointer capture if the pending
838 // capture target and capture target were the same to prevent infinite
839 // got/lostpointercapture event sequence.
840 // See https://github.com/w3c/pointerevents/issues/32.
841 if (wasCaptureStationary) {
842 m_frame->document()->postTask(
843 BLINK_FROM_HERE,
844 createSameThreadTask(
845 &PointerEventManager::immediatelyProcessPendingPointerCapture,
846 wrapWeakPersistent(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
« 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