Wayland: implement DnD file drop via SCTK DataDeviceManager#4504
Open
joeleaver wants to merge 1 commit intorust-windowing:masterfrom
Open
Wayland: implement DnD file drop via SCTK DataDeviceManager#4504joeleaver wants to merge 1 commit intorust-windowing:masterfrom
joeleaver wants to merge 1 commit intorust-windowing:masterfrom
Conversation
Implements Wayland drag-and-drop file dropping by integrating SCTK's DataDeviceManagerState. Emits DragEntered, DragMoved, DragDropped, and DragLeft window events with file paths parsed from text/uri-list MIME. Key design decisions: - set_actions() called only once in enter() — repeated calls restart negotiation and race with fast drops - conn.flush() after every protocol response so the compositor receives acceptance before the user releases the mouse - Pipe read on a background thread with safe OwnedFd (no unsafe) to avoid deadlocking the Wayland event loop - Data devices stored in AHashMap<ObjectId, DataDevice> keyed by seat for proper cleanup when seats are removed - Re-accept MIME type on every motion event and in selected_action callback for broad compositor compatibility (GNOME, KDE, wlroots) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements Wayland drag-and-drop (file drop) by integrating SCTK's
DataDeviceManagerStateintowinit-wayland. EmitsDragEntered,DragMoved,DragDropped, andDragLeftwindow events with file paths parsed fromtext/uri-list.Closes #1881.
Relationship to #2429 and #4009
There are two existing open PRs for this feature. I built a new one because:
src/platform_impl/layout. winit has since been restructured into per-platform crates (winit-wayland/), so that PR can't merge as-is. The event loop integration pattern has also changed.This PR is written from scratch against the current
winit-waylandcrate, but incorporates the same core approach (SCTK DataDeviceManager +text/uri-listpipe read) and the lessons from debugging those earlier PRs.Design decisions
set_actions()only inenter(), never on motion. Callingset_actionson every motion event restarts the DnD negotiation. If the user drops during re-negotiation, the compositor sendsleaveinstead ofdrop_performed. This was the primary reliability issue we hit — a fast drop would race the buffered protocol messages.conn.flush()after every protocol response. Without explicit flushes afteraccept_mime_type/set_actions, a fast drop can arrive at the compositor before it has processed our acceptance. The accept/set_actions sit in the client-side buffer while the user releases the mouse.Pipe read on a background thread with safe
OwnedFd. The compositor won't write to the pipe until it processes ourreceiverequest, which requires the Wayland event loop to dispatch — but we're inside a handler on that thread. Reading directly would deadlock. We dup the fd viatry_clone_to_owned()(nounsafe), drop the originalReadPipe, flush the connection, thenthread::spawn+jointo read.Data devices keyed by seat
ObjectId. Stored inHashMap<ObjectId, DataDevice>so they're properly cleaned up inremove_seat. AVecwould leak devices when seats are removed.Re-accept MIME on motion and
selected_action. Some compositors (KDE) need the MIME acceptance refreshed on motion or after action negotiation. We re-accepttext/uri-liston everymotionevent and in theselected_actioncallback, but without callingset_actionsagain.Testing
Tested on GNOME (Mutter), KDE (KWin), and wlroots (Sway). File drops from Nautilus, Dolphin, and Thunar all work reliably including fast drops. Clipboard access via external crates (e.g.
smithay-clipboard) continues to work — per @kchibisov's note on #2429, the GNOME bug that caused conflicts has been fixed and backported.Changes
New file:
winit-wayland/src/seat/data_device.rs—DataDeviceHandler,DataOfferHandler,DataSourceHandlerimpls, URI parsing with unit testswinit-wayland/src/state.rs— addsDataDeviceManagerState, per-seat data devices, DnD tracking statewinit-wayland/src/seat/mod.rs— registers module, creates/removes data devices on seat add/removeTested on all platforms changed
Added an entry to
CHANGELOG.mdif knowledge of this change could be valuable to usersUpdated documentation to reflect any user-facing changes
Created or updated an example program
Updated feature matrix