浏览代码

feat: add drag-n-drop position (#7601)

Amr Bashir 2 年之前
父节点
当前提交
6177150b6f
共有 4 个文件被更改,包括 45 次插入12 次删除
  1. 7 0
      .changes/dnd-position.md
  2. 8 6
      core/tauri-runtime-wry/src/lib.rs
  3. 12 2
      core/tauri-runtime/src/window.rs
  4. 18 4
      core/tauri/src/manager.rs

+ 7 - 0
.changes/dnd-position.md

@@ -0,0 +1,7 @@
+---
+'tauri': 'minor:feat'
+'tauri-runtime': 'minor'
+'tauri-runtime-wry': 'minor'
+---
+
+Changed `FileDropEvent` to include drop and hover position.

+ 8 - 6
core/tauri-runtime-wry/src/lib.rs

@@ -881,12 +881,14 @@ fn decode_path(path: PathBuf) -> PathBuf {
 impl From<FileDropEventWrapper> for FileDropEvent {
   fn from(event: FileDropEventWrapper) -> Self {
     match event.0 {
-      WryFileDropEvent::Hovered { paths, position: _ } => {
-        FileDropEvent::Hovered(paths.into_iter().map(decode_path).collect())
-      }
-      WryFileDropEvent::Dropped { paths, position: _ } => {
-        FileDropEvent::Dropped(paths.into_iter().map(decode_path).collect())
-      }
+      WryFileDropEvent::Hovered { paths, position } => FileDropEvent::Hovered {
+        paths: paths.into_iter().map(decode_path).collect(),
+        position: PhysicalPositionWrapper(position).into(),
+      },
+      WryFileDropEvent::Dropped { paths, position } => FileDropEvent::Dropped {
+        paths: paths.into_iter().map(decode_path).collect(),
+        position: PhysicalPositionWrapper(position).into(),
+      },
       // default to cancelled
       // FIXME(maybe): Add `FileDropEvent::Unknown` event?
       _ => FileDropEvent::Cancelled,

+ 12 - 2
core/tauri-runtime/src/window.rs

@@ -22,6 +22,8 @@ use std::{
   sync::mpsc::Sender,
 };
 
+use self::dpi::PhysicalPosition;
+
 type UriSchemeProtocol =
   dyn Fn(&HttpRequest) -> Result<HttpResponse, Box<dyn std::error::Error>> + Send + Sync + 'static;
 
@@ -76,9 +78,17 @@ pub enum WindowEvent {
 #[non_exhaustive]
 pub enum FileDropEvent {
   /// The file(s) have been dragged onto the window, but have not been dropped yet.
-  Hovered(Vec<PathBuf>),
+  Hovered {
+    paths: Vec<PathBuf>,
+    /// The position of the mouse cursor.
+    position: PhysicalPosition<f64>,
+  },
   /// The file(s) have been dropped onto the window.
-  Dropped(Vec<PathBuf>),
+  Dropped {
+    paths: Vec<PathBuf>,
+    /// The position of the mouse cursor.
+    position: PhysicalPosition<f64>,
+  },
   /// The file drop was aborted.
   Cancelled,
 }

+ 18 - 4
core/tauri/src/manager.rs

@@ -7,6 +7,7 @@ use std::{
   collections::{HashMap, HashSet},
   fmt,
   fs::create_dir_all,
+  path::PathBuf,
   sync::{Arc, Mutex, MutexGuard},
 };
 
@@ -38,7 +39,10 @@ use crate::{
       ResponseBuilder as HttpResponseBuilder,
     },
     webview::WindowBuilder,
-    window::{dpi::PhysicalSize, DetachedWindow, FileDropEvent, PendingWindow},
+    window::{
+      dpi::{PhysicalPosition, PhysicalSize},
+      DetachedWindow, FileDropEvent, PendingWindow,
+    },
   },
   utils::{
     assets::Assets,
@@ -1399,6 +1403,12 @@ impl<R: Runtime> WindowManager<R> {
   }
 }
 
+#[derive(Serialize, Clone)]
+struct FileDropPayload<'a> {
+  paths: &'a Vec<PathBuf>,
+  position: &'a PhysicalPosition<f64>,
+}
+
 fn on_window_event<R: Runtime>(
   window: &Window<R>,
   manager: &WindowManager<R>,
@@ -1444,8 +1454,11 @@ fn on_window_event<R: Runtime>(
       },
     )?,
     WindowEvent::FileDrop(event) => match event {
-      FileDropEvent::Hovered(paths) => window.emit(WINDOW_FILE_DROP_HOVER_EVENT, paths)?,
-      FileDropEvent::Dropped(paths) => {
+      FileDropEvent::Hovered { paths, position } => {
+        let payload = FileDropPayload { paths, position };
+        window.emit(WINDOW_FILE_DROP_HOVER_EVENT, payload)?
+      }
+      FileDropEvent::Dropped { paths, position } => {
         let scopes = window.state::<Scopes>();
         for path in paths {
           if path.is_file() {
@@ -1454,7 +1467,8 @@ fn on_window_event<R: Runtime>(
             let _ = scopes.allow_directory(path, false);
           }
         }
-        window.emit(WINDOW_FILE_DROP_EVENT, paths)?
+        let payload = FileDropPayload { paths, position };
+        window.emit(WINDOW_FILE_DROP_EVENT, payload)?
       }
       FileDropEvent::Cancelled => window.emit(WINDOW_FILE_DROP_CANCELLED_EVENT, ())?,
       _ => unimplemented!(),