mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 13:12:46 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									af7cb7ce1b
								
							
						
					
					
						commit
						cfcb38dff1
					
				
					 13 changed files with 50 additions and 15 deletions
				
			
		|  | @ -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: | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -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); |                 auto text_data = model()->data(index); | ||||||
|                 builder.append(data.to_string()); |                 text_builder.append(text_data.to_string()); | ||||||
|                 builder.append(" "); |                 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: | ||||||
|  |  | ||||||
|  | @ -36,6 +36,7 @@ public: | ||||||
|         BackgroundColor, |         BackgroundColor, | ||||||
|         Icon, |         Icon, | ||||||
|         Font, |         Font, | ||||||
|  |         DragData, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     virtual ~GModel(); |     virtual ~GModel(); | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -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&) | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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) =| | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling