Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .tasks/interface/TAURI-001-graceful-shortcut-conflicts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
id: TAURI-001
title: "Gracefully handle Alt+Space shortcut conflicts"
status: "Done"
assignee: "jamiepine"
priority: "Medium"
tags: ["interface", "tauri", "desktop"]
---

## Description

The Spacedrive Tauri application maps `Alt+Space` as the default global shortcut to toggle the voice overlay. Previously, this shortcut was registered at builder-time during the app's initialization sequence. If another application (such as Windows PowerToys Run, macOS Spotlight, or Wox) already had `Alt+Space` bound, the `expect("failed to register Alt+Space global shortcut")` call would cause the entire Tauri application to panic and crash on startup.

## The Why

Global shortcut collisions are extremely common on user machines. A failure to register a non-critical global shortcut (like the voice overlay) should never result in a fatal crash of the main application. By moving the registration from builder-time to runtime, we can catch the error, log a graceful warning via `tracing`, and allow the app to boot normally.

## The How (Implementation Steps)

1. **Remove Builder-Time Registration**:
We removed the hardcoded `.with_shortcut("Alt+Space").expect(...)` from the `tauri_plugin_global_shortcut` builder initialization.
2. **Implement Runtime Registration**:
After the app is built and running, we use `app.handle().global_shortcut().register("Alt+Space")` to dynamically register the shortcut.
3. **Graceful Error Handling**:
We match the `Result` of the registration attempt. On success, we log an `info!` tracing event. On failure, we log a `warn!` event and continue execution.

### Example Diff

```diff
- .plugin(
- tauri_plugin_global_shortcut::Builder::new()
- .with_shortcut("Alt+Space")
- .expect("failed to register Alt+Space global shortcut")
- .with_handler(|app, _shortcut, event| {
+ // Registration moved to runtime:
+ #[cfg(not(target_os = "linux"))]
+ {
+ use tauri_plugin_global_shortcut::GlobalShortcutExt;
+ match app.handle().global_shortcut().register("Alt+Space") {
+ Ok(_) => tracing::info!("Registered Alt+Space global shortcut"),
+ Err(error) => tracing::warn!(?error, "Failed to register Alt+Space global shortcut, voice overlay disabled"),
+ }
+ }
```

> **Note**: The implementation uses `#[cfg(not(target_os = "linux"))]` because global shortcuts on Linux (especially under Wayland) are handled at the desktop environment level and are not reliably supported by the Tauri plugin architecture.

## Acceptance Criteria
- Tauri app boots normally even if `Alt+Space` is bound by another program.
- A descriptive warning is printed to the daemon logs when a shortcut collision occurs.

## Review Refinements
- **Neutral Log Messaging:** Updated the `tracing::warn!` message for `Alt+Space` registration failure to be error-agnostic and explicitly log the underlying `Err(e)` details, rather than assuming the shortcut was already in use.
21 changes: 16 additions & 5 deletions apps/tauri/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use std::sync::Arc;
use tauri::menu::MenuItem;
use tauri::Emitter;
use tauri::{AppHandle, Manager};
use tauri_plugin_global_shortcut::ShortcutState;
use tokio::sync::oneshot;
use tokio::sync::RwLock;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
Expand Down Expand Up @@ -1928,10 +1927,10 @@ fn main() {
.plugin(tauri_plugin_updater::Builder::new().build())
.plugin(
tauri_plugin_global_shortcut::Builder::new()
.with_shortcut("Alt+Space")
.expect("failed to register Alt+Space global shortcut")
.with_handler(|app, _shortcut, event| {
if event.state() == ShortcutState::Pressed {
.with_handler(|app, shortcut, event| {
if event.state() == tauri_plugin_global_shortcut::ShortcutState::Pressed
&& shortcut.to_string() == "Alt+Space"
{
if let Err(error) = windows::toggle_voice_overlay_internal(app.clone()) {
tracing::warn!(
?error,
Expand Down Expand Up @@ -2004,6 +2003,18 @@ fn main() {

tracing::info!("Spacedrive Tauri app starting...");

// Register Alt+Space global shortcut for the voice overlay.
// Done at runtime (not at builder time) so a conflict with another
// app (e.g. PowerToys Run) is handled gracefully instead of panicking.
#[cfg(not(target_os = "linux"))]
{
use tauri_plugin_global_shortcut::GlobalShortcutExt;
match app.handle().global_shortcut().register("Alt+Space") {
Ok(_) => tracing::info!("Registered Alt+Space global shortcut"),
Err(error) => tracing::warn!(?error, "Failed to register Alt+Space global shortcut, voice overlay disabled"),
}
}

// Apply Windows-specific window customizations (dark titlebar)
#[cfg(target_os = "windows")]
{
Expand Down