Browse Source

feat(core): add `on_window_event` (global) API to app::Builder (#1759)

Lucas Fernandes Nogueira 4 years ago
parent
commit
34b6032df7
3 changed files with 50 additions and 3 deletions
  1. 36 1
      core/tauri/src/app.rs
  2. 1 1
      core/tauri/src/lib.rs
  3. 13 1
      core/tauri/src/manager.rs

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

@@ -12,7 +12,7 @@ use crate::{
     menu::{Menu, MenuId, SystemTrayMenuItem},
     tag::Tag,
     webview::{CustomProtocol, WebviewAttributes, WindowBuilder},
-    window::PendingWindow,
+    window::{PendingWindow, WindowEvent},
     Dispatch, Params, Runtime,
   },
   sealed::{ManagerBase, RuntimeOrDispatch},
@@ -25,6 +25,7 @@ use std::{collections::HashMap, sync::Arc};
 use crate::updater;
 
 pub(crate) type GlobalMenuEventListener<P> = Box<dyn Fn(WindowMenuEvent<P>) + Send + Sync>;
+pub(crate) type GlobalWindowEventListener<P> = Box<dyn Fn(GlobalWindowEvent<P>) + Send + Sync>;
 type SystemTrayEventListener<P> =
   Box<dyn Fn(&AppHandle<P>, SystemTrayEvent<<P as Params>::SystemTrayMenuId>) + Send + Sync>;
 
@@ -58,6 +59,24 @@ impl<P: Params> WindowMenuEvent<P> {
   }
 }
 
+/// A window event that was triggered on the specified window.
+pub struct GlobalWindowEvent<P: Params> {
+  pub(crate) event: WindowEvent,
+  pub(crate) window: Window<P>,
+}
+
+impl<P: Params> GlobalWindowEvent<P> {
+  /// The eventpayload.
+  pub fn event(&self) -> &WindowEvent {
+    &self.event
+  }
+
+  /// The window that the menu belongs to.
+  pub fn window(&self) -> &Window<P> {
+    &self.window
+  }
+}
+
 /// A handle to the currently running application.
 pub struct AppHandle<P: Params> {
   manager: WindowManager<P>,
@@ -206,6 +225,9 @@ where
   /// Menu event handlers that listens to all windows.
   menu_event_listeners: Vec<GlobalMenuEventListener<Args<E, L, MID, TID, A, R>>>,
 
+  /// Window event handlers that listens to all windows.
+  window_event_listeners: Vec<GlobalWindowEventListener<Args<E, L, MID, TID, A, R>>>,
+
   /// The app system tray menu items.
   system_tray: Vec<SystemTrayMenuItem<TID>>,
 
@@ -234,6 +256,7 @@ where
       state: StateManager::new(),
       menu: Vec::new(),
       menu_event_listeners: Vec::new(),
+      window_event_listeners: Vec::new(),
       system_tray: Vec::new(),
       system_tray_event_listeners: Vec::new(),
     }
@@ -372,6 +395,17 @@ where
     self
   }
 
+  /// Registers a window event handler for all windows.
+  pub fn on_window_event<
+    F: Fn(GlobalWindowEvent<Args<E, L, MID, TID, A, R>>) + Send + Sync + 'static,
+  >(
+    mut self,
+    handler: F,
+  ) -> Self {
+    self.window_event_listeners.push(Box::new(handler));
+    self
+  }
+
   /// Registers a system tray event handler.
   pub fn on_system_tray_event<
     F: Fn(&AppHandle<Args<E, L, MID, TID, A, R>>, SystemTrayEvent<TID>) + Send + Sync + 'static,
@@ -421,6 +455,7 @@ where
       self.state,
       self.menu,
       self.menu_event_listeners,
+      self.window_event_listeners,
     );
 
     // set up all the windows defined in the config

+ 1 - 1
core/tauri/src/lib.rs

@@ -56,7 +56,7 @@ use std::{borrow::Borrow, collections::HashMap, path::PathBuf, sync::Arc};
 pub use {
   self::api::assets::Assets,
   self::api::config::{Config, WindowUrl},
-  self::app::{App, Builder, SystemTrayEvent, WindowMenuEvent},
+  self::app::{App, Builder, GlobalWindowEvent, SystemTrayEvent, WindowMenuEvent},
   self::hooks::{
     Invoke, InvokeError, InvokeHandler, InvokeMessage, InvokeResolver, InvokeResponse, OnPageLoad,
     PageLoadPayload, SetupHook,

+ 13 - 1
core/tauri/src/manager.rs

@@ -9,7 +9,7 @@ use crate::{
     path::{resolve_path, BaseDirectory},
     PackageInfo,
   },
-  app::{GlobalMenuEventListener, WindowMenuEvent},
+  app::{GlobalMenuEventListener, GlobalWindowEvent, GlobalWindowEventListener, WindowMenuEvent},
   event::{Event, EventHandler, Listeners},
   hooks::{InvokeHandler, OnPageLoad, PageLoadPayload},
   plugin::PluginStore,
@@ -86,6 +86,8 @@ pub struct InnerWindowManager<P: Params> {
   menu: Vec<Menu<P::MenuId>>,
   /// Menu event listeners to all windows.
   menu_event_listeners: Arc<Vec<GlobalMenuEventListener<P>>>,
+  /// Window event listeners to all windows.
+  window_event_listeners: Arc<Vec<GlobalWindowEventListener<P>>>,
   menu_ids: HashMap<u32, P::MenuId>,
 }
 
@@ -169,6 +171,7 @@ impl<P: Params> WindowManager<P> {
     state: StateManager,
     menu: Vec<Menu<P::MenuId>>,
     menu_event_listeners: Vec<GlobalMenuEventListener<P>>,
+    window_event_listeners: Vec<GlobalWindowEventListener<P>>,
   ) -> Self {
     let menu_ids = get_menu_ids(&menu);
     Self {
@@ -187,6 +190,7 @@ impl<P: Params> WindowManager<P> {
         uri_scheme_protocols,
         menu,
         menu_event_listeners: Arc::new(menu_event_listeners),
+        window_event_listeners: Arc::new(window_event_listeners),
         menu_ids,
       }),
       _marker: Args::default(),
@@ -468,6 +472,7 @@ mod test {
         StateManager::new(),
         Vec::new(),
         Default::default(),
+        Default::default(),
       );
 
     #[cfg(custom_protocol)]
@@ -549,8 +554,15 @@ impl<P: Params> WindowManager<P> {
     let window = Window::new(self.clone(), window);
 
     let window_ = window.clone();
+    let window_event_listeners = self.inner.window_event_listeners.clone();
     window.on_window_event(move |event| {
       let _ = on_window_event(&window_, event);
+      for handler in window_event_listeners.iter() {
+        handler(GlobalWindowEvent {
+          window: window_.clone(),
+          event: event.clone(),
+        });
+      }
     });
     let window_ = window.clone();
     let menu_event_listeners = self.inner.menu_event_listeners.clone();