Sfoglia il codice sorgente

fix(runtime-wry): run `cursor_position` getter on main thread (#11401)

* fix(runtime-wry): run `cursor_position` getter on main thread

closes #10340

* clippy

* clippy

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
Amr Bashir 9 mesi fa
parent
commit
8c6d1e8e6c

+ 6 - 0
.changes/curosr-position-gtk.md

@@ -0,0 +1,6 @@
+---
+"tauri": "patch:bug"
+"tauri-runtime-wry": "patch:bug"
+---
+
+Fix `App/AppHandle/Window/Webview/WebviewWindow::cursor_position` getter method failing on Linux with `GDK may only be used from the main thread`.

+ 3 - 11
crates/tauri-cli/src/mobile/init.rs

@@ -198,17 +198,9 @@ fn get_str<'a>(helper: &'a Helper) -> &'a str {
 
 fn get_str_array(helper: &Helper, formatter: impl Fn(&str) -> String) -> Option<Vec<String>> {
   helper.param(0).and_then(|v| {
-    v.value().as_array().and_then(|arr| {
-      arr
-        .iter()
-        .map(|val| {
-          val.as_str().map(
-            #[allow(clippy::redundant_closure)]
-            &formatter,
-          )
-        })
-        .collect()
-    })
+    v.value()
+      .as_array()
+      .and_then(|arr| arr.iter().map(|val| val.as_str().map(&formatter)).collect())
   })
 }
 

+ 22 - 10
crates/tauri-runtime-wry/src/lib.rs

@@ -181,6 +181,13 @@ macro_rules! window_getter {
   }};
 }
 
+macro_rules! event_loop_window_getter {
+  ($self: ident, $message: expr) => {{
+    let (tx, rx) = channel();
+    getter!($self, rx, Message::EventLoopWindowTarget($message(tx)))
+  }};
+}
+
 macro_rules! webview_getter {
   ($self: ident, $message: expr) => {{
     let (tx, rx) = channel();
@@ -1268,6 +1275,10 @@ pub enum WebviewMessage {
   IsDevToolsOpen(Sender<bool>),
 }
 
+pub enum EventLoopWindowTargetMessage {
+  CursorPosition(Sender<Result<PhysicalPosition<f64>>>),
+}
+
 pub type CreateWindowClosure<T> =
   Box<dyn FnOnce(&EventLoopWindowTarget<Message<T>>) -> Result<WindowWrapper> + Send>;
 
@@ -1282,6 +1293,7 @@ pub enum Message<T: 'static> {
   Application(ApplicationMessage),
   Window(WindowId, WindowMessage),
   Webview(WindowId, WebviewId, WebviewMessage),
+  EventLoopWindowTarget(EventLoopWindowTargetMessage),
   CreateWebview(WindowId, CreateWebviewClosure),
   CreateWindow(WindowId, CreateWindowClosure<T>),
   CreateRawWindow(
@@ -2325,11 +2337,7 @@ impl<T: UserEvent> RuntimeHandle<T> for WryHandle<T> {
   }
 
   fn cursor_position(&self) -> Result<PhysicalPosition<f64>> {
-    self
-      .context
-      .main_thread
-      .window_target
-      .cursor_position()
+    event_loop_window_getter!(self, EventLoopWindowTargetMessage::CursorPosition)?
       .map(PhysicalPositionWrapper)
       .map(Into::into)
       .map_err(|_| Error::FailedToGetCursorPosition)
@@ -2616,11 +2624,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
   }
 
   fn cursor_position(&self) -> Result<PhysicalPosition<f64>> {
-    self
-      .context
-      .main_thread
-      .window_target
-      .cursor_position()
+    event_loop_window_getter!(self, EventLoopWindowTargetMessage::CursorPosition)?
       .map(PhysicalPositionWrapper)
       .map(Into::into)
       .map_err(|_| Error::FailedToGetCursorPosition)
@@ -3452,6 +3456,14 @@ fn handle_user_message<T: UserEvent>(
     }
 
     Message::UserEvent(_) => (),
+    Message::EventLoopWindowTarget(message) => match message {
+      EventLoopWindowTargetMessage::CursorPosition(sender) => {
+        let pos = event_loop
+          .cursor_position()
+          .map_err(|_| Error::FailedToSendMessage);
+        sender.send(pos).unwrap();
+      }
+    },
   }
 }