global-hotkey

repository·dev·Indexed 42 days ago

https://github.com/tauri-apps/global-hotkey

A Rust library for registering and listening for global keyboard shortcuts in desktop applications, allowing them to function even when the application is not in focus. Version 0.8.0 supports Windows (requires win32 event loop), macOS (requires main thread event loop), and Linux (X11 only). It provides the GlobalHotKeyManager for lifecycle management and GlobalHotKeyEvent for processing press and release events via receivers or custom handlers.

Tokens
2.5K
Snippets
9
Records
13
Agent score
53%

What's inside global-hotkey

  1. Register Global HotKeys

    dev

    To register a global hotkey, you must first initialize a GlobalHotKeyManager, construct a HotKey using specific Modifiers and a Code, and then call register on the manager.

    Platform Requirements:

    • Windows: A win32 event loop must be running on the thread. The GlobalHotKeyManager must be created on the same thread as that event loop (not necessarily the main thread).
    • macOS: An event loop must be running on the main thread. You must create the GlobalHotKeyManager on the main thread.
    • Linux: Supported on X11 only.
    use global_hotkey::{GlobalHotKeyManager, hotkey::{HotKey, Modifiers, Code}};
    
    // initialize the hotkeys manager
    let manager = GlobalHotKeyManager::new().unwrap();
    
    // construct the hotkey
    let hotkey = HotKey::new(Some(Modifiers::SHIFT), Code::KeyD);
    
    // register it
    manager.register(hotkey);
  2. Process global hotkey events

    dev

    There are two ways to consume global hotkey events:

    1. Using a Receiver: Use GlobalHotKeyEvent::receiver() to get a GlobalHotKeyEventReceiver (a crossbeam channel receiver). This is the default method.
    2. Using an Event Handler: Use GlobalHotKeyEvent::set_event_handler(Some(callback)) to register a custom closure that is called whenever a hotkey event occurs.

    Important: If you set a custom event handler using set_event_handler, the channel accessed via GlobalHotKeyEvent::receiver() will not receive any new events.

    use global_hotkey::GlobalHotKeyEvent;
    
    // Try to receive an event from the global channel
    if let Ok(event) = GlobalHotKeyEvent::receiver().try_recv() {
        println!("{:?}", event);
    }
  3. Register Global HotKeys with GlobalHotKeyManager

    dev

    Use GlobalHotKeyManager to manage the lifecycle of global hotkeys. You must first initialize the manager, then you can register or unregister specific HotKey instances or batches of hotkeys.

    Platform Requirements

    • Windows: A Win32 event loop must be running on the thread where the GlobalHotKeyManager is created. It does not have to be the main thread.
    • macOS: An event loop must be running on the main thread, so the GlobalHotKeyManager must also be created on the main thread.
    • Linux: Supported on X11 only.
    use global_hotkey::{GlobalHotKeyManager, hotkey::{HotKey, Modifiers, Code}};
    
    // initialize the hotkeys manager
    let manager = GlobalHotKeyManager::new().unwrap();
    
    // construct the hotkey
    let hotkey = HotKey::new(Some(Modifiers::SHIFT), Code::KeyD);
    
    // register it
    manager.register(hotkey);
  4. Process global hotkey events

    dev

    To handle hotkey press events, use GlobalHotKeyEvent::receiver() to obtain a receiver. You can then use try_recv() to non-blockingly check for new events in your application loop.

    use global_hotkey::GlobalHotKeyEvent;
    
    if let Ok(event) = GlobalHotKeyEvent::receiver().try_recv() {
        println!("{:?}", event);
    }
  5. Create a HotKey using the HotKey::new constructor

    dev

    You can create a HotKey programmatically by providing an optional set of Modifiers and a specific Code (the main key).

    Note that Modifiers::SUPER is automatically converted to Modifiers::META during construction.

    # use global_hotkey::hotkey::{HotKey, Modifiers, Code};
    let hotkey = HotKey::new(Some(Modifiers::SHIFT), Code::KeyQ);
    let hotkey_without_mods = HotKey::new(None, Code::KeyQ);
  6. GlobalHotKeyEvent API Reference

    dev

    Represents a global hotkey event emitted when a HotKey is pressed or released.

    Methods

    • id(&self) -> u32: Returns the unique ID of the associated HotKey.
    • state(&self) -> HotKeyState: Returns whether the key was Pressed or Released.
    • receiver() -> &'static GlobalHotKeyEventReceiver: Returns a reference to the event channel's receiver. Note: This stops receiving events if a custom event handler is set.
    • set_event_handler<F>(f: Option<F>): Sets a custom handler for new events. If Some(f) is passed, the handler is called directly instead of sending events to the channel. If None is passed, it reverts to the default channel behavior.
  7. Parse a HotKey from a string

    dev

    You can create a HotKey from a string slice using .parse() or TryFrom.

    Important Rules for String Formatting:

    1. Order matters: All modifiers must be listed before the non-modifier key (e.g., shift+alt+KeyQ is valid, but shift+q+alt is invalid).
    2. Single Key: A hotkey must contain exactly one main key. A string containing only modifiers (e.g., Shift+Ctrl) is invalid.
    3. Case Insensitivity: The parser is case-insensitive for both modifiers and keys.

    Supported Modifier Tokens:

    • ALT or OPTION
    • CONTROL or CTRL
    • META, COMMAND, CMD, or SUPER
    • SHIFT
    • COMMANDORCONTROL (maps to META on macOS, CONTROL on other platforms)

    Supported Key Tokens (Examples):

    • Letters: A, B, C...
    • Digits: 0, 1, 2...
    • Special: Space, Enter, Escape (or ESC), Tab, Backspace, ArrowUp, ArrowDown, etc.
    • Function keys: F1 through F24 (and up to F35).
    # use global_hotkey::hotkey::HotKey;
    let hotkey: HotKey = "shift+alt+KeyQ".parse().unwrap();
  8. GlobalHotKeyManager API Reference

    dev

    Manages the registration and unregistration of global hotkeys on the host platform.

    Methods

    • new() -> crate::Result<Self>: Creates a new instance of the manager.
    • register(&self, hotkey: HotKey) -> crate::Result<()>: Registers a single hotkey.
    • unregister(&self, hotkey: HotKey) -> crate::Result<()>: Unregisters a single hotkey.
    • register_all(&self, hotkeys: &[HotKey]) -> crate::Result<()>: Registers multiple hotkeys at once.
    • unregister_all(&self, hotkeys: &[HotKey]) -> crate::Result<()>: Unregisters multiple hotkeys at once.
  9. Check if modifiers and a key match a HotKey

    dev

    Use the matches method to determine if a given combination of Modifiers and Code corresponds to a specific HotKey.

    # use global_hotkey::hotkey::{HotKey, Modifiers, Code};
    let hotkey = HotKey::new(Some(Modifiers::SHIFT), Code::KeyQ);
    // Returns true if the provided modifiers and key match the hotkey
    let is_match = hotkey.matches(Modifiers::SHIFT, Code::KeyQ);
  10. HotKeyState and GlobalHotKeyEvent Types

    dev

    HotKeyState

    An enum describing the state of a HotKey:

    • Pressed: The key is down.
    • Released: The key is up.

    GlobalHotKeyEvent

    Struct containing event data:

    • id: u32: The ID of the associated HotKey.
    • state: HotKeyState: The state of the key.
  11. Handle HotKeyParseError during parsing

    dev

    When parsing a string into a HotKey, you may encounter the following errors:

    • UnsupportedKey(String): The provided key string could not be recognized as a valid Code.
    • EmptyToken(String): The hotkey string contained an empty token (e.g., Shift++KeyA).
    • InvalidFormat(String): The hotkey format is incorrect, such as having multiple main keys or having modifiers listed after the main key.
  12. Handle errors in global-hotkey

    dev

    The global_hotkey::Error enum represents all possible failure states when registering, unregistering, or parsing hotkeys. When working with the library, you should handle these errors to manage issues such as invalid hotkey strings, OS-level IO errors, or conflicts where a hotkey is already in use.

    Common error scenarios include:

    • HotKeyParseError, EmptyHotKeyToken, or UnexpectedHotKeyFormat: Occur when the provided hotkey string is malformed (e.g., missing modifiers or containing multiple main keys).
    • UnrecognizedHotKeyCode: Occurs when a key name in the hotkey string cannot be mapped to a valid code.
    • AlreadyRegistered: Occurs if you attempt to register a HotKey that is already active.
    • FailedToRegister or FailedToUnRegister: General failures during the registration lifecycle.
    • OsError: Wraps standard std::io::Error for platform-specific issues.
    // Example of how you might handle the Error enum
    match result {
        Ok(_) => println!("Hotkey managed successfully"),
        Err(global_hotkey::Error::AlreadyRegistered(hk)) => println!("Hotkey {:?} is already in use", hk),
        Err(global_hotkey::Error::UnrecognizedHotKeyCode(code)) => println!("Invalid key code: {}", code),
        Err(e) => eprintln!("An error occurred: {}", e),
    }