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 {
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)
});

View file

@ -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<ShortcutId, ShortcutRegistryError> {
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

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_html::input_data::keyboard_types::Modifiers;
@ -57,11 +57,9 @@ impl ShortcutRegistry {
pub(crate) fn add_shortcut(
&self,
modifiers: impl Into<Option<ModifiersState>>,
key: KeyCode,
accelerator: Accelerator,
callback: Box<dyn FnMut()>,
) -> Result<ShortcutId, ShortcutRegistryError> {
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<ShortcutHandle, ShortcutRegistryError> {
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,