dioxus_desktop/
hooks.rs

1use std::rc::Rc;
2
3use crate::{
4    assets::*, ipc::UserWindowEvent, shortcut::IntoAccelerator, window, DesktopContext,
5    ShortcutHandle, ShortcutRegistryError, WryEventHandler,
6};
7use dioxus_core::{
8    prelude::{consume_context, use_hook_with_cleanup},
9    use_hook, Runtime,
10};
11
12use dioxus_hooks::use_callback;
13use tao::{event::Event, event_loop::EventLoopWindowTarget};
14use wry::RequestAsyncResponder;
15
16/// Get an imperative handle to the current window
17pub fn use_window() -> DesktopContext {
18    use_hook(consume_context::<DesktopContext>)
19}
20
21/// Register an event handler that runs when a wry event is processed.
22pub fn use_wry_event_handler(
23    mut handler: impl FnMut(&Event<UserWindowEvent>, &EventLoopWindowTarget<UserWindowEvent>) + 'static,
24) -> WryEventHandler {
25    use dioxus_core::prelude::current_scope_id;
26
27    // Capture the current runtime and scope ID.
28    let runtime = Runtime::current().unwrap();
29    let scope_id = current_scope_id().unwrap();
30
31    use_hook_with_cleanup(
32        move || {
33            window().create_wry_event_handler(move |event, target| {
34                runtime.on_scope(scope_id, || handler(event, target))
35            })
36        },
37        move |handler| handler.remove(),
38    )
39}
40
41/// Register an event handler that runs when a muda event is processed.
42#[cfg_attr(
43    docsrs,
44    doc(cfg(any(target_os = "windows", target_os = "linux", target_os = "macos")))
45)]
46#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
47pub fn use_muda_event_handler(
48    mut handler: impl FnMut(&muda::MenuEvent) + 'static,
49) -> WryEventHandler {
50    use_wry_event_handler(move |event, _| {
51        if let Event::UserEvent(UserWindowEvent::MudaMenuEvent(event)) = event {
52            handler(event);
53        }
54    })
55}
56
57/// Register an event handler that runs when a tray icon menu event is processed.
58#[cfg_attr(
59    docsrs,
60    doc(cfg(any(target_os = "windows", target_os = "linux", target_os = "macos")))
61)]
62#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
63pub fn use_tray_menu_event_handler(
64    mut handler: impl FnMut(&tray_icon::menu::MenuEvent) + 'static,
65) -> WryEventHandler {
66    use_wry_event_handler(move |event, _| {
67        if let Event::UserEvent(UserWindowEvent::TrayMenuEvent(event)) = event {
68            handler(event);
69        }
70    })
71}
72
73/// Register an event handler that runs when a tray icon event is processed.
74/// This is only for tray icon and not it's menus.
75/// If you want to register tray icon menus handler use `use_tray_menu_event_handler` instead.
76#[cfg_attr(
77    docsrs,
78    doc(cfg(any(target_os = "windows", target_os = "linux", target_os = "macos")))
79)]
80#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
81pub fn use_tray_icon_event_handler(
82    mut handler: impl FnMut(&tray_icon::TrayIconEvent) + 'static,
83) -> WryEventHandler {
84    use_wry_event_handler(move |event, _| {
85        if let Event::UserEvent(UserWindowEvent::TrayIconEvent(event)) = event {
86            handler(event);
87        }
88    })
89}
90
91/// Provide a callback to handle asset loading yourself.
92///
93/// The callback takes a path as requested by the web view, and it should return `Some(response)`
94/// if you want to load the asset, and `None` if you want to fallback on the default behavior.
95pub fn use_asset_handler(
96    name: &str,
97    mut handler: impl FnMut(AssetRequest, RequestAsyncResponder) + 'static,
98) {
99    // wrap the user's handler in something that keeps it up to date
100    let cb = use_callback(move |(asset, responder)| handler(asset, responder));
101
102    use_hook_with_cleanup(
103        || {
104            crate::window()
105                .asset_handlers
106                .register_handler(name.to_string(), cb);
107
108            Rc::new(name.to_string())
109        },
110        move |name| {
111            _ = crate::window().asset_handlers.remove_handler(name.as_ref());
112        },
113    );
114}
115
116/// Get a closure that executes any JavaScript in the WebView context.
117pub fn use_global_shortcut(
118    accelerator: impl IntoAccelerator,
119    mut handler: impl FnMut() + 'static,
120) -> Result<ShortcutHandle, ShortcutRegistryError> {
121    // wrap the user's handler in something that keeps it up to date
122    let cb = use_callback(move |_| handler());
123
124    use_hook_with_cleanup(
125        move || window().create_shortcut(accelerator.accelerator(), move || cb(())),
126        |handle| {
127            if let Ok(handle) = handle {
128                handle.remove();
129            }
130        },
131    )
132}