Commit fef9e5a5 authored by Navid Zolghadr's avatar Navid Zolghadr Committed by Commit Bot

Experiment with sending click as PointerEvent

This CL adds a runtime flag that sends the
click and auxclick events as PointerEvents.

There are more cases to fix such as context menu
events and click from other paths such as
touch and pointerlock.

Bug: 989958
Change-Id: I0e440ceef29e6cad202bc7f07150c7f3b6b35da0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1762792Reviewed-by: default avatarDave Tapuska <dtapuska@chromium.org>
Reviewed-by: default avatarNavid Zolghadr <nzolghadr@chromium.org>
Reviewed-by: default avatarMustaq Ahmed <mustaq@chromium.org>
Reviewed-by: default avatarElla Ge <eirage@chromium.org>
Commit-Queue: Navid Zolghadr <nzolghadr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#693152}
parent 08ed8f83
...@@ -12,8 +12,14 @@ namespace blink { ...@@ -12,8 +12,14 @@ namespace blink {
PointerEvent::PointerEvent(const AtomicString& type, PointerEvent::PointerEvent(const AtomicString& type,
const PointerEventInit* initializer, const PointerEventInit* initializer,
base::TimeTicks platform_time_stamp) base::TimeTicks platform_time_stamp,
: MouseEvent(type, initializer, platform_time_stamp), MouseEvent::SyntheticEventType synthetic_event_type,
WebMenuSourceType menu_source_type)
: MouseEvent(type,
initializer,
platform_time_stamp,
synthetic_event_type,
menu_source_type),
pointer_id_(0), pointer_id_(0),
width_(0), width_(0),
height_(0), height_(0),
...@@ -56,6 +62,13 @@ PointerEvent::PointerEvent(const AtomicString& type, ...@@ -56,6 +62,13 @@ PointerEvent::PointerEvent(const AtomicString& type,
} }
bool PointerEvent::IsMouseEvent() const { bool PointerEvent::IsMouseEvent() const {
if (RuntimeEnabledFeatures::ClickPointerEventEnabled() &&
(type() == event_type_names::kClick ||
type() == event_type_names::kAuxclick ||
type() == event_type_names::kContextmenu)) {
return true;
}
return false; return false;
} }
...@@ -129,6 +142,13 @@ DispatchEventResult PointerEvent::DispatchEvent(EventDispatcher& dispatcher) { ...@@ -129,6 +142,13 @@ DispatchEventResult PointerEvent::DispatchEvent(EventDispatcher& dispatcher) {
if (type().IsEmpty()) if (type().IsEmpty())
return DispatchEventResult::kNotCanceled; // Shouldn't happen. return DispatchEventResult::kNotCanceled; // Shouldn't happen.
if (RuntimeEnabledFeatures::ClickPointerEventEnabled() &&
type() == event_type_names::kClick) {
// The MouseEvent::DispatchEvent will take care of sending dblclick event if
// needed.
return MouseEvent::DispatchEvent(dispatcher);
}
DCHECK(!target() || target() != relatedTarget()); DCHECK(!target() || target() != relatedTarget());
GetEventPath().AdjustForRelatedTarget(dispatcher.GetNode(), relatedTarget()); GetEventPath().AdjustForRelatedTarget(dispatcher.GetNode(), relatedTarget());
......
...@@ -14,11 +14,16 @@ class CORE_EXPORT PointerEvent final : public MouseEvent { ...@@ -14,11 +14,16 @@ class CORE_EXPORT PointerEvent final : public MouseEvent {
DEFINE_WRAPPERTYPEINFO(); DEFINE_WRAPPERTYPEINFO();
public: public:
static PointerEvent* Create(const AtomicString& type, static PointerEvent* Create(
const PointerEventInit* initializer, const AtomicString& type,
base::TimeTicks platform_time_stamp) { const PointerEventInit* initializer,
return MakeGarbageCollected<PointerEvent>(type, initializer, base::TimeTicks platform_time_stamp,
platform_time_stamp); MouseEvent::SyntheticEventType synthetic_event_type =
kRealOrIndistinguishable,
WebMenuSourceType menu_source_type = kMenuSourceNone) {
return MakeGarbageCollected<PointerEvent>(
type, initializer, platform_time_stamp, synthetic_event_type,
menu_source_type);
} }
static PointerEvent* Create(const AtomicString& type, static PointerEvent* Create(const AtomicString& type,
const PointerEventInit* initializer) { const PointerEventInit* initializer) {
...@@ -27,7 +32,9 @@ class CORE_EXPORT PointerEvent final : public MouseEvent { ...@@ -27,7 +32,9 @@ class CORE_EXPORT PointerEvent final : public MouseEvent {
PointerEvent(const AtomicString&, PointerEvent(const AtomicString&,
const PointerEventInit*, const PointerEventInit*,
base::TimeTicks platform_time_stamp); base::TimeTicks platform_time_stamp,
MouseEvent::SyntheticEventType synthetic_event_type,
WebMenuSourceType menu_source_type);
PointerId pointerId() const { return pointer_id_; } PointerId pointerId() const { return pointer_id_; }
double width() const { return width_; } double width() const { return width_; }
......
...@@ -96,6 +96,45 @@ void UpdateMouseMovementXY(const WebMouseEvent& mouse_event, ...@@ -96,6 +96,45 @@ void UpdateMouseMovementXY(const WebMouseEvent& mouse_event,
} }
} }
void SetMouseEventAttributes(MouseEventInit* initializer,
Node* target_node,
const AtomicString& mouse_event_type,
const WebMouseEvent& mouse_event,
const String& canvas_region_id,
const FloatPoint* last_position,
EventTarget* related_target,
int click_count) {
bool is_mouse_enter_or_leave =
mouse_event_type == event_type_names::kMouseenter ||
mouse_event_type == event_type_names::kMouseleave;
initializer->setBubbles(!is_mouse_enter_or_leave);
initializer->setCancelable(!is_mouse_enter_or_leave);
MouseEvent::SetCoordinatesFromWebPointerProperties(
mouse_event.FlattenTransform(), target_node->GetDocument().domWindow(),
initializer);
UpdateMouseMovementXY(mouse_event, last_position,
target_node->GetDocument().domWindow(), initializer);
initializer->setButton(static_cast<int16_t>(mouse_event.button));
initializer->setButtons(
MouseEvent::WebInputEventModifiersToButtons(mouse_event.GetModifiers()));
initializer->setView(target_node->GetDocument().domWindow());
initializer->setComposed(true);
initializer->setDetail(click_count);
initializer->setRegion(canvas_region_id);
initializer->setRelatedTarget(related_target);
UIEventWithKeyState::SetFromWebInputEventModifiers(
initializer,
static_cast<WebInputEvent::Modifiers>(mouse_event.GetModifiers()));
initializer->setSourceCapabilities(
target_node->GetDocument().domWindow()
? target_node->GetDocument()
.domWindow()
->GetInputDeviceCapabilities()
->FiresTouchEvents(mouse_event.FromTouch())
: nullptr);
}
// The amount of time to wait before sending a fake mouse event triggered // The amount of time to wait before sending a fake mouse event triggered
// during a scroll. // during a scroll.
constexpr base::TimeDelta kFakeMouseMoveIntervalDuringScroll = constexpr base::TimeDelta kFakeMouseMoveIntervalDuringScroll =
...@@ -248,7 +287,20 @@ WebInputEventResult MouseEventManager::DispatchMouseEvent( ...@@ -248,7 +287,20 @@ WebInputEventResult MouseEventManager::DispatchMouseEvent(
const String& canvas_region_id, const String& canvas_region_id,
const FloatPoint* last_position, const FloatPoint* last_position,
EventTarget* related_target, EventTarget* related_target,
bool check_for_listener) { bool check_for_listener,
const PointerId& pointer_id,
const String& pointer_type) {
DCHECK(mouse_event_type == event_type_names::kMouseup ||
mouse_event_type == event_type_names::kMousedown ||
mouse_event_type == event_type_names::kMousemove ||
mouse_event_type == event_type_names::kMouseout ||
mouse_event_type == event_type_names::kMouseover ||
mouse_event_type == event_type_names::kMouseleave ||
mouse_event_type == event_type_names::kMouseenter ||
mouse_event_type == event_type_names::kContextmenu ||
mouse_event_type == event_type_names::kClick ||
mouse_event_type == event_type_names::kAuxclick);
if (target && target->ToNode() && if (target && target->ToNode() &&
(!check_for_listener || target->HasEventListeners(mouse_event_type))) { (!check_for_listener || target->HasEventListeners(mouse_event_type))) {
Node* target_node = target->ToNode(); Node* target_node = target->ToNode();
...@@ -256,47 +308,42 @@ WebInputEventResult MouseEventManager::DispatchMouseEvent( ...@@ -256,47 +308,42 @@ WebInputEventResult MouseEventManager::DispatchMouseEvent(
if (mouse_event_type == event_type_names::kMouseup || if (mouse_event_type == event_type_names::kMouseup ||
mouse_event_type == event_type_names::kMousedown || mouse_event_type == event_type_names::kMousedown ||
mouse_event_type == event_type_names::kClick || mouse_event_type == event_type_names::kClick ||
mouse_event_type == event_type_names::kAuxclick || mouse_event_type == event_type_names::kAuxclick) {
mouse_event_type == event_type_names::kDblclick) {
click_count = click_count_; click_count = click_count_;
} }
bool is_mouse_enter_or_leave =
mouse_event_type == event_type_names::kMouseenter || DispatchEventResult dispatch_result;
mouse_event_type == event_type_names::kMouseleave;
MouseEventInit* initializer = MouseEventInit::Create(); if (RuntimeEnabledFeatures::ClickPointerEventEnabled() &&
initializer->setBubbles(!is_mouse_enter_or_leave); (mouse_event_type == event_type_names::kContextmenu ||
initializer->setCancelable(!is_mouse_enter_or_leave); mouse_event_type == event_type_names::kClick ||
MouseEvent::SetCoordinatesFromWebPointerProperties( mouse_event_type == event_type_names::kAuxclick)) {
mouse_event.FlattenTransform(), target_node->GetDocument().domWindow(), PointerEventInit* initializer = PointerEventInit::Create();
initializer); SetMouseEventAttributes(initializer, target_node, mouse_event_type,
UpdateMouseMovementXY(mouse_event, last_position, mouse_event, canvas_region_id, last_position,
target_node->GetDocument().domWindow(), initializer); related_target, click_count);
initializer->setButton(static_cast<int16_t>(mouse_event.button)); initializer->setPointerId(pointer_id);
initializer->setButtons(MouseEvent::WebInputEventModifiersToButtons( initializer->setPointerType(pointer_type);
mouse_event.GetModifiers())); PointerEvent* event = PointerEvent::Create(
initializer->setView(target_node->GetDocument().domWindow()); mouse_event_type, initializer, mouse_event.TimeStamp(),
initializer->setComposed(true); mouse_event.FromTouch() ? MouseEvent::kFromTouch
initializer->setDetail(click_count); : MouseEvent::kRealOrIndistinguishable,
initializer->setRegion(canvas_region_id); mouse_event.menu_source_type);
initializer->setRelatedTarget(related_target); dispatch_result = target->DispatchEvent(*event);
UIEventWithKeyState::SetFromWebInputEventModifiers( } else {
initializer, MouseEventInit* initializer = MouseEventInit::Create();
static_cast<WebInputEvent::Modifiers>(mouse_event.GetModifiers())); SetMouseEventAttributes(initializer, target_node, mouse_event_type,
initializer->setSourceCapabilities( mouse_event, canvas_region_id, last_position,
target_node->GetDocument().domWindow() related_target, click_count);
? target_node->GetDocument() MouseEvent* event = MouseEvent::Create(
.domWindow() mouse_event_type, initializer, mouse_event.TimeStamp(),
->GetInputDeviceCapabilities() mouse_event.FromTouch() ? MouseEvent::kFromTouch
->FiresTouchEvents(mouse_event.FromTouch()) : MouseEvent::kRealOrIndistinguishable,
: nullptr); mouse_event.menu_source_type);
MouseEvent* event = MouseEvent::Create( dispatch_result = target->DispatchEvent(*event);
mouse_event_type, initializer, mouse_event.TimeStamp(), }
mouse_event.FromTouch() ? MouseEvent::kFromTouch
: MouseEvent::kRealOrIndistinguishable,
mouse_event.menu_source_type);
DispatchEventResult dispatch_result = target->DispatchEvent(*event);
return event_handling_util::ToWebInputEventResult(dispatch_result); return event_handling_util::ToWebInputEventResult(dispatch_result);
} }
return WebInputEventResult::kNotHandled; return WebInputEventResult::kNotHandled;
...@@ -315,7 +362,9 @@ WebInputEventResult MouseEventManager::SetMousePositionAndDispatchMouseEvent( ...@@ -315,7 +362,9 @@ WebInputEventResult MouseEventManager::SetMousePositionAndDispatchMouseEvent(
WebInputEventResult MouseEventManager::DispatchMouseClickIfNeeded( WebInputEventResult MouseEventManager::DispatchMouseClickIfNeeded(
Element* mouse_release_target, Element* mouse_release_target,
const WebMouseEvent& mouse_event, const WebMouseEvent& mouse_event,
const String& canvas_region_id) { const String& canvas_region_id,
const PointerId& pointer_id,
const String& pointer_type) {
// We only prevent click event when the click may cause contextmenu to popup. // We only prevent click event when the click may cause contextmenu to popup.
// However, we always send auxclick. // However, we always send auxclick.
bool context_menu_event = false; bool context_menu_event = false;
...@@ -382,7 +431,8 @@ WebInputEventResult MouseEventManager::DispatchMouseClickIfNeeded( ...@@ -382,7 +431,8 @@ WebInputEventResult MouseEventManager::DispatchMouseClickIfNeeded(
(mouse_event.button == WebPointerProperties::Button::kLeft) (mouse_event.button == WebPointerProperties::Button::kLeft)
? event_type_names::kClick ? event_type_names::kClick
: event_type_names::kAuxclick, : event_type_names::kAuxclick,
mouse_event, canvas_region_id, nullptr, nullptr); mouse_event, canvas_region_id, nullptr, nullptr, false, pointer_id,
pointer_type);
} }
return WebInputEventResult::kNotHandled; return WebInputEventResult::kNotHandled;
......
...@@ -50,7 +50,9 @@ class CORE_EXPORT MouseEventManager final ...@@ -50,7 +50,9 @@ class CORE_EXPORT MouseEventManager final
const String& canvas_region_id, const String& canvas_region_id,
const FloatPoint* last_position, const FloatPoint* last_position,
EventTarget* related_target, EventTarget* related_target,
bool check_for_listener = false); bool check_for_listener = false,
const PointerId& pointer_id = 0,
const String& pointer_type = "");
WebInputEventResult SetMousePositionAndDispatchMouseEvent( WebInputEventResult SetMousePositionAndDispatchMouseEvent(
Element* target_element, Element* target_element,
...@@ -61,7 +63,9 @@ class CORE_EXPORT MouseEventManager final ...@@ -61,7 +63,9 @@ class CORE_EXPORT MouseEventManager final
WebInputEventResult DispatchMouseClickIfNeeded( WebInputEventResult DispatchMouseClickIfNeeded(
Element* mouse_release_target, Element* mouse_release_target,
const WebMouseEvent& mouse_event, const WebMouseEvent& mouse_event,
const String& canvas_region_id); const String& canvas_region_id,
const PointerId& pointer_id,
const String& pointer_type);
WebInputEventResult DispatchDragSrcEvent(const AtomicString& event_type, WebInputEventResult DispatchDragSrcEvent(const AtomicString& event_type,
const WebMouseEvent&); const WebMouseEvent&);
......
...@@ -828,7 +828,8 @@ WebInputEventResult PointerEventManager::SendMousePointerEvent( ...@@ -828,7 +828,8 @@ WebInputEventResult PointerEventManager::SendMousePointerEvent(
if (!skip_click_dispatch && mouse_target && if (!skip_click_dispatch && mouse_target &&
event_type == WebInputEvent::kPointerUp) { event_type == WebInputEvent::kPointerUp) {
mouse_event_manager_->DispatchMouseClickIfNeeded( mouse_event_manager_->DispatchMouseClickIfNeeded(
mouse_target, mouse_event, canvas_region_id); mouse_target, mouse_event, canvas_region_id,
pointer_event->pointerId(), pointer_event->pointerType());
} }
} }
......
...@@ -267,6 +267,10 @@ ...@@ -267,6 +267,10 @@
name: "CanvasImageSmoothing", name: "CanvasImageSmoothing",
status: "experimental", status: "experimental",
}, },
{
name: "ClickPointerEvent",
status: "experimental",
},
{ {
name: "ClickRetargetting", name: "ClickRetargetting",
status: "experimental", status: "experimental",
......
...@@ -5,10 +5,10 @@ PASS event.pageX is 100 ...@@ -5,10 +5,10 @@ PASS event.pageX is 100
PASS event.pageY is 100 PASS event.pageY is 100
Just zoomed Just zoomed
PASS event.clientX is 83 FAIL event.clientX should be 83. Was 83.33332824707031.
PASS event.clientY is 83 FAIL event.clientY should be 83. Was 83.33332824707031.
PASS event.pageX is 83 FAIL event.pageX should be 83. Was 83.33332824707031.
PASS event.pageY is 83 FAIL event.pageY should be 83. Was 83.33332824707031.
Just scrolled Just scrolled
PASS event.clientX is 100 PASS event.clientX is 100
...@@ -17,10 +17,10 @@ PASS event.pageX is 150 ...@@ -17,10 +17,10 @@ PASS event.pageX is 150
PASS event.pageY is 150 PASS event.pageY is 150
Zoomed and scrolled Zoomed and scrolled
PASS event.clientX is 83 FAIL event.clientX should be 83. Was 83.33332824707031.
PASS event.clientY is 83 FAIL event.clientY should be 83. Was 83.33332824707031.
PASS event.pageX is 133 FAIL event.pageX should be 133. Was 133.33332443237305.
PASS event.pageY is 133 FAIL event.pageY should be 133. Was 133.33332443237305.
RTL and scrolled RTL and scrolled
PASS event.clientX is 100 PASS event.clientX is 100
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment