LibWebView: Implement drag-and-drop for OutOfProcessWebView

Almost the entirety of drag-and-drop operations are handled within
LibWeb. This patch just hooks up the UI-side operations to trigger
the events.

A FIXME is left here to open files in the browser that were not accepted
by the web page.
This commit is contained in:
Timothy Flynn authored and Tim Flynn committed 2024-12-04 08:00:21 -05:00
1 parent c3b1d533f6
commit 4a52145f8e
2 files changed
+91

No files matched your search

@@ -60,6 +60,10 @@ OutOfProcessWebView::OutOfProcessWebView()
finish_handling_key_event(event);
};
on_finish_handling_drag_event = [this](auto const& event) {
finish_handling_drag_event(event);
};
on_request_worker_agent = []() {
auto worker_client = MUST(Web::HTML::WebWorkerClient::try_create());
return worker_client->dup_socket();
@@ -282,6 +286,35 @@ void OutOfProcessWebView::hide_event(GUI::HideEvent&)
set_system_visibility_state(false);
}
void OutOfProcessWebView::drag_enter_event(GUI::DragEvent& event)
{
if (!event.mime_data().has_urls())
return;
enqueue_native_event(Web::DragEvent::Type::DragStart, event);
event.accept();
}
void OutOfProcessWebView::drag_move_event(GUI::DragEvent& event)
{
enqueue_native_event(Web::DragEvent::Type::DragMove, event);
event.accept();
}
void OutOfProcessWebView::drag_leave_event(GUI::Event&)
{
Web::DragEvent event {};
event.type = Web::DragEvent::Type::DragEnd;
enqueue_input_event(move(event));
}
void OutOfProcessWebView::drop_event(GUI::DropEvent& event)
{
enqueue_native_event(Web::DragEvent::Type::Drop, event);
event.accept();
}
static constexpr Web::UIEvents::MouseButton web_button_from_gui_button(GUI::MouseButton button)
{
switch (button) {
@@ -342,6 +375,56 @@ void OutOfProcessWebView::enqueue_native_event(Web::MouseEvent::Type type, GUI::
enqueue_input_event(Web::MouseEvent { type, position, screen_position, button, buttons, modifiers, wheel_delta_x, wheel_delta_y, nullptr });
}
struct DragData : Web::ChromeInputData {
explicit DragData(GUI::DropEvent const& event)
: event(make<GUI::DropEvent>(event))
{
}
NonnullOwnPtr<GUI::DropEvent> event;
};
void OutOfProcessWebView::enqueue_native_event(Web::DragEvent::Type type, GUI::DropEvent const& event)
{
auto position = to_content_position(event.position()).to_type<Web::DevicePixels>();
auto screen_position = (event.position() + (window()->position() + relative_position())).to_type<Web::DevicePixels>();
auto button = web_button_from_gui_button(event.button());
auto buttons = web_buttons_from_gui_buttons(event.buttons());
auto modifiers = web_modifiers_from_gui_modifiers(event.modifiers());
Vector<Web::HTML::SelectedFile> files;
OwnPtr<DragData> chrome_data;
if (type == Web::DragEvent::Type::DragStart) {
VERIFY(event.mime_data().has_urls());
for (auto const& url : event.mime_data().urls()) {
auto file_path = URL::percent_decode(url.serialize_path());
if (auto file = Web::HTML::SelectedFile::from_file_path(file_path); file.is_error())
warnln("Unable to open file {} for drag-and-drop: {}", file_path, file.error());
else
files.append(file.release_value());
}
} else if (type == Web::DragEvent::Type::Drop) {
chrome_data = make<DragData>(event);
} else {
VERIFY(type == Web::DragEvent::Type::DragMove);
}
enqueue_input_event(Web::DragEvent { type, position, screen_position, button, buttons, modifiers, move(files), move(chrome_data) });
}
void OutOfProcessWebView::finish_handling_drag_event(Web::DragEvent const& event)
{
if (event.type != Web::DragEvent::Type::Drop)
return;
// FIXME: Implement opening the event URLs in the Browser.
[[maybe_unused]] auto const& chrome_data = verify_cast<DragData>(*event.chrome_data);
}
struct KeyData : Web::ChromeInputData {
explicit KeyData(GUI::KeyEvent const& event)
: event(make<GUI::KeyEvent>(event))
@@ -71,6 +71,10 @@ private:
virtual void focusout_event(GUI::FocusEvent&) override;
virtual void show_event(GUI::ShowEvent&) override;
virtual void hide_event(GUI::HideEvent&) override;
virtual void drag_enter_event(GUI::DragEvent&) override;
virtual void drag_move_event(GUI::DragEvent&) override;
virtual void drag_leave_event(GUI::Event&) override;
virtual void drop_event(GUI::DropEvent&) override;
// ^WebView::ViewImplementation
virtual void initialize_client(CreateNewClient) override;
@@ -81,6 +85,10 @@ private:
virtual Gfx::IntPoint to_widget_position(Gfx::IntPoint content_position) const override;
void enqueue_native_event(Web::MouseEvent::Type, GUI::MouseEvent const& event);
void enqueue_native_event(Web::DragEvent::Type, GUI::DropEvent const& event);
void finish_handling_drag_event(Web::DragEvent const&);
void enqueue_native_event(Web::KeyEvent::Type, GUI::KeyEvent const& event);
void finish_handling_key_event(Web::KeyEvent const&);