From c84e028bd6121d52bf41f750fb6365e4994ebfa3 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Tue, 30 May 2023 12:09:20 -0500 Subject: [PATCH] Add richer API for describing global shortcut accelerators. --- examples/shortcut.rs | 2 +- packages/desktop/src/desktop_context.rs | 13 ++----- packages/desktop/src/shortcut.rs | 49 ++++++++++++++++--------- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/examples/shortcut.rs b/examples/shortcut.rs index d98a69ad6..0d8ffae81 100644 --- a/examples/shortcut.rs +++ b/examples/shortcut.rs @@ -8,7 +8,7 @@ fn main() { fn app(cx: Scope) -> Element { let toggled = use_state(cx, || false); - use_global_shortcut(cx, KeyCode::S, ModifiersState::CONTROL, { + use_global_shortcut(cx, "ctrl+s", { to_owned![toggled]; move || toggled.modify(|t| !*t) }); diff --git a/packages/desktop/src/desktop_context.rs b/packages/desktop/src/desktop_context.rs index 6af6401f3..d4519399d 100644 --- a/packages/desktop/src/desktop_context.rs +++ b/packages/desktop/src/desktop_context.rs @@ -6,8 +6,6 @@ use crate::create_new_window; use crate::eval::EvalResult; use crate::events::IpcMessage; use crate::query::QueryEngine; -use crate::shortcut::IntoKeyCode; -use crate::shortcut::IntoModifersState; use crate::shortcut::ShortcutId; use crate::shortcut::ShortcutRegistry; use crate::shortcut::ShortcutRegistryError; @@ -18,6 +16,7 @@ use dioxus_core::VirtualDom; #[cfg(all(feature = "hot-reload", debug_assertions))] use dioxus_hot_reload::HotReloadMsg; use slab::Slab; +use wry::application::accelerator::Accelerator; use wry::application::event::Event; use wry::application::event_loop::EventLoopProxy; use wry::application::event_loop::EventLoopWindowTarget; @@ -237,15 +236,11 @@ impl DesktopContext { /// Linux: Only works on x11. See [this issue](https://github.com/tauri-apps/tao/issues/331) for more information. pub fn create_shortcut( &self, - key: impl IntoKeyCode, - modifiers: impl IntoModifersState, + accelerator: Accelerator, callback: impl FnMut() + 'static, ) -> Result { - self.shortcut_manager.add_shortcut( - modifiers.into_modifiers_state(), - key.into_key_code(), - Box::new(callback), - ) + self.shortcut_manager + .add_shortcut(accelerator, Box::new(callback)) } /// Remove a global shortcut diff --git a/packages/desktop/src/shortcut.rs b/packages/desktop/src/shortcut.rs index e5cc05315..06287b7bd 100644 --- a/packages/desktop/src/shortcut.rs +++ b/packages/desktop/src/shortcut.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, collections::HashMap, rc::Rc}; +use std::{cell::RefCell, collections::HashMap, rc::Rc, str::FromStr}; use dioxus_core::ScopeState; use dioxus_html::input_data::keyboard_types::Modifiers; @@ -57,11 +57,9 @@ impl ShortcutRegistry { pub(crate) fn add_shortcut( &self, - modifiers: impl Into>, - key: KeyCode, + accelerator: Accelerator, callback: Box, ) -> Result { - let accelerator = Accelerator::new(modifiers, key); let accelerator_id = accelerator.clone().id(); let mut shortcuts = self.shortcuts.borrow_mut(); Ok( @@ -111,12 +109,6 @@ impl ShortcutRegistry { let mut shortcuts = self.shortcuts.borrow_mut(); shortcuts.clear(); let _ = self.manager.borrow_mut().unregister_all(); - // prevent CTRL+R from reloading the page which breaks apps - let _ = self.add_shortcut( - Some(ModifiersState::CONTROL), - KeyCode::KeyR, - Box::new(|| {}), - ); } } @@ -144,22 +136,45 @@ pub struct ShortcutHandle { pub shortcut_id: ShortcutId, } +pub trait IntoAccelerator { + fn accelerator(&self) -> Accelerator; +} + +impl IntoAccelerator for (dioxus_html::KeyCode, ModifiersState) { + fn accelerator(&self) -> Accelerator { + Accelerator::new(Some(self.1), self.0.into_key_code()) + } +} + +impl IntoAccelerator for (ModifiersState, dioxus_html::KeyCode) { + fn accelerator(&self) -> Accelerator { + Accelerator::new(Some(self.0), self.1.into_key_code()) + } +} + +impl IntoAccelerator for dioxus_html::KeyCode { + fn accelerator(&self) -> Accelerator { + Accelerator::new(None, self.into_key_code()) + } +} + +impl IntoAccelerator for &str { + fn accelerator(&self) -> Accelerator { + Accelerator::from_str(self).unwrap() + } +} + /// Get a closure that executes any JavaScript in the WebView context. pub fn use_global_shortcut( cx: &ScopeState, - key: impl IntoKeyCode, - modifiers: impl IntoModifersState, + accelerator: impl IntoAccelerator, handler: impl FnMut() + 'static, ) -> &Result { let desktop = use_window(cx); cx.use_hook(move || { let desktop = desktop.clone(); - let id = desktop.create_shortcut( - key.into_key_code(), - modifiers.into_modifiers_state(), - handler, - ); + let id = desktop.create_shortcut(accelerator.accelerator(), handler); Ok(ShortcutHandle { desktop,