0

UseCounter for explicit mouse capture affecting click event target.

In PEWG, we are considering making the target of a click event the same
as the pointerup target when the pointerup event is dispatched to a
captured target.  Currently the click event target is the common
ancestor of pointerdown and pointerup targets.  Before we make the
change, we want to check what fraction of page loads would be affected
by this possible change in click target.

Spec discussion: https://github.com/w3c/pointerevents/issues/356

Fixed: 1199099
Change-Id: I9e28c9ab5138f187635352a74befb8cb800aa80a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2876145
Commit-Queue: Mustaq Ahmed <mustaq@chromium.org>
Reviewed-by: Robert Flack <flackr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#893096}
This commit is contained in:
Mustaq Ahmed
2021-06-16 19:15:49 +00:00
committed by Chromium LUCI CQ
parent b5117b594d
commit d424e6fa4b
10 changed files with 42 additions and 14 deletions

@ -3254,6 +3254,7 @@ enum WebFeature {
kXRFrameFillJointRadii = 3939,
kXRFrameFillPoses = 3940,
kWindowOpenNewPopupBehaviorMismatch = 3941,
kExplicitPointerCaptureClickTargetDiff = 3942,
// Add new features immediately above this line. Don't change assigned
// numbers of any item, and don't reuse removed slots.

@ -4787,8 +4787,8 @@ void Element::setPointerCapture(PointerId pointer_id,
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"InvalidStateError");
} else {
GetDocument().GetFrame()->GetEventHandler().SetPointerCapture(pointer_id,
this);
GetDocument().GetFrame()->GetEventHandler().SetPointerCapture(
pointer_id, this, /* explicit_capture */ true);
}
}
}

