feat: add alt+space global shortcut to show window

This commit is contained in:
ByteAtATime 2025-06-18 17:40:21 -07:00
parent bc67e6dcfb
commit fed96e0cf2
No known key found for this signature in database
7 changed files with 122 additions and 16 deletions

View file

@ -18,6 +18,7 @@
"@raycast-linux/protocol": "workspace:*",
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-clipboard-manager": "~2.2.2",
"@tauri-apps/plugin-global-shortcut": "~2.2.1",
"@tauri-apps/plugin-opener": "~2",
"@tauri-apps/plugin-shell": "~2.2.1",
"embla-carousel-svelte": "^8.6.0",

10
pnpm-lock.yaml generated
View file

@ -17,6 +17,9 @@ importers:
'@tauri-apps/plugin-clipboard-manager':
specifier: ~2.2.2
version: 2.2.2
'@tauri-apps/plugin-global-shortcut':
specifier: ~2.2.1
version: 2.2.1
'@tauri-apps/plugin-opener':
specifier: ~2
version: 2.2.7
@ -999,6 +1002,9 @@ packages:
'@tauri-apps/plugin-clipboard-manager@2.2.2':
resolution: {integrity: sha512-bZvDLMqfcNmsw7Ag8I49jlaCjdpDvvlJHnpp6P+Gg/3xtpSERdwlDxm7cKGbs2mj46dsw4AuG3RoAgcpwgioUA==}
'@tauri-apps/plugin-global-shortcut@2.2.1':
resolution: {integrity: sha512-b64/TI1t5LIi2JY4OWlYjZpPRq60T5GVVL/no27sUuxaNUZY8dVtwsMtDUgxUpln2yR+P2PJsYlqY5V8sLSxEw==}
'@tauri-apps/plugin-opener@2.2.7':
resolution: {integrity: sha512-uduEyvOdjpPOEeDRrhwlCspG/f9EQalHumWBtLBnp3fRp++fKGLqDOyUhSIn7PzX45b/rKep//ZQSAQoIxobLA==}
@ -3519,6 +3525,10 @@ snapshots:
dependencies:
'@tauri-apps/api': 2.5.0
'@tauri-apps/plugin-global-shortcut@2.2.1':
dependencies:
'@tauri-apps/api': 2.5.0
'@tauri-apps/plugin-opener@2.2.7':
dependencies:
'@tauri-apps/api': 2.5.0

34
src-tauri/Cargo.lock generated
View file

@ -1742,6 +1742,24 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
[[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.1",
"objc2-app-kit",
"once_cell",
"serde",
"thiserror 2.0.12",
"windows-sys 0.59.0",
"x11rb",
"xkeysym",
]
[[package]]
name = "gobject-sys"
version = "0.18.0"
@ -3595,6 +3613,7 @@ dependencies = [
"tauri",
"tauri-build",
"tauri-plugin-clipboard-manager",
"tauri-plugin-global-shortcut",
"tauri-plugin-opener",
"tauri-plugin-shell",
"url",
@ -4570,6 +4589,21 @@ dependencies = [
"thiserror 2.0.12",
]
[[package]]
name = "tauri-plugin-global-shortcut"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31919f3c07bcb585afef217c0c33cde80da9ebccf5b8e2c90e0e0a535b14ab47"
dependencies = [
"global-hotkey",
"log",
"serde",
"serde_json",
"tauri",
"tauri-plugin",
"thiserror 2.0.12",
]
[[package]]
name = "tauri-plugin-opener"
version = "2.2.7"

View file

@ -35,3 +35,6 @@ reqwest = "0.12.20"
zip = "4.1.0"
bytes = "1.10.1"
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
tauri-plugin-global-shortcut = "2"

View file

@ -0,0 +1,14 @@
{
"identifier": "desktop-capability",
"platforms": [
"macOS",
"windows",
"linux"
],
"windows": [
"main"
],
"permissions": [
"global-shortcut:allow-register"
]
}

View file

@ -3,18 +3,18 @@ mod cache;
mod desktop;
mod error;
use crate::{app::App, cache::AppCache};
#[cfg(target_os = "linux")]
use arboard;
use crate::{app::App, cache::AppCache};
use selection::get_text;
use std::fs;
use std::io::{self, Cursor};
#[cfg(target_os = "linux")]
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use std::thread;
use std::time::Duration;
#[cfg(target_os = "linux")]
use std::path::Path;
use tauri::Manager;
#[cfg(target_os = "linux")]
use url::Url;
@ -217,7 +217,7 @@ async fn get_from_file_manager() -> Result<Vec<FileSystemItem>, String> {
Ok(r) => r,
Err(_) => return Ok(vec![]),
};
let body = response.body();
let windows: Vec<zbus::zvariant::ObjectPath> = body.deserialize().unwrap_or_default();
@ -230,14 +230,17 @@ async fn get_from_file_manager() -> Result<Vec<FileSystemItem>, String> {
window_path,
window_interface_ref,
)
.await
{
Ok(p) => p,
Err(_) => continue,
};
.await
{
Ok(p) => p,
Err(_) => continue,
};
if let Ok(is_active) = window_proxy.get_property::<bool>("Active").await {
if is_active {
if let Ok(uris) = window_proxy.get_property::<Vec<String>>("SelectedUris").await {
if let Ok(uris) = window_proxy
.get_property::<Vec<String>>("SelectedUris")
.await
{
let paths = uris
.iter()
.filter_map(|uri_str| Url::parse(uri_str).ok())
@ -354,7 +357,7 @@ async fn install_extension(
.map_err(|e| format!("Failed to read response bytes: {}", e))?;
let mut archive = zip::ZipArchive::new(Cursor::new(content)).map_err(|e| e.to_string())?;
let prefix_to_strip = {
let file_names: Vec<PathBuf> = archive.file_names().map(PathBuf::from).collect();
@ -363,7 +366,10 @@ async fn install_extension(
} else {
let first_path = &file_names[0];
if let Some(first_component) = first_path.components().next() {
if file_names.iter().all(|path| path.starts_with(first_component)) {
if file_names
.iter()
.all(|path| path.starts_with(first_component))
{
Some(PathBuf::from(first_component.as_os_str()))
} else {
None
@ -425,6 +431,7 @@ async fn install_extension(
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_global_shortcut::Builder::new().build())
.plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_clipboard_manager::init())
.plugin(tauri_plugin_opener::init())
@ -435,7 +442,9 @@ pub fn run() {
get_selected_finder_items,
install_extension
])
.setup(|_app| {
.setup(|app| {
use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, Modifiers, Shortcut, ShortcutState};
thread::spawn(|| {
thread::sleep(Duration::from_secs(60));
loop {
@ -443,8 +452,35 @@ pub fn run() {
thread::sleep(Duration::from_secs(300));
}
});
let spotlight_shortcut = Shortcut::new(Some(Modifiers::ALT), Code::Space);
let handle = app.handle().clone();
println!("Spotlight shortcut: {:?}", spotlight_shortcut);
app.handle().plugin(
tauri_plugin_global_shortcut::Builder::new()
.with_handler(move |_app, shortcut, event| {
println!("Shortcut: {:?}, Event: {:?}", shortcut, event);
if shortcut == &spotlight_shortcut && event.state() == ShortcutState::Pressed {
let spotlight_window = handle.get_webview_window("raycast-linux").unwrap();
println!("Spotlight window: {:?}", spotlight_window);
if spotlight_window.is_visible().unwrap_or(false) {
spotlight_window.hide().unwrap();
} else {
spotlight_window.show().unwrap();
spotlight_window.set_focus().unwrap();
}
}
})
.build(),
)?;
app.global_shortcut().register(spotlight_shortcut)?;
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
}

View file

@ -13,8 +13,16 @@
"windows": [
{
"title": "raycast-linux",
"width": 800,
"height": 600
"visible": false,
"decorations": false,
"alwaysOnTop": true,
"transparent": true,
"resizable": false,
"skipTaskbar": true,
"fullscreen": false,
"width": 600,
"height": 80,
"center": true
}
],
"security": {