add functionality

This commit is contained in:
Benedikt Terhechte 2023-07-04 14:47:45 +02:00
parent 0ec30345d4
commit 6a705b6a0e
2 changed files with 75 additions and 8 deletions

View file

@ -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,

View file

@ -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,
@ -121,6 +121,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({
@ -176,18 +178,33 @@ pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config)
Event::WindowEvent {
event, window_id, ..
} => match event {
WindowEvent::CloseRequested => {
WindowEvent::CloseRequested => match window_behaviour {
cfg::WindowCloseBehaviour::LastWindowExitsApp => {
webviews.remove(&window_id);
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
}
}
_ => {}
@ -411,3 +428,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_variables)]
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];
});
}
}