diff --git a/Libraries/LibGUI/GDragOperation.cpp b/Libraries/LibGUI/GDragOperation.cpp index b88b863f84..729e7269f8 100644 --- a/Libraries/LibGUI/GDragOperation.cpp +++ b/Libraries/LibGUI/GDragOperation.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -17,7 +18,17 @@ GDragOperation::Outcome GDragOperation::exec() ASSERT(!s_current_drag_operation); ASSERT(!m_event_loop); - auto response = GWindowServerConnection::the().send_sync(m_text, -1, Size()); + int bitmap_id = -1; + Size bitmap_size; + RefPtr shared_bitmap; + if (m_bitmap) { + shared_bitmap = m_bitmap->to_shareable_bitmap(); + shared_bitmap->shared_buffer()->share_with(GWindowServerConnection::the().server_pid()); + bitmap_id = shared_bitmap->shared_buffer_id(); + bitmap_size = shared_bitmap->size(); + } + + auto response = GWindowServerConnection::the().send_sync(m_text, bitmap_id, bitmap_size); if (!response->started()) { m_outcome = Outcome::Cancelled; return m_outcome; diff --git a/Libraries/LibGUI/GDragOperation.h b/Libraries/LibGUI/GDragOperation.h index e21b9d4470..a4f87c15b4 100644 --- a/Libraries/LibGUI/GDragOperation.h +++ b/Libraries/LibGUI/GDragOperation.h @@ -3,6 +3,7 @@ #include #include +class GraphicsBitmap; class GWindowServerConnection; class GDragOperation : public CObject { @@ -17,6 +18,7 @@ public: virtual ~GDragOperation() override; void set_text(const String& text) { m_text = text; } + void set_bitmap(const GraphicsBitmap* bitmap) { m_bitmap = bitmap; } Outcome exec(); Outcome outcome() const { return m_outcome; } @@ -33,4 +35,5 @@ private: OwnPtr m_event_loop; Outcome m_outcome { Outcome::None }; String m_text; + RefPtr m_bitmap; }; diff --git a/Libraries/LibGUI/GItemView.cpp b/Libraries/LibGUI/GItemView.cpp index 042c0f164a..599db7e773 100644 --- a/Libraries/LibGUI/GItemView.cpp +++ b/Libraries/LibGUI/GItemView.cpp @@ -113,14 +113,23 @@ void GItemView::mousemove_event(GMouseEvent& event) dbg() << "Initiate drag!"; auto drag_operation = GDragOperation::construct(); + RefPtr bitmap; + StringBuilder builder; selection().for_each_index([&](auto& index) { auto data = model()->data(index); builder.append(data.to_string()); builder.append(" "); + + if (!bitmap) { + GVariant icon_data = model()->data(index, GModel::Role::Icon); + if (icon_data.is_icon()) + bitmap = icon_data.as_icon().bitmap_for_size(32); + } }); drag_operation->set_text(builder.to_string()); + drag_operation->set_bitmap(bitmap); auto outcome = drag_operation->exec(); switch (outcome) { case GDragOperation::Outcome::Accepted: diff --git a/Servers/WindowServer/WSCompositor.cpp b/Servers/WindowServer/WSCompositor.cpp index 8369217935..51d1e55e97 100644 --- a/Servers/WindowServer/WSCompositor.cpp +++ b/Servers/WindowServer/WSCompositor.cpp @@ -424,11 +424,16 @@ void WSCompositor::draw_cursor() if (wm.dnd_client()) { auto dnd_rect = wm.dnd_rect(); + m_back_painter->fill_rect(dnd_rect, Color(110, 34, 9, 200)); if (!wm.dnd_text().is_empty()) { - m_back_painter->fill_rect(dnd_rect, Color(110, 34, 9, 200)); - m_back_painter->draw_text(dnd_rect, wm.dnd_text(), TextAlignment::Center, Color::White); + auto text_rect = dnd_rect; + if (wm.dnd_bitmap()) + text_rect.move_by(wm.dnd_bitmap()->width(), 0); + m_back_painter->draw_text(text_rect, wm.dnd_text(), TextAlignment::CenterLeft, Color::White); + } + if (wm.dnd_bitmap()) { + m_back_painter->blit(dnd_rect.top_left(), *wm.dnd_bitmap(), wm.dnd_bitmap()->rect()); } - // FIXME: Also do the drag_bitmap if present m_last_dnd_rect = dnd_rect; } else { m_last_dnd_rect = {}; diff --git a/Servers/WindowServer/WSWindowManager.cpp b/Servers/WindowServer/WSWindowManager.cpp index 2bb4c12bd3..e6b2a86449 100644 --- a/Servers/WindowServer/WSWindowManager.cpp +++ b/Servers/WindowServer/WSWindowManager.cpp @@ -1199,8 +1199,10 @@ void WSWindowManager::end_dnd_drag() Rect WSWindowManager::dnd_rect() const { - int width = font().width(m_dnd_text); - int height = font().glyph_height(); + int bitmap_width = m_dnd_bitmap ? m_dnd_bitmap->width() : 0; + int bitmap_height = m_dnd_bitmap ? m_dnd_bitmap->width() : 0; + int width = font().width(m_dnd_text) + bitmap_width; + int height = max((int)font().glyph_height(), bitmap_height); auto location = WSCompositor::the().current_cursor_rect().center().translated(8, 8); return Rect(location, { width, height }).inflated(4, 4); }