Ladybird+LibWeb: Add MouseEvent screenX and screenY support

This commit is contained in:
Bastiaan van der Plaat 2023-09-08 18:48:44 +02:00 committed by Alexander Kalenik
parent e584189b8f
commit 836a7b00dd
19 changed files with 125 additions and 103 deletions

View file

@ -10,7 +10,7 @@
<script>
function handle(e) {
var out = document.getElementById('out');
out.innerHTML = e.type + ' @ ' + e.offsetX + ',' + e.y + '\n' + out.innerHTML;
out.innerHTML = `${e.type} | client: ${e.clientX}x${e.y} | screen: ${e.screenX}x${e.screenY}\n${out.innerHTML}`;
}
var rect = document.getElementById('rect');

View file

@ -16,6 +16,7 @@ namespace Ladybird {
struct MouseEvent {
Gfx::IntPoint position {};
Gfx::IntPoint screen_position {};
GUI::MouseButton button { GUI::MouseButton::Primary };
KeyModifier modifiers { KeyModifier::Mod_None };
};

View file

@ -39,9 +39,10 @@ static KeyModifier ns_modifiers_to_key_modifiers(NSEventModifierFlags modifier_f
MouseEvent ns_event_to_mouse_event(NSEvent* event, NSView* view, GUI::MouseButton button)
{
auto position = [view convertPoint:event.locationInWindow fromView:nil];
auto screen_position = [NSEvent mouseLocation];
auto modifiers = ns_modifiers_to_key_modifiers(event.modifierFlags, button);
return { ns_point_to_gfx_point(position), button, modifiers };
return { ns_point_to_gfx_point(position), ns_point_to_gfx_point(screen_position), button, modifiers };
}
NSEvent* create_context_menu_mouse_event(NSView* view, Gfx::IntPoint position)

View file

@ -956,58 +956,58 @@ static void copy_text_to_clipboard(StringView text)
- (void)mouseMoved:(NSEvent*)event
{
auto [position, button, modifiers] = Ladybird::ns_event_to_mouse_event(event, self, GUI::MouseButton::None);
m_web_view_bridge->mouse_move_event(position, button, modifiers);
auto [position, screen_position, button, modifiers] = Ladybird::ns_event_to_mouse_event(event, self, GUI::MouseButton::None);
m_web_view_bridge->mouse_move_event(position, screen_position, button, modifiers);
}
- (void)mouseDown:(NSEvent*)event
{
[[self window] makeFirstResponder:self];
auto [position, button, modifiers] = Ladybird::ns_event_to_mouse_event(event, self, GUI::MouseButton::Primary);
auto [position, screen_position, button, modifiers] = Ladybird::ns_event_to_mouse_event(event, self, GUI::MouseButton::Primary);
if (event.clickCount % 2 == 0) {
m_web_view_bridge->mouse_double_click_event(position, button, modifiers);
m_web_view_bridge->mouse_double_click_event(position, screen_position, button, modifiers);
} else {
m_web_view_bridge->mouse_down_event(position, button, modifiers);
m_web_view_bridge->mouse_down_event(position, screen_position, button, modifiers);
}
}
- (void)mouseUp:(NSEvent*)event
{
auto [position, button, modifiers] = Ladybird::ns_event_to_mouse_event(event, self, GUI::MouseButton::Primary);
m_web_view_bridge->mouse_up_event(position, button, modifiers);
auto [position, screen_position, button, modifiers] = Ladybird::ns_event_to_mouse_event(event, self, GUI::MouseButton::Primary);
m_web_view_bridge->mouse_up_event(position, screen_position, button, modifiers);
}
- (void)mouseDragged:(NSEvent*)event
{
auto [position, button, modifiers] = Ladybird::ns_event_to_mouse_event(event, self, GUI::MouseButton::Primary);
m_web_view_bridge->mouse_move_event(position, button, modifiers);
auto [position, screen_position, button, modifiers] = Ladybird::ns_event_to_mouse_event(event, self, GUI::MouseButton::Primary);
m_web_view_bridge->mouse_move_event(position, screen_position, button, modifiers);
}
- (void)rightMouseDown:(NSEvent*)event
{
[[self window] makeFirstResponder:self];
auto [position, button, modifiers] = Ladybird::ns_event_to_mouse_event(event, self, GUI::MouseButton::Secondary);
auto [position, screen_position, button, modifiers] = Ladybird::ns_event_to_mouse_event(event, self, GUI::MouseButton::Secondary);
if (event.clickCount % 2 == 0) {
m_web_view_bridge->mouse_double_click_event(position, button, modifiers);
m_web_view_bridge->mouse_double_click_event(position, screen_position, button, modifiers);
} else {
m_web_view_bridge->mouse_down_event(position, button, modifiers);
m_web_view_bridge->mouse_down_event(position, screen_position, button, modifiers);
}
}
- (void)rightMouseUp:(NSEvent*)event
{
auto [position, button, modifiers] = Ladybird::ns_event_to_mouse_event(event, self, GUI::MouseButton::Secondary);
m_web_view_bridge->mouse_up_event(position, button, modifiers);
auto [position, screen_position, button, modifiers] = Ladybird::ns_event_to_mouse_event(event, self, GUI::MouseButton::Secondary);
m_web_view_bridge->mouse_up_event(position, screen_position, button, modifiers);
}
- (void)rightMouseDragged:(NSEvent*)event
{
auto [position, button, modifiers] = Ladybird::ns_event_to_mouse_event(event, self, GUI::MouseButton::Secondary);
m_web_view_bridge->mouse_move_event(position, button, modifiers);
auto [position, screen_position, button, modifiers] = Ladybird::ns_event_to_mouse_event(event, self, GUI::MouseButton::Secondary);
m_web_view_bridge->mouse_move_event(position, screen_position, button, modifiers);
}
- (void)keyDown:(NSEvent*)event

View file

@ -100,24 +100,24 @@ void WebViewBridge::set_preferred_color_scheme(Web::CSS::PreferredColorScheme co
client().async_set_preferred_color_scheme(color_scheme);
}
void WebViewBridge::mouse_down_event(Gfx::IntPoint position, GUI::MouseButton button, KeyModifier modifiers)
void WebViewBridge::mouse_down_event(Gfx::IntPoint position, Gfx::IntPoint screen_position, GUI::MouseButton button, KeyModifier modifiers)
{
client().async_mouse_down(to_content_position(position), to_underlying(button), to_underlying(button), modifiers);
client().async_mouse_down(to_content_position(position), screen_position, to_underlying(button), to_underlying(button), modifiers);
}
void WebViewBridge::mouse_up_event(Gfx::IntPoint position, GUI::MouseButton button, KeyModifier modifiers)
void WebViewBridge::mouse_up_event(Gfx::IntPoint position, Gfx::IntPoint screen_position, GUI::MouseButton button, KeyModifier modifiers)
{
client().async_mouse_up(to_content_position(position), to_underlying(button), to_underlying(button), modifiers);
client().async_mouse_up(to_content_position(position), screen_position, to_underlying(button), to_underlying(button), modifiers);
}
void WebViewBridge::mouse_move_event(Gfx::IntPoint position, GUI::MouseButton button, KeyModifier modifiers)
void WebViewBridge::mouse_move_event(Gfx::IntPoint position, Gfx::IntPoint screen_position, GUI::MouseButton button, KeyModifier modifiers)
{
client().async_mouse_move(to_content_position(position), 0, to_underlying(button), modifiers);
client().async_mouse_move(to_content_position(position), screen_position, 0, to_underlying(button), modifiers);
}
void WebViewBridge::mouse_double_click_event(Gfx::IntPoint position, GUI::MouseButton button, KeyModifier modifiers)
void WebViewBridge::mouse_double_click_event(Gfx::IntPoint position, Gfx::IntPoint screen_position, GUI::MouseButton button, KeyModifier modifiers)
{
client().async_doubleclick(to_content_position(position), button, to_underlying(button), modifiers);
client().async_doubleclick(to_content_position(position), screen_position, button, to_underlying(button), modifiers);
}
void WebViewBridge::key_down_event(KeyCode key_code, KeyModifier modifiers, u32 code_point)

View file

@ -39,10 +39,10 @@ public:
void update_palette();
void set_preferred_color_scheme(Web::CSS::PreferredColorScheme);
void mouse_down_event(Gfx::IntPoint, GUI::MouseButton, KeyModifier);
void mouse_up_event(Gfx::IntPoint, GUI::MouseButton, KeyModifier);
void mouse_move_event(Gfx::IntPoint, GUI::MouseButton, KeyModifier);
void mouse_double_click_event(Gfx::IntPoint, GUI::MouseButton, KeyModifier);
void mouse_down_event(Gfx::IntPoint, Gfx::IntPoint, GUI::MouseButton, KeyModifier);
void mouse_up_event(Gfx::IntPoint, Gfx::IntPoint, GUI::MouseButton, KeyModifier);
void mouse_move_event(Gfx::IntPoint, Gfx::IntPoint, GUI::MouseButton, KeyModifier);
void mouse_double_click_event(Gfx::IntPoint, Gfx::IntPoint, GUI::MouseButton, KeyModifier);
void key_down_event(KeyCode, KeyModifier, u32);
void key_up_event(KeyCode, KeyModifier, u32);

View file

@ -325,13 +325,14 @@ void WebContentView::wheelEvent(QWheelEvent* event)
{
if (!event->modifiers().testFlag(Qt::ControlModifier)) {
Gfx::IntPoint position(event->position().x() / m_inverse_pixel_scaling_ratio, event->position().y() / m_inverse_pixel_scaling_ratio);
Gfx::IntPoint screen_position(event->globalPosition().x() / m_inverse_pixel_scaling_ratio, event->globalPosition().y() / m_inverse_pixel_scaling_ratio);
auto button = get_button_from_qt_event(*event);
auto buttons = get_buttons_from_qt_event(*event);
auto modifiers = get_modifiers_from_qt_mouse_event(*event);
auto num_pixels = -event->pixelDelta();
if (!num_pixels.isNull()) {
client().async_mouse_wheel(to_content_position(position), button, buttons, modifiers, num_pixels.x(), num_pixels.y());
client().async_mouse_wheel(to_content_position(position), screen_position, button, buttons, modifiers, num_pixels.x(), num_pixels.y());
} else {
auto num_degrees = -event->angleDelta();
float delta_x = -num_degrees.x() / 120;
@ -339,7 +340,7 @@ void WebContentView::wheelEvent(QWheelEvent* event)
auto step_x = delta_x * QApplication::wheelScrollLines() * devicePixelRatio();
auto step_y = delta_y * QApplication::wheelScrollLines() * devicePixelRatio();
int scroll_step_size = verticalScrollBar()->singleStep();
client().async_mouse_wheel(to_content_position(position), button, buttons, modifiers, step_x * scroll_step_size, step_y * scroll_step_size);
client().async_mouse_wheel(to_content_position(position), screen_position, button, buttons, modifiers, step_x * scroll_step_size, step_y * scroll_step_size);
}
event->accept();
return;
@ -350,14 +351,16 @@ void WebContentView::wheelEvent(QWheelEvent* event)
void WebContentView::mouseMoveEvent(QMouseEvent* event)
{
Gfx::IntPoint position(event->position().x() / m_inverse_pixel_scaling_ratio, event->position().y() / m_inverse_pixel_scaling_ratio);
Gfx::IntPoint screen_position(event->globalPosition().x() / m_inverse_pixel_scaling_ratio, event->globalPosition().y() / m_inverse_pixel_scaling_ratio);
auto buttons = get_buttons_from_qt_event(*event);
auto modifiers = get_modifiers_from_qt_mouse_event(*event);
client().async_mouse_move(to_content_position(position), 0, buttons, modifiers);
client().async_mouse_move(to_content_position(position), screen_position, 0, buttons, modifiers);
}
void WebContentView::mousePressEvent(QMouseEvent* event)
{
Gfx::IntPoint position(event->position().x() / m_inverse_pixel_scaling_ratio, event->position().y() / m_inverse_pixel_scaling_ratio);
Gfx::IntPoint screen_position(event->globalPosition().x() / m_inverse_pixel_scaling_ratio, event->globalPosition().y() / m_inverse_pixel_scaling_ratio);
auto button = get_button_from_qt_event(*event);
if (button == 0) {
// We could not convert Qt buttons to something that Lagom can
@ -367,12 +370,13 @@ void WebContentView::mousePressEvent(QMouseEvent* event)
}
auto modifiers = get_modifiers_from_qt_mouse_event(*event);
auto buttons = get_buttons_from_qt_event(*event);
client().async_mouse_down(to_content_position(position), button, buttons, modifiers);
client().async_mouse_down(to_content_position(position), screen_position, button, buttons, modifiers);
}
void WebContentView::mouseReleaseEvent(QMouseEvent* event)
{
Gfx::IntPoint position(event->position().x() / m_inverse_pixel_scaling_ratio, event->position().y() / m_inverse_pixel_scaling_ratio);
Gfx::IntPoint screen_position(event->globalPosition().x() / m_inverse_pixel_scaling_ratio, event->globalPosition().y() / m_inverse_pixel_scaling_ratio);
auto button = get_button_from_qt_event(*event);
if (event->button() & Qt::MouseButton::BackButton) {
@ -391,12 +395,13 @@ void WebContentView::mouseReleaseEvent(QMouseEvent* event)
}
auto modifiers = get_modifiers_from_qt_mouse_event(*event);
auto buttons = get_buttons_from_qt_event(*event);
client().async_mouse_up(to_content_position(position), button, buttons, modifiers);
client().async_mouse_up(to_content_position(position), screen_position, button, buttons, modifiers);
}
void WebContentView::mouseDoubleClickEvent(QMouseEvent* event)
{
Gfx::IntPoint position(event->position().x() / m_inverse_pixel_scaling_ratio, event->position().y() / m_inverse_pixel_scaling_ratio);
Gfx::IntPoint screen_position(event->globalPosition().x() / m_inverse_pixel_scaling_ratio, event->globalPosition().y() / m_inverse_pixel_scaling_ratio);
auto button = get_button_from_qt_event(*event);
if (button == 0) {
// We could not convert Qt buttons to something that Lagom can
@ -406,7 +411,7 @@ void WebContentView::mouseDoubleClickEvent(QMouseEvent* event)
}
auto modifiers = get_modifiers_from_qt_mouse_event(*event);
auto buttons = get_buttons_from_qt_event(*event);
client().async_doubleclick(to_content_position(position), button, buttons, modifiers);
client().async_doubleclick(to_content_position(position), screen_position, button, buttons, modifiers);
}
void WebContentView::dragEnterEvent(QDragEnterEvent* event)

View file

@ -144,7 +144,7 @@ Painting::PaintableBox const* EventHandler::paint_root() const
return m_browsing_context->active_document()->paintable_box();
}
bool EventHandler::handle_mousewheel(CSSPixelPoint position, unsigned button, unsigned buttons, unsigned int modifiers, int wheel_delta_x, int wheel_delta_y)
bool EventHandler::handle_mousewheel(CSSPixelPoint position, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned int modifiers, int wheel_delta_x, int wheel_delta_y)
{
if (m_browsing_context->active_document())
m_browsing_context->active_document()->update_layout();
@ -189,7 +189,7 @@ bool EventHandler::handle_mousewheel(CSSPixelPoint position, unsigned button, un
auto offset = compute_mouse_event_offset(position, *layout_node);
auto client_offset = compute_mouse_event_client_offset(position);
auto page_offset = compute_mouse_event_page_offset(client_offset);
if (node->dispatch_event(UIEvents::WheelEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::wheel, page_offset, client_offset, offset, wheel_delta_x, wheel_delta_y, button, buttons).release_value_but_fixme_should_propagate_errors())) {
if (node->dispatch_event(UIEvents::WheelEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::wheel, screen_position, page_offset, client_offset, offset, wheel_delta_x, wheel_delta_y, button, buttons).release_value_but_fixme_should_propagate_errors())) {
if (auto* page = m_browsing_context->page()) {
if (m_browsing_context == &page->top_level_browsing_context())
page->client().page_did_request_scroll(wheel_delta_x, wheel_delta_y);
@ -203,7 +203,7 @@ bool EventHandler::handle_mousewheel(CSSPixelPoint position, unsigned button, un
return handled_event;
}
bool EventHandler::handle_mouseup(CSSPixelPoint position, unsigned button, unsigned buttons, unsigned modifiers)
bool EventHandler::handle_mouseup(CSSPixelPoint position, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers)
{
if (m_browsing_context->active_document())
m_browsing_context->active_document()->update_layout();
@ -234,7 +234,7 @@ bool EventHandler::handle_mouseup(CSSPixelPoint position, unsigned button, unsig
if (node) {
if (is<HTML::HTMLIFrameElement>(*node)) {
if (auto* nested_browsing_context = static_cast<HTML::HTMLIFrameElement&>(*node).nested_browsing_context())
return nested_browsing_context->event_handler().handle_mouseup(position.translated(compute_mouse_event_offset({}, paintable->layout_node())), button, buttons, modifiers);
return nested_browsing_context->event_handler().handle_mouseup(position.translated(compute_mouse_event_offset({}, paintable->layout_node())), screen_position, button, buttons, modifiers);
return false;
}
@ -250,15 +250,15 @@ bool EventHandler::handle_mouseup(CSSPixelPoint position, unsigned button, unsig
auto offset = compute_mouse_event_offset(position, *layout_node);
auto client_offset = compute_mouse_event_client_offset(position);
auto page_offset = compute_mouse_event_page_offset(client_offset);
node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::mouseup, page_offset, client_offset, offset, {}, button, buttons).release_value_but_fixme_should_propagate_errors());
node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::mouseup, screen_position, page_offset, client_offset, offset, {}, button, buttons).release_value_but_fixme_should_propagate_errors());
handled_event = true;
bool run_activation_behavior = false;
if (node.ptr() == m_mousedown_target) {
if (button == GUI::MouseButton::Primary)
run_activation_behavior = node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::click, page_offset, client_offset, offset, {}, 1, button).release_value_but_fixme_should_propagate_errors());
run_activation_behavior = node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::click, screen_position, page_offset, client_offset, offset, {}, 1, button).release_value_but_fixme_should_propagate_errors());
else if (button == GUI::MouseButton::Secondary && !(modifiers & Mod_Shift)) // Allow the user to bypass custom context menus by holding shift, like Firefox.
run_activation_behavior = node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::contextmenu, page_offset, client_offset, offset, {}, 1, button).release_value_but_fixme_should_propagate_errors());
run_activation_behavior = node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::contextmenu, screen_position, page_offset, client_offset, offset, {}, 1, button).release_value_but_fixme_should_propagate_errors());
}
if (run_activation_behavior) {
@ -333,7 +333,7 @@ after_node_use:
return handled_event;
}
bool EventHandler::handle_mousedown(CSSPixelPoint position, unsigned button, unsigned buttons, unsigned modifiers)
bool EventHandler::handle_mousedown(CSSPixelPoint position, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers)
{
if (m_browsing_context->active_document())
m_browsing_context->active_document()->update_layout();
@ -368,7 +368,7 @@ bool EventHandler::handle_mousedown(CSSPixelPoint position, unsigned button, uns
if (is<HTML::HTMLIFrameElement>(*node)) {
if (auto* nested_browsing_context = static_cast<HTML::HTMLIFrameElement&>(*node).nested_browsing_context())
return nested_browsing_context->event_handler().handle_mousedown(position.translated(compute_mouse_event_offset({}, paintable->layout_node())), button, buttons, modifiers);
return nested_browsing_context->event_handler().handle_mousedown(position.translated(compute_mouse_event_offset({}, paintable->layout_node())), screen_position, button, buttons, modifiers);
return false;
}
@ -386,7 +386,7 @@ bool EventHandler::handle_mousedown(CSSPixelPoint position, unsigned button, uns
auto offset = compute_mouse_event_offset(position, *layout_node);
auto client_offset = compute_mouse_event_client_offset(position);
auto page_offset = compute_mouse_event_page_offset(client_offset);
node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::mousedown, page_offset, client_offset, offset, {}, button, buttons).release_value_but_fixme_should_propagate_errors());
node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::mousedown, screen_position, page_offset, client_offset, offset, {}, button, buttons).release_value_but_fixme_should_propagate_errors());
}
// NOTE: Dispatching an event may have disturbed the world.
@ -424,7 +424,7 @@ bool EventHandler::handle_mousedown(CSSPixelPoint position, unsigned button, uns
return true;
}
bool EventHandler::handle_mousemove(CSSPixelPoint position, unsigned buttons, unsigned modifiers)
bool EventHandler::handle_mousemove(CSSPixelPoint position, CSSPixelPoint screen_position, unsigned buttons, unsigned modifiers)
{
if (m_browsing_context->active_document())
m_browsing_context->active_document()->update_layout();
@ -462,7 +462,7 @@ bool EventHandler::handle_mousemove(CSSPixelPoint position, unsigned buttons, un
if (node && is<HTML::HTMLIFrameElement>(*node)) {
if (auto* nested_browsing_context = static_cast<HTML::HTMLIFrameElement&>(*node).nested_browsing_context())
return nested_browsing_context->event_handler().handle_mousemove(position.translated(compute_mouse_event_offset({}, paintable->layout_node())), buttons, modifiers);
return nested_browsing_context->event_handler().handle_mousemove(position.translated(compute_mouse_event_offset({}, paintable->layout_node())), screen_position, buttons, modifiers);
return false;
}
@ -499,9 +499,9 @@ bool EventHandler::handle_mousemove(CSSPixelPoint position, unsigned buttons, un
auto offset = compute_mouse_event_offset(position, *layout_node);
auto client_offset = compute_mouse_event_client_offset(position);
auto page_offset = compute_mouse_event_page_offset(client_offset);
auto movement = compute_mouse_event_movement(client_offset);
node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::mousemove, page_offset, client_offset, offset, movement, 1, buttons).release_value_but_fixme_should_propagate_errors());
m_mousemove_previous_client_offset = client_offset;
auto movement = compute_mouse_event_movement(screen_position);
node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::mousemove, screen_position, page_offset, client_offset, offset, movement, 1, buttons).release_value_but_fixme_should_propagate_errors());
m_mousemove_previous_screen_position = screen_position;
// NOTE: Dispatching an event may have disturbed the world.
if (!paint_root() || paint_root() != node->document().paintable_box())
return true;
@ -543,7 +543,7 @@ bool EventHandler::handle_mousemove(CSSPixelPoint position, unsigned buttons, un
return true;
}
bool EventHandler::handle_doubleclick(CSSPixelPoint position, unsigned button, unsigned buttons, unsigned modifiers)
bool EventHandler::handle_doubleclick(CSSPixelPoint position, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers)
{
if (m_browsing_context->active_document())
m_browsing_context->active_document()->update_layout();
@ -573,7 +573,7 @@ bool EventHandler::handle_doubleclick(CSSPixelPoint position, unsigned button, u
if (is<HTML::HTMLIFrameElement>(*node)) {
if (auto* nested_browsing_context = static_cast<HTML::HTMLIFrameElement&>(*node).nested_browsing_context())
return nested_browsing_context->event_handler().handle_doubleclick(position.translated(compute_mouse_event_offset({}, paintable->layout_node())), button, buttons, modifiers);
return nested_browsing_context->event_handler().handle_doubleclick(position.translated(compute_mouse_event_offset({}, paintable->layout_node())), screen_position, button, buttons, modifiers);
return false;
}
@ -586,7 +586,7 @@ bool EventHandler::handle_doubleclick(CSSPixelPoint position, unsigned button, u
auto offset = compute_mouse_event_offset(position, *layout_node);
auto client_offset = compute_mouse_event_client_offset(position);
auto page_offset = compute_mouse_event_page_offset(client_offset);
node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::dblclick, page_offset, client_offset, offset, {}, button, buttons).release_value_but_fixme_should_propagate_errors());
node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(node->realm(), UIEvents::EventNames::dblclick, screen_position, page_offset, client_offset, offset, {}, button, buttons).release_value_but_fixme_should_propagate_errors());
// NOTE: Dispatching an event may have disturbed the world.
if (!paint_root() || paint_root() != node->document().paintable_box())
@ -838,21 +838,20 @@ CSSPixelPoint EventHandler::compute_mouse_event_page_offset(CSSPixelPoint event_
return event_client_offset.translated(scroll_offset);
}
CSSPixelPoint EventHandler::compute_mouse_event_movement(CSSPixelPoint event_client_offset) const
CSSPixelPoint EventHandler::compute_mouse_event_movement(CSSPixelPoint screen_position) const
{
// https://w3c.github.io/pointerlock/#dom-mouseevent-movementx
// The attributes movementX movementY must provide the change in position of the pointer,
// as if the values of screenX, screenY, were stored between two subsequent mousemove events eNow and ePrevious and the difference taken movementX = eNow.screenX-ePrevious.screenX.
// FIXME: Using client_offset as screenX and screenY is currently equal to clientX and clientY
if (!m_mousemove_previous_client_offset.has_value())
if (!m_mousemove_previous_screen_position.has_value())
// When unlocked, the system cursor can exit and re-enter the user agent window.
// If it does so and the user agent was not the target of operating system mouse move events
// then the most recent pointer position will be unknown to the user agent and movementX/movementY can not be computed and must be set to zero.
// FIXME: For this to actually work, m_mousemove_previous_client_offset needs to be cleared when the mouse leaves the window
return { 0, 0 };
return { event_client_offset.x() - m_mousemove_previous_client_offset.value().x(), event_client_offset.y() - m_mousemove_previous_client_offset.value().y() };
return { screen_position.x() - m_mousemove_previous_screen_position.value().x(), screen_position.y() - m_mousemove_previous_screen_position.value().y() };
}
Optional<EventHandler::Target> EventHandler::target_for_mouse_position(CSSPixelPoint position)

