From edad9f4f55dcc69a06cd9d6d5a5068c94ecb77dd Mon Sep 17 00:00:00 2001 From: Lucas Fernandes Nogueira Date: Mon, 28 Mar 2022 13:26:25 -0700 Subject: [PATCH] refactor(core): add `RunEvent::WindowEvent` (#3793) --- .changes/refactor-runtime-window-event.md | 6 ++ .changes/refactor-window-event.md | 5 ++ core/tauri-runtime-wry/src/lib.rs | 23 +++--- core/tauri-runtime/src/lib.rs | 10 +-- core/tauri-runtime/src/window.rs | 3 - core/tauri/src/app.rs | 89 ++++++++++++++++++++--- core/tauri/src/lib.rs | 4 +- core/tauri/src/manager.rs | 8 +- examples/api/src-tauri/src/main.rs | 9 ++- 9 files changed, 115 insertions(+), 42 deletions(-) create mode 100644 .changes/refactor-runtime-window-event.md create mode 100644 .changes/refactor-window-event.md diff --git a/.changes/refactor-runtime-window-event.md b/.changes/refactor-runtime-window-event.md new file mode 100644 index 000000000..bbb1765df --- /dev/null +++ b/.changes/refactor-runtime-window-event.md @@ -0,0 +1,6 @@ +--- +"tauri-runtime": minor +"tauri-runtime-wry": minor +--- + +**Breaking change:** Use the dedicated `WindowEvent` enum on `RunEvent`. diff --git a/.changes/refactor-window-event.md b/.changes/refactor-window-event.md new file mode 100644 index 000000000..5cc8699a1 --- /dev/null +++ b/.changes/refactor-window-event.md @@ -0,0 +1,5 @@ +--- +"tauri": patch +--- + +**Breaking change:** Removed `RunEvent::CloseRequested` and `RunEvent::WindowClosed` and added `RunEvent::WindowEvent`. diff --git a/core/tauri-runtime-wry/src/lib.rs b/core/tauri-runtime-wry/src/lib.rs index 9ed9b52c7..fe08daf5d 100644 --- a/core/tauri-runtime-wry/src/lib.rs +++ b/core/tauri-runtime-wry/src/lib.rs @@ -2458,9 +2458,16 @@ fn handle_event_loop( { let windows_lock = windows.lock().expect("poisoned webview collection"); - if let Some(window_handle) = windows_lock.get(&window_id).map(|w| &w.inner) { + if let Some((label, window_handle)) = + windows_lock.get(&window_id).map(|w| (&w.label, &w.inner)) + { if let Some(event) = WindowEventWrapper::parse(window_handle, &event).0 { + let label = label.clone(); drop(windows_lock); + callback(RunEvent::WindowEvent { + label, + event: event.clone(), + }); for handler in window_event_listeners .lock() .unwrap() @@ -2519,7 +2526,6 @@ fn handle_event_loop( Event::UserEvent(message) => match message { Message::Window(id, WindowMessage::Close) => { on_window_close( - callback, id, windows.lock().expect("poisoned webview collection"), menu_event_listeners.clone(), @@ -2574,19 +2580,17 @@ fn on_close_requested<'a, T: UserEvent>( .values() { handler(&WindowEvent::CloseRequested { - label: label.clone(), signal_tx: tx.clone(), }); } - callback(RunEvent::CloseRequested { + callback(RunEvent::WindowEvent { label, - signal_tx: tx, + event: WindowEvent::CloseRequested { signal_tx: tx }, }); if let Ok(true) = rx.try_recv() { None } else { on_window_close( - callback, window_id, windows.lock().expect("poisoned webview collection"), menu_event_listeners, @@ -2597,17 +2601,14 @@ fn on_close_requested<'a, T: UserEvent>( } } -fn on_window_close<'a, T: UserEvent>( - callback: &'a mut (dyn FnMut(RunEvent) + 'static), +fn on_window_close( window_id: WebviewId, - mut windows: MutexGuard<'a, HashMap>, + mut windows: MutexGuard<'_, HashMap>, menu_event_listeners: MenuEventListeners, ) -> Option { #[allow(unused_mut)] let w = if let Some(mut webview) = windows.remove(&window_id) { - drop(windows); menu_event_listeners.lock().unwrap().remove(&window_id); - callback(RunEvent::WindowClose(webview.label.clone())); Some(webview) } else { None diff --git a/core/tauri-runtime/src/lib.rs b/core/tauri-runtime/src/lib.rs index 82614dc80..26cd65da1 100644 --- a/core/tauri-runtime/src/lib.rs +++ b/core/tauri-runtime/src/lib.rs @@ -208,15 +208,13 @@ pub enum RunEvent { ExitRequested { tx: Sender, }, - /// Window close was requested by the user. - CloseRequested { + /// An event associated with a window. + WindowEvent { /// The window label. label: String, - /// A signal sender. If a `true` value is emitted, the window won't be closed. - signal_tx: Sender, + /// The detailed event. + event: WindowEvent, }, - /// Window closed. - WindowClose(String), /// Application ready. Ready, /// Sent if the event loop is being resumed. diff --git a/core/tauri-runtime/src/window.rs b/core/tauri-runtime/src/window.rs index dbcf5576a..9d954bc6c 100644 --- a/core/tauri-runtime/src/window.rs +++ b/core/tauri-runtime/src/window.rs @@ -28,7 +28,6 @@ pub mod dpi; /// An event from a window. #[derive(Debug, Clone)] -#[non_exhaustive] pub enum WindowEvent { /// The size of the window has changed. Contains the client area's new dimensions. Resized(dpi::PhysicalSize), @@ -36,8 +35,6 @@ pub enum WindowEvent { Moved(dpi::PhysicalPosition), /// The window has been requested to close. CloseRequested { - /// The window label. - label: String, /// A signal sender. If a `true` value is emitted, the window won't be closed. signal_tx: Sender, }, diff --git a/core/tauri/src/app.rs b/core/tauri/src/app.rs index af5b46839..c1280ec7e 100644 --- a/core/tauri/src/app.rs +++ b/core/tauri/src/app.rs @@ -16,7 +16,7 @@ use crate::{ runtime::{ http::{Request as HttpRequest, Response as HttpResponse}, webview::{WebviewAttributes, WindowBuilder as _}, - window::{PendingWindow, WindowEvent}, + window::{PendingWindow, WindowEvent as RuntimeWindowEvent}, Dispatch, ExitRequestedEventAction, RunEvent as RuntimeRunEvent, }, scope::FsScope, @@ -32,6 +32,10 @@ use crate::{ use crate::scope::ShellScope; use tauri_macros::default_runtime; +use tauri_runtime::window::{ + dpi::{PhysicalPosition, PhysicalSize}, + FileDropEvent, +}; use tauri_utils::PackageInfo; use std::{ @@ -69,7 +73,7 @@ impl ExitRequestApi { } /// Api exposed on the `CloseRequested` event. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct CloseRequestApi(Sender); impl CloseRequestApi { @@ -79,6 +83,66 @@ impl CloseRequestApi { } } +/// An event from a window. +#[derive(Debug, Clone)] +#[non_exhaustive] +pub enum WindowEvent { + /// The size of the window has changed. Contains the client area's new dimensions. + Resized(PhysicalSize), + /// The position of the window has changed. Contains the window's new position. + Moved(PhysicalPosition), + /// The window has been requested to close. + #[non_exhaustive] + CloseRequested { + /// An API modify the behavior of the close requested event. + api: CloseRequestApi, + }, + /// The window has been destroyed. + Destroyed, + /// The window gained or lost focus. + /// + /// The parameter is true if the window has gained focus, and false if it has lost focus. + Focused(bool), + /// The window's scale factor has changed. + /// + /// The following user actions can cause DPI changes: + /// + /// - Changing the display's resolution. + /// - Changing the display's scale factor (e.g. in Control Panel on Windows). + /// - Moving the window to a display with a different scale factor. + #[non_exhaustive] + ScaleFactorChanged { + /// The new scale factor. + scale_factor: f64, + /// The window inner size. + new_inner_size: PhysicalSize, + }, + /// An event associated with the file drop action. + FileDrop(FileDropEvent), +} + +impl From for WindowEvent { + fn from(event: RuntimeWindowEvent) -> Self { + match event { + RuntimeWindowEvent::Resized(size) => Self::Resized(size), + RuntimeWindowEvent::Moved(position) => Self::Moved(position), + RuntimeWindowEvent::CloseRequested { signal_tx } => Self::CloseRequested { + api: CloseRequestApi(signal_tx), + }, + RuntimeWindowEvent::Destroyed => Self::Destroyed, + RuntimeWindowEvent::Focused(flag) => Self::Focused(flag), + RuntimeWindowEvent::ScaleFactorChanged { + scale_factor, + new_inner_size, + } => Self::ScaleFactorChanged { + scale_factor, + new_inner_size, + }, + RuntimeWindowEvent::FileDrop(event) => Self::FileDrop(event), + } + } +} + /// An application event, triggered from the event loop. #[derive(Debug)] #[non_exhaustive] @@ -91,16 +155,14 @@ pub enum RunEvent { /// Event API api: ExitRequestApi, }, - /// Window close was requested by the user. + /// An event associated with a window. #[non_exhaustive] - CloseRequested { + WindowEvent { /// The window label. label: String, - /// Event API. - api: CloseRequestApi, + /// The detailed event. + event: WindowEvent, }, - /// Window closed. - WindowClosed(String), /// Application ready. Ready, /// Sent if the event loop is being resumed. @@ -1428,7 +1490,11 @@ fn on_event_loop_event, RunEvent) + 'static>( manager: &WindowManager, callback: Option<&mut F>, ) { - if let RuntimeRunEvent::WindowClose(label) = &event { + if let RuntimeRunEvent::WindowEvent { + label, + event: RuntimeWindowEvent::Destroyed, + } = &event + { manager.on_window_close(label); } @@ -1437,11 +1503,10 @@ fn on_event_loop_event, RunEvent) + 'static>( RuntimeRunEvent::ExitRequested { tx } => RunEvent::ExitRequested { api: ExitRequestApi(tx), }, - RuntimeRunEvent::CloseRequested { label, signal_tx } => RunEvent::CloseRequested { + RuntimeRunEvent::WindowEvent { label, event } => RunEvent::WindowEvent { label, - api: CloseRequestApi(signal_tx), + event: event.into(), }, - RuntimeRunEvent::WindowClose(label) => RunEvent::WindowClosed(label), RuntimeRunEvent::Ready => RunEvent::Ready, RuntimeRunEvent::Resumed => RunEvent::Resumed, RuntimeRunEvent::MainEventsCleared => RunEvent::MainEventsCleared, diff --git a/core/tauri/src/lib.rs b/core/tauri/src/lib.rs index 47aa3a9d1..124933805 100644 --- a/core/tauri/src/lib.rs +++ b/core/tauri/src/lib.rs @@ -203,7 +203,7 @@ pub use { pub use { self::app::{ App, AppHandle, AssetResolver, Builder, CloseRequestApi, GlobalWindowEvent, PathResolver, - RunEvent, + RunEvent, WindowEvent, }, self::hooks::{ Invoke, InvokeError, InvokeHandler, InvokeMessage, InvokePayload, InvokeResolver, @@ -214,7 +214,7 @@ pub use { webview::{WebviewAttributes, WindowBuilder}, window::{ dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Pixel, Position, Size}, - FileDropEvent, WindowEvent, + FileDropEvent, }, ClipboardManager, GlobalShortcutManager, RunIteration, TrayIcon, UserAttentionType, }, diff --git a/core/tauri/src/manager.rs b/core/tauri/src/manager.rs index 368461d69..5bb0ee5e0 100644 --- a/core/tauri/src/manager.rs +++ b/core/tauri/src/manager.rs @@ -1147,7 +1147,7 @@ impl WindowManager { for handler in window_event_listeners.iter() { handler(GlobalWindowEvent { window: window_.clone(), - event: event.clone(), + event: event.clone().into(), }); } }); @@ -1274,10 +1274,7 @@ fn on_window_event( match event { WindowEvent::Resized(size) => window.emit(WINDOW_RESIZED_EVENT, size)?, WindowEvent::Moved(position) => window.emit(WINDOW_MOVED_EVENT, position)?, - WindowEvent::CloseRequested { - label: _, - signal_tx, - } => { + WindowEvent::CloseRequested { signal_tx } => { if window.has_js_listener(Some(window.label().into()), WINDOW_CLOSE_REQUESTED_EVENT) { signal_tx.send(true).unwrap(); } @@ -1328,7 +1325,6 @@ fn on_window_event( FileDropEvent::Cancelled => window.emit("tauri://file-drop-cancelled", ())?, _ => unimplemented!(), }, - _ => unimplemented!(), } Ok(()) } diff --git a/examples/api/src-tauri/src/main.rs b/examples/api/src-tauri/src/main.rs index f21f415dd..c7e629aa4 100644 --- a/examples/api/src-tauri/src/main.rs +++ b/examples/api/src-tauri/src/main.rs @@ -17,7 +17,8 @@ use std::sync::atomic::{AtomicBool, Ordering}; use serde::{Deserialize, Serialize}; use tauri::{ api::dialog::ask, http::ResponseBuilder, window::WindowBuilder, CustomMenuItem, - GlobalShortcutManager, Manager, RunEvent, SystemTray, SystemTrayEvent, SystemTrayMenu, WindowUrl, + GlobalShortcutManager, Manager, RunEvent, SystemTray, SystemTrayEvent, SystemTrayMenu, + WindowEvent, WindowUrl, }; #[derive(Clone, Serialize)] @@ -227,7 +228,11 @@ fn main() { } // Triggered when a window is trying to close - RunEvent::CloseRequested { label, api, .. } => { + RunEvent::WindowEvent { + label, + event: WindowEvent::CloseRequested { api, .. }, + .. + } => { let app_handle = app_handle.clone(); let window = app_handle.get_window(&label).unwrap(); // use the exposed close api, and prevent the event loop to close