@ -80,7 +80,7 @@ class CORE_EXPORT PointerEventFactory {
// Otherwise it returns WebPointerProperties::PointerType::Unknown.
WebPointerProperties::PointerType GetPointerType(PointerId pointer_id) const;
// Returns whether a WebPoinerProperties is primary pointer.
// Returns whether a WebPoinerProperties is a primary pointer.
bool IsPrimary(const WebPointerProperties&) const;
static const PointerId kMouseId;

@ -1430,15 +1430,17 @@ LocalFrame* EventHandler::DetermineActivePointerTrackerFrame(
return nullptr;
}
void EventHandler::SetPointerCapture(PointerId pointer_id, Element* target) {
void EventHandler::SetPointerCapture(PointerId pointer_id,
Element* target,
bool explicit_capture) {
// TODO(crbug.com/591387): This functionality should be per page not per
// frame.
LocalFrame* tracking_frame = DetermineActivePointerTrackerFrame(pointer_id);
bool captured =
tracking_frame &&
tracking_frame->GetEventHandler()
.pointer_event_manager_->SetPointerCapture(pointer_id, target);
tracking_frame && tracking_frame->GetEventHandler()
.pointer_event_manager_->SetPointerCapture(
pointer_id, target, explicit_capture);
if (captured && pointer_id == PointerEventFactory::kMouseId) {
CaptureMouseEventsToWidget(true);

@ -220,7 +220,7 @@ class CORE_EXPORT EventHandler final : public GarbageCollected<EventHandler> {
// Returns whether pointerId is active or not
bool IsPointerEventActive(PointerId);
void SetPointerCapture(PointerId, Element*);
void SetPointerCapture(PointerId, Element*, bool explicit_capture = false);
void ReleasePointerCapture(PointerId, Element*);
void ReleaseMousePointerCapture();
bool HasPointerCapture(PointerId, const Element*) const;

@ -1222,6 +1222,10 @@ void MouseEventManager::SetMousePressNode(Node* node) {
mouse_press_node_ = node;
}
Element* MouseEventManager::MouseDownElement() {
return mouse_down_element_;
}
void MouseEventManager::SetClickElement(Element* element) {
SetDocument(element ? element->ownerDocument() : nullptr);
click_element_ = element;

@ -143,6 +143,8 @@ class CORE_EXPORT MouseEventManager final
Node* MousePressNode();
void SetMousePressNode(Node*);
Element* MouseDownElement();
void SetClickElement(Element*);
void SetClickCount(int);
@ -234,6 +236,8 @@ class CORE_EXPORT MouseEventManager final
unsigned captures_dragging_ : 1;
unsigned mouse_down_may_start_drag_ : 1;
// TODO(crbug.com/1220669): Do we need both |mouse_press_node_| and
// |mouse_down_element_|?
Member<Node> mouse_press_node_;
int click_count_;

@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/events/event_path.h"
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/event_type_names.h"
#include "third_party/blink/renderer/core/events/mouse_event.h"
#include "third_party/blink/renderer/core/frame/event_handler_registry.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@ -45,6 +46,7 @@ const char kSkipTouchEventFilterTrialTypeParamName[] = "type";
size_t ToPointerTypeIndex(WebPointerProperties::PointerType t) {
return static_cast<size_t>(t);
}
bool HasPointerEventListener(const EventHandlerRegistry& registry) {
return registry.HasEventHandlers(EventHandlerRegistry::kPointerEvent) ||
registry.HasEventHandlers(
@ -449,7 +451,7 @@ PointerEventManager::ComputePointerEventTarget(
}
} else {
// Set the target of pointer event to the captured element as this
// pointer is captured otherwise it would have gone to the if block
// pointer is captured otherwise it would have gone to the |if| block
// and perform a hit-test.
pointer_event_target.target_element =
pending_pointer_capture_target_.at(pointer_id);
@ -518,8 +520,10 @@ WebInputEventResult PointerEventManager::SendTouchPointerEvent(
ProcessCaptureAndPositionOfPointerEvent(pointer_event, target);
// Setting the implicit capture for touch
if (pointer_event->type() == event_type_names::kPointerdown)
SetPointerCapture(pointer_event->pointerId(), target);
if (pointer_event->type() == event_type_names::kPointerdown) {
SetPointerCapture(pointer_event->pointerId(), target,
/* explicit_capture */ false);
}
WebInputEventResult result = DispatchPointerEvent(
GetEffectiveTargetForPointerEvent(target, pointer_event->pointerId()),
@ -1028,8 +1032,17 @@ void PointerEventManager::ElementRemoved(Element* target) {
}
bool PointerEventManager::SetPointerCapture(PointerId pointer_id,
Element* target) {
UseCounter::Count(frame_->GetDocument(), WebFeature::kPointerEventSetCapture);
Element* target,
bool explicit_capture) {
if (explicit_capture) {
UseCounter::Count(frame_->GetDocument(),
WebFeature::kPointerEventSetCapture);
if (pointer_id == PointerEventFactory::kMouseId &&
target != mouse_event_manager_->MouseDownElement()) {
UseCounter::Count(frame_->GetDocument(),
WebFeature::kExplicitPointerCaptureClickTargetDiff);
}
}
if (pointer_event_factory_.IsActiveButtonsState(pointer_id)) {
if (pointer_id != dispatching_pointer_id_) {
UseCounter::Count(frame_->GetDocument(),

@ -77,7 +77,10 @@ class CORE_EXPORT PointerEventManager final
void ElementRemoved(Element*);
bool SetPointerCapture(PointerId, Element*);
// Starts capturing of all events with the given |PointerId| to the given
// |Element|. The paramenter |explicit_capture| identifies if this call was
// triggered by an explicit |elem.setPointerCapture()| call from JS.
bool SetPointerCapture(PointerId, Element*, bool explicit_capture);
bool ReleasePointerCapture(PointerId, Element*);
void ReleaseMousePointerCapture();

@ -32968,6 +32968,7 @@ Called by update_use_counter_feature_enum.py.-->
<int value="3939" label="XRFrameFillJointRadii"/>
<int value="3940" label="XRFrameFillPoses"/>
<int value="3941" label="WindowOpenNewPopupBehaviorMismatch"/>
<int value="3942" label="ExplicitPointerCaptureClickTargetDiff"/>
</enum>
<enum name="FeaturePolicyAllowlistType">