From 402cc6d7152bb11508df599057c61be011b990e2 Mon Sep 17 00:00:00 2001 From: tekai-crabnebula Date: Thu, 7 Dec 2023 14:39:28 +0800 Subject: [PATCH 1/3] Handles forward slash path in Windows --- crates/drag/src/platform_impl/windows/utils.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/drag/src/platform_impl/windows/utils.rs b/crates/drag/src/platform_impl/windows/utils.rs index 479b8eb..538750c 100644 --- a/crates/drag/src/platform_impl/windows/utils.rs +++ b/crates/drag/src/platform_impl/windows/utils.rs @@ -6,8 +6,10 @@ use std::path::{Path, PathBuf}; /// Using std::fs::canonicalize on Windows will retuen a UNC path ("\\?\C:\\path\to\file.txt") /// Some applications do not support this for dropping as URI. +/// Also forward slash path does not work in Windows, so we just replace it. pub(crate) fn adjust_canonicalization>(p: P) -> PathBuf { let p = p.as_ref().display().to_string(); + let p = p.replace("/", r"\"); if let Some(stripped) = p.strip_prefix(r"\\?\") { PathBuf::from(stripped) } else { From cceae7baa183a610244061a5dec821ed5a743f67 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 7 Dec 2023 10:00:19 -0300 Subject: [PATCH 2/3] use dunce::canonicalize --- crates/drag/Cargo.toml | 3 +++ crates/drag/src/lib.rs | 2 ++ crates/drag/src/platform_impl/windows/image.rs | 7 ++++--- crates/drag/src/platform_impl/windows/mod.rs | 12 ++++++++---- crates/drag/src/platform_impl/windows/utils.rs | 18 ------------------ 5 files changed, 17 insertions(+), 25 deletions(-) delete mode 100644 crates/drag/src/platform_impl/windows/utils.rs diff --git a/crates/drag/Cargo.toml b/crates/drag/Cargo.toml index e63768c..d599173 100644 --- a/crates/drag/Cargo.toml +++ b/crates/drag/Cargo.toml @@ -25,6 +25,9 @@ objc = "0.2" gtk = "0.15" gdkx11 = "0.15" +[target."cfg(target_os = \"windows\")".dependencies] +dunce = "1" + [target."cfg(target_os = \"windows\")".dependencies.windows] version = "0.51" features = [ diff --git a/crates/drag/src/lib.rs b/crates/drag/src/lib.rs index f075449..4fa0a6e 100644 --- a/crates/drag/src/lib.rs +++ b/crates/drag/src/lib.rs @@ -89,6 +89,8 @@ pub enum Error { #[cfg(windows)] #[error("{0}")] WindowsError(#[from] windows::core::Error), + #[error(transparent)] + Io(#[from] std::io::Error), #[error("unsupported window handle")] UnsupportedWindowHandle, #[error("failed to start drag")] diff --git a/crates/drag/src/platform_impl/windows/image.rs b/crates/drag/src/platform_impl/windows/image.rs index e6d91fa..045f6f7 100644 --- a/crates/drag/src/platform_impl/windows/image.rs +++ b/crates/drag/src/platform_impl/windows/image.rs @@ -4,6 +4,8 @@ use std::os::windows::ffi::OsStrExt; use std::{ffi::c_void, iter::once, path::Path}; +use windows::core::PCWSTR; +use windows::Win32::Foundation::*; use windows::Win32::{ Graphics::{ Gdi::{CreateBitmap, HBITMAP}, @@ -14,9 +16,8 @@ use windows::Win32::{ }, System::Com::{CoCreateInstance, CLSCTX_INPROC_SERVER}, }; -use windows::{core::*, Win32::Foundation::*}; -use super::utils::adjust_canonicalization; +use crate::Result; pub(crate) fn read_bytes_to_hbitmap(bytes: &[u8]) -> Result { unsafe { @@ -41,7 +42,7 @@ pub(crate) fn read_path_to_hbitmap(path: &Path) -> Result { let factory: IWICImagingFactory = CoCreateInstance(&CLSID_WICImagingFactory, None, CLSCTX_INPROC_SERVER)?; - let path = adjust_canonicalization(path); + let path = dunce::canonicalize(path)?; let wide_path: Vec = path.as_os_str().encode_wide().chain(once(0)).collect(); let decoder = factory.CreateDecoderFromFilename( diff --git a/crates/drag/src/platform_impl/windows/mod.rs b/crates/drag/src/platform_impl/windows/mod.rs index d6eadcf..68e8b6e 100644 --- a/crates/drag/src/platform_impl/windows/mod.rs +++ b/crates/drag/src/platform_impl/windows/mod.rs @@ -32,7 +32,6 @@ use windows::{ }; mod image; -mod utils; static mut OLE_RESULT: Result<()> = Ok(()); static OLE_UNINITIALIZE: Once = Once::new(); @@ -199,7 +198,13 @@ pub fn start_drag( return Err(e.clone().into()); } } - let data_object: IDataObject = get_file_data_object(&files).unwrap(); + + let mut paths = Vec::new(); + for f in files { + paths.push(dunce::canonicalize(f)?); + } + + let data_object: IDataObject = get_file_data_object(&paths).unwrap(); let drop_source: IDropSource = DropSource::new().into(); unsafe { @@ -276,7 +281,7 @@ fn get_hglobal(size: usize, buffer: Vec) -> Result { Ok(handle) } -pub fn create_instance(clsid: &GUID) -> windows::core::Result { +pub fn create_instance(clsid: &GUID) -> Result { unsafe { CoCreateInstance(clsid, None, CLSCTX_ALL) } } @@ -299,7 +304,6 @@ fn get_shell_item_array(paths: &[PathBuf]) -> Option { fn get_file_item_id(path: &Path) -> *mut Common::ITEMIDLIST { unsafe { - let path = utils::adjust_canonicalization(path); let wide_path: Vec = path.as_os_str().encode_wide().chain(once(0)).collect(); windows::Win32::UI::Shell::ILCreateFromPathW(PCWSTR::from_raw(wide_path.as_ptr())) } diff --git a/crates/drag/src/platform_impl/windows/utils.rs b/crates/drag/src/platform_impl/windows/utils.rs deleted file mode 100644 index 538750c..0000000 --- a/crates/drag/src/platform_impl/windows/utils.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2023-2023 CrabNebula Ltd. -// SPDX-License-Identifier: Apache-2.0 -// SPDX-License-Identifier: MIT - -use std::path::{Path, PathBuf}; - -/// Using std::fs::canonicalize on Windows will retuen a UNC path ("\\?\C:\\path\to\file.txt") -/// Some applications do not support this for dropping as URI. -/// Also forward slash path does not work in Windows, so we just replace it. -pub(crate) fn adjust_canonicalization>(p: P) -> PathBuf { - let p = p.as_ref().display().to_string(); - let p = p.replace("/", r"\"); - if let Some(stripped) = p.strip_prefix(r"\\?\") { - PathBuf::from(stripped) - } else { - PathBuf::from(p) - } -} From 20de75d74c186dde7dba7c14f83e2e9b5b649922 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 7 Dec 2023 10:01:44 -0300 Subject: [PATCH 3/3] fix example --- crates/drag/src/lib.rs | 6 +++--- examples/tao/src/main.rs | 2 +- examples/winit/src/main.rs | 2 +- examples/wry/src/main.rs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/drag/src/lib.rs b/crates/drag/src/lib.rs index 4fa0a6e..dd9acdf 100644 --- a/crates/drag/src/lib.rs +++ b/crates/drag/src/lib.rs @@ -23,7 +23,7 @@ //! let window = tao::window::WindowBuilder::new().build(&event_loop).unwrap(); //! //! let item = drag::DragItem::Files(vec![std::fs::canonicalize("./examples/icon.png").unwrap()]); -//! let preview_icon = drag::Image::File("../../icon.png".into()); +//! let preview_icon = drag::Image::File("./examples/icon.png".into()); //! //! drag::start_drag( //! #[cfg(target_os = "linux")] @@ -45,7 +45,7 @@ //! let webview = wry::webview::WebViewBuilder::new(window).unwrap().build().unwrap(); //! //! let item = drag::DragItem::Files(vec![std::fs::canonicalize("./examples/icon.png").unwrap()]); -//! let preview_icon = drag::Image::File("../../icon.png".into()); +//! let preview_icon = drag::Image::File("./examples/icon.png".into()); //! //! drag::start_drag( //! #[cfg(target_os = "linux")] @@ -66,7 +66,7 @@ //! let window = winit::window::WindowBuilder::new().build(&event_loop).unwrap(); //! //! let item = drag::DragItem::Files(vec![std::fs::canonicalize("./examples/icon.png").unwrap()]); -//! let preview_icon = drag::Image::File("../../icon.png".into()); +//! let preview_icon = drag::Image::File("./examples/icon.png".into()); //! //! # #[cfg(not(target_os = "linux"))] //! let _ = drag::start_drag(&window, item, preview_icon); diff --git a/examples/tao/src/main.rs b/examples/tao/src/main.rs index ad50f24..21c974d 100644 --- a/examples/tao/src/main.rs +++ b/examples/tao/src/main.rs @@ -51,7 +51,7 @@ fn main() { &window, DragItem::Files(vec![std::fs::canonicalize("./examples/icon.png").unwrap()]), Image::Raw(include_bytes!("../../icon.png").to_vec()), - // Image::File("../../icon.png".into()), + // Image::File("./examples/icon.png".into()), ) .unwrap(); } diff --git a/examples/winit/src/main.rs b/examples/winit/src/main.rs index d39c40b..e4e2215 100644 --- a/examples/winit/src/main.rs +++ b/examples/winit/src/main.rs @@ -45,7 +45,7 @@ fn main() { vec![std::fs::canonicalize("./examples/icon.png").unwrap()], ), Image::Raw(include_bytes!("../../icon.png").to_vec()), - // Image::File("../../icon.png".into()), + // Image::File("./examples/icon.png".into()), ) .unwrap(); } diff --git a/examples/wry/src/main.rs b/examples/wry/src/main.rs index 0498d58..4e8b6cb 100644 --- a/examples/wry/src/main.rs +++ b/examples/wry/src/main.rs @@ -96,7 +96,7 @@ fn main() -> wry::Result<()> { std::fs::canonicalize("./examples/icon.bmp").unwrap(), ]), Image::Raw(include_bytes!("../../icon.png").to_vec()), - // Image::File("../../icon.png".into()), + // Image::File("./examples/icon.png".into()), ) .unwrap(); }