Browse Source

feat(core): add monitor functions for `App/AppHandle`, closes #6394 (#6403)

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
Amr Bashir 2 years ago
parent
commit
84c4159754

+ 5 - 0
.changes/core-app-montior.md

@@ -0,0 +1,5 @@
+---
+'tauri': 'minor:feat'
+---
+
+Add `App::primary_monitor`, `App::available_monitors`, `AppHandle::primary_monitor`, and `AppHandle::available_monitors`

+ 6 - 0
.changes/runtime-monitor.md

@@ -0,0 +1,6 @@
+---
+"tauri-runtime": "minor:feat"
+"tauri-runtime-wry": "minor:feat"
+---
+
+Added `primary_monitor` and `available_monitors` to `Runtime` and `RuntimeHandle`.

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

@@ -1912,6 +1912,25 @@ impl<T: UserEvent> RuntimeHandle<T> for WryHandle<T> {
     self.context.main_thread.window_target.raw_display_handle()
   }
 
+  fn primary_monitor(&self) -> Option<Monitor> {
+    self
+      .context
+      .main_thread
+      .window_target
+      .primary_monitor()
+      .map(|m| MonitorHandleWrapper(m).into())
+  }
+
+  fn available_monitors(&self) -> Vec<Monitor> {
+    self
+      .context
+      .main_thread
+      .window_target
+      .available_monitors()
+      .map(|m| MonitorHandleWrapper(m).into())
+      .collect()
+  }
+
   #[cfg(target_os = "macos")]
   fn show(&self) -> tauri_runtime::Result<()> {
     send_user_message(
@@ -2090,6 +2109,25 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
       .push(Arc::new(Box::new(f)));
   }
 
+  fn primary_monitor(&self) -> Option<Monitor> {
+    self
+      .context
+      .main_thread
+      .window_target
+      .primary_monitor()
+      .map(|m| MonitorHandleWrapper(m).into())
+  }
+
+  fn available_monitors(&self) -> Vec<Monitor> {
+    self
+      .context
+      .main_thread
+      .window_target
+      .available_monitors()
+      .map(|m| MonitorHandleWrapper(m).into())
+      .collect()
+  }
+
   #[cfg(target_os = "macos")]
   fn set_activation_policy(&mut self, activation_policy: ActivationPolicy) {
     self

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

@@ -387,6 +387,9 @@ pub trait RuntimeHandle<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'st
 
   fn raw_display_handle(&self) -> RawDisplayHandle;
 
+  fn primary_monitor(&self) -> Option<Monitor>;
+  fn available_monitors(&self) -> Vec<Monitor>;
+
   /// Shows the application, but does not automatically focus it.
   #[cfg(target_os = "macos")]
   #[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
@@ -460,6 +463,9 @@ pub trait Runtime<T: UserEvent>: Debug + Sized + 'static {
   #[cfg_attr(doc_cfg, doc(cfg(feature = "system-tray")))]
   fn on_system_tray_event<F: Fn(TrayId, &SystemTrayEvent) + Send + 'static>(&mut self, f: F);
 
+  fn primary_monitor(&self) -> Option<Monitor>;
+  fn available_monitors(&self) -> Vec<Monitor>;
+
   /// Sets the activation policy for the application. It is set to `NSApplicationActivationPolicyRegular` by default.
   #[cfg(target_os = "macos")]
   #[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]

+ 30 - 1
core/tauri/src/app.rs

@@ -24,7 +24,7 @@ use crate::{
   utils::config::Config,
   utils::{assets::Assets, Env},
   Context, DeviceEventFilter, EventLoopMessage, Icon, Invoke, InvokeError, InvokeResponse, Manager,
-  Runtime, Scopes, StateManager, Theme, Window,
+  Monitor, Runtime, Scopes, StateManager, Theme, Window,
 };
 
 #[cfg(feature = "protocol-asset")]
@@ -570,6 +570,35 @@ macro_rules! shared_app_impl {
         }
       }
 
+      /// Returns the primary monitor of the system.
+      ///
+      /// Returns None if it can't identify any monitor as a primary one.
+      pub fn primary_monitor(&self) -> crate::Result<Option<Monitor>> {
+       Ok(match self.runtime() {
+          RuntimeOrDispatch::Runtime(h) => h
+            .primary_monitor().map(Into::into),
+          RuntimeOrDispatch::RuntimeHandle(h) =>  h
+            .primary_monitor().map(Into::into),
+          _ => unreachable!()
+        })
+      }
+
+      /// Returns the list of all the monitors available on the system.
+      pub fn available_monitors(&self) -> crate::Result<Vec<Monitor>> {
+        Ok(match self.runtime() {
+          RuntimeOrDispatch::Runtime(h) => h
+            .available_monitors()
+            .into_iter()
+            .map(Into::into)
+            .collect(),
+          RuntimeOrDispatch::RuntimeHandle(h) => h
+            .available_monitors()
+            .into_iter()
+            .map(Into::into)
+            .collect(),
+          _ => unreachable!()
+        })
+      }
       /// Returns the default window icon.
       pub fn default_window_icon(&self) -> Option<&Icon> {
         self.manager.inner.default_window_icon.as_ref()

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

@@ -154,6 +154,14 @@ impl<T: UserEvent> RuntimeHandle<T> for MockRuntimeHandle {
     return unimplemented!();
   }
 
+  fn primary_monitor(&self) -> Option<Monitor> {
+    unimplemented!()
+  }
+
+  fn available_monitors(&self) -> Vec<Monitor> {
+    unimplemented!()
+  }
+
   /// Shows the application, but does not automatically focus it.
   #[cfg(target_os = "macos")]
   fn show(&self) -> Result<()> {
@@ -815,6 +823,14 @@ impl<T: UserEvent> Runtime<T> for MockRuntime {
   #[cfg_attr(doc_cfg, doc(cfg(feature = "system-tray")))]
   fn on_system_tray_event<F: Fn(TrayId, &SystemTrayEvent) + Send + 'static>(&mut self, f: F) {}
 
+  fn primary_monitor(&self) -> Option<Monitor> {
+    unimplemented!()
+  }
+
+  fn available_monitors(&self) -> Vec<Monitor> {
+    unimplemented!()
+  }
+
   #[cfg(target_os = "macos")]
   #[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
   fn set_activation_policy(&mut self, activation_policy: tauri_runtime::ActivationPolicy) {}