LibGUI+WindowServer+Applications: Carry more data across drag events

To support drag-and-drop for LibWeb, the drag events need the full mime
data from WindowServer, not just the list of stringified mime types. We
only provided the full data in the drop events. This patch provides the
Core::MimeData type, as well as other mouse-event information needed for
LibWeb (what buttons / modifiers are pressed).

To do this, we add a specific WindowServer IPC to inform the Application
of the event. We previously tagged mouse-move events with some drag data
and formed the drag event client-side. That extra data is removed in
favor of this new IPC.
This commit is contained in:
Timothy Flynn 2024-12-02 08:32:26 -05:00 committed by Tim Flynn
parent b499279162
commit 81e469c911
37 changed files with 116 additions and 130 deletions

View file

@ -131,8 +131,7 @@ private:
void GLContextWidget::drag_enter_event(GUI::DragEvent& event)
{
auto const& mime_types = event.mime_types();
if (mime_types.contains_slow("text/uri-list"sv))
if (event.mime_data().has_urls())
event.accept();
}

View file

@ -992,8 +992,7 @@ void MainWidget::update_preview()
void MainWidget::drag_enter_event(GUI::DragEvent& event)
{
auto const& mime_types = event.mime_types();
if (mime_types.contains_slow("text/uri-list"sv))
if (event.mime_data().has_urls())
event.accept();
}

View file

@ -833,8 +833,7 @@ void HexEditorWidget::set_value_inspector_visible(bool visible)
void HexEditorWidget::drag_enter_event(GUI::DragEvent& event)
{
auto const& mime_types = event.mime_types();
if (mime_types.contains_slow("text/uri-list"sv))
if (event.mime_data().has_urls())
event.accept();
}

View file

@ -283,8 +283,7 @@ ErrorOr<void> ViewWidget::try_open_file(String const& path, Core::File& file)
void ViewWidget::drag_enter_event(GUI::DragEvent& event)
{
auto const& mime_types = event.mime_types();
if (mime_types.contains_slow("text/uri-list"sv))
if (event.mime_data().has_urls())
event.accept();
}

View file

