mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 20:52:45 +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); | ||||
|         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) { | ||||
|         switch (index.column()) { | ||||
|         case Column::Icon: | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ GDragOperation::Outcome GDragOperation::exec() | |||
|         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()) { | ||||
|         m_outcome = Outcome::Cancelled; | ||||
|         return m_outcome; | ||||
|  |  | |||
|  | @ -19,6 +19,11 @@ public: | |||
| 
 | ||||
|     void set_text(const String& text) { m_text = text; } | ||||
|     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 outcome() const { return m_outcome; } | ||||
|  | @ -35,5 +40,7 @@ private: | |||
|     OwnPtr<CEventLoop> m_event_loop; | ||||
|     Outcome m_outcome { Outcome::None }; | ||||
|     String m_text; | ||||
|     String m_data_type; | ||||
|     String m_data; | ||||
|     RefPtr<GraphicsBitmap> m_bitmap; | ||||
| }; | ||||
|  |  | |||
|  | @ -282,17 +282,23 @@ private: | |||
| 
 | ||||
| class GDropEvent final : public GEvent { | ||||
| 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) | ||||
|         , m_position(position) | ||||
|         , m_text(text) | ||||
|         , m_data_type(data_type) | ||||
|         , m_data(data) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     const Point& position() const { return m_position; } | ||||
|     const String& text() const { return m_text; } | ||||
|     const String& data_type() const { return m_data_type; } | ||||
|     const String& data() const { return m_data; } | ||||
| 
 | ||||
| private: | ||||
|     Point m_position; | ||||
|     String m_text; | ||||
|     String m_data_type; | ||||
|     String m_data; | ||||
| }; | ||||
|  |  | |||
|  | @ -115,11 +115,16 @@ void GItemView::mousemove_event(GMouseEvent& event) | |||
| 
 | ||||
|             RefPtr<GraphicsBitmap> bitmap; | ||||
| 
 | ||||
|             StringBuilder builder; | ||||
|             StringBuilder text_builder; | ||||
|             StringBuilder data_builder; | ||||
|             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) { | ||||
|                     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_data("url-list", data_builder.to_string()); | ||||
|             auto outcome = drag_operation->exec(); | ||||
|             switch (outcome) { | ||||
|             case GDragOperation::Outcome::Accepted: | ||||
|  |  | |||
|  | @ -36,6 +36,7 @@ public: | |||
|         BackgroundColor, | ||||
|         Icon, | ||||
|         Font, | ||||
|         DragData, | ||||
|     }; | ||||
| 
 | ||||
|     virtual ~GModel(); | ||||
|  |  | |||
|  | @ -159,7 +159,7 @@ void GWindow::event(CEvent& event) | |||
|         if (!m_main_widget) | ||||
|             return; | ||||
|         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); | ||||
|         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) | ||||
| { | ||||
|     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&) | ||||
|  |  | |||
|  | @ -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()); | ||||
|     } | ||||
| 
 | ||||
|     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); | ||||
| } | ||||
|  |  | |||
|  | @ -649,7 +649,7 @@ bool WSWindowManager::process_ongoing_drag(WSMouseEvent& event, WSWindow*& hover | |||
|         m_dnd_client->post_message(WindowClient::DragAccepted()); | ||||
|         if (hovered_window->client()) { | ||||
|             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 { | ||||
|         m_dnd_client->post_message(WindowClient::DragCancelled()); | ||||
|  | @ -1190,12 +1190,14 @@ WSMenu* WSWindowManager::find_internal_menu_by_id(int menu_id) | |||
|     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); | ||||
|     m_dnd_client = client.make_weak_ptr(); | ||||
|     m_dnd_text = text; | ||||
|     m_dnd_bitmap = bitmap; | ||||
|     m_dnd_data_type = data_type; | ||||
|     m_dnd_data = data; | ||||
|     WSCompositor::the().invalidate_cursor(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -68,10 +68,12 @@ public: | |||
| 
 | ||||
|     WSClientConnection* dnd_client() { return m_dnd_client.ptr(); } | ||||
|     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; } | ||||
|     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(); | ||||
| 
 | ||||
|     WSWindow* active_window() { return m_active_window.ptr(); } | ||||
|  | @ -283,6 +285,8 @@ private: | |||
| 
 | ||||
|     WeakPtr<WSClientConnection> m_dnd_client; | ||||
|     String m_dnd_text; | ||||
|     String m_dnd_data_type; | ||||
|     String m_dnd_data; | ||||
|     RefPtr<GraphicsBitmap> m_dnd_bitmap; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -31,5 +31,5 @@ endpoint WindowClient = 4 | |||
|     DragAccepted() =| | ||||
|     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) | ||||
|     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