ソースを参照

WindowServer+LibGUI: Add data_type and data fields to drag operations

These fields are intended to carry the real meat of a drag operation,
and the "text" is just for what we show on screen (alongside the cursor
during the actual drag.)

The data field is just a String for now, but in the future we should
make it something more flexible.
Andreas Kling 5 年 前
コミット
cfcb38dff1

+ 9 - 0
Libraries/LibGUI/GDirectoryModel.cpp

@@ -247,6 +247,15 @@ GVariant GDirectoryModel::data(const GModelIndex& index, Role role) const
         ASSERT(index.column() == Column::Name);
         ASSERT(index.column() == Column::Name);
         return entry.full_path(*this);
         return entry.full_path(*this);
     }
     }
+    if (role == Role::DragData) {
+        if (index.column() == Column::Name) {
+            StringBuilder builder;
+            builder.append("file://");
+            builder.append(entry.full_path(*this));
+            return builder.to_string();
+        }
+        return {};
+    }
     if (role == Role::Sort) {
     if (role == Role::Sort) {
         switch (index.column()) {
         switch (index.column()) {
         case Column::Icon:
         case Column::Icon:

+ 1 - 1
Libraries/LibGUI/GDragOperation.cpp

@@ -28,7 +28,7 @@ GDragOperation::Outcome GDragOperation::exec()
         bitmap_size = shared_bitmap->size();
         bitmap_size = shared_bitmap->size();
     }
     }
 
 
-    auto response = GWindowServerConnection::the().send_sync<WindowServer::StartDrag>(m_text, bitmap_id, bitmap_size);
+    auto response = GWindowServerConnection::the().send_sync<WindowServer::StartDrag>(m_text, m_data_type, m_data, bitmap_id, bitmap_size);
     if (!response->started()) {
     if (!response->started()) {
         m_outcome = Outcome::Cancelled;
         m_outcome = Outcome::Cancelled;
         return m_outcome;
         return m_outcome;

+ 7 - 0
Libraries/LibGUI/GDragOperation.h

@@ -19,6 +19,11 @@ public:
 
 
     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; }
     void set_bitmap(const GraphicsBitmap* bitmap) { m_bitmap = bitmap; }
+    void set_data(const String& data_type, const String& data)
+    {
+        m_data_type = data_type;
+        m_data = data;
+    }
 
 
     Outcome exec();
     Outcome exec();
     Outcome outcome() const { return m_outcome; }
     Outcome outcome() const { return m_outcome; }
@@ -35,5 +40,7 @@ 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;
+    String m_data_type;
+    String m_data;
     RefPtr<GraphicsBitmap> m_bitmap;
     RefPtr<GraphicsBitmap> m_bitmap;
 };
 };

+ 7 - 1
Libraries/LibGUI/GEvent.h

@@ -282,17 +282,23 @@ private:
 
 
 class GDropEvent final : public GEvent {
 class GDropEvent final : public GEvent {
 public:
 public:
-    GDropEvent(const Point& position, const String& text)
+    GDropEvent(const Point& position, const String& text, const String& data_type, const String& data)
         : GEvent(GEvent::Drop)
         : GEvent(GEvent::Drop)
         , m_position(position)
         , m_position(position)
         , m_text(text)
         , m_text(text)
+        , m_data_type(data_type)
+        , m_data(data)
     {
     {
     }
     }
 
 
     const Point& position() const { return m_position; }
     const Point& position() const { return m_position; }
     const String& text() const { return m_text; }
     const String& text() const { return m_text; }
+    const String& data_type() const { return m_data_type; }
+    const String& data() const { return m_data; }
 
 
 private:
 private:
     Point m_position;
     Point m_position;
     String m_text;
     String m_text;
+    String m_data_type;
+    String m_data;
 };
 };

+ 11 - 5
Libraries/LibGUI/GItemView.cpp

@@ -115,11 +115,16 @@ void GItemView::mousemove_event(GMouseEvent& event)
 
 
             RefPtr<GraphicsBitmap> bitmap;
             RefPtr<GraphicsBitmap> bitmap;
 
 
-            StringBuilder builder;
+            StringBuilder text_builder;
+            StringBuilder data_builder;
             selection().for_each_index([&](auto& index) {
             selection().for_each_index([&](auto& index) {
-                auto data = model()->data(index);
-                builder.append(data.to_string());
-                builder.append(" ");
+                auto text_data = model()->data(index);
+                text_builder.append(text_data.to_string());
+                text_builder.append(" ");
+
+                auto drag_data = model()->data(index, GModel::Role::DragData);
+                data_builder.append(drag_data.to_string());
+                data_builder.append('\n');
 
 
                 if (!bitmap) {
                 if (!bitmap) {
                     GVariant icon_data = model()->data(index, GModel::Role::Icon);
                     GVariant icon_data = model()->data(index, GModel::Role::Icon);
@@ -128,8 +133,9 @@ void GItemView::mousemove_event(GMouseEvent& event)
                 }
                 }
             });
             });
 
 
-            drag_operation->set_text(builder.to_string());
+            drag_operation->set_text(text_builder.to_string());
             drag_operation->set_bitmap(bitmap);
             drag_operation->set_bitmap(bitmap);
+            drag_operation->set_data("url-list", data_builder.to_string());
             auto outcome = drag_operation->exec();
             auto outcome = drag_operation->exec();
             switch (outcome) {
             switch (outcome) {
             case GDragOperation::Outcome::Accepted:
             case GDragOperation::Outcome::Accepted:

+ 1 - 0
Libraries/LibGUI/GModel.h

@@ -36,6 +36,7 @@ public:
         BackgroundColor,
         BackgroundColor,
         Icon,
         Icon,
         Font,
         Font,
+        DragData,
     };
     };
 
 
     virtual ~GModel();
     virtual ~GModel();

+ 1 - 1
Libraries/LibGUI/GWindow.cpp

@@ -159,7 +159,7 @@ void GWindow::event(CEvent& event)
         if (!m_main_widget)
         if (!m_main_widget)
             return;
             return;
         auto result = m_main_widget->hit_test(drop_event.position());
         auto result = m_main_widget->hit_test(drop_event.position());
-        auto local_event = make<GDropEvent>(result.local_position, drop_event.text());
+        auto local_event = make<GDropEvent>(result.local_position, drop_event.text(), drop_event.data_type(), drop_event.data());
         ASSERT(result.widget);
         ASSERT(result.widget);
         return result.widget->dispatch_event(*local_event, this);
         return result.widget->dispatch_event(*local_event, this);
     }
     }

+ 1 - 1
Libraries/LibGUI/GWindowServerConnection.cpp

@@ -266,7 +266,7 @@ void GWindowServerConnection::handle(const WindowClient::AsyncSetWallpaperFinish
 void GWindowServerConnection::handle(const WindowClient::DragDropped& message)
 void GWindowServerConnection::handle(const WindowClient::DragDropped& message)
 {
 {
     if (auto* window = GWindow::from_window_id(message.window_id()))
     if (auto* window = GWindow::from_window_id(message.window_id()))
-        CEventLoop::current().post_event(*window, make<GDropEvent>(message.mouse_position(), message.text()));
+        CEventLoop::current().post_event(*window, make<GDropEvent>(message.mouse_position(), message.text(), message.data_type(), message.data()));
 }
 }
 
 
 void GWindowServerConnection::handle(const WindowClient::DragAccepted&)
 void GWindowServerConnection::handle(const WindowClient::DragAccepted&)

+ 1 - 1
Servers/WindowServer/WSClientConnection.cpp

@@ -651,6 +651,6 @@ OwnPtr<WindowServer::StartDragResponse> WSClientConnection::handle(const WindowS
         bitmap = GraphicsBitmap::create_with_shared_buffer(GraphicsBitmap::Format::RGBA32, *shared_buffer, message.bitmap_size());
         bitmap = GraphicsBitmap::create_with_shared_buffer(GraphicsBitmap::Format::RGBA32, *shared_buffer, message.bitmap_size());
     }
     }
 
 
-    wm.start_dnd_drag(*this, message.text(), bitmap);
+    wm.start_dnd_drag(*this, message.text(), bitmap, message.data_type(), message.data());
     return make<WindowServer::StartDragResponse>(true);
     return make<WindowServer::StartDragResponse>(true);
 }
 }

+ 4 - 2
Servers/WindowServer/WSWindowManager.cpp

