Add richer API for describing global shortcut accelerators.

This commit is contained in:
Nolan Darilek 2023-05-30 12:09:20 -05:00
parent f4e1d78d7a
commit c84e028bd6
3 changed files with 37 additions and 27 deletions

View file

@ -8,7 +8,7 @@ fn main() {
fn app(cx: Scope) -> Element { fn app(cx: Scope) -> Element {
let toggled = use_state(cx, || false); let toggled = use_state(cx, || false);
use_global_shortcut(cx, KeyCode::S, ModifiersState::CONTROL, { use_global_shortcut(cx, "ctrl+s", {
to_owned![toggled]; to_owned![toggled];
move || toggled.modify(|t| !*t) move || toggled.modify(|t| !*t)
}); });

View file

@ -6,8 +6,6 @@ use crate::create_new_window;
use crate::eval::EvalResult; use crate::eval::EvalResult;
use crate::events::IpcMessage; use crate::events::IpcMessage;
use crate::query::QueryEngine; use crate::query::QueryEngine;
use crate::shortcut::IntoKeyCode;
use crate::shortcut::IntoModifersState;
use crate::shortcut::ShortcutId; use crate::shortcut::ShortcutId;
use crate::shortcut::ShortcutRegistry; use crate::shortcut::ShortcutRegistry;
use crate::shortcut::ShortcutRegistryError; use crate::shortcut::ShortcutRegistryError;
@ -18,6 +16,7 @@ use dioxus_core::VirtualDom;
#[cfg(all(feature = "hot-reload", debug_assertions))] #[cfg(all(feature = "hot-reload", debug_assertions))]
use dioxus_hot_reload::HotReloadMsg; use dioxus_hot_reload::HotReloadMsg;
use slab::Slab; use slab::Slab;
use wry::application::accelerator::Accelerator;
use wry::application::event::Event; use wry::application::event::Event;
use wry::application::event_loop::EventLoopProxy; use wry::application::event_loop::EventLoopProxy;
use wry::application::event_loop::EventLoopWindowTarget; 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. /// Linux: Only works on x11. See [this issue](https://github.com/tauri-apps/tao/issues/331) for more information.
pub fn create_shortcut( pub fn create_shortcut(
&self, &self,
key: impl IntoKeyCode, accelerator: Accelerator,
modifiers: impl IntoModifersState,
callback: impl FnMut() + 'static, callback: impl FnMut() + 'static,
) -> Result<ShortcutId, ShortcutRegistryError> { ) -> Result<ShortcutId, ShortcutRegistryError> {
self.shortcut_manager.add_shortcut( self.shortcut_manager
modifiers.into_modifiers_state(), .add_shortcut(accelerator, Box::new(callback))
key.into_key_code(),
Box::new(callback),
)
} }
/// Remove a global shortcut /// Remove a global shortcut

View file

@ -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_core::ScopeState;
use dioxus_html::input_data::keyboard_types::Modifiers; use dioxus_html::input_data::keyboard_types::Modifiers;
@ -57,11 +57,9 @@ impl ShortcutRegistry {
pub(crate) fn add_shortcut( pub(crate) fn add_shortcut(
&self, &self,
modifiers: impl Into<Option<ModifiersState>>, accelerator: Accelerator,
key: KeyCode,
callback: Box<dyn FnMut()>, callback: Box<dyn FnMut()>,
) -> Result<ShortcutId, ShortcutRegistryError> { ) -> Result<ShortcutId, ShortcutRegistryError> {
let accelerator = Accelerator::new(modifiers, key);
let accelerator_id = accelerator.clone().id(); let accelerator_id = accelerator.clone().id();
let mut shortcuts = self.shortcuts.borrow_mut(); let mut shortcuts = self.shortcuts.borrow_mut();
Ok( Ok(
@ -111,12 +109,6 @@ impl ShortcutRegistry {
let mut shortcuts = self.shortcuts.borrow_mut(); let mut shortcuts = self.shortcuts.borrow_mut();
shortcuts.clear(); shortcuts.clear();
let _ = self.manager.borrow_mut().unregister_all(); 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 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. /// Get a closure that executes any JavaScript in the WebView context.
pub fn use_global_shortcut( pub fn use_global_shortcut(
cx: &ScopeState, cx: &ScopeState,
key: impl IntoKeyCode, accelerator: impl IntoAccelerator,
modifiers: impl IntoModifersState,
handler: impl FnMut() + 'static, handler: impl FnMut() + 'static,
) -> &Result<ShortcutHandle, ShortcutRegistryError> { ) -> &Result<ShortcutHandle, ShortcutRegistryError> {
let desktop = use_window(cx); let desktop = use_window(cx);
cx.use_hook(move || { cx.use_hook(move || {
let desktop = desktop.clone(); let desktop = desktop.clone();
let id = desktop.create_shortcut( let id = desktop.create_shortcut(accelerator.accelerator(), handler);
key.into_key_code(),
modifiers.into_modifiers_state(),
handler,
);
Ok(ShortcutHandle { Ok(ShortcutHandle {
desktop, desktop,