diff --git a/src/Files.App/MainWindow.Linux.cs b/src/Files.App/MainWindow.Linux.cs index e208814e6966..5e33cabff562 100644 --- a/src/Files.App/MainWindow.Linux.cs +++ b/src/Files.App/MainWindow.Linux.cs @@ -26,9 +26,9 @@ public sealed partial class MainWindow #if UNO_WAYLAND private bool _waylandWindow; // The Wayland host implements caption regions, move and maximize itself (InputNonClientPointerSource, presenter). - private bool IsWaylandWindow => _waylandWindow; + internal bool IsWaylandWindow => _waylandWindow; #else - private static bool IsWaylandWindow => false; + internal bool IsWaylandWindow => false; #endif public bool UseClientSideDecorations => OperatingSystem.IsLinux() && Ioc.Default.GetRequiredService().Get("UseClientSideDecorations", true); diff --git a/src/Files.App/Platforms/Desktop/Services/DesktopFileDragHelper.cs b/src/Files.App/Platforms/Desktop/Services/DesktopFileDragHelper.cs index f4974195a8bc..22d2cfc47fb4 100644 --- a/src/Files.App/Platforms/Desktop/Services/DesktopFileDragHelper.cs +++ b/src/Files.App/Platforms/Desktop/Services/DesktopFileDragHelper.cs @@ -91,6 +91,24 @@ 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. + /// + public static void StartDrag(DataPackage data, IEnumerable paths) + { + if (!MainWindow.Instance.IsWaylandWindow) + { + StartExternalDrag(paths); + return; + } + + var existing = ExistingPaths(paths); + if (existing.Count > 0) + data.SetData(Files.Platform.Linux.Clipboard.ClipboardFormats.UriList, Files.Platform.Linux.Clipboard.ClipboardFormats.BuildUriList(existing)); + } + /// /// Starts offering the dragged items to other applications while the pointer is outside this window. Returns immediately; the /// drag source follows the pointer until the primary button is released. diff --git a/src/Files.App/UserControls/Pane/ShelfPane.xaml.cs b/src/Files.App/UserControls/Pane/ShelfPane.xaml.cs index 31459e25f346..c41395d8cd42 100644 --- a/src/Files.App/UserControls/Pane/ShelfPane.xaml.cs +++ b/src/Files.App/UserControls/Pane/ShelfPane.xaml.cs @@ -69,7 +69,7 @@ private void ListView_DragItemsStarting(object sender, DragItemsStartingEventArg return; e.Data.Properties["Files_ActionBinder"] = "Files_ShelfBinder"; - Files.App.Services.Desktop.DesktopFileDragHelper.StartExternalDrag(paths); + Files.App.Services.Desktop.DesktopFileDragHelper.StartDrag(e.Data, paths); } private void ShelfItemsList_RightTapped(object sender, Microsoft.UI.Xaml.Input.RightTappedRoutedEventArgs e) diff --git a/src/Files.App/Utils/Storage/Operations/FilesystemHelpers.Linux.cs b/src/Files.App/Utils/Storage/Operations/FilesystemHelpers.Linux.cs index 040d75f01a27..881c8390927d 100644 --- a/src/Files.App/Utils/Storage/Operations/FilesystemHelpers.Linux.cs +++ b/src/Files.App/Utils/Storage/Operations/FilesystemHelpers.Linux.cs @@ -20,8 +20,13 @@ public static async Task> GetDraggedStorageIte IEnumerable paths; if (packageView.Contains(ClipboardFormats.UriList)) { - var data = await packageView.GetDataAsync(ClipboardFormats.UriList); - paths = data is string text ? ClipboardFormats.ParseUriList(text) : []; + // Uno's X11 host exposes the list as text, the Wayland host as the raw bytes it received. + paths = await packageView.GetDataAsync(ClipboardFormats.UriList) switch + { + string text => ClipboardFormats.ParseUriList(text), + byte[] bytes => ClipboardFormats.ParseUriList(System.Text.Encoding.UTF8.GetString(bytes)), + _ => [], + }; } else if (packageView.Contains(StandardDataFormats.StorageItems)) { diff --git a/src/Files.App/Views/Layouts/BaseLayoutPage.cs b/src/Files.App/Views/Layouts/BaseLayoutPage.cs index 6bd0f8d0346b..f1a929488d35 100644 --- a/src/Files.App/Views/Layouts/BaseLayoutPage.cs +++ b/src/Files.App/Views/Layouts/BaseLayoutPage.cs @@ -1160,7 +1160,7 @@ protected virtual void FileList_DragItemsStarting(object sender, DragItemsStarti // Set can window to front (#13255) MainWindow.Instance.SetCanWindowToFront(false); itemDragging = true; - Files.App.Services.Desktop.DesktopFileDragHelper.StartExternalDrag(orderedItems.Select(x => x.ItemPath)); + Files.App.Services.Desktop.DesktopFileDragHelper.StartDrag(e.Data, orderedItems.Select(x => x.ItemPath)); } catch (Exception) {