@@ -649,7 +649,7 @@ bool WSWindowManager::process_ongoing_drag(WSMouseEvent& event, WSWindow*& hover
         m_dnd_client->post_message(WindowClient::DragAccepted());
         m_dnd_client->post_message(WindowClient::DragAccepted());
         if (hovered_window->client()) {
         if (hovered_window->client()) {
             auto translated_event = event.translated(-hovered_window->position());
             auto translated_event = event.translated(-hovered_window->position());
-            hovered_window->client()->post_message(WindowClient::DragDropped(hovered_window->window_id(), translated_event.position(), m_dnd_text));
+            hovered_window->client()->post_message(WindowClient::DragDropped(hovered_window->window_id(), translated_event.position(), m_dnd_text, m_dnd_data_type, m_dnd_data));
         }
         }
     } else {
     } else {
         m_dnd_client->post_message(WindowClient::DragCancelled());
         m_dnd_client->post_message(WindowClient::DragCancelled());
@@ -1190,12 +1190,14 @@ WSMenu* WSWindowManager::find_internal_menu_by_id(int menu_id)
     return nullptr;
     return nullptr;
 }
 }
 
 
-void WSWindowManager::start_dnd_drag(WSClientConnection& client, const String& text, GraphicsBitmap* bitmap)
+void WSWindowManager::start_dnd_drag(WSClientConnection& client, const String& text, GraphicsBitmap* bitmap, const String& data_type, const String& data)
 {
 {
     ASSERT(!m_dnd_client);
     ASSERT(!m_dnd_client);
     m_dnd_client = client.make_weak_ptr();
     m_dnd_client = client.make_weak_ptr();
     m_dnd_text = text;
     m_dnd_text = text;
     m_dnd_bitmap = bitmap;
     m_dnd_bitmap = bitmap;
+    m_dnd_data_type = data_type;
+    m_dnd_data = data;
     WSCompositor::the().invalidate_cursor();
     WSCompositor::the().invalidate_cursor();
 }
 }
 
 

+ 5 - 1
Servers/WindowServer/WSWindowManager.h

@@ -68,10 +68,12 @@ public:
 
 
     WSClientConnection* dnd_client() { return m_dnd_client.ptr(); }
     WSClientConnection* dnd_client() { return m_dnd_client.ptr(); }
     const String& dnd_text() const { return m_dnd_text; }
     const String& dnd_text() const { return m_dnd_text; }
+    const String& dnd_data_type() const { return m_dnd_data_type; }
+    const String& dnd_data() const { return m_dnd_data; }
     const GraphicsBitmap* dnd_bitmap() const { return m_dnd_bitmap; }
     const GraphicsBitmap* dnd_bitmap() const { return m_dnd_bitmap; }
     Rect dnd_rect() const;
     Rect dnd_rect() const;
 
 
-    void start_dnd_drag(WSClientConnection&, const String& text, GraphicsBitmap*);
+    void start_dnd_drag(WSClientConnection&, const String& text, GraphicsBitmap*, const String& data_type, const String& data);
     void end_dnd_drag();
     void end_dnd_drag();
 
 
     WSWindow* active_window() { return m_active_window.ptr(); }
     WSWindow* active_window() { return m_active_window.ptr(); }
@@ -283,6 +285,8 @@ private:
 
 
     WeakPtr<WSClientConnection> m_dnd_client;
     WeakPtr<WSClientConnection> m_dnd_client;
     String m_dnd_text;
     String m_dnd_text;
+    String m_dnd_data_type;
+    String m_dnd_data;
     RefPtr<GraphicsBitmap> m_dnd_bitmap;
     RefPtr<GraphicsBitmap> m_dnd_bitmap;
 };
 };
 
 

+ 1 - 1
Servers/WindowServer/WindowClient.ipc

@@ -31,5 +31,5 @@ endpoint WindowClient = 4
     DragAccepted() =|
     DragAccepted() =|
     DragCancelled() =|
     DragCancelled() =|
 
 
-    DragDropped(i32 window_id, Point mouse_position, String text) =|
+    DragDropped(i32 window_id, Point mouse_position, String text, String data_type, String data) =|
 }
 }

+ 1 - 1
Servers/WindowServer/WindowServer.ipc

@@ -67,5 +67,5 @@ endpoint WindowServer = 2
     GetWallpaper() => (String path)
     GetWallpaper() => (String path)
     SetWindowOverrideCursor(i32 window_id, i32 cursor_type) => ()
     SetWindowOverrideCursor(i32 window_id, i32 cursor_type) => ()
 
 
-    StartDrag(String text, i32 bitmap_id, Size bitmap_size) => (bool started)
+    StartDrag(String text, String data_type, String data, i32 bitmap_id, Size bitmap_size) => (bool started)
 }
 }