@ -523,8 +523,7 @@ PDF::PDFErrorOr<void> PDFViewerWidget::try_open_file(StringView path, NonnullOwn
void PDFViewerWidget::drag_enter_event(GUI::DragEvent& event)
{
auto const& mime_types = event.mime_types();
if (mime_types.contains_slow("text/uri-list"sv))
if (event.mime_data().has_urls())
event.accept();
}

View file

@ -1492,8 +1492,7 @@ ImageEditor& MainWidget::create_new_editor(NonnullRefPtr<Image> image)
void MainWidget::drag_enter_event(GUI::DragEvent& event)
{
auto const& mime_types = event.mime_types();
if (mime_types.contains_slow("text/uri-list"sv))
if (event.mime_data().has_urls())
event.accept();
}

View file

@ -205,8 +205,7 @@ void PresenterWidget::second_paint_event(GUI::PaintEvent& event)
void PresenterWidget::drag_enter_event(GUI::DragEvent& event)
{
auto const& mime_types = event.mime_types();
if (mime_types.contains_slow("text/uri-list"sv))
if (event.mime_data().has_urls())
event.accept();
}

View file

@ -147,8 +147,7 @@ void SoundPlayerWidget::set_nonlinear_volume_slider(bool nonlinear)
void SoundPlayerWidget::drag_enter_event(GUI::DragEvent& event)
{
auto const& mime_types = event.mime_types();
if (mime_types.contains_slow("text/uri-list"sv))
if (event.mime_data().has_urls())
event.accept();
}

View file

@ -835,8 +835,7 @@ bool MainWidget::request_close()
void MainWidget::drag_enter_event(GUI::DragEvent& event)
{
auto const& mime_types = event.mime_types();
if (mime_types.contains_slow("text/uri-list"sv))
if (event.mime_data().has_urls())
event.accept();
}

View file

@ -682,8 +682,7 @@ ErrorOr<void> MainWidget::load_from_file(ByteString const& filename, NonnullOwnP
void MainWidget::drag_enter_event(GUI::DragEvent& event)
{
auto const& mime_types = event.mime_types();
if (mime_types.contains_slow("text/uri-list"sv))
if (event.mime_data().has_urls())
event.accept();
}

View file

@ -320,8 +320,7 @@ GUI::Window::CloseRequestDecision MainWidget::request_close()
void MainWidget::drag_enter_event(GUI::DragEvent& event)
{
auto const& mime_types = event.mime_types();
if (mime_types.contains_slow("text/uri-list"sv))
if (event.mime_data().has_urls())
event.accept();
}

View file

@ -346,8 +346,7 @@ void Editor::mousedown_event(GUI::MouseEvent& event)
void Editor::drag_enter_event(GUI::DragEvent& event)
{
auto const& mime_types = event.mime_types();
if (mime_types.contains_slow("text/uri-list"sv))
if (event.mime_data().has_urls())
event.accept();
}

View file

@ -463,8 +463,7 @@ void MainWidget::update_editor_actions(ScriptEditor* editor)
void MainWidget::drag_enter_event(GUI::DragEvent& event)
{
auto const& mime_types = event.mime_types();
if (mime_types.contains_slow("text/uri-list"sv))
if (event.mime_data().has_urls())
event.accept();
}

View file

@ -791,7 +791,7 @@ void AbstractView::drag_enter_event(DragEvent& event)
// We might be able to reduce event traffic by communicating the set of drag-accepting
// rects in this widget to the windowing system somehow.
event.accept();
dbgln_if(DRAG_DEBUG, "accepting drag of {}", event.mime_types());
dbgln_if(DRAG_DEBUG, "accepting drag of {}", event.mime_data().formats());
}
void AbstractView::drag_move_event(DragEvent& event)
@ -801,7 +801,7 @@ void AbstractView::drag_move_event(DragEvent& event)
auto index = index_at_event_position(event.position());
ModelIndex new_drop_candidate_index;
bool acceptable = model()->accepts_drag(index, event.mime_types());
bool acceptable = model()->accepts_drag(index, event.mime_data());
if (acceptable && index.is_valid())
new_drop_candidate_index = index;

View file

@ -283,7 +283,7 @@ void Application::set_pending_drop_widget(Widget* widget)
m_pending_drop_widget->update();
}
void Application::set_drag_hovered_widget_impl(Widget* widget, Gfx::IntPoint position, Vector<String> mime_types)
void Application::set_drag_hovered_widget_impl(Widget* widget, Gfx::IntPoint position, Optional<DragEvent const&> drag_event)
{
if (widget == m_drag_hovered_widget)
return;
@ -296,8 +296,8 @@ void Application::set_drag_hovered_widget_impl(Widget* widget, Gfx::IntPoint pos
set_pending_drop_widget(nullptr);
m_drag_hovered_widget = widget;
if (m_drag_hovered_widget) {
DragEvent enter_event(Event::DragEnter, position, move(mime_types));
if (m_drag_hovered_widget && drag_event.has_value()) {
DragEvent enter_event(Event::DragEnter, position, drag_event->button(), drag_event->buttons(), drag_event->modifiers(), drag_event->text(), drag_event->mime_data());
enter_event.ignore();
m_drag_hovered_widget->dispatch_event(enter_event, m_drag_hovered_widget->window());
if (enter_event.is_accepted())

View file

@ -78,9 +78,9 @@ public:
Widget* pending_drop_widget() { return m_pending_drop_widget.ptr(); }
Widget const* pending_drop_widget() const { return m_pending_drop_widget.ptr(); }
void set_drag_hovered_widget(Badge<Window>, Widget* widget, Gfx::IntPoint position = {}, Vector<String> mime_types = {})
void set_drag_hovered_widget(Badge<Window>, Widget* widget, Gfx::IntPoint position = {}, Optional<DragEvent const&> drag_event = {})
{
set_drag_hovered_widget_impl(widget, position, move(mime_types));
set_drag_hovered_widget_impl(widget, position, move(drag_event));
}
void notify_drag_cancelled(Badge<ConnectionToWindowServer>);
@ -106,7 +106,7 @@ private:
void request_tooltip_show();
void tooltip_hide_timer_did_fire();
void set_drag_hovered_widget_impl(Widget*, Gfx::IntPoint = {}, Vector<String> = {});
void set_drag_hovered_widget_impl(Widget*, Gfx::IntPoint = {}, Optional<DragEvent const&> = {});
void set_pending_drop_widget(Widget*);
OwnPtr<Core::EventLoop> m_event_loop;

View file

@ -259,14 +259,10 @@ void ConnectionToWindowServer::mouse_up(i32 window_id, Gfx::IntPoint mouse_posit
Core::EventLoop::current().post_event(*window, make<MouseEvent>(Event::MouseUp, mouse_position, buttons, to_mouse_button(button), modifiers, wheel_delta_x, wheel_delta_y, wheel_raw_delta_x, wheel_raw_delta_y));
}
void ConnectionToWindowServer::mouse_move(i32 window_id, Gfx::IntPoint mouse_position, u32 button, u32 buttons, u32 modifiers, i32 wheel_delta_x, i32 wheel_delta_y, i32 wheel_raw_delta_x, i32 wheel_raw_delta_y, bool is_drag, Vector<String> const& mime_types)
void ConnectionToWindowServer::mouse_move(i32 window_id, Gfx::IntPoint mouse_position, u32 button, u32 buttons, u32 modifiers, i32 wheel_delta_x, i32 wheel_delta_y, i32 wheel_raw_delta_x, i32 wheel_raw_delta_y)
{
if (auto* window = Window::from_window_id(window_id)) {
if (is_drag)
Core::EventLoop::current().post_event(*window, make<DragEvent>(Event::DragMove, mouse_position, mime_types));
else
Core::EventLoop::current().post_event(*window, make<MouseEvent>(Event::MouseMove, mouse_position, buttons, to_mouse_button(button), modifiers, wheel_delta_x, wheel_delta_y, wheel_raw_delta_x, wheel_raw_delta_y));
}
if (auto* window = Window::from_window_id(window_id))
Core::EventLoop::current().post_event(*window, make<MouseEvent>(Event::MouseMove, mouse_position, buttons, to_mouse_button(button), modifiers, wheel_delta_x, wheel_delta_y, wheel_raw_delta_x, wheel_raw_delta_y));
}
void ConnectionToWindowServer::mouse_double_click(i32 window_id, Gfx::IntPoint mouse_position, u32 button, u32 buttons, u32 modifiers, i32 wheel_delta_x, i32 wheel_delta_y, i32 wheel_raw_delta_x, i32 wheel_raw_delta_y)
@ -349,12 +345,16 @@ void ConnectionToWindowServer::applet_area_rect_changed(Gfx::IntRect const& rect
});
}
void ConnectionToWindowServer::drag_dropped(i32 window_id, Gfx::IntPoint mouse_position, ByteString const& text, HashMap<String, ByteBuffer> const& mime_data)
void ConnectionToWindowServer::drag_moved(i32 window_id, Gfx::IntPoint mouse_position, u32 button, u32 buttons, u32 modifiers, ByteString const& text, HashMap<String, ByteBuffer> const& mime_data)
{
if (auto* window = Window::from_window_id(window_id)) {
auto mime_data_obj = Core::MimeData::construct(mime_data);
Core::EventLoop::current().post_event(*window, make<DropEvent>(mouse_position, text, mime_data_obj));
}
if (auto* window = Window::from_window_id(window_id))
Core::EventLoop::current().post_event(*window, make<DragEvent>(Event::Type::DragMove, mouse_position, to_mouse_button(button), buttons, modifiers, text, Core::MimeData::construct(mime_data)));
}
void ConnectionToWindowServer::drag_dropped(i32 window_id, Gfx::IntPoint mouse_position, u32 button, u32 buttons, u32 modifiers, ByteString const& text, HashMap<String, ByteBuffer> const& mime_data)
{
if (auto* window = Window::from_window_id(window_id))
Core::EventLoop::current().post_event(*window, make<DropEvent>(Event::Type::Drop, mouse_position, to_mouse_button(button), buttons, modifiers, text, Core::MimeData::construct(mime_data)));
}
void ConnectionToWindowServer::drag_accepted()

View file

@ -26,7 +26,7 @@ private:
virtual void fast_greet(Vector<Gfx::IntRect> const&, u32, u32, u32, Core::AnonymousBuffer const&, ByteString const&, ByteString const&, ByteString const&, Vector<bool> const&, i32) override;
virtual void paint(i32, Gfx::IntSize, Vector<Gfx::IntRect> const&) override;
virtual void mouse_move(i32, Gfx::IntPoint, u32, u32, u32, i32, i32, i32, i32, bool, Vector<String> const&) override;
virtual void mouse_move(i32, Gfx::IntPoint, u32, u32, u32, i32, i32, i32, i32) override;
virtual void mouse_down(i32, Gfx::IntPoint, u32, u32, u32, i32, i32, i32, i32) override;
virtual void mouse_double_click(i32, Gfx::IntPoint, u32, u32, u32, i32, i32, i32, i32) override;
virtual void mouse_up(i32, Gfx::IntPoint, u32, u32, u32, i32, i32, i32, i32) override;
@ -48,7 +48,8 @@ private:
virtual void menu_visibility_did_change(i32, bool) override;
virtual void screen_rects_changed(Vector<Gfx::IntRect> const&, u32, u32, u32) override;
virtual void applet_area_rect_changed(Gfx::IntRect const&) override;
virtual void drag_dropped(i32, Gfx::IntPoint, ByteString const&, HashMap<String, ByteBuffer> const&) override;
virtual void drag_moved(i32, Gfx::IntPoint, u32 button, u32 buttons, u32 modifiers, ByteString const&, HashMap<String, ByteBuffer> const&) override;
virtual void drag_dropped(i32, Gfx::IntPoint, u32 button, u32 buttons, u32 modifiers, ByteString const&, HashMap<String, ByteBuffer> const&) override;
virtual void drag_accepted() override;
virtual void drag_cancelled() override;
virtual void update_system_theme(Core::AnonymousBuffer const&) override;

View file

@ -12,9 +12,12 @@
namespace GUI {
DropEvent::DropEvent(Gfx::IntPoint position, ByteString const& text, NonnullRefPtr<Core::MimeData const> mime_data)
: Event(Event::Drop)
DropEvent::DropEvent(Type type, Gfx::IntPoint position, MouseButton button, u32 buttons, u32 modifiers, ByteString const& text, NonnullRefPtr<Core::MimeData const> mime_data)
: Event(type)
, m_position(position)
, m_button(button)
, m_buttons(buttons)
, m_modifiers(modifiers)
, m_text(text)
, m_mime_data(move(mime_data))
{
@ -22,6 +25,13 @@ DropEvent::DropEvent(Gfx::IntPoint position, ByteString const& text, NonnullRefP
DropEvent::~DropEvent() = default;
DragEvent::DragEvent(Type type, Gfx::IntPoint position, MouseButton button, u32 buttons, u32 modifiers, ByteString const& text, NonnullRefPtr<Core::MimeData const> mime_data)
: DropEvent(type, position, button, buttons, modifiers, text, move(mime_data))
{
}
DragEvent::~DragEvent() = default;
ByteString KeyEvent::to_byte_string() const
{
Vector<ByteString, 8> parts;

View file

@ -482,39 +482,33 @@ private:
int m_wheel_raw_delta_y { 0 };
};
class DragEvent final : public Event {
class DropEvent : public Event {
public:
DragEvent(Type type, Gfx::IntPoint position, Vector<String> mime_types)
: Event(type)
, m_position(position)
, m_mime_types(move(mime_types))
{
}
Gfx::IntPoint position() const { return m_position; }
Vector<String> const& mime_types() const { return m_mime_types; }
private:
Gfx::IntPoint m_position;
Vector<String> m_mime_types;
};
class DropEvent final : public Event {
public:
DropEvent(Gfx::IntPoint, ByteString const& text, NonnullRefPtr<Core::MimeData const> mime_data);
DropEvent(Type type, Gfx::IntPoint, MouseButton button, u32 buttons, u32 modifiers, ByteString const& text, NonnullRefPtr<Core::MimeData const> mime_data);
~DropEvent();
Gfx::IntPoint position() const { return m_position; }
MouseButton button() const { return m_button; }
unsigned buttons() const { return m_buttons; }
unsigned modifiers() const { return m_modifiers; }
ByteString const& text() const { return m_text; }
Core::MimeData const& mime_data() const { return m_mime_data; }
private:
Gfx::IntPoint m_position;
MouseButton m_button { MouseButton::None };
unsigned m_buttons { 0 };
unsigned m_modifiers { 0 };
ByteString m_text;
NonnullRefPtr<Core::MimeData const> m_mime_data;
};
class DragEvent final : public DropEvent {
public:
DragEvent(Type type, Gfx::IntPoint, MouseButton button, u32 buttons, u32 modifiers, ByteString const& text, NonnullRefPtr<Core::MimeData const> mime_data);
~DragEvent();
};
class ThemeChangeEvent final : public Event {
public:
ThemeChangeEvent()

View file

@ -855,9 +855,9 @@ ErrorOr<String> FileSystemModel::column_name(int column) const
VERIFY_NOT_REACHED();
}
bool FileSystemModel::accepts_drag(ModelIndex const& index, Vector<String> const& mime_types) const
bool FileSystemModel::accepts_drag(ModelIndex const& index, Core::MimeData const& mime_data) const
{
if (!mime_types.contains_slow("text/uri-list"sv))
if (!mime_data.has_urls())
return false;
if (!index.is_valid())

View file

@ -133,7 +133,7 @@ public:
virtual ModelIndex parent_index(ModelIndex const&) const override;
virtual ModelIndex index(int row, int column = 0, ModelIndex const& parent = ModelIndex()) const override;
virtual StringView drag_data_type() const override { return "text/uri-list"sv; }
virtual bool accepts_drag(ModelIndex const&, Vector<String> const& mime_types) const override;
virtual bool accepts_drag(ModelIndex const&, Core::MimeData const&) const override;
virtual bool is_column_sortable(int column_index) const override { return column_index != Column::Icon; }
virtual bool is_editable(ModelIndex const&) const override;
virtual bool is_searchable() const override { return true; }

View file

@ -63,7 +63,7 @@ ModelIndex Model::index(int row, int column, ModelIndex const&) const
return create_index(row, column);
}
bool Model::accepts_drag(ModelIndex const&, Vector<String> const&) const
bool Model::accepts_drag(ModelIndex const&, Core::MimeData const&) const
{
return false;
}

View file

@ -81,7 +81,7 @@ public:
virtual bool is_searchable() const { return false; }
virtual void set_data(ModelIndex const&, Variant const&) { }
virtual int tree_column() const { return 0; }
virtual bool accepts_drag(ModelIndex const&, Vector<String> const& mime_types) const;
virtual bool accepts_drag(ModelIndex const&, Core::MimeData const&) const;
virtual Vector<ModelIndex> matches(StringView, unsigned = MatchesFlag::AllMatching, ModelIndex const& = ModelIndex()) { return {}; }
virtual bool is_column_sortable([[maybe_unused]] int column_index) const { return true; }

View file

@ -69,7 +69,7 @@ PathBreadcrumbbar::PathBreadcrumbbar(NonnullRefPtr<GUI::TextBox> location_text_b
};
m_breadcrumbbar->on_segment_drag_enter = [&](size_t, GUI::DragEvent& event) {
if (event.mime_types().contains_slow("text/uri-list"sv))
if (event.mime_data().has_urls())
event.accept();
};

View file

@ -49,9 +49,9 @@ void SortingProxyModel::model_did_update(unsigned flags)
update_sort(flags);
}
bool SortingProxyModel::accepts_drag(ModelIndex const& proxy_index, Vector<String> const& mime_types) const
bool SortingProxyModel::accepts_drag(ModelIndex const& proxy_index, Core::MimeData const& mime_data) const
{
return source().accepts_drag(map_to_source(proxy_index), mime_types);
return source().accepts_drag(map_to_source(proxy_index), mime_data);
}
int SortingProxyModel::row_count(ModelIndex const& proxy_index) const

View file

@ -34,7 +34,7 @@ public:
virtual bool is_searchable() const override;
virtual void set_data(ModelIndex const&, Variant const&) override;
virtual Vector<ModelIndex> matches(StringView, unsigned = MatchesFlag::AllMatching, ModelIndex const& = ModelIndex()) override;
virtual bool accepts_drag(ModelIndex const&, Vector<String> const& mime_types) const override;
virtual bool accepts_drag(ModelIndex const&, Core::MimeData const&) const override;
virtual bool is_column_sortable(int column_index) const override;

View file

@ -11,6 +11,7 @@
#include <AK/JsonObject.h>
#include <AK/NonnullRefPtr.h>
#include <AK/RefPtr.h>
#include <LibCore/MimeData.h>
#include <LibGUI/Action.h>
#include <LibGUI/Application.h>
#include <LibGUI/BoxLayout.h>
@ -532,9 +533,7 @@ void Widget::drag_move_event(DragEvent&)
void Widget::drag_enter_event(DragEvent& event)
{
StringBuilder builder;
builder.join(',', event.mime_types());
dbgln_if(DRAG_DEBUG, "{} {:p} DRAG ENTER @ {}, {}", class_name(), this, event.position(), builder.string_view());
dbgln_if(DRAG_DEBUG, "{} {:p} DRAG ENTER @ {}, {}", class_name(), this, event.position(), event.mime_data().formats());
}
void Widget::drag_leave_event(Event&)

View file

@ -432,7 +432,7 @@ void Window::handle_drop_event(DropEvent& event)
if (!m_main_widget)
return;
auto result = m_main_widget->hit_test(event.position());
auto local_event = make<DropEvent>(result.local_position, event.text(), event.mime_data());
auto local_event = make<DropEvent>(Event::Type::Drop, result.local_position, event.button(), event.buttons(), event.modifiers(), event.text(), event.mime_data());
VERIFY(result.widget);
result.widget->dispatch_event(*local_event, this);
@ -766,14 +766,14 @@ void Window::handle_drag_move_event(DragEvent& event)
auto result = m_main_widget->hit_test(event.position());
VERIFY(result.widget);
Application::the()->set_drag_hovered_widget({}, result.widget, result.local_position, event.mime_types());
Application::the()->set_drag_hovered_widget({}, result.widget, result.local_position, event);
// NOTE: Setting the drag hovered widget may have executed arbitrary code, so re-check that the widget is still there.
if (!result.widget)
return;
if (result.widget->has_pending_drop()) {
DragEvent drag_move_event(static_cast<Event::Type>(event.type()), result.local_position, event.mime_types());
DragEvent drag_move_event(static_cast<Event::Type>(event.type()), result.local_position, event.button(), event.buttons(), event.modifiers(), event.text(), event.mime_data());
result.widget->dispatch_event(drag_move_event, this);
}
}

View file

@ -1199,8 +1199,7 @@ void TerminalWidget::context_menu_event(GUI::ContextMenuEvent& event)
void TerminalWidget::drag_enter_event(GUI::DragEvent& event)
{
auto const& mime_types = event.mime_types();
if (mime_types.contains_slow("text/plain"sv) || mime_types.contains_slow("text/uri-list"sv))
if (event.mime_data().has_text() || event.mime_data().has_urls())
event.accept();
}

View file

@ -152,8 +152,7 @@ void QuickLaunchWidget::config_string_did_change(StringView domain, StringView g
void QuickLaunchWidget::drag_enter_event(GUI::DragEvent& event)
{
auto const& mime_types = event.mime_types();
if (mime_types.contains_slow("text/uri-list"sv))
if (event.mime_data().has_urls())
event.accept();
}

View file

@ -5,6 +5,7 @@
*/
#include <AK/Badge.h>
#include <LibCore/MimeData.h>
#include <LibGfx/Bitmap.h>
#include <LibGfx/StandardCursor.h>
#include <LibGfx/SystemTheme.h>

View file

@ -9,7 +9,6 @@
#include <AK/ByteString.h>
#include <Kernel/API/KeyCode.h>
#include <LibCore/Event.h>
#include <LibCore/MimeData.h>
#include <LibGfx/Rect.h>
#include <WindowServer/Cursor.h>
#include <WindowServer/WindowType.h>
@ -115,17 +114,6 @@ public:
int wheel_delta_y() const { return m_wheel_delta_y; }
int wheel_raw_delta_x() const { return m_wheel_raw_delta_x; }
int wheel_raw_delta_y() const { return m_wheel_raw_delta_y; }
bool is_drag() const { return m_drag; }
Vector<String> mime_types() const
{
if (!m_mime_data)
return {};
return m_mime_data->formats();
}
void set_drag(bool b) { m_drag = b; }
void set_mime_data(Core::MimeData const& mime_data) { m_mime_data = mime_data; }
MouseEvent translated(Gfx::IntPoint delta) const
{
@ -143,8 +131,6 @@ private:
int m_wheel_delta_y { 0 };
int m_wheel_raw_delta_x { 0 };
int m_wheel_raw_delta_y { 0 };
bool m_drag { false };
RefPtr<Core::MimeData const> m_mime_data;
};
class ResizeEvent final : public Event {

View file

@ -438,10 +438,9 @@ void ScreenInput::on_receive_mouse_data(MousePacket const& packet)
post_mousedown_or_mouseup_if_needed(MouseButton::Middle);
post_mousedown_or_mouseup_if_needed(MouseButton::Backward);
post_mousedown_or_mouseup_if_needed(MouseButton::Forward);
if (m_cursor_location != prev_location) {
auto message = make<MouseEvent>(Event::MouseMove, m_cursor_location, buttons, MouseButton::None, m_modifiers);
if (WindowManager::the().dnd_client())
message->set_mime_data(WindowManager::the().dnd_mime_data());
Core::EventLoop::current().post_event(WindowManager::the(), move(message));
}

View file

@ -209,7 +209,7 @@ void Window::handle_mouse_event(MouseEvent const& event)
switch (event.type()) {
case Event::MouseMove:
m_client->async_mouse_move(m_window_id, event.position(), (u32)event.button(), event.buttons(), event.modifiers(), event.wheel_delta_x(), event.wheel_delta_y(), event.wheel_raw_delta_x(), event.wheel_raw_delta_y(), event.is_drag(), event.mime_types());
m_client->async_mouse_move(m_window_id, event.position(), (u32)event.button(), event.buttons(), event.modifiers(), event.wheel_delta_x(), event.wheel_delta_y(), event.wheel_raw_delta_x(), event.wheel_raw_delta_y());
break;
case Event::MouseDown:
m_client->async_mouse_down(m_window_id, event.position(), (u32)event.button(), event.buttons(), event.modifiers(), event.wheel_delta_x(), event.wheel_delta_y(), event.wheel_raw_delta_x(), event.wheel_raw_delta_y());

View file

@ -6,7 +6,7 @@ endpoint WindowClient
fast_greet(Vector<Gfx::IntRect> screen_rects, u32 main_screen_index, u32 workspace_rows, u32 workspace_columns, Core::AnonymousBuffer theme_buffer, ByteString default_font_query, ByteString fixed_width_font_query, ByteString window_title_font_query, Vector<bool> effects, i32 client_id) =|
paint(i32 window_id, Gfx::IntSize window_size, Vector<Gfx::IntRect> rects) =|
mouse_move(i32 window_id, Gfx::IntPoint mouse_position, u32 button, u32 buttons, u32 modifiers, i32 wheel_delta_x, i32 wheel_delta_y, i32 wheel_raw_delta_x, i32 wheel_raw_delta_y, bool is_drag, Vector<String> mime_types) =|
mouse_move(i32 window_id, Gfx::IntPoint mouse_position, u32 button, u32 buttons, u32 modifiers, i32 wheel_delta_x, i32 wheel_delta_y, i32 wheel_raw_delta_x, i32 wheel_raw_delta_y) =|
mouse_down(i32 window_id, Gfx::IntPoint mouse_position, u32 button, u32 buttons, u32 modifiers, i32 wheel_delta_x, i32 wheel_delta_y, i32 wheel_raw_delta_x, i32 wheel_raw_delta_y) =|
mouse_double_click(i32 window_id, Gfx::IntPoint mouse_position, u32 button, u32 buttons, u32 modifiers, i32 wheel_delta_x, i32 wheel_delta_y, i32 wheel_raw_delta_x, i32 wheel_raw_delta_y) =|
mouse_up(i32 window_id, Gfx::IntPoint mouse_position, u32 button, u32 buttons, u32 modifiers, i32 wheel_delta_x, i32 wheel_delta_y, i32 wheel_raw_delta_x, i32 wheel_raw_delta_y) =|
@ -36,7 +36,8 @@ endpoint WindowClient
drag_accepted() =|
drag_cancelled() =|
drag_dropped(i32 window_id, Gfx::IntPoint mouse_position, [UTF8] ByteString text, HashMap<String, ByteBuffer> mime_data) =|
drag_moved(i32 window_id, Gfx::IntPoint mouse_position, u32 button, u32 buttons, u32 modifiers, [UTF8] ByteString text, HashMap<String, ByteBuffer> mime_data) =|
drag_dropped(i32 window_id, Gfx::IntPoint mouse_position, u32 button, u32 buttons, u32 modifiers, [UTF8] ByteString text, HashMap<String, ByteBuffer> mime_data) =|
update_system_theme(Core::AnonymousBuffer theme_buffer) =|
update_system_fonts(ByteString default_font_query, ByteString fixed_width_font_query, ByteString window_title_font_query) =|

View file

@ -1110,38 +1110,48 @@ bool WindowManager::process_ongoing_drag(MouseEvent& event)
if (!m_dnd_client)
return false;
auto send_dnd_event = [&](auto callback) {
auto* window = hovered_window();
if (!window || !window->client())
return false;
auto translated_event = event.translated(-window->position());
auto mime_data = m_dnd_mime_data->all_data().clone();
// If the mime data is so large that it causes memory troubles, we should silently drop the drag'n'drop request entirely.
if (mime_data.is_error()) {
dbgln("Drag and drop mimetype data nearly caused OOM and was dropped: {}", mime_data.release_error());
return false;
}
callback(*window, translated_event.position(), mime_data.release_value());
return true;
};
if (event.type() == Event::MouseMove) {
m_dnd_overlay->cursor_moved();
// We didn't let go of the drag yet, see if we should send some drag move events..
if (auto* window = hovered_window()) {
event.set_drag(true);
event.set_mime_data(*m_dnd_mime_data);
deliver_mouse_event(*window, event);
} else {
auto event_sent = send_dnd_event([&](auto& window, auto event_position, auto mime_data) {
window.client()->async_drag_moved(window.window_id(), event_position, event.button(), event.buttons(), event.modifiers(), m_dnd_text, move(mime_data));
});
if (!event_sent)
set_accepts_drag(false);
}
}
if (!(event.type() == Event::MouseUp && event.button() == MouseButton::Primary))
return true;
if (event.type() == Event::MouseUp && event.button() == MouseButton::Primary) {
auto event_sent = send_dnd_event([&](auto& window, auto event_position, auto mime_data) {
m_dnd_client->async_drag_accepted();
window.client()->async_drag_dropped(window.window_id(), event_position, event.button(), event.buttons(), event.modifiers(), m_dnd_text, move(mime_data));
});
if (auto* window = hovered_window()) {
m_dnd_client->async_drag_accepted();
if (window->client()) {
auto translated_event = event.translated(-window->position());
auto copied_mime_data_or_error = m_dnd_mime_data->all_data().clone();
// If the mime data is so large that it causes memory troubles, we should silently drop the drag'n'drop request entirely.
if (copied_mime_data_or_error.is_error())
dbgln("Drag and drop mimetype data nearly caused OOM and was dropped: {}", copied_mime_data_or_error.release_error());
else
window->client()->async_drag_dropped(window->window_id(), translated_event.position(), m_dnd_text, copied_mime_data_or_error.release_value());
}
} else {
m_dnd_client->async_drag_cancelled();
if (!event_sent)
m_dnd_client->async_drag_cancelled();
end_dnd_drag();
}
end_dnd_drag();
return true;
}