View file

@ -24,11 +24,11 @@ public:
explicit EventHandler(Badge<HTML::BrowsingContext>, HTML::BrowsingContext&);
~EventHandler();
bool handle_mouseup(CSSPixelPoint, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_mousedown(CSSPixelPoint, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_mousemove(CSSPixelPoint, unsigned buttons, unsigned modifiers);
bool handle_mousewheel(CSSPixelPoint, unsigned button, unsigned buttons, unsigned modifiers, int wheel_delta_x, int wheel_delta_y);
bool handle_doubleclick(CSSPixelPoint, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_mouseup(CSSPixelPoint, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_mousedown(CSSPixelPoint, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_mousemove(CSSPixelPoint, CSSPixelPoint screen_position, unsigned buttons, unsigned modifiers);
bool handle_mousewheel(CSSPixelPoint, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, int wheel_delta_x, int wheel_delta_y);
bool handle_doubleclick(CSSPixelPoint, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_keydown(KeyCode, unsigned modifiers, u32 code_point);
bool handle_keyup(KeyCode, unsigned modifiers, u32 code_point);
@ -65,7 +65,7 @@ private:
WeakPtr<DOM::EventTarget> m_mousedown_target;
Optional<CSSPixelPoint> m_mousemove_previous_client_offset;
Optional<CSSPixelPoint> m_mousemove_previous_screen_position;
};
}

View file

@ -132,29 +132,29 @@ DevicePixelRect Page::rounded_device_rect(CSSPixelRect rect) const
};
}
bool Page::handle_mousewheel(DevicePixelPoint position, unsigned button, unsigned buttons, unsigned modifiers, int wheel_delta_x, int wheel_delta_y)
bool Page::handle_mousewheel(DevicePixelPoint position, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, int wheel_delta_x, int wheel_delta_y)
{
return top_level_browsing_context().event_handler().handle_mousewheel(device_to_css_point(position), button, buttons, modifiers, wheel_delta_x, wheel_delta_y);
return top_level_browsing_context().event_handler().handle_mousewheel(device_to_css_point(position), device_to_css_point(screen_position), button, buttons, modifiers, wheel_delta_x, wheel_delta_y);
}
bool Page::handle_mouseup(DevicePixelPoint position, unsigned button, unsigned buttons, unsigned modifiers)
bool Page::handle_mouseup(DevicePixelPoint position, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers)
{
return top_level_browsing_context().event_handler().handle_mouseup(device_to_css_point(position), button, buttons, modifiers);
return top_level_browsing_context().event_handler().handle_mouseup(device_to_css_point(position), device_to_css_point(screen_position), button, buttons, modifiers);
}
bool Page::handle_mousedown(DevicePixelPoint position, unsigned button, unsigned buttons, unsigned modifiers)
bool Page::handle_mousedown(DevicePixelPoint position, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers)
{
return top_level_browsing_context().event_handler().handle_mousedown(device_to_css_point(position), button, buttons, modifiers);
return top_level_browsing_context().event_handler().handle_mousedown(device_to_css_point(position), device_to_css_point(screen_position), button, buttons, modifiers);
}
bool Page::handle_mousemove(DevicePixelPoint position, unsigned buttons, unsigned modifiers)
bool Page::handle_mousemove(DevicePixelPoint position, DevicePixelPoint screen_position, unsigned buttons, unsigned modifiers)
{
return top_level_browsing_context().event_handler().handle_mousemove(device_to_css_point(position), buttons, modifiers);
return top_level_browsing_context().event_handler().handle_mousemove(device_to_css_point(position), device_to_css_point(screen_position), buttons, modifiers);
}
bool Page::handle_doubleclick(DevicePixelPoint position, unsigned button, unsigned buttons, unsigned modifiers)
bool Page::handle_doubleclick(DevicePixelPoint position, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers)
{
return top_level_browsing_context().event_handler().handle_doubleclick(device_to_css_point(position), button, buttons, modifiers);
return top_level_browsing_context().event_handler().handle_doubleclick(device_to_css_point(position), device_to_css_point(screen_position), button, buttons, modifiers);
}
bool Page::handle_keydown(KeyCode key, unsigned modifiers, u32 code_point)

View file

@ -69,11 +69,11 @@ public:
DevicePixelRect enclosing_device_rect(CSSPixelRect) const;
DevicePixelRect rounded_device_rect(CSSPixelRect) const;
bool handle_mouseup(DevicePixelPoint, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_mousedown(DevicePixelPoint, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_mousemove(DevicePixelPoint, unsigned buttons, unsigned modifiers);
bool handle_mousewheel(DevicePixelPoint, unsigned button, unsigned buttons, unsigned modifiers, int wheel_delta_x, int wheel_delta_y);
bool handle_doubleclick(DevicePixelPoint, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_mouseup(DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_mousedown(DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_mousemove(DevicePixelPoint, DevicePixelPoint screen_position, unsigned buttons, unsigned modifiers);
bool handle_mousewheel(DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, int wheel_delta_x, int wheel_delta_y);
bool handle_doubleclick(DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers);
bool handle_keydown(KeyCode, unsigned modifiers, u32 code_point);
bool handle_keyup(KeyCode, unsigned modifiers, u32 code_point);

View file

@ -63,9 +63,11 @@ JS::NonnullGCPtr<MouseEvent> MouseEvent::create(JS::Realm& realm, FlyString cons
return realm.heap().allocate<MouseEvent>(realm, realm, event_name, event_init, page_x, page_y, offset_x, offset_y);
}
WebIDL::ExceptionOr<JS::NonnullGCPtr<MouseEvent>> MouseEvent::create_from_platform_event(JS::Realm& realm, FlyString const& event_name, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, Optional<CSSPixelPoint> movement, unsigned button, unsigned buttons)
WebIDL::ExceptionOr<JS::NonnullGCPtr<MouseEvent>> MouseEvent::create_from_platform_event(JS::Realm& realm, FlyString const& event_name, CSSPixelPoint screen, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, Optional<CSSPixelPoint> movement, unsigned button, unsigned buttons)
{
MouseEventInit event_init {};
event_init.screen_x = screen.x().to_double();
event_init.screen_y = screen.y().to_double();
event_init.client_x = client.x().to_double();
event_init.client_y = client.y().to_double();
if (movement.has_value()) {

View file

@ -29,7 +29,7 @@ class MouseEvent : public UIEvent {
public:
[[nodiscard]] static JS::NonnullGCPtr<MouseEvent> create(JS::Realm&, FlyString const& event_name, MouseEventInit const& = {}, double page_x = 0, double page_y = 0, double offset_x = 0, double offset_y = 0);
static WebIDL::ExceptionOr<JS::NonnullGCPtr<MouseEvent>> create_from_platform_event(JS::Realm&, FlyString const& event_name, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, Optional<CSSPixelPoint> movement, unsigned button, unsigned buttons);
static WebIDL::ExceptionOr<JS::NonnullGCPtr<MouseEvent>> create_from_platform_event(JS::Realm&, FlyString const& event_name, CSSPixelPoint screen, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, Optional<CSSPixelPoint> movement, unsigned button, unsigned buttons);
virtual ~MouseEvent() override;

View file

@ -34,9 +34,11 @@ JS::NonnullGCPtr<WheelEvent> WheelEvent::create(JS::Realm& realm, FlyString cons
return realm.heap().allocate<WheelEvent>(realm, realm, event_name, event_init, page_x, page_y, offset_x, offset_y);
}
WebIDL::ExceptionOr<JS::NonnullGCPtr<WheelEvent>> WheelEvent::create_from_platform_event(JS::Realm& realm, FlyString const& event_name, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, double delta_x, double delta_y, unsigned button, unsigned buttons)
WebIDL::ExceptionOr<JS::NonnullGCPtr<WheelEvent>> WheelEvent::create_from_platform_event(JS::Realm& realm, FlyString const& event_name, CSSPixelPoint screen, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, double delta_x, double delta_y, unsigned button, unsigned buttons)
{
WheelEventInit event_init {};
event_init.screen_x = screen.x().to_double();
event_init.screen_y = screen.y().to_double();
event_init.client_x = client.x().to_double();
event_init.client_y = client.y().to_double();
event_init.button = button;

View file

@ -30,7 +30,7 @@ class WheelEvent final : public MouseEvent {
public:
[[nodiscard]] static JS::NonnullGCPtr<WheelEvent> create(JS::Realm&, FlyString const& event_name, WheelEventInit const& event_init = {}, double page_x = 0, double page_y = 0, double offset_x = 0, double offset_y = 0);
static WebIDL::ExceptionOr<JS::NonnullGCPtr<WheelEvent>> create_from_platform_event(JS::Realm&, FlyString const& event_name, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, double delta_x, double delta_y, unsigned button, unsigned buttons);
static WebIDL::ExceptionOr<JS::NonnullGCPtr<WheelEvent>> create_from_platform_event(JS::Realm&, FlyString const& event_name, CSSPixelPoint screen, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, double delta_x, double delta_y, unsigned button, unsigned buttons);
virtual ~WheelEvent() override;

View file

@ -328,24 +328,25 @@ void OutOfProcessWebView::process_next_input_event()
}
},
[this](GUI::MouseEvent const& event) {
auto screen_position = event.position() + (window()->position() + relative_position());
switch (event.type()) {
case GUI::Event::Type::MouseDown:
client().async_mouse_down(to_content_position(event.position()), event.button(), event.buttons(), event.modifiers());
client().async_mouse_down(to_content_position(event.position()), screen_position, event.button(), event.buttons(), event.modifiers());
break;
case GUI::Event::Type::MouseUp:
client().async_mouse_up(to_content_position(event.position()), event.button(), event.buttons(), event.modifiers());
client().async_mouse_up(to_content_position(event.position()), screen_position, event.button(), event.buttons(), event.modifiers());
break;
case GUI::Event::Type::MouseMove:
client().async_mouse_move(to_content_position(event.position()), event.button(), event.buttons(), event.modifiers());
client().async_mouse_move(to_content_position(event.position()), screen_position, event.button(), event.buttons(), event.modifiers());
break;
case GUI::Event::Type::MouseWheel: {
// FIXME: This wheel delta step size multiplier is used to remain the old scroll behaviour, in future use system step size.
constexpr int scroll_step_size = 24;
client().async_mouse_wheel(to_content_position(event.position()), event.button(), event.buttons(), event.modifiers(), event.wheel_delta_x() * scroll_step_size, event.wheel_delta_y() * scroll_step_size);
client().async_mouse_wheel(to_content_position(event.position()), screen_position, event.button(), event.buttons(), event.modifiers(), event.wheel_delta_x() * scroll_step_size, event.wheel_delta_y() * scroll_step_size);
break;
}
case GUI::Event::Type::MouseDoubleClick:
client().async_doubleclick(to_content_position(event.position()), event.button(), event.buttons(), event.modifiers());
client().async_doubleclick(to_content_position(event.position()), screen_position, event.button(), event.buttons(), event.modifiers());
break;
default:
dbgln("Unrecognized mouse event type in OOPWV input event queue: {}", event.type());

View file

@ -182,11 +182,13 @@ void ConnectionFromClient::process_next_input_event()
case QueuedMouseEvent::Type::MouseDown:
report_finished_handling_input_event(page().handle_mousedown(
event.position.to_type<Web::DevicePixels>(),
event.screen_position.to_type<Web::DevicePixels>(),
event.button, event.buttons, event.modifiers));
break;
case QueuedMouseEvent::Type::MouseUp:
report_finished_handling_input_event(page().handle_mouseup(
event.position.to_type<Web::DevicePixels>(),
event.screen_position.to_type<Web::DevicePixels>(),
event.button, event.buttons, event.modifiers));
break;
case QueuedMouseEvent::Type::MouseMove:
@ -197,11 +199,13 @@ void ConnectionFromClient::process_next_input_event()
}
report_finished_handling_input_event(page().handle_mousemove(
event.position.to_type<Web::DevicePixels>(),
event.screen_position.to_type<Web::DevicePixels>(),
event.buttons, event.modifiers));
break;
case QueuedMouseEvent::Type::DoubleClick:
report_finished_handling_input_event(page().handle_doubleclick(
event.position.to_type<Web::DevicePixels>(),
event.screen_position.to_type<Web::DevicePixels>(),
event.button, event.buttons, event.modifiers));
break;
case QueuedMouseEvent::Type::MouseWheel:
@ -210,6 +214,7 @@ void ConnectionFromClient::process_next_input_event()
}
report_finished_handling_input_event(page().handle_mousewheel(
event.position.to_type<Web::DevicePixels>(),
event.screen_position.to_type<Web::DevicePixels>(),
event.button, event.buttons, event.modifiers, event.wheel_delta_x, event.wheel_delta_y));
break;
}
@ -229,23 +234,25 @@ void ConnectionFromClient::process_next_input_event()
m_input_event_queue_timer->start();
}
void ConnectionFromClient::mouse_down(Gfx::IntPoint position, unsigned int button, unsigned int buttons, unsigned int modifiers)
void ConnectionFromClient::mouse_down(Gfx::IntPoint position, Gfx::IntPoint screen_position, unsigned int button, unsigned int buttons, unsigned int modifiers)
{
enqueue_input_event(
QueuedMouseEvent {
.type = QueuedMouseEvent::Type::MouseDown,
.position = position,
.screen_position = screen_position,
.button = button,
.buttons = buttons,
.modifiers = modifiers,
});
}
void ConnectionFromClient::mouse_move(Gfx::IntPoint position, [[maybe_unused]] unsigned int button, unsigned int buttons, unsigned int modifiers)
void ConnectionFromClient::mouse_move(Gfx::IntPoint position, Gfx::IntPoint screen_position, [[maybe_unused]] unsigned int button, unsigned int buttons, unsigned int modifiers)
{
auto event = QueuedMouseEvent {
.type = QueuedMouseEvent::Type::MouseMove,
.position = position,
.screen_position = screen_position,
.button = button,
.buttons = buttons,
.modifiers = modifiers,
@ -263,23 +270,25 @@ void ConnectionFromClient::mouse_move(Gfx::IntPoint position, [[maybe_unused]] u
enqueue_input_event(move(event));
}
void ConnectionFromClient::mouse_up(Gfx::IntPoint position, unsigned int button, unsigned int buttons, unsigned int modifiers)
void ConnectionFromClient::mouse_up(Gfx::IntPoint position, Gfx::IntPoint screen_position, unsigned int button, unsigned int buttons, unsigned int modifiers)
{
enqueue_input_event(
QueuedMouseEvent {
.type = QueuedMouseEvent::Type::MouseUp,
.position = position,
.screen_position = screen_position,
.button = button,
.buttons = buttons,
.modifiers = modifiers,
});
}
void ConnectionFromClient::mouse_wheel(Gfx::IntPoint position, unsigned int button, unsigned int buttons, unsigned int modifiers, i32 wheel_delta_x, i32 wheel_delta_y)
void ConnectionFromClient::mouse_wheel(Gfx::IntPoint position, Gfx::IntPoint screen_position, unsigned int button, unsigned int buttons, unsigned int modifiers, i32 wheel_delta_x, i32 wheel_delta_y)
{
auto event = QueuedMouseEvent {
.type = QueuedMouseEvent::Type::MouseWheel,
.position = position,
.screen_position = screen_position,
.button = button,
.buttons = buttons,
.modifiers = modifiers,
@ -302,12 +311,13 @@ void ConnectionFromClient::mouse_wheel(Gfx::IntPoint position, unsigned int butt
enqueue_input_event(move(event));
}
void ConnectionFromClient::doubleclick(Gfx::IntPoint position, unsigned int button, unsigned int buttons, unsigned int modifiers)
void ConnectionFromClient::doubleclick(Gfx::IntPoint position, Gfx::IntPoint screen_position, unsigned int button, unsigned int buttons, unsigned int modifiers)
{
enqueue_input_event(
QueuedMouseEvent {
.type = QueuedMouseEvent::Type::DoubleClick,
.position = position,
.screen_position = screen_position,
.button = button,
.buttons = buttons,
.modifiers = modifiers,

View file

@ -58,11 +58,11 @@ private:
virtual void load_html(DeprecatedString const&, URL const&) override;
virtual void paint(Gfx::IntRect const&, i32) override;
virtual void set_viewport_rect(Gfx::IntRect const&) override;
virtual void mouse_down(Gfx::IntPoint, unsigned, unsigned, unsigned) override;
virtual void mouse_move(Gfx::IntPoint, unsigned, unsigned, unsigned) override;
virtual void mouse_up(Gfx::IntPoint, unsigned, unsigned, unsigned) override;
virtual void mouse_wheel(Gfx::IntPoint, unsigned, unsigned, unsigned, i32, i32) override;
virtual void doubleclick(Gfx::IntPoint, unsigned, unsigned, unsigned) override;
virtual void mouse_down(Gfx::IntPoint, Gfx::IntPoint, unsigned, unsigned, unsigned) override;
virtual void mouse_move(Gfx::IntPoint, Gfx::IntPoint, unsigned, unsigned, unsigned) override;
virtual void mouse_up(Gfx::IntPoint, Gfx::IntPoint, unsigned, unsigned, unsigned) override;
virtual void mouse_wheel(Gfx::IntPoint, Gfx::IntPoint, unsigned, unsigned, unsigned, i32, i32) override;
virtual void doubleclick(Gfx::IntPoint, Gfx::IntPoint, unsigned, unsigned, unsigned) override;
virtual void key_down(i32, unsigned, u32) override;
virtual void key_up(i32, unsigned, u32) override;
virtual void add_backing_store(i32, Gfx::ShareableBitmap const&) override;
@ -144,6 +144,7 @@ private:
};
Type type {};
Gfx::IntPoint position {};
Gfx::IntPoint screen_position {};
unsigned button {};
unsigned buttons {};
unsigned modifiers {};

View file

@ -27,11 +27,11 @@ endpoint WebContentServer
paint(Gfx::IntRect content_rect, i32 backing_store_id) =|
set_viewport_rect(Gfx::IntRect rect) =|
mouse_down(Gfx::IntPoint position, unsigned button, unsigned buttons, unsigned modifiers) =|
mouse_move(Gfx::IntPoint position, unsigned button, unsigned buttons, unsigned modifiers) =|
mouse_up(Gfx::IntPoint position, unsigned button, unsigned buttons, unsigned modifiers) =|
mouse_wheel(Gfx::IntPoint position, unsigned button, unsigned buttons, unsigned modifiers, i32 wheel_delta_x, i32 wheel_delta_y) =|
doubleclick(Gfx::IntPoint position, unsigned button, unsigned buttons, unsigned modifiers) =|
mouse_down(Gfx::IntPoint position, Gfx::IntPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers) =|
mouse_move(Gfx::IntPoint position, Gfx::IntPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers) =|
mouse_up(Gfx::IntPoint position, Gfx::IntPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers) =|
mouse_wheel(Gfx::IntPoint position, Gfx::IntPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, i32 wheel_delta_x, i32 wheel_delta_y) =|
doubleclick(Gfx::IntPoint position, Gfx::IntPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers) =|
key_down(i32 key, unsigned modifiers, u32 code_point) =|
key_up(i32 key, unsigned modifiers, u32 code_point) =|