فهرست منبع

feat: add `cursor_position` getter (#9297)

* feat: add `cursor_position` getter

closes #9250

* js api

* Update mod.rs

* fix build on iOS and android

* use existing wrapper

* fmt

* adjust wording

* update docs

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
Amr Bashir 1 سال پیش
والد
کامیت
477bb8cd4e

+ 5 - 0
.changes/cursor_position.md

@@ -0,0 +1,5 @@
+---
+'tauri': 'patch:feat'
+---
+
+Add `App/AppHandle/Window/Webview/WebviewWindow::cursor_position` getter to get the current cursor position.

+ 5 - 0
.changes/cursor_position_js.md

@@ -0,0 +1,5 @@
+---
+'@tauri-apps/api': 'patch:feat'
+---
+
+Add `cursorPosition` function in `window` module to get the current cursor position.

+ 22 - 0
core/tauri-runtime-wry/src/lib.rs

@@ -2162,6 +2162,17 @@ impl<T: UserEvent> RuntimeHandle<T> for WryHandle<T> {
       .collect()
   }
 
+  fn cursor_position(&self) -> Result<PhysicalPosition<f64>> {
+    self
+      .context
+      .main_thread
+      .window_target
+      .cursor_position()
+      .map(PhysicalPositionWrapper)
+      .map(Into::into)
+      .map_err(|_| Error::FailedToGetCursorPosition)
+  }
+
   #[cfg(target_os = "macos")]
   fn show(&self) -> tauri_runtime::Result<()> {
     send_user_message(
@@ -2409,6 +2420,17 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
       .collect()
   }
 
+  fn cursor_position(&self) -> Result<PhysicalPosition<f64>> {
+    self
+      .context
+      .main_thread
+      .window_target
+      .cursor_position()
+      .map(PhysicalPositionWrapper)
+      .map(Into::into)
+      .map_err(|_| Error::FailedToGetCursorPosition)
+  }
+
   #[cfg(target_os = "macos")]
   fn set_activation_policy(&mut self, activation_policy: ActivationPolicy) {
     self

+ 7 - 0
core/tauri-runtime/src/lib.rs

@@ -158,6 +158,9 @@ pub enum Error {
   /// Failed to get monitor on window operation.
   #[error("failed to get monitor")]
   FailedToGetMonitor,
+  /// Failed to get cursor position.
+  #[error("failed to get cursor position")]
+  FailedToGetCursorPosition,
   #[error("Invalid header name: {0}")]
   InvalidHeaderName(#[from] InvalidHeaderName),
   #[error("Invalid header value: {0}")]
@@ -293,6 +296,8 @@ pub trait RuntimeHandle<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'st
   fn primary_monitor(&self) -> Option<Monitor>;
   fn available_monitors(&self) -> Vec<Monitor>;
 
+  fn cursor_position(&self) -> Result<PhysicalPosition<f64>>;
+
   /// Shows the application, but does not automatically focus it.
   #[cfg(target_os = "macos")]
   #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
@@ -373,6 +378,8 @@ pub trait Runtime<T: UserEvent>: Debug + Sized + 'static {
   fn primary_monitor(&self) -> Option<Monitor>;
   fn available_monitors(&self) -> Vec<Monitor>;
 
+  fn cursor_position(&self) -> Result<PhysicalPosition<f64>>;
+
   /// Sets the activation policy for the application.
   #[cfg(target_os = "macos")]
   #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]

+ 1 - 0
core/tauri/build.rs

@@ -64,6 +64,7 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[
       ("current_monitor", true),
       ("primary_monitor", true),
       ("available_monitors", true),
+      ("cursor_position", true),
       ("theme", true),
       // setters
       ("center", false),

+ 2 - 0
core/tauri/permissions/window/autogenerated/reference.md

@@ -10,6 +10,8 @@
 |`deny-create`|Denies the create command without any pre-configured scope.|
 |`allow-current-monitor`|Enables the current_monitor command without any pre-configured scope.|
 |`deny-current-monitor`|Denies the current_monitor command without any pre-configured scope.|
+|`allow-cursor-position`|Enables the cursor_position command without any pre-configured scope.|
+|`deny-cursor-position`|Denies the cursor_position command without any pre-configured scope.|
 |`allow-destroy`|Enables the destroy command without any pre-configured scope.|
 |`deny-destroy`|Denies the destroy command without any pre-configured scope.|
 |`allow-hide`|Enables the hide command without any pre-configured scope.|

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
core/tauri/scripts/bundle.global.js


+ 17 - 0
core/tauri/src/app.rs

@@ -596,6 +596,23 @@ macro_rules! shared_app_impl {
           _ => unreachable!(),
         })
       }
+
+      /// Get the cursor position relative to the top-left hand corner of the desktop.
+      ///
+      /// Note that the top-left hand corner of the desktop is not necessarily the same as the screen.
+      /// If the user uses a desktop with multiple monitors,
+      /// the top-left hand corner of the desktop is the top-left hand corner of the main monitor on Windows and macOS
+      /// or the top-left of the leftmost monitor on X11.
+      ///
+      /// The coordinates can be negative if the top-left hand corner of the window is outside of the visible screen region.
+      pub fn cursor_position(&self) -> crate::Result<PhysicalPosition<f64>> {
+        Ok(match self.runtime() {
+          RuntimeOrDispatch::Runtime(h) => h.cursor_position()?,
+          RuntimeOrDispatch::RuntimeHandle(h) => h.cursor_position()?,
+          _ => unreachable!(),
+        })
+      }
+
       /// Returns the default window icon.
       pub fn default_window_icon(&self) -> Option<&Image<'_>> {
         self.manager.window.default_icon.as_ref()

+ 8 - 0
core/tauri/src/test/mock_runtime.rs

@@ -268,6 +268,10 @@ impl<T: UserEvent> RuntimeHandle<T> for MockRuntimeHandle {
   {
     todo!()
   }
+
+  fn cursor_position(&self) -> Result<PhysicalPosition<f64>> {
+    Ok(PhysicalPosition::new(0.0, 0.0))
+  }
 }
 
 #[derive(Debug, Clone)]
@@ -1152,4 +1156,8 @@ impl<T: UserEvent> Runtime<T> for MockRuntime {
 
     callback(RunEvent::Exit);
   }
+
+  fn cursor_position(&self) -> Result<PhysicalPosition<f64>> {
+    Ok(PhysicalPosition::new(0.0, 0.0))
+  }
 }

+ 12 - 0
core/tauri/src/webview/mod.rs

@@ -895,6 +895,18 @@ impl<R: Runtime> Webview<R> {
     self.webview.dispatcher.print().map_err(Into::into)
   }
 
+  /// Get the cursor position relative to the top-left hand corner of the desktop.
+  ///
+  /// Note that the top-left hand corner of the desktop is not necessarily the same as the screen.
+  /// If the user uses a desktop with multiple monitors,
+  /// the top-left hand corner of the desktop is the top-left hand corner of the main monitor on Windows and macOS
+  /// or the top-left of the leftmost monitor on X11.
+  ///
+  /// The coordinates can be negative if the top-left hand corner of the window is outside of the visible screen region.
+  pub fn cursor_position(&self) -> crate::Result<PhysicalPosition<f64>> {
+    self.app_handle.cursor_position()
+  }
+
   /// Closes this webview.
   pub fn close(&self) -> crate::Result<()> {
     self.webview.dispatcher.close()?;

+ 16 - 0
core/tauri/src/webview/webview_window.rs

@@ -1221,6 +1221,22 @@ impl<R: Runtime> WebviewWindow<R> {
   }
 }
 
+/// Desktop window getters.
+#[cfg(desktop)]
+impl<R: Runtime> WebviewWindow<R> {
+  /// Get the cursor position relative to the top-left hand corner of the desktop.
+  ///
+  /// Note that the top-left hand corner of the desktop is not necessarily the same as the screen.
+  /// If the user uses a desktop with multiple monitors,
+  /// the top-left hand corner of the desktop is the top-left hand corner of the main monitor on Windows and macOS
+  /// or the top-left of the leftmost monitor on X11.
+  ///
+  /// The coordinates can be negative if the top-left hand corner of the window is outside of the visible screen region.
+  pub fn cursor_position(&self) -> crate::Result<PhysicalPosition<f64>> {
+    self.webview.cursor_position()
+  }
+}
+
 /// Desktop window setters and actions.
 #[cfg(desktop)]
 impl<R: Runtime> WebviewWindow<R> {

+ 16 - 0
core/tauri/src/window/mod.rs

@@ -1553,6 +1553,22 @@ impl<R: Runtime> Window<R> {
   }
 }
 
+/// Desktop window getters.
+#[cfg(desktop)]
+impl<R: Runtime> Window<R> {
+  /// Get the cursor position relative to the top-left hand corner of the desktop.
+  ///
+  /// Note that the top-left hand corner of the desktop is not necessarily the same as the screen.
+  /// If the user uses a desktop with multiple monitors,
+  /// the top-left hand corner of the desktop is the top-left hand corner of the main monitor on Windows and macOS
+  /// or the top-left of the leftmost monitor on X11.
+  ///
+  /// The coordinates can be negative if the top-left hand corner of the window is outside of the visible screen region.
+  pub fn cursor_position(&self) -> crate::Result<PhysicalPosition<f64>> {
+    self.app_handle.cursor_position()
+  }
+}
+
 /// Desktop window setters and actions.
 #[cfg(desktop)]
 impl<R: Runtime> Window<R> {

+ 2 - 0
core/tauri/src/window/plugin.rs

@@ -90,6 +90,7 @@ mod desktop_commands {
   getter!(current_monitor, Option<Monitor>);
   getter!(primary_monitor, Option<Monitor>);
   getter!(available_monitors, Vec<Monitor>);
+  getter!(cursor_position, PhysicalPosition<f64>);
   getter!(theme, Theme);
 
   setter!(center);
@@ -222,6 +223,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
             desktop_commands::current_monitor,
             desktop_commands::primary_monitor,
             desktop_commands::available_monitors,
+            desktop_commands::cursor_position,
             desktop_commands::theme,
             // setters
             desktop_commands::center,

+ 18 - 1
tooling/api/src/window.ts

@@ -2256,6 +2256,22 @@ async function availableMonitors(): Promise<Monitor[]> {
   )
 }
 
+/**
+ * Get the cursor position relative to the top-left hand corner of the desktop.
+ *
+ * Note that the top-left hand corner of the desktop is not necessarily the same as the screen.
+ * If the user uses a desktop with multiple monitors,
+ * the top-left hand corner of the desktop is the top-left hand corner of the main monitor on Windows and macOS
+ * or the top-left of the leftmost monitor on X11.
+ *
+ * The coordinates can be negative if the top-left hand corner of the window is outside of the visible screen region.
+ */
+async function cursorPosition(): Promise<PhysicalPosition> {
+  return invoke<PhysicalPosition>('plugin:window|cursor_position').then(
+    mapPhysicalPosition
+  )
+}
+
 export {
   Window,
   CloseRequestedEvent,
@@ -2270,7 +2286,8 @@ export {
   EffectState,
   currentMonitor,
   primaryMonitor,
-  availableMonitors
+  availableMonitors,
+  cursorPosition
 }
 
 export type {

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است