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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/Source/core/input/PointerEventManager.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/core/input/PointerEventManager.cpp
diff --git a/third_party/WebKit/Source/core/input/PointerEventManager.cpp b/third_party/WebKit/Source/core/input/PointerEventManager.cpp
index c3cb5b770a9521f9937ea289373426c9127a9dcf..fa0834c32ff14d96146acb603f8a6c227c294e24 100644
--- a/third_party/WebKit/Source/core/input/PointerEventManager.cpp
+++ b/third_party/WebKit/Source/core/input/PointerEventManager.cpp
@@ -5,6 +5,7 @@
#include "core/input/PointerEventManager.h"
#include "core/dom/ElementTraversal.h"
+#include "core/dom/ExecutionContextTask.h"
#include "core/dom/shadow/FlatTreeTraversal.h"
#include "core/events/MouseEvent.h"
#include "core/frame/FrameView.h"
@@ -366,7 +367,7 @@ void PointerEventManager::blockTouchPointers()
getEffectiveTargetForPointerEvent(target, pointerEvent->pointerId()),
pointerEvent);
- releasePointerCapture(pointerEvent->pointerId());
+ modifyPendingPointerCapture(pointerEvent->pointerId(), nullptr);
// Sending the leave/out events and lostpointercapture
// because the next touch event will have a different id. So delayed
@@ -512,7 +513,7 @@ WebInputEventResult PointerEventManager::sendTouchPointerEvent(
if (pointerEvent->type() == EventTypeNames::pointerup
|| pointerEvent->type() == EventTypeNames::pointercancel) {
- releasePointerCapture(pointerEvent->pointerId());
+ modifyPendingPointerCapture(pointerEvent->pointerId(), nullptr);
// Sending the leave/out events and lostpointercapture
// because the next touch event will have a different id. So delayed
@@ -578,7 +579,7 @@ WebInputEventResult PointerEventManager::sendMousePointerEvent(
}
if (pointerEvent->buttons() == 0) {
- releasePointerCapture(pointerEvent->pointerId());
+ modifyPendingPointerCapture(pointerEvent->pointerId(), nullptr);
if (pointerEvent->isPrimary()) {
m_preventMouseEventForPointerType[toPointerTypeIndex(
mouseEvent.pointerProperties().pointerType)] = false;
@@ -612,6 +613,25 @@ void PointerEventManager::clear()
m_pendingPointerCaptureTarget.clear();
}
+bool PointerEventManager::getPointerCaptureState(int pointerId,
+ EventTarget** pointerCaptureTarget,
+ EventTarget** pendingPointerCaptureTarget)
+{
+ PointerCapturingMap::iterator it;
+
+ it = m_pointerCaptureTarget.find(pointerId);
+ EventTarget* pointercaptureTargetTemp = (it != m_pointerCaptureTarget.end()) ? it->value : nullptr;
+ it = m_pendingPointerCaptureTarget.find(pointerId);
+ EventTarget* pendingPointercaptureTargetTemp = (it != m_pendingPointerCaptureTarget.end()) ? it->value : nullptr;
+
+ if (pointerCaptureTarget)
+ *pointerCaptureTarget = pointercaptureTargetTemp;
+ if (pendingPointerCaptureTarget)
+ *pendingPointerCaptureTarget = pendingPointercaptureTargetTemp;
+
+ return pointercaptureTargetTemp != pendingPointercaptureTargetTemp;
+}
+
void PointerEventManager::processCaptureAndPositionOfPointerEvent(
PointerEvent* pointerEvent,
EventTarget* hitTestTarget,
@@ -636,23 +656,56 @@ void PointerEventManager::processCaptureAndPositionOfPointerEvent(
}
}
+void PointerEventManager::immediatelyProcessPendingPointerCapture(int pointerId)
+{
+ EventTarget* pointerCaptureTarget;
+ EventTarget* pendingPointerCaptureTarget;
+ const bool isCaptureChanged = getPointerCaptureState(pointerId,
+ &pointerCaptureTarget, &pendingPointerCaptureTarget);
+
+ if (!isCaptureChanged)
+ return;
+
+ if (pointerCaptureTarget) {
+ // Re-target lostpointercapture to the document when the element is
+ // no longer participating in the tree.
+ EventTarget* target = pointerCaptureTarget;
+ if (target->toNode()
+ && !target->toNode()->isConnected()) {
+ target = target->toNode()->ownerDocument();
+ }
+ dispatchPointerEvent(target,
+ m_pointerEventFactory.createPointerCaptureEvent(
+ pointerId, EventTypeNames::lostpointercapture));
+ }
+ dispatchPointerEvent(pendingPointerCaptureTarget,
+ m_pointerEventFactory.createPointerCaptureEvent(
+ pointerId, EventTypeNames::gotpointercapture));
+
+ // Setting |m_pointerCaptureTarget| comes at the end to prevent the infinite
+ // loop if js calls set/releasepointercapture in got/lostpointercapture
+ // handlers.
+ if (pendingPointerCaptureTarget)
+ m_pointerCaptureTarget.set(pointerId, pendingPointerCaptureTarget);
+ else
+ m_pointerCaptureTarget.remove(pointerId);
+}
+
+// TODO(crbug.com/629921): This function should be merged with |immediatelyProcessPendingPointerCapture|
+// when we stop hit-testing while a pointer is captured.
bool PointerEventManager::processPendingPointerCapture(
PointerEvent* pointerEvent,
EventTarget* hitTestTarget,
const PlatformMouseEvent& mouseEvent, bool sendMouseEvent)
{
int pointerId = pointerEvent->pointerId();
- EventTarget* pointerCaptureTarget =
- m_pointerCaptureTarget.contains(pointerId)
- ? m_pointerCaptureTarget.get(pointerId) : nullptr;
- EventTarget* pendingPointerCaptureTarget =
- m_pendingPointerCaptureTarget.contains(pointerId)
- ? m_pendingPointerCaptureTarget.get(pointerId) : nullptr;
+ EventTarget* pointerCaptureTarget;
+ EventTarget* pendingPointerCaptureTarget;
+ const bool isCaptureChanged = getPointerCaptureState(pointerId,
+ &pointerCaptureTarget, &pendingPointerCaptureTarget);
const EventTargetAttributes &nodeUnderPointerAtt =
m_nodeUnderPointer.contains(pointerId)
? m_nodeUnderPointer.get(pointerId) : EventTargetAttributes();
- const bool isCaptureChanged =
- pointerCaptureTarget != pendingPointerCaptureTarget;
if (isCaptureChanged) {
if ((hitTestTarget != nodeUnderPointerAtt.target
@@ -678,7 +731,7 @@ bool PointerEventManager::processPendingPointerCapture(
}
dispatchPointerEvent(target,
m_pointerEventFactory.createPointerCaptureEvent(
- pointerEvent, EventTypeNames::lostpointercapture));
+ pointerId, EventTypeNames::lostpointercapture));
}
}
@@ -694,7 +747,7 @@ bool PointerEventManager::processPendingPointerCapture(
if (isCaptureChanged) {
dispatchPointerEvent(pendingPointerCaptureTarget,
m_pointerEventFactory.createPointerCaptureEvent(
- pointerEvent, EventTypeNames::gotpointercapture));
+ pointerId, EventTypeNames::gotpointercapture));
if ((pendingPointerCaptureTarget == hitTestTarget
|| !pendingPointerCaptureTarget)
&& (nodeUnderPointerAtt.target != hitTestTarget
@@ -751,8 +804,9 @@ void PointerEventManager::elementRemoved(EventTarget* target)
void PointerEventManager::setPointerCapture(int pointerId, EventTarget* target)
{
UseCounter::count(m_frame->document(), UseCounter::PointerEventSetCapture);
- if (m_pointerEventFactory.isActiveButtonsState(pointerId))
- m_pendingPointerCaptureTarget.set(pointerId, target);
+ if (m_pointerEventFactory.isActiveButtonsState(pointerId)) {
+ modifyPendingPointerCapture(pointerId, target);
+ }
}
void PointerEventManager::releasePointerCapture(int pointerId, EventTarget* target)
@@ -765,12 +819,30 @@ void PointerEventManager::releasePointerCapture(int pointerId, EventTarget* targ
// very next pointer event. They will be the same if there was no change in
// capturing of a particular |pointerId|. See crbug.com/614481.
if (m_pendingPointerCaptureTarget.get(pointerId) == target)
- releasePointerCapture(pointerId);
+ modifyPendingPointerCapture(pointerId, nullptr);
}
-void PointerEventManager::releasePointerCapture(int pointerId)
+void PointerEventManager::modifyPendingPointerCapture(
+ int pointerId, EventTarget* target)
{
- m_pendingPointerCaptureTarget.remove(pointerId);
+ bool wasCaptureStationary = !getPointerCaptureState(pointerId, nullptr, nullptr);
+
+ if (target)
+ m_pendingPointerCaptureTarget.set(pointerId, target);
+ else
+ m_pendingPointerCaptureTarget.remove(pointerId);
+
+ // Only queue the processing pending pointer capture if the pending
+ // capture target and capture target were the same to prevent infinite
+ // got/lostpointercapture event sequence.
+ // See https://github.com/w3c/pointerevents/issues/32.
+ if (wasCaptureStationary) {
+ m_frame->document()->postTask(
+ BLINK_FROM_HERE,
+ createSameThreadTask(
+ &EventHandler::immediatelyProcessPendingPointerCapture,
+ wrapWeakPersistent(&m_frame->eventHandler()), pointerId));
+ }
}
bool PointerEventManager::isActive(const int pointerId) const
« 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