From 95fcabaacbb1ea1f3af3ebca6057124ee9dbdf30 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Wed, 22 Jul 2026 11:58:39 +0300 Subject: [PATCH] feat(open): drag & drop files onto the window (#344) Dropping a supported file (dwg / dxf / bak / sv$, case-insensitive) opens it through the existing open flow: an already-open drawing switches to its tab, a load in progress queues the drop behind it (multi-file drops arrive one event each), anything unsupported reports on the command line instead of failing silently in the parser. Platform support follows winit 0.30: Windows, macOS and Linux/X11 (incl. XWayland) deliver FileDropped; the Wayland backend does not implement file drag & drop yet, so drops are inert there until winit gains it. Closes #344 Co-Authored-By: Claude Fable 5 --- src/app/mod.rs | 2 ++ src/app/update/mod.rs | 28 ++++++++++++++++++++++++++++ src/app/view/mod.rs | 3 +++ 3 files changed, 33 insertions(+) diff --git a/src/app/mod.rs b/src/app/mod.rs index e6ef8494c..16c09ee57 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1260,6 +1260,8 @@ pub enum Message { /// File picker returned. `Some((path, size_in_bytes))` → start loading; /// `None` → user cancelled the dialog (no overlay shown). OpenPathPicked(Option<(PathBuf, u64)>), + /// A file was dragged from the desktop and dropped on the window (#344). + FileDropped(PathBuf), /// Open a path from the Start tab's recent-documents list (skips the /// file picker; the path is already known). OpenRecent(PathBuf), diff --git a/src/app/update/mod.rs b/src/app/update/mod.rs index 637857cbd..8614024f0 100644 --- a/src/app/update/mod.rs +++ b/src/app/update/mod.rs @@ -292,6 +292,34 @@ impl OpenCADStudio { } } + Message::FileDropped(path) => { + // Desktop drag & drop (#344): accept the formats the Open + // dialog accepts — a drop has no picker filter, so anything + // else reports instead of failing silently in the parser. + let ext = path + .extension() + .map(|e| e.to_string_lossy().to_lowercase()) + .unwrap_or_default(); + if !matches!(ext.as_str(), "dwg" | "dxf" | "bak" | "sv$") { + self.command_line.push_error(&format!( + "Unsupported file type: {}", + path.display() + )); + return Task::none(); + } + // Already open → switch to its tab; a load in progress → + // queue behind it (multi-file drops arrive one event each). + if let Some(idx) = self.tab_showing(&path) { + return self.update(Message::TabSwitch(idx)); + } + if self.opening.is_some() { + self.pending_opens.push_back(path); + Task::none() + } else { + self.update(Message::OpenRecent(path)) + } + } + Message::RecentRemove(path) => { self.remove_recent(&path); Task::none() diff --git a/src/app/view/mod.rs b/src/app/view/mod.rs index d0be2b8b7..da2effcbc 100644 --- a/src/app/view/mod.rs +++ b/src/app/view/mod.rs @@ -1732,6 +1732,9 @@ impl OpenCADStudio { iced::Event::Window(window::Event::Resized(sz)) => { Some(Message::WindowResized(sz.width as f32, sz.height as f32)) } + iced::Event::Window(window::Event::FileDropped(path)) => { + Some(Message::FileDropped(path)) + } iced::Event::Keyboard(keyboard::Event::ModifiersChanged(m)) => { // `command()` is Cmd on macOS, Ctrl elsewhere — the // platform multi-select modifier for the layer list.