From 66ee08c3dc97dda9822f90565ff1c58524956736 Mon Sep 17 00:00:00 2001 From: Itamar Date: Sat, 31 Dec 2022 16:04:48 +0200 Subject: [PATCH] LibWeb: Fix calculation of MouseEvent::client_{x,y} MouseEvent.client{X,Y} should be relative to the viewport. --- .../Libraries/LibWeb/Page/EventHandler.cpp | 23 +++++++++++++++---- Userland/Libraries/LibWeb/Page/EventHandler.h | 1 + 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp index b2e46c4338..ef188bb7d3 100644 --- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp @@ -247,12 +247,13 @@ bool EventHandler::handle_mouseup(CSSPixelPoint position, unsigned button, unsig } auto offset = compute_mouse_event_offset(position, *layout_node); - node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::mouseup, offset.x(), offset.y(), position.x(), position.y(), buttons, button)); + auto client_offset = compute_mouse_event_client_offset(position); + node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::mouseup, offset.x(), offset.y(), client_offset.x(), client_offset.y(), buttons, button)); handled_event = true; bool run_activation_behavior = true; if (node.ptr() == m_mousedown_target && button == GUI::MouseButton::Primary) { - run_activation_behavior = node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::click, offset.x(), offset.y(), position.x(), position.y(), button)); + run_activation_behavior = node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::click, offset.x(), offset.y(), client_offset.x(), client_offset.y(), button)); } if (run_activation_behavior) { @@ -368,7 +369,8 @@ bool EventHandler::handle_mousedown(CSSPixelPoint position, unsigned button, uns m_mousedown_target = node.ptr(); auto offset = compute_mouse_event_offset(position, *layout_node); - node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::mousedown, offset.x(), offset.y(), position.x(), position.y(), buttons, button)); + auto client_offset = compute_mouse_event_client_offset(position); + node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::mousedown, offset.x(), offset.y(), client_offset.x(), client_offset.y(), buttons, button)); } // NOTE: Dispatching an event may have disturbed the world. @@ -480,7 +482,8 @@ bool EventHandler::handle_mousemove(CSSPixelPoint position, unsigned buttons, un } auto offset = compute_mouse_event_offset(position, *layout_node); - node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::mousemove, offset.x(), offset.y(), position.x(), position.y(), buttons)); + auto client_offset = compute_mouse_event_client_offset(position); + node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::mousemove, offset.x(), offset.y(), client_offset.x(), client_offset.y(), buttons)); // NOTE: Dispatching an event may have disturbed the world. if (!paint_root() || paint_root() != node->document().paint_box()) return true; @@ -561,7 +564,8 @@ bool EventHandler::handle_doubleclick(CSSPixelPoint position, unsigned button, u return false; auto offset = compute_mouse_event_offset(position, *layout_node); - node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::dblclick, offset.x(), offset.y(), position.x(), position.y(), buttons, button)); + auto client_offset = compute_mouse_event_client_offset(position); + node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::dblclick, offset.x(), offset.y(), client_offset.x(), client_offset.y(), buttons, button)); // NOTE: Dispatching an event may have disturbed the world. if (!paint_root() || paint_root() != node->document().paint_box()) @@ -785,4 +789,13 @@ void EventHandler::set_mouse_event_tracking_layout_node(Layout::Node* layout_nod m_mouse_event_tracking_layout_node = layout_node; } +CSSPixelPoint EventHandler::compute_mouse_event_client_offset(CSSPixelPoint event_page_position) const +{ + // https://w3c.github.io/csswg-drafts/cssom-view/#dom-mouseevent-clientx + // The clientX attribute must return the x-coordinate of the position where the event occurred relative to the origin of the viewport. + + auto scroll_offset = m_browsing_context.viewport_scroll_offset(); + return event_page_position.translated(-scroll_offset.to_rounded()); +} + } diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.h b/Userland/Libraries/LibWeb/Page/EventHandler.h index ee1de0cbda..b482c52484 100644 --- a/Userland/Libraries/LibWeb/Page/EventHandler.h +++ b/Userland/Libraries/LibWeb/Page/EventHandler.h @@ -41,6 +41,7 @@ private: bool focus_previous_element(); bool fire_keyboard_event(FlyString const& event_name, HTML::BrowsingContext& browsing_context, KeyCode key, unsigned modifiers, u32 code_point); + CSSPixelPoint compute_mouse_event_client_offset(CSSPixelPoint event_page_position) const; Layout::InitialContainingBlock* layout_root(); Layout::InitialContainingBlock const* layout_root() const;