From a58d84407fce85f8a17633a7bb3cc745f967f85e Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 14 Mar 2023 13:47:40 +0100 Subject: [PATCH] WebContent: Coalesce multiple sequential MouseMove events This can avoid getting into a situation where lots of MouseMove events are queued up and they all trigger relayout (or something else that takes a lot of time). To make sure that we don't get out of sync with the input events queue on the UI process side, we still send acknowledgements for coalesced MouseMoves. There's room for improvement here. My Discord friends list is now pleasantly responsive. :^) --- .../WebContent/ConnectionFromClient.cpp | 31 ++++++++++++++----- .../WebContent/ConnectionFromClient.h | 1 + 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/Userland/Services/WebContent/ConnectionFromClient.cpp b/Userland/Services/WebContent/ConnectionFromClient.cpp index d3f9ce3195..4e77df6bc8 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.cpp +++ b/Userland/Services/WebContent/ConnectionFromClient.cpp @@ -176,6 +176,11 @@ void ConnectionFromClient::process_next_input_event() event.button, event.buttons, event.modifiers)); break; case QueuedMouseEvent::Type::MouseMove: + // NOTE: We have to notify the client about coalesced MouseMoves, + // so we do that by saying none of them were handled by the web page. + for (size_t i = 0; i < event.coalesced_event_count; ++i) { + report_finished_handling_input_event(false); + } report_finished_handling_input_event(page().handle_mousemove( event.position.to_type(), event.buttons, event.modifiers)); @@ -221,14 +226,24 @@ void ConnectionFromClient::mouse_down(Gfx::IntPoint position, unsigned int butto void ConnectionFromClient::mouse_move(Gfx::IntPoint position, [[maybe_unused]] unsigned int button, unsigned int buttons, unsigned int modifiers) { - enqueue_input_event( - QueuedMouseEvent { - .type = QueuedMouseEvent::Type::MouseMove, - .position = position, - .button = button, - .buttons = buttons, - .modifiers = modifiers, - }); + auto event = QueuedMouseEvent { + .type = QueuedMouseEvent::Type::MouseMove, + .position = position, + .button = button, + .buttons = buttons, + .modifiers = modifiers, + }; + + // OPTIMIZATION: Coalesce with previous unprocessed event iff the previous event is also a MouseMove event. + if (!m_input_event_queue.is_empty() + && m_input_event_queue.tail().has() + && m_input_event_queue.tail().get().type == QueuedMouseEvent::Type::MouseMove) { + event.coalesced_event_count = m_input_event_queue.tail().get().coalesced_event_count + 1; + m_input_event_queue.tail() = event; + return; + } + + enqueue_input_event(move(event)); } void ConnectionFromClient::mouse_up(Gfx::IntPoint position, unsigned int button, unsigned int buttons, unsigned int modifiers) diff --git a/Userland/Services/WebContent/ConnectionFromClient.h b/Userland/Services/WebContent/ConnectionFromClient.h index 4d0fe3d134..d5aab3ab1d 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.h +++ b/Userland/Services/WebContent/ConnectionFromClient.h @@ -136,6 +136,7 @@ private: unsigned modifiers {}; int wheel_delta_x {}; int wheel_delta_y {}; + size_t coalesced_event_count { 0 }; }; struct QueuedKeyboardEvent {