talonvoice / talon

Issue Tracker for the main Talon app
85 stars 0 forks source link

Hotkeys for Linux #179

Closed fmagin closed 2 years ago

fmagin commented 3 years ago

As requested, a short description of my use case that requires hotkeys:

Short Version

OS: Arch Linux with X11 I would like support for registering callbacks on a hotkey combination both for the press and the release. I.e. when all keys of the hotkey combination are pressed and either when one or all of the keys is released again.

The callback should be activate globally and the keys should not be passed on to the application.

Details:

I have a script that uses the eye tracking plugin to get the current position of the gaze, to detect GUI elements or text around it by using the MSER algorithm. I am aware that the API for this isn't considered stable.

Currently it is configured like this:

I have a hotkey combination (Windows+q) that activates an overlay when the keys are pressed down: image

to prevent this from messing with applications I have a line in my i3 config that declares this a noop so it get's eaten by i3 but still detected by the library I am using: bindsym $mod+q nop foo.

I then hold the keys, look at the box I want to interact with, which will then be marked in red and when the hot key is released the script triggers a click event at the center of the box.

I am using Arch Linux and the pynput library with an extended class to support events on hotkey release:

from pynput import keyboard

def on_activate():
    print('Global hotkey activated!')
    toggle_mser_overlay(True)

def on_release():
    print('Global hotkey released!')
    toggle_mser_overlay(False)

def for_canonical(f):
    return lambda k: f(l.canonical(k))

class HotKeyRelease(keyboard.HotKey):

    def __init__(self, keys, on_activate, on_release):
        super().__init__(keys, on_activate)
        self._just_activated = False
        self._on_release = on_release

    def release(self, key):
        super().release(key)
        if self._just_activated and self._state != self._keys:
            self._on_release()
            self._just_activated = False

    def press(self, key):
        if key in self._keys and key not in self._state:
            self._state.add(key)
            if self._state == self._keys:
                self._on_activate()
                self._just_activated = True
lunixbochs commented 2 years ago

hotkeys for linux just landed in beta 0.2.0-154