mirror of
https://github.com/RGBCube/serenity
synced 2025-07-02 15:32:13 +00:00
LibGUI+WindowServer: Allow specifying an optional drag bitmap
This bitmap is displayed alongside the dragged text underneath the mouse cursor while dragging. This will be a perfect fit for dragging e.g files around. :^)
This commit is contained in:
parent
183ee5847c
commit
f5dfb29607
5 changed files with 36 additions and 6 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
#include <LibDraw/GraphicsBitmap.h>
|
||||||
#include <LibGUI/GDragOperation.h>
|
#include <LibGUI/GDragOperation.h>
|
||||||
#include <LibGUI/GWindowServerConnection.h>
|
#include <LibGUI/GWindowServerConnection.h>
|
||||||
|
|
||||||
|
@ -17,7 +18,17 @@ GDragOperation::Outcome GDragOperation::exec()
|
||||||
ASSERT(!s_current_drag_operation);
|
ASSERT(!s_current_drag_operation);
|
||||||
ASSERT(!m_event_loop);
|
ASSERT(!m_event_loop);
|
||||||
|
|
||||||
auto response = GWindowServerConnection::the().send_sync<WindowServer::StartDrag>(m_text, -1, Size());
|
int bitmap_id = -1;
|
||||||
|
Size bitmap_size;
|
||||||
|
RefPtr<GraphicsBitmap> 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<WindowServer::StartDrag>(m_text, bitmap_id, bitmap_size);
|
||||||
if (!response->started()) {
|
if (!response->started()) {
|
||||||
m_outcome = Outcome::Cancelled;
|
m_outcome = Outcome::Cancelled;
|
||||||
return m_outcome;
|
return m_outcome;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <LibCore/CEventLoop.h>
|
#include <LibCore/CEventLoop.h>
|
||||||
#include <LibCore/CObject.h>
|
#include <LibCore/CObject.h>
|
||||||
|
|
||||||
|
class GraphicsBitmap;
|
||||||
class GWindowServerConnection;
|
class GWindowServerConnection;
|
||||||
|
|
||||||
class GDragOperation : public CObject {
|
class GDragOperation : public CObject {
|
||||||
|
@ -17,6 +18,7 @@ public:
|
||||||
virtual ~GDragOperation() override;
|
virtual ~GDragOperation() override;
|
||||||
|
|
||||||
void set_text(const String& text) { m_text = text; }
|
void set_text(const String& text) { m_text = text; }
|
||||||
|
void set_bitmap(const GraphicsBitmap* bitmap) { m_bitmap = bitmap; }
|
||||||
|
|
||||||
Outcome exec();
|
Outcome exec();
|
||||||
Outcome outcome() const { return m_outcome; }
|
Outcome outcome() const { return m_outcome; }
|
||||||
|
@ -33,4 +35,5 @@ private:
|
||||||
OwnPtr<CEventLoop> m_event_loop;
|
OwnPtr<CEventLoop> m_event_loop;
|
||||||
Outcome m_outcome { Outcome::None };
|
Outcome m_outcome { Outcome::None };
|
||||||
String m_text;
|
String m_text;
|
||||||
|
RefPtr<GraphicsBitmap> m_bitmap;
|
||||||
};
|
};
|
||||||
|
|
|
@ -113,14 +113,23 @@ void GItemView::mousemove_event(GMouseEvent& event)
|
||||||
dbg() << "Initiate drag!";
|
dbg() << "Initiate drag!";
|
||||||
auto drag_operation = GDragOperation::construct();
|
auto drag_operation = GDragOperation::construct();
|
||||||
|
|
||||||
|
RefPtr<GraphicsBitmap> bitmap;
|
||||||
|
|
||||||
StringBuilder builder;
|
StringBuilder builder;
|
||||||
selection().for_each_index([&](auto& index) {
|
selection().for_each_index([&](auto& index) {
|
||||||
auto data = model()->data(index);
|
auto data = model()->data(index);
|
||||||
builder.append(data.to_string());
|
builder.append(data.to_string());
|
||||||
builder.append(" ");
|
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_text(builder.to_string());
|
||||||
|
drag_operation->set_bitmap(bitmap);
|
||||||
auto outcome = drag_operation->exec();
|
auto outcome = drag_operation->exec();
|
||||||
switch (outcome) {
|
switch (outcome) {
|
||||||
case GDragOperation::Outcome::Accepted:
|
case GDragOperation::Outcome::Accepted:
|
||||||
|
|
|
@ -424,11 +424,16 @@ void WSCompositor::draw_cursor()
|
||||||
|
|
||||||
if (wm.dnd_client()) {
|
if (wm.dnd_client()) {
|
||||||
auto dnd_rect = wm.dnd_rect();
|
auto dnd_rect = wm.dnd_rect();
|
||||||
|
m_back_painter->fill_rect(dnd_rect, Color(110, 34, 9, 200));
|
||||||
if (!wm.dnd_text().is_empty()) {
|
if (!wm.dnd_text().is_empty()) {
|
||||||
m_back_painter->fill_rect(dnd_rect, Color(110, 34, 9, 200));
|
auto text_rect = dnd_rect;
|
||||||
m_back_painter->draw_text(dnd_rect, wm.dnd_text(), TextAlignment::Center, Color::White);
|
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;
|
m_last_dnd_rect = dnd_rect;
|
||||||
} else {
|
} else {
|
||||||
m_last_dnd_rect = {};
|
m_last_dnd_rect = {};
|
||||||
|
|
|
@ -1199,8 +1199,10 @@ void WSWindowManager::end_dnd_drag()
|
||||||
|
|
||||||
Rect WSWindowManager::dnd_rect() const
|
Rect WSWindowManager::dnd_rect() const
|
||||||
{
|
{
|
||||||
int width = font().width(m_dnd_text);
|
int bitmap_width = m_dnd_bitmap ? m_dnd_bitmap->width() : 0;
|
||||||
int height = font().glyph_height();
|
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);
|
auto location = WSCompositor::the().current_cursor_rect().center().translated(8, 8);
|
||||||
return Rect(location, { width, height }).inflated(4, 4);
|
return Rect(location, { width, height }).inflated(4, 4);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue