Skip to content

Instantly share code, notes, and snippets.

@dreamcat4
Last active May 2, 2023 09:06
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dreamcat4/507a1c2f707e8099159b173df37826ae to your computer and use it in GitHub Desktop.
Save dreamcat4/507a1c2f707e8099159b173df37826ae to your computer and use it in GitHub Desktop.
wayland gnome - how to setup a global hotkey, to trigger something useful inside of an application, etc.

Global Hotkeys in Wayland (Gnome) - 2021

1st task - Configure just 1 global hotkey

  • Figure out how to set up 1 global hotkey in your chosen desktop environment,
  • Assign to it some simple dummy target ommand. Which you know always works. And is easily verified

That will ensure you can check and test that a specific hotkey assignment is actually definately working independantly of the specific desired action. This is important because the desktop environment can also occupy pre-configured 'system keys' and if they are already being mapped to something other default system wide actions then (likely) will silently be ignored.

So being independant here from the subsequent specific desired target actions in some special app or whatever. Which themselves definately might have other own different issues or not behave correctly. And especially when being invoked from the compositor via this method (rather than a logged in user terminal etc.)

What are the typical limitations of Global Hotkeys?

  • A global hotkey can only be bound to always execute 1 specific program binary executable or cmdline string of your choosing
  • Therefore it can be launching any cli app or a gui app on your system
  • Providing also that the command (which runs as your own username) also has any necessary login privileges to execute properly on the system
  • The global hotkey assignment should also let you pass in any fixed strings of program arguments after the command
  • But they will be invariant and mapped directly just unique only for that specific particular key binding
  • So not any wildcard substitution etc. and 1 command per individual key combination etc.
  • Triggered only on keydown (not keyup), and not possible to do fancy things like press and hold for long keypress, etc.

Is the target program cmdline, or GUI?

  • In the case of the CLI program, if it's something not already running in the background then that's usually no problem
  • Just directly execute it from the hotkey assignment keybinding. And you're done
  • However in the case of the GUI program (or a background task). Then things might be easy. Or they might turn out to be a lot more complicated

If the target program is GUI, or some other background task

This could go variety of different ways, depending entirely on the specific target program which you want to interact with. Some examples:

Cmdline flags

  • If the GUI program (or other background task) is
    • single-instance
    • does not relaunch any new instance once it is already running
    • instead supports being sent control signals with subsequent invocations on the cmdline
      • Great! --> then check for messaging flags / controls for the app in it's --help terminal output

D-Bus

  • If the program exposes a dbus messaging interface
    • Great! ---> that can be probed with the GUI helper utility known as d-feet
      • After launching d-feet ---> BE SURE to click the Session Bus tab
        • Because Session Bus = the USER dbus session infos (rather than System Bus, the default shown)
    • While the app is running, it may expose actions on it's D-Bus control interface
      • but only if it specifically supports and implements them on D-Bus protocol
      • not all programs support D-Bus or expose all of the controls you might require
      • but some programs (for example OBS), might have 3rd party plugins or helper service etc.
  • With the d-feet program you can directly test those exposed d-bus interface commands api
    • And also discover what the d-bus address endpoint name is, which command names to use, etc.
    • After gathering these necessary info, Then you can bind your global hotkey to run a dbus-send ... command

Example:

dbus-send --print-reply=literal --session --dest=org.mpris.MediaPlayer2.audacious /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get string:org.mpris.MediaPlayer2.Player string:Volume

Other control mechanisms

  • if the program has other interface to control it by, for example:
    • an optional localhost http web interface, or http API endpoint for json / rest etc.
    • a shared background daemon etc. if the gui program is just a client side interface
    • piping to a unix socket file in /tmp/ folder, or writing other files to disk
    • using the inotify command to watch for local file or folder changes on the disk
    • in memory message passing via other message passing protocol (which isnt dbus), eg POSIX SHM semaphores, etc.
    • writing things or sending messages to the kernel, via some system wide exposed kernel api or interface
    • directly writing to a block of shared memory, or other types of debugging interface (like adb for android)

Is it a DAW Audio Software?

  • if the GUI program is a DAW you can
    • map a global hotkey to execute a cmdline send midi ...
    • then use send-midi command to send midi commands to it
    • then seperately map and match up those midi commands to execute specific actions within the DAW

No other ways, the difficult ones

  • if the GUI program
    • exposes no reasonable way to interface with it
      • then you will need to use some general system privelidge level of cmdline tool(s)
    • wrap them into a more complex shell script to
      • find the app window, from the list of currently running GUI apps
      • activate the found app
      • change window focus. so the app is in foreground and currently focussed
      • simulate the necessary keypress events and mouse movements, mouse clicks etc.
      • unfocus the targeted app, and switch back focus to the original app

To achieve this ^^ above tasks for wayland (gnome) requires some different set of tools. Withing the exact features supported by specific tools there is sometimes a bit of overlap between xorg/x11 and wayland. And sometimes no overlap. And it's complicated! You will need to cobble together a variety of lower level stuff. And the actual names of these tools, and functionally what they exactly can support - that will also change over time too.

Right now (as of oct-2021), the best solutions can all be found by browsing the following link tree:

https://raindrop.io/dreamcat4/wayland-gnome-global-hotkeys-input-events-window-info-window-focus-activation-linux-autohotkey-etc-20939866

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment