From a606ad92f893622ca58d821f660256c58c9957b5 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Mon, 13 Oct 2025 12:47:24 +0200 Subject: [PATCH 1/3] register shortcut --- src-tauri/Cargo.lock | 40 ++++++++++++++++++++++++++++ src-tauri/Cargo.toml | 1 + src-tauri/src/bin/defguard-client.rs | 23 ++++++++++++++++ src-tauri/src/service/mod.rs | 2 +- 4 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f9647ce4..3c7eba8d 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1293,6 +1293,7 @@ dependencies = [ "tauri-plugin-deep-link", "tauri-plugin-dialog", "tauri-plugin-fs", + "tauri-plugin-global-shortcut", "tauri-plugin-http", "tauri-plugin-log", "tauri-plugin-notification", @@ -2298,6 +2299,24 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +[[package]] +name = "global-hotkey" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9247516746aa8e53411a0db9b62b0e24efbcf6a76e0ba73e5a91b512ddabed7" +dependencies = [ + "crossbeam-channel", + "keyboard-types", + "objc2 0.6.2", + "objc2-app-kit", + "once_cell", + "serde", + "thiserror 2.0.16", + "windows-sys 0.59.0", + "x11rb", + "xkeysym", +] + [[package]] name = "gloo-timers" version = "0.3.0" @@ -6291,6 +6310,21 @@ dependencies = [ "url", ] +[[package]] +name = "tauri-plugin-global-shortcut" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6df9f0f7bf2fe768b85fee4951c2505a35b72c44df1f6403e74e110bc13c5f58" +dependencies = [ + "global-hotkey", + "log", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.16", +] + [[package]] name = "tauri-plugin-http" version = "2.5.2" @@ -8431,6 +8465,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + [[package]] name = "yoke" version = "0.8.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 466a0b5d..85b570e7 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -110,6 +110,7 @@ x25519-dalek = { version = "2", features = [ "serde", "static_secrets", ] } +tauri-plugin-global-shortcut = "2.3.0" [target.'cfg(unix)'.dependencies] hyper-util = "0.1" diff --git a/src-tauri/src/bin/defguard-client.rs b/src-tauri/src/bin/defguard-client.rs index c9a337d3..2c0855c3 100644 --- a/src-tauri/src/bin/defguard-client.rs +++ b/src-tauri/src/bin/defguard-client.rs @@ -263,6 +263,29 @@ fn main() { .build(), )?; + use tauri_plugin_global_shortcut::{ + Code, GlobalShortcutExt, Modifiers, Shortcut, ShortcutState, + }; + let ctrl_q_shortcut = Shortcut::new(Some(Modifiers::CONTROL), Code::KeyQ); + app_handle.plugin( + tauri_plugin_global_shortcut::Builder::new() + .with_handler(move |_app, shortcut, event| { + info!("{:?}", shortcut); + if shortcut == &ctrl_q_shortcut { + match event.state() { + ShortcutState::Pressed => { + info!("Ctrl-Q Pressed!"); + } + ShortcutState::Released => { + info!("Ctrl-N Released!"); + } + } + } + }) + .build(), + )?; + app.global_shortcut().register(ctrl_q_shortcut)?; + let state = AppState::new(config); app.manage(state); diff --git a/src-tauri/src/service/mod.rs b/src-tauri/src/service/mod.rs index db05c90b..def6aced 100644 --- a/src-tauri/src/service/mod.rs +++ b/src-tauri/src/service/mod.rs @@ -133,7 +133,7 @@ impl DesktopDaemonService for DaemonService { let ifname = &config.name; let _span = info_span!("create_interface", interface_name = &ifname).entered(); // setup WireGuard API - let wgapi = setup_wgapi(ifname)?; + let mut wgapi = setup_wgapi(ifname)?; #[cfg(not(windows))] { From ce7436871e90b4f0e5f99fdd0795111070af52eb Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Mon, 13 Oct 2025 12:56:45 +0200 Subject: [PATCH 2/3] ctrl+q keyboard shortcut closes active connections and exits --- src-tauri/src/bin/defguard-client.rs | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src-tauri/src/bin/defguard-client.rs b/src-tauri/src/bin/defguard-client.rs index 2c0855c3..76514a4a 100644 --- a/src-tauri/src/bin/defguard-client.rs +++ b/src-tauri/src/bin/defguard-client.rs @@ -28,6 +28,7 @@ use log::{Level, LevelFilter}; #[cfg(target_os = "macos")] use tauri::{process, Env}; use tauri::{AppHandle, Builder, Manager, RunEvent, WindowEvent}; +use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, Modifiers, Shortcut, ShortcutState}; use tauri_plugin_log::{Target, TargetKind}; #[macro_use] @@ -263,23 +264,14 @@ fn main() { .build(), )?; - use tauri_plugin_global_shortcut::{ - Code, GlobalShortcutExt, Modifiers, Shortcut, ShortcutState, - }; + // Setup ctrl-q keyboard shortcut let ctrl_q_shortcut = Shortcut::new(Some(Modifiers::CONTROL), Code::KeyQ); app_handle.plugin( tauri_plugin_global_shortcut::Builder::new() - .with_handler(move |_app, shortcut, event| { - info!("{:?}", shortcut); - if shortcut == &ctrl_q_shortcut { - match event.state() { - ShortcutState::Pressed => { - info!("Ctrl-Q Pressed!"); - } - ShortcutState::Released => { - info!("Ctrl-N Released!"); - } - } + .with_handler(move |app, shortcut, event| { + if shortcut == &ctrl_q_shortcut && event.state() == ShortcutState::Pressed { + info!("Ctrl-Q pressed, closing active connections and exiting"); + app.exit(0); } }) .build(), From 242bc1d57539355c769c82931cc02f470e4e1253 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Mon, 13 Oct 2025 13:00:58 +0200 Subject: [PATCH 3/3] fix clippy issue --- src-tauri/src/service/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/src/service/mod.rs b/src-tauri/src/service/mod.rs index def6aced..db05c90b 100644 --- a/src-tauri/src/service/mod.rs +++ b/src-tauri/src/service/mod.rs @@ -133,7 +133,7 @@ impl DesktopDaemonService for DaemonService { let ifname = &config.name; let _span = info_span!("create_interface", interface_name = &ifname).entered(); // setup WireGuard API - let mut wgapi = setup_wgapi(ifname)?; + let wgapi = setup_wgapi(ifname)?; #[cfg(not(windows))] {