From 77adb3f8a8625f48a0ae58b820b06689dd300e53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kov=C3=A1cs=20B=C3=A1lint=20Hunor?= Date: Thu, 15 Oct 2026 20:39:32 +0300 Subject: [PATCH 1/2] Use Uno's X11 drag source when the Uno packages have it Uno's X11 host gains an XDND source on MemerGamer/uno wayland/host-x11dnd (drag icon, cursors, Escape, own-window routing, KWin XWayland bridge). With FilesUnoX11NativeDrag=true Files puts the file list into the drag's DataPackage on X11 too, as on Wayland, and stops starting its own X11 drag source. The switch stays off until a released UnoWaylandVersion contains the branch. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01BTZhMsNyJ6k4VC68CNb5WU --- Directory.Packages.props | 2 ++ docs/linux-port/dnd.md | 22 ++++++++++++++++++- src/Files.App/Files.App.csproj | 1 + .../Desktop/Services/DesktopFileDragHelper.cs | 15 +++++++++---- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 6347de0a891c..879ed682595d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -52,6 +52,8 @@ 6.7.135-wayland.6 + + false $(MSBuildThisFileDirectory)nuget.wayland.config diff --git a/docs/linux-port/dnd.md b/docs/linux-port/dnd.md index d4bb65261966..b8c0cc86826e 100644 --- a/docs/linux-port/dnd.md +++ b/docs/linux-port/dnd.md @@ -46,6 +46,26 @@ When the pointer leaves the window Uno still calls `StartNativeDrag` and raises `Application.UnhandledException`. `DesktopRuntimeGuards` marks exactly that exception as handled instead of letting Files' crash handler exit the app (that was the reported crash). Uno then ends its own drag when the button is released. +## Uno's own X11 drag source (`FilesUnoX11NativeDrag`) + +The MemerGamer/uno branch `wayland/host-x11dnd` gives Uno's X11 host an XDND v5 source, built like the Wayland host's +outgoing drag: it takes the drag as soon as Uno's drag starts (`IImmediateDragDropExtension`), moves the pointer grab to a private +X connection (drag icon window from the DragView snapshot, copy/move/link/no-drop cursors, Escape and Shift/Ctrl through a keyboard +grab), routes the pointer back into Uno while it is over the window the drag started in, and offers `text/uri-list` plus the text +targets. Files then only has to put the file list into `e.Data`, as on Wayland (`DesktopFileDragHelper.StartDrag`). + +Released packages up to `6.7.135-wayland.6` do not contain it, so `FilesUnoX11NativeDrag` (Directory.Packages.props) defaults to +`false` and Files keeps starting its own X11 drag source. Set it to `true` together with the first `UnoWaylandVersion` that includes +the branch; `UNO_X11_NATIVE_DRAG` then skips `StartExternalDrag` on X11. The old source and `DesktopRuntimeGuards` stay as the path +for packages without it. + +Verified with a LinuxFiles build using `-p:FilesUnoX11NativeDrag=true` and the branch's `Uno.UI.Runtime.Skia.X11.dll`: +- private Xvfb with a GTK3 drop target: copy, Shift move, Escape, a rejecting target (no-drop cursor), drop onto a folder in the + same window, and out to the target and back into the window; +- nested KWin with XWayland and a Wayland-native Dolphin: Copy Here from the drop menu, Shift move, Escape, out and back. + On Escape KWin ends its bridged drag without telling the X source and XWayland gets no button release; the Uno source cancels + when its target window disappears under a still pointer. + ## Dragging out to Wayland-native apps on KDE (XWayland bridge) Files runs under XWayland, so a Wayland-native target (Dolphin, Kate) is not a window on the X server and the XDND tree walk never @@ -85,7 +105,7 @@ under `dbus-run-session` with a private `XDG_RUNTIME_DIR` (the socket path must ## LINUX-TODO -- `LINUX-TODO(dnd)`: no drag icon or cursor feedback outside the window (the pointer is grabbed by Uno's window; changing it needs +- `LINUX-TODO(dnd)`: (fixed by Uno's X11 source once `FilesUnoX11NativeDrag` is on) no drag icon or cursor feedback outside the window (the pointer is grabbed by Uno's window; changing it needs `XChangeActivePointerGrab` on that connection, or the Uno extension point). Dropping on a window that answers `XdndStatus` with "reject" silently does nothing. - `LINUX-TODO(dnd)`: the guard only covers file lists (`FileList_DragItemsStarting`). Drags from the sidebar, tabs and the shelf leave diff --git a/src/Files.App/Files.App.csproj b/src/Files.App/Files.App.csproj index 1c1d3386c9c7..a9384147ef15 100644 --- a/src/Files.App/Files.App.csproj +++ b/src/Files.App/Files.App.csproj @@ -96,6 +96,7 @@ $(DefineConstants);UNO_WAYLAND + $(DefineConstants);UNO_X11_NATIVE_DRAG diff --git a/src/Files.App/Platforms/Desktop/Services/DesktopFileDragHelper.cs b/src/Files.App/Platforms/Desktop/Services/DesktopFileDragHelper.cs index 22d2cfc47fb4..8690a1100632 100644 --- a/src/Files.App/Platforms/Desktop/Services/DesktopFileDragHelper.cs +++ b/src/Files.App/Platforms/Desktop/Services/DesktopFileDragHelper.cs @@ -92,13 +92,13 @@ public static async Task TryPasteFilesAsync(string destinationPath, IShell } /// - /// Makes a drag of available to other applications. On the native Wayland host the dragged - /// carries the file list (text/uri-list) and the host offers it to the compositor once the - /// pointer leaves the window; on X11 the Files selection host follows the pointer instead. + /// Makes a drag of available to other applications. When the Uno host drags to other clients + /// itself (Wayland, and X11 with UNO_X11_NATIVE_DRAG) the dragged carries the file list + /// (text/uri-list) and the host offers it; otherwise the Files X11 selection host follows the pointer. /// public static void StartDrag(DataPackage data, IEnumerable paths) { - if (!MainWindow.Instance.IsWaylandWindow) + if (!HostDragsToOtherApps) { StartExternalDrag(paths); return; @@ -137,6 +137,13 @@ static async Task DragAsync(IFileDragSource source, List existing) } } + // FilesUnoX11NativeDrag (Directory.Packages.props) marks Uno packages whose X11 host has its own XDND source. +#if UNO_X11_NATIVE_DRAG + private static bool HostDragsToOtherApps => true; +#else + private static bool HostDragsToOtherApps => MainWindow.Instance.IsWaylandWindow; +#endif + private static List ExistingPaths(IEnumerable paths) => paths .Where(path => !string.IsNullOrEmpty(path) && path[0] == '/' && (File.Exists(path) || Directory.Exists(path))) From 65fc3d391c3ee7e4c05c2814bac333cead5365a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kov=C3=A1cs=20B=C3=A1lint=20Hunor?= Date: Thu, 15 Oct 2026 22:47:33 +0300 Subject: [PATCH 2/2] Document the X11 drop fix and the XDND trace switch Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01BTZhMsNyJ6k4VC68CNb5WU --- docs/linux-port/dnd.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/linux-port/dnd.md b/docs/linux-port/dnd.md index b8c0cc86826e..6f50cce8435b 100644 --- a/docs/linux-port/dnd.md +++ b/docs/linux-port/dnd.md @@ -66,6 +66,15 @@ Verified with a LinuxFiles build using `-p:FilesUnoX11NativeDrag=true` and the b On Escape KWin ends its bridged drag without telling the X source and XWayland gets no button release; the Uno source cancels when its target window disappears under a still pointer. +The same Uno branch fixes drops *into* Files from Wayland-native apps under XWayland (broken in alpha7 too): Uno's selection readers +threw away the host window's other X events while waiting for data, so KWin's `XdndDrop`/`XdndPosition` could be lost, after which +KWin waited for an answer forever and ignored the window for later drags. `XdndFinished` now also waits for the drop handlers. +Verified in a fresh nested KWin: Dolphin to the file list and onto a folder, repeated drops, Escape. Note that Files performs the +operation it accepted in DragOver (move within a file system) even when the source requested a copy; that is Files' own drop logic. + +To trace a drag on a real desktop: `UNO_X11_DND_LOG=/tmp/xdnd.log` makes Uno's X11 host append every XDND message it sends and +receives (both directions) to that file. + ## Dragging out to Wayland-native apps on KDE (XWayland bridge) Files runs under XWayland, so a Wayland-native target (Dolphin, Kate) is not a window on the X server and the XDND tree walk never