From 948b6de3b122b50d67d967ed780133e847d629df Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sat, 17 Aug 2024 13:36:28 -0400 Subject: [PATCH] LibWeb+LibWebView+WebContent: Add IPC to send drag-and-drop events This adds the IPC and related hooks to allow the UI to send drag-and- drop events from the UI process to the WebContent process. --- Userland/Libraries/LibWeb/Page/InputEvent.cpp | 27 +++++++++++++++++++ Userland/Libraries/LibWeb/Page/InputEvent.h | 8 +++++- .../LibWebView/ViewImplementation.cpp | 27 ++++++++++++++----- .../Libraries/LibWebView/ViewImplementation.h | 1 + .../WebContent/ConnectionFromClient.cpp | 8 ++++++ .../WebContent/ConnectionFromClient.h | 1 + .../Services/WebContent/WebContentServer.ipc | 1 + 7 files changed, 65 insertions(+), 8 deletions(-) diff --git a/Userland/Libraries/LibWeb/Page/InputEvent.cpp b/Userland/Libraries/LibWeb/Page/InputEvent.cpp index 3fa38cf97cc..d32784d481f 100644 --- a/Userland/Libraries/LibWeb/Page/InputEvent.cpp +++ b/Userland/Libraries/LibWeb/Page/InputEvent.cpp @@ -76,3 +76,30 @@ ErrorOr IPC::decode(Decoder& decoder) return Web::MouseEvent { type, position, screen_position, button, buttons, modifiers, wheel_delta_x, wheel_delta_y, nullptr }; } + +template<> +ErrorOr IPC::encode(Encoder& encoder, Web::DragEvent const& event) +{ + TRY(encoder.encode(event.type)); + TRY(encoder.encode(event.position)); + TRY(encoder.encode(event.screen_position)); + TRY(encoder.encode(event.button)); + TRY(encoder.encode(event.buttons)); + TRY(encoder.encode(event.modifiers)); + TRY(encoder.encode(event.files)); + return {}; +} + +template<> +ErrorOr IPC::decode(Decoder& decoder) +{ + auto type = TRY(decoder.decode()); + auto position = TRY(decoder.decode()); + auto screen_position = TRY(decoder.decode()); + auto button = TRY(decoder.decode()); + auto buttons = TRY(decoder.decode()); + auto modifiers = TRY(decoder.decode()); + auto files = TRY(decoder.decode>()); + + return Web::DragEvent { type, position, screen_position, button, buttons, modifiers, move(files), nullptr }; +} diff --git a/Userland/Libraries/LibWeb/Page/InputEvent.h b/Userland/Libraries/LibWeb/Page/InputEvent.h index 61015f51b82..20952fbd557 100644 --- a/Userland/Libraries/LibWeb/Page/InputEvent.h +++ b/Userland/Libraries/LibWeb/Page/InputEvent.h @@ -82,7 +82,7 @@ struct DragEvent { OwnPtr chrome_data; }; -using InputEvent = Variant; +using InputEvent = Variant; } @@ -100,4 +100,10 @@ ErrorOr encode(Encoder&, Web::MouseEvent const&); template<> ErrorOr decode(Decoder&); +template<> +ErrorOr encode(Encoder&, Web::DragEvent const&); + +template<> +ErrorOr decode(Decoder&); + } diff --git a/Userland/Libraries/LibWebView/ViewImplementation.cpp b/Userland/Libraries/LibWebView/ViewImplementation.cpp index bfdc7c1af2d..72d3f1ee304 100644 --- a/Userland/Libraries/LibWebView/ViewImplementation.cpp +++ b/Userland/Libraries/LibWebView/ViewImplementation.cpp @@ -137,6 +137,12 @@ void ViewImplementation::enqueue_input_event(Web::InputEvent event) }, [this](Web::MouseEvent const& event) { client().async_mouse_event(m_client_state.page_index, event.clone_without_chrome_data()); + }, + [this](Web::DragEvent& event) { + auto cloned_event = event.clone_without_chrome_data(); + cloned_event.files = move(event.files); + + client().async_drag_event(m_client_state.page_index, move(cloned_event)); }); } @@ -144,14 +150,21 @@ void ViewImplementation::did_finish_handling_input_event(Badge { auto event = m_pending_input_events.dequeue(); - if (!event_was_accepted && event.has()) { - auto const& key_event = event.get(); + if (event_was_accepted) + return; - // Here we handle events that were not consumed or cancelled by the WebContent. Propagate the event back - // to the concrete view implementation. - if (on_finish_handling_key_event) - on_finish_handling_key_event(key_event); - } + // Here we handle events that were not consumed or cancelled by the WebContent. Propagate the event back + // to the concrete view implementation. + event.visit( + [this](Web::KeyEvent const& event) { + if (on_finish_handling_key_event) + on_finish_handling_key_event(event); + }, + [this](Web::DragEvent const& event) { + if (on_finish_handling_drag_event) + on_finish_handling_drag_event(event); + }, + [](auto const&) {}); } void ViewImplementation::set_preferred_color_scheme(Web::CSS::PreferredColorScheme color_scheme) diff --git a/Userland/Libraries/LibWebView/ViewImplementation.h b/Userland/Libraries/LibWebView/ViewImplementation.h index 2e12d0e4ca4..dea99dd9e01 100644 --- a/Userland/Libraries/LibWebView/ViewImplementation.h +++ b/Userland/Libraries/LibWebView/ViewImplementation.h @@ -203,6 +203,7 @@ public: Function on_request_file_picker; Function items)> on_request_select_dropdown; Function on_finish_handling_key_event; + Function on_finish_handling_drag_event; Function on_text_test_finish; Function const& total_match_count)> on_find_in_page; Function on_theme_color_change; diff --git a/Userland/Services/WebContent/ConnectionFromClient.cpp b/Userland/Services/WebContent/ConnectionFromClient.cpp index 373ace15945..f20ff2205eb 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.cpp +++ b/Userland/Services/WebContent/ConnectionFromClient.cpp @@ -207,6 +207,9 @@ void ConnectionFromClient::process_next_input_event() return page->page().handle_doubleclick(event.position, event.screen_position, event.button, event.buttons, event.modifiers); } VERIFY_NOT_REACHED(); + }, + [&](Web::DragEvent& event) { + return page->page().handle_drag_and_drop_event(event.type, event.position, event.screen_position, event.button, event.buttons, event.modifiers, move(event.files)); }); // We have to notify the client about coalesced events, so we do that by saying none of them were handled by the web page-> @@ -257,6 +260,11 @@ void ConnectionFromClient::mouse_event(u64 page_id, Web::MouseEvent const& event enqueue_input_event({ page_id, move(const_cast(event)), 0 }); } +void ConnectionFromClient::drag_event(u64 page_id, Web::DragEvent const& event) +{ + enqueue_input_event({ page_id, move(const_cast(event)), 0 }); +} + void ConnectionFromClient::enqueue_input_event(QueuedInputEvent event) { m_input_event_queue.enqueue(move(event)); diff --git a/Userland/Services/WebContent/ConnectionFromClient.h b/Userland/Services/WebContent/ConnectionFromClient.h index 7f4c5ed0465..496fa54ee85 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.h +++ b/Userland/Services/WebContent/ConnectionFromClient.h @@ -67,6 +67,7 @@ private: virtual void set_viewport_size(u64 page_id, Web::DevicePixelSize const) override; virtual void key_event(u64 page_id, Web::KeyEvent const&) override; virtual void mouse_event(u64 page_id, Web::MouseEvent const&) override; + virtual void drag_event(u64 page_id, Web::DragEvent const&) override; virtual void ready_to_paint(u64 page_id) override; virtual void debug_request(u64 page_id, ByteString const&, ByteString const&) override; virtual void get_source(u64 page_id) override; diff --git a/Userland/Services/WebContent/WebContentServer.ipc b/Userland/Services/WebContent/WebContentServer.ipc index e61898bba5b..6c583319994 100644 --- a/Userland/Services/WebContent/WebContentServer.ipc +++ b/Userland/Services/WebContent/WebContentServer.ipc @@ -35,6 +35,7 @@ endpoint WebContentServer key_event(u64 page_id, Web::KeyEvent event) =| mouse_event(u64 page_id, Web::MouseEvent event) =| + drag_event(u64 page_id, Web::DragEvent event) =| debug_request(u64 page_id, ByteString request, ByteString argument) =| get_source(u64 page_id) =|