Per-app profiles
Automatically swap button bindings and Actions Ring layouts based on the frontmost app by authoring overlays in config.toml.
Per-app profiles let OpenLogi swap a device's button bindings automatically based
on the frontmost app. A background watcher reads the foreground app's identifier
once per second; when it changes, the overlay you authored for that app is
layered on top of the device's global
bindings, with per-app entries winning and any
unlisted button falling through to the global map. The
Actions Ring can switch per app too, as a
complete layout rather than an overlay. DPI presets, scrolling, and lighting
stay device-wide.
App identifiers
The identifier is whatever the platform reports for the frontmost window, and it must match a config key exactly; there is no wildcard or pattern matching.
| Platform | Identifier | Example |
|---|---|---|
| macOS | Bundle id | com.microsoft.VSCode |
| Linux (X11 / XWayland, GNOME Shell) | WM_CLASS class | Code |
| Linux (wlroots compositors) | xdg-shell app_id | code |
| Windows | Lower-cased executable path, or exe:<name>.exe | exe:sharex.exe |
The Linux backends do not share a namespace: a profile authored under a
wlroots compositor (app_id) will not match under GNOME or X11 (WM_CLASS),
and vice versa. Author the form your session actually reports.
On Windows an exact path entry wins when both forms exist, so exe: is the
stable fallback for Store apps and self-updating installs whose path moves.
From the GUI
There is no per-app editor for button bindings yet; the action picker edits the
device's global bindings, and overlays are hand-authored in
config.toml. Two things are surfaced:
- Active profile — a read-only row on the configuration card showing the frontmost app's identifier as the active profile, or a Default profile label when no app is frontmost. It is a status display, not an editor.
- Auto-switch — fully automatic, with no control. When the watcher reports a new identifier, OpenLogi rebuilds the in-memory binding map and hands it to the event hook, so the next button press picks up the new app's overlay.
Authoring overlays
Add a table under [devices.<key>.per_app_bindings."<app-id>"] holding a partial
button → action map. Buttons you list override the global binding while that app
is frontmost; buttons you omit keep their global value.
[devices."receiver:aabbccdd:slot:1".bindings]
Back = "BrowserBack"
Forward = "BrowserForward"
# While VS Code is frontmost, Back becomes Undo and Forward becomes Redo.
[devices."receiver:aabbccdd:slot:1".per_app_bindings."com.microsoft.VSCode"]
Back = "Undo"
Forward = "Redo"Values are action names written verbatim.
The overlay only adds or overrides keys; it never removes one, so to make a
button do nothing in a given app set it to None rather than omitting it. A
per-app overlay always maps a button to a single action; per-direction gesture
maps stay device-wide.
Switching is polled at roughly 1 second, so expect up to a second of latency after you change apps.
Status: macOS, Linux, and Windows. On Linux the identifier depends on the
session backend (X11 / XWayland, GNOME Shell, or a wlroots compositor); a
session with none of those available reports no app and everything falls back to
the Default profile. Authored in
config.toml; driven by the OS
foreground-app API, not a HID++ feature.