Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5a2fd31

Browse files
committedMar 10, 2025·
Provide HotkeyState on Global Shortcut Events
Instead of ignoring the events where the shortcut is released, the state is now provided as an argument to the event handler.
1 parent 172447e commit 5a2fd31

File tree

7 files changed

+36
-21
lines changed

7 files changed

+36
-21
lines changed
 

‎examples/overlay.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//! We also add a global shortcut to toggle the overlay on and off, so you could build a raycast-type app with this.
77
88
use dioxus::desktop::{
9-
tao::dpi::PhysicalPosition, use_global_shortcut, LogicalSize, WindowBuilder,
9+
tao::dpi::PhysicalPosition, use_global_shortcut, HotKeyState, LogicalSize, WindowBuilder,
1010
};
1111
use dioxus::prelude::*;
1212

@@ -19,7 +19,11 @@ fn main() {
1919
fn app() -> Element {
2020
let mut show_overlay = use_signal(|| true);
2121

22-
_ = use_global_shortcut("cmd+g", move || show_overlay.toggle());
22+
_ = use_global_shortcut("cmd+g", move |state| {
23+
if state == HotKeyState::Pressed {
24+
show_overlay.toggle();
25+
}
26+
});
2327

2428
rsx! {
2529
document::Link {

‎examples/shortcut.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
//!
66
//! These are *global* shortcuts, so they will work even if your app is not in focus.
77
8-
use dioxus::desktop::use_global_shortcut;
8+
use dioxus::desktop::{use_global_shortcut, HotKeyState};
99
use dioxus::prelude::*;
1010

1111
fn main() {
@@ -15,7 +15,11 @@ fn main() {
1515
fn app() -> Element {
1616
let mut toggled = use_signal(|| false);
1717

18-
_ = use_global_shortcut("ctrl+s", move || toggled.toggle());
18+
_ = use_global_shortcut("ctrl+s", move |state| {
19+
if state == HotKeyState::Pressed {
20+
toggled.toggle();
21+
}
22+
});
1923

2024
rsx!("toggle: {toggled}")
2125
}

‎packages/desktop/src/desktop_context.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{
44
file_upload::NativeFileHover,
55
ipc::UserWindowEvent,
66
query::QueryEngine,
7-
shortcut::{HotKey, ShortcutHandle, ShortcutRegistryError},
7+
shortcut::{HotKey, HotKeyState, ShortcutHandle, ShortcutRegistryError},
88
webview::WebviewInstance,
99
AssetRequest, Config, WryEventHandler,
1010
};
@@ -214,7 +214,7 @@ impl DesktopService {
214214
pub fn create_shortcut(
215215
&self,
216216
hotkey: HotKey,
217-
callback: impl FnMut() + 'static,
217+
callback: impl FnMut(HotKeyState) + 'static,
218218
) -> Result<ShortcutHandle, ShortcutRegistryError> {
219219
self.shared
220220
.shortcut_manager

‎packages/desktop/src/hooks.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::rc::Rc;
22

33
use crate::{
44
assets::*, ipc::UserWindowEvent, shortcut::IntoAccelerator, window, DesktopContext,
5-
ShortcutHandle, ShortcutRegistryError, WryEventHandler,
5+
HotKeyState, ShortcutHandle, ShortcutRegistryError, WryEventHandler,
66
};
77
use dioxus_core::{
88
prelude::{consume_context, use_hook_with_cleanup},
@@ -116,13 +116,14 @@ pub fn use_asset_handler(
116116
/// Get a closure that executes any JavaScript in the WebView context.
117117
pub fn use_global_shortcut(
118118
accelerator: impl IntoAccelerator,
119-
mut handler: impl FnMut() + 'static,
119+
handler: impl FnMut(HotKeyState) + 'static,
120120
) -> Result<ShortcutHandle, ShortcutRegistryError> {
121121
// wrap the user's handler in something that keeps it up to date
122-
let cb = use_callback(move |_| handler());
122+
let cb = use_callback(handler);
123123

124124
use_hook_with_cleanup(
125-
move || window().create_shortcut(accelerator.accelerator(), move || cb(())),
125+
#[allow(clippy::redundant_closure)]
126+
move || window().create_shortcut(accelerator.accelerator(), move |state| cb(state)),
126127
|handle| {
127128
if let Ok(handle) = handle {
128129
handle.remove();

‎packages/desktop/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,5 @@ pub use config::{Config, WindowCloseBehaviour};
5151
pub use desktop_context::{window, DesktopContext, DesktopService, WeakDesktopContext};
5252
pub use event_handlers::WryEventHandler;
5353
pub use hooks::*;
54-
pub use shortcut::{ShortcutHandle, ShortcutRegistryError};
54+
pub use shortcut::{HotKeyState, ShortcutHandle, ShortcutRegistryError};
5555
pub use wry::RequestAsyncResponder;

‎packages/desktop/src/mobile_shortcut.rs

+10
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,16 @@ impl fmt::Display for HotkeyError {
7878

7979
pub struct GlobalHotKeyEvent {
8080
pub id: u32,
81+
pub state: HotKeyState,
82+
}
83+
84+
/// Describes the state of the hotkey.
85+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
86+
pub enum HotKeyState {
87+
/// The hotkey is pressed.
88+
Pressed,
89+
/// The hotkey is released.
90+
Released,
8191
}
8292

8393
pub(crate) type Code = dioxus_html::input_data::keyboard_types::Code;

‎packages/desktop/src/shortcut.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
))]
1010
pub use global_hotkey::{
1111
hotkey::{Code, HotKey},
12-
Error as HotkeyError, GlobalHotKeyEvent, GlobalHotKeyManager,
12+
Error as HotkeyError, GlobalHotKeyEvent, GlobalHotKeyManager, HotKeyState,
1313
};
1414

1515
#[cfg(any(target_os = "ios", target_os = "android"))]
@@ -53,7 +53,7 @@ pub(crate) struct ShortcutRegistry {
5353
struct ShortcutInner {
5454
#[allow(unused)]
5555
shortcut: HotKey,
56-
callbacks: Slab<Box<dyn FnMut()>>,
56+
callbacks: Slab<Box<dyn FnMut(HotKeyState)>>,
5757
}
5858

5959
impl ShortcutRegistry {
@@ -66,21 +66,17 @@ impl ShortcutRegistry {
6666

6767
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
6868
pub(crate) fn call_handlers(&self, id: GlobalHotKeyEvent) {
69-
if id.state == global_hotkey::HotKeyState::Pressed {
70-
if let Some(ShortcutInner { callbacks, .. }) =
71-
self.shortcuts.borrow_mut().get_mut(&id.id)
72-
{
73-
for (_, callback) in callbacks.iter_mut() {
74-
(callback)();
75-
}
69+
if let Some(ShortcutInner { callbacks, .. }) = self.shortcuts.borrow_mut().get_mut(&id.id) {
70+
for (_, callback) in callbacks.iter_mut() {
71+
(callback)(id.state);
7672
}
7773
}
7874
}
7975

8076
pub(crate) fn add_shortcut(
8177
&self,
8278
hotkey: HotKey,
83-
callback: Box<dyn FnMut()>,
79+
callback: Box<dyn FnMut(HotKeyState)>,
8480
) -> Result<ShortcutHandle, ShortcutRegistryError> {
8581
let accelerator_id = hotkey.clone().id();
8682

0 commit comments

Comments
 (0)
Please sign in to comment.