mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-23 20:53:06 +00:00
Merge pull request #1150 from terhechte/feat/window_close_behaviour
Window Close Behaviour
This commit is contained in:
commit
747c03938a
4 changed files with 80 additions and 9 deletions
|
@ -2,9 +2,12 @@ use dioxus::prelude::*;
|
|||
use dioxus_desktop::tao::event::WindowEvent;
|
||||
use dioxus_desktop::use_wry_event_handler;
|
||||
use dioxus_desktop::wry::application::event::Event as WryEvent;
|
||||
use dioxus_desktop::{Config, WindowCloseBehaviour};
|
||||
|
||||
fn main() {
|
||||
dioxus_desktop::launch(app);
|
||||
let cfg = Config::new().with_close_behaviour(WindowCloseBehaviour::CloseWindow);
|
||||
|
||||
dioxus_desktop::launch_cfg(app, cfg);
|
||||
}
|
||||
|
||||
fn app(cx: Scope) -> Element {
|
||||
|
|
|
@ -49,6 +49,7 @@ objc_id = "0.1.1"
|
|||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
core-foundation = "0.9.3"
|
||||
objc = "0.2.7"
|
||||
|
||||
[features]
|
||||
default = ["tokio_runtime", "hot-reload"]
|
||||
|
|
|
@ -11,6 +11,17 @@ use wry::{
|
|||
|
||||
// pub(crate) type DynEventHandlerFn = dyn Fn(&mut EventLoop<()>, &mut WebView);
|
||||
|
||||
/// The behaviour of the application when the last window is closed.
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
pub enum WindowCloseBehaviour {
|
||||
/// Default behaviour, closing the last window exits the app
|
||||
LastWindowExitsApp,
|
||||
/// Closing the last window will not actually close it, just hide it
|
||||
LastWindowHides,
|
||||
/// Closing the last window will close it but the app will keep running so that new windows can be opened
|
||||
CloseWindow,
|
||||
}
|
||||
|
||||
/// The configuration for the desktop application.
|
||||
pub struct Config {
|
||||
pub(crate) window: WindowBuilder,
|
||||
|
@ -24,6 +35,7 @@ pub struct Config {
|
|||
pub(crate) custom_index: Option<String>,
|
||||
pub(crate) root_name: String,
|
||||
pub(crate) background_color: Option<(u8, u8, u8, u8)>,
|
||||
pub(crate) last_window_close_behaviour: WindowCloseBehaviour,
|
||||
}
|
||||
|
||||
type DropHandler = Box<dyn Fn(&Window, FileDropEvent) -> bool>;
|
||||
|
@ -52,6 +64,7 @@ impl Config {
|
|||
custom_index: None,
|
||||
root_name: "main".to_string(),
|
||||
background_color: None,
|
||||
last_window_close_behaviour: WindowCloseBehaviour::LastWindowExitsApp,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,6 +102,12 @@ impl Config {
|
|||
self
|
||||
}
|
||||
|
||||
/// Sets the behaviour of the application when the last window is closed.
|
||||
pub fn with_close_behaviour(mut self, behaviour: WindowCloseBehaviour) -> Self {
|
||||
self.last_window_close_behaviour = behaviour;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set a file drop handler
|
||||
pub fn with_file_drop_handler(
|
||||
mut self,
|
||||
|
|
|
@ -20,7 +20,7 @@ mod webview;
|
|||
mod mobile_shortcut;
|
||||
|
||||
use crate::query::QueryResult;
|
||||
pub use cfg::Config;
|
||||
pub use cfg::{Config, WindowCloseBehaviour};
|
||||
pub use desktop_context::DesktopContext;
|
||||
pub use desktop_context::{
|
||||
use_window, use_wry_event_handler, DesktopService, WryEventHandler, WryEventHandlerId,
|
||||
|
@ -122,6 +122,8 @@ pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config)
|
|||
|
||||
let proxy = event_loop.create_proxy();
|
||||
|
||||
let window_behaviour = cfg.last_window_close_behaviour;
|
||||
|
||||
// Intialize hot reloading if it is enabled
|
||||
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
||||
dioxus_hot_reload::connect({
|
||||
|
@ -169,18 +171,33 @@ pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config)
|
|||
Event::WindowEvent {
|
||||
event, window_id, ..
|
||||
} => match event {
|
||||
WindowEvent::CloseRequested => {
|
||||
webviews.remove(&window_id);
|
||||
WindowEvent::CloseRequested => match window_behaviour {
|
||||
cfg::WindowCloseBehaviour::LastWindowExitsApp => {
|
||||
webviews.remove(&window_id);
|
||||
|
||||
if webviews.is_empty() {
|
||||
*control_flow = ControlFlow::Exit
|
||||
if webviews.is_empty() {
|
||||
*control_flow = ControlFlow::Exit
|
||||
}
|
||||
}
|
||||
}
|
||||
cfg::WindowCloseBehaviour::LastWindowHides => {
|
||||
let Some(webview) = webviews.get(&window_id) else {
|
||||
return;
|
||||
};
|
||||
hide_app_window(&webview.desktop_context.webview);
|
||||
}
|
||||
cfg::WindowCloseBehaviour::CloseWindow => {
|
||||
webviews.remove(&window_id);
|
||||
}
|
||||
},
|
||||
WindowEvent::Destroyed { .. } => {
|
||||
webviews.remove(&window_id);
|
||||
|
||||
if webviews.is_empty() {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
if matches!(
|
||||
window_behaviour,
|
||||
cfg::WindowCloseBehaviour::LastWindowExitsApp
|
||||
) && webviews.is_empty()
|
||||
{
|
||||
*control_flow = ControlFlow::Exit
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -423,3 +440,34 @@ fn send_edits(edits: Mutations, webview: &WebView) {
|
|||
// todo: use SSE and binary data to send the edits with lower overhead
|
||||
_ = webview.evaluate_script(&format!("window.interpreter.handleEdits({serialized})"));
|
||||
}
|
||||
|
||||
/// Different hide implementations per platform
|
||||
#[allow(unused)]
|
||||
fn hide_app_window(webview: &WebView) {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
use wry::application::platform::windows::WindowExtWindows;
|
||||
webview.window().set_visible(false);
|
||||
webview.window().set_skip_taskbar(true);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
use wry::application::platform::unix::WindowExtUnix;
|
||||
webview.window().set_visible(false);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
// webview.window().set_visible(false); has the wrong behaviour on macOS
|
||||
// It will hide the window but not show it again when the user switches
|
||||
// back to the app. `NSApplication::hide:` has the correct behaviour
|
||||
use objc::runtime::Object;
|
||||
use objc::{msg_send, sel, sel_impl};
|
||||
objc::rc::autoreleasepool(|| unsafe {
|
||||
let app: *mut Object = msg_send![objc::class!(NSApplication), sharedApplication];
|
||||
let nil = std::ptr::null_mut::<Object>();
|
||||
let _: () = msg_send![app, hide: nil];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue