Single instance
This commit is contained in:
45
README.md
45
README.md
@@ -87,6 +87,12 @@ The window starts from the saved mappings: it loads
|
||||
`~/.config/gKeyMapper/mappings.conf` when it opens, so `Save mappings` in a fresh
|
||||
window rewrites the same content instead of emptying the file.
|
||||
|
||||
Only one window is open at a time, and it is the one you just started: a new
|
||||
start closes the instance that is already running — including one from an older
|
||||
build — and then shows its own window, so a stale window can never stay next to a
|
||||
fresh one. Row edits that were not saved are lost with the replaced window,
|
||||
because saving is always explicit (`Save mappings`).
|
||||
|
||||
## Running the daemon
|
||||
|
||||
The daemon reads G1–G9 from the keyboard and replays the configured action
|
||||
@@ -129,6 +135,13 @@ The daemon reads G1–G9 from the keyboard and replays the configured action
|
||||
- A G key fires when its report first shows it as pressed: holding it down does
|
||||
not repeat the action, and two G keys held at once both fire (the report
|
||||
carries the state of all nine keys, not one key per report).
|
||||
- `keyhold` is the exception to that: its keys stay pressed for as long as the G
|
||||
key is held, like a normal key (including the desktop's auto-repeat), so a game
|
||||
or a push-to-talk sees a key that is down exactly as long as you hold the G key.
|
||||
The keyboard's release report ends it. If the keyboard is unplugged or the
|
||||
daemon stops while a key is held, the daemon lets it go, so nothing stays stuck.
|
||||
Holding only makes sense for a single step: `keyhold:ctrl+w` is held,
|
||||
`keyhold:ctrl+c,ctrl+v` is replayed as a tap (the log says so).
|
||||
- Only one instance may run: a second one prints why it cannot get the bus name
|
||||
and exits, instead of fighting over the keyboard and creating a second virtual
|
||||
keyboard.
|
||||
@@ -252,13 +265,16 @@ modifiers are joined with `+`, steps are separated with `,`
|
||||
G1=key:ctrl+c,ctrl+v
|
||||
G2=command:/usr/bin/firefox
|
||||
G3=disabled:
|
||||
G4=keyhold:ctrl+w
|
||||
```
|
||||
|
||||
The same format is used by Export/Import. `key` holds a captured shortcut
|
||||
sequence, `command` a program path or command line, `disabled` ignores the
|
||||
G key. These map to the `shortcut` / `run` / `nothing` hotkey types of the
|
||||
reference project; the native C++ daemon (`gkeymapper-daemon`) reads this file
|
||||
and replays the actions — no Python involved.
|
||||
sequence and fires it once, `command` a program path or command line,
|
||||
`disabled` ignores the G key, and `keyhold` keeps a single shortcut pressed for
|
||||
as long as the G key is held (in the GUI it is the `Key (hold)` entry in the
|
||||
Type dropdown). These map to the `shortcut` / `run` / `nothing` hotkey types of
|
||||
the reference project; the native C++ daemon (`gkeymapper-daemon`) reads this
|
||||
file and replays the actions — no Python involved.
|
||||
|
||||
`Save mappings` writes atomically (temporary file + `rename`), so the daemon
|
||||
never sees a half-written file and the watch reloads exactly once per save.
|
||||
@@ -271,6 +287,7 @@ src/keyrow.h # KeyRow (one per G key)
|
||||
src/mappings.{h,cpp} # GUI glue: config file <-> row widgets
|
||||
src/capturedialog.{h,cpp} # key-capture dialog
|
||||
src/daemonclient.{h,cpp} # D-Bus client for the daemon (status/reload)
|
||||
src/singleinstance.{h,cpp} # one GUI only: a new start closes a running instance
|
||||
shared/mapping.{h,cpp} # mappings format + shortcut parsing (GUI & daemon)
|
||||
shared/keys.{h,cpp} # canonical key names -> Linux key codes
|
||||
shared/keymap.{h,cpp} # layout-aware key lookups (xkbcommon), GUI + daemon
|
||||
@@ -279,7 +296,7 @@ daemon/main.cpp # event loop: read G-keys, run the action
|
||||
daemon/device_tables.{h,cpp} # per-model raw HID report tables (G910)
|
||||
daemon/g910_device.{h,cpp} # libusb access to the vendor interface
|
||||
daemon/uinput_keyboard.{h,cpp}# virtual keyboard for "key" mappings
|
||||
daemon/action.{h,cpp} # dispatch "key" / "command" / "disabled"
|
||||
daemon/action.{h,cpp} # dispatch "key" / "command" / "disabled" / "keyhold"
|
||||
daemon/config_watch.{h,cpp} # inotify watch on mappings.conf (auto-reload)
|
||||
daemon/ipc_dbus.{h,cpp} # D-Bus service (status/reload/test/signals)
|
||||
data/60-gkeymapper.rules # udev rule (uaccess for device + /dev/uinput)
|
||||
@@ -320,10 +337,16 @@ export PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/share/pkgconfig:
|
||||
|
||||
## Planned next steps
|
||||
|
||||
- Make the media keys remappable (they are forwarded unchanged today, see above)
|
||||
and support the M1–M3 / MR keys of the G910.
|
||||
- `typeout`: type out a fixed text, like the reference project's action of that
|
||||
name (the daemon would resolve the text through the active layout).
|
||||
- Profiles: swap mapping sets on the fly (the G910's M keys), which is what the
|
||||
reserved `SetProfile` D-Bus method was meant for.
|
||||
- The M1–M3 / MR keys of the G910 and profiles: swap mapping sets on the fly,
|
||||
which is what the reserved `SetProfile` D-Bus method was meant for. Deliberately
|
||||
left for later (see `docs/daemon-plan.md` §11).
|
||||
- Key sequence timing: per-step delays for recorded macros.
|
||||
- `typeout`: type out a fixed text, like the reference project's action of that
|
||||
name — not decided yet (see §11).
|
||||
|
||||
## Not planned
|
||||
|
||||
- Remapping the media keys. The daemon forwards mute / volume / play / next /
|
||||
previous / stop unchanged, and that is meant to stay that way (see the note
|
||||
above): they are not G keys, so they get no rows in the GUI and no entry in the
|
||||
config file.
|
||||
|
||||
Reference in New Issue
Block a user