This commit is contained in:
2026-10-27 18:57:14 +01:00
parent f45596a7e3
commit 5410ed2ae5
9 changed files with 258 additions and 178 deletions

View File

@@ -10,10 +10,10 @@ live in the daemon, not the GUI. Code is split across `src/` (GUI), `shared/`
## Build / run / verify
- `make` — builds the `gkeymapper` GUI, the `gkeymapper-daemon` and the `.mo`
catalogs. Needs `g++` (C++17), `make`, `gettext`, `libgtk-4-dev`,
`libusb-1.0-0-dev`, `libxkbcommon-dev` and `libglib2.0-dev` (see README for
`libxkbcommon-dev` and `libglib2.0-dev` (see README for
`apt install` on a fresh machine). `libglib2.0-dev` also provides
`glib-compile-resources`, which generates the icons embedded into the GUI.
- `make daemon` — builds only `gkeymapper-daemon` (needs libusb, xkbcommon and
- `make daemon` — builds only `gkeymapper-daemon` (needs xkbcommon and
gio-2.0, not GTK).
- `make translations` — only runs `msgfmt` on the existing `.po` files.
- `make run` — builds, then runs with `GKEYMAPPER_LOCALEDIR=$PWD/locale` and
@@ -66,11 +66,9 @@ live in the daemon, not the GUI. Code is split across `src/` (GUI), `shared/`
`optionsdialog` and `popovers` (the popup input grab, see below).
- The Makefile globs sources: `make` builds the GUI (`src/*.cpp` + `shared/*.cpp`
+ the generated `build/gresources.c`, see Assets) **and** the daemon
(`daemon/*.cpp` + `shared/*.cpp`, needs `libusb-1.0-0-dev`,
`libxkbcommon-dev` and `libglib2.0-dev`). `make daemon` builds only the daemon.
(`daemon/*.cpp` + `shared/*.cpp`, needs `libxkbcommon-dev` and `libglib2.0-dev`). `make daemon` builds only the daemon.
- The daemon is split into: `device_tables` (raw HID report tables per model plus
`decode_gkey_state`, the report → pressed-bitmap decoder), `g910_device` (libusb
open/detach/claim/read), `uinput_keyboard` (virtual keyboard), `action`
`decode_gkey_state`, the report → pressed-bitmap decoder), `g910_device` (hidraw open/read/close), `uinput_keyboard` (virtual keyboard), `action`
(dispatch `key`/`command`/`disabled`/`keyhold`), `config_watch` (inotify auto-reload of
the mappings file) and `ipc_dbus` (the GDBus service). `shared/keymap` does the
layout lookups for both sides. The hot path never touches the GUI: D-Bus is
@@ -100,7 +98,7 @@ live in the daemon, not the GUI. Code is split across `src/` (GUI), `shared/`
2 s while D-Bus and the config watch keep running. Never make it exit on a
missing device — that would drop the bus name and make the GUI look like the
daemon died. `GKeyDevice::open(quiet)` exists so those retries stay out of the
journal (libusb-level errors always log).
journal (hidraw-level errors always log).
- `make install` (PREFIX default `/usr/local`) also installs the packaging
files from `data/`: the udev rule, the `modules-load.d` fragment, the
systemd **user** unit and the D-Bus activation file. Both contain an
@@ -389,9 +387,9 @@ over any installed file; the file lookup remains only as a safety net.
families, which must *not* decode as media keys (see the bit table above);
- build the daemon with a **fake** `GKeyDevice`: keep the header, script
`open()`/`read_report()`, link `daemon/*.cpp` **without** `g910_device.cpp`
and without libusb. That runs the real loop, so it covers "no keyboard at
and without g910_device.cpp. That runs the real loop, so it covers "no keyboard at
start", "device lost" and the reopen, emits real D-Bus signals and never
claims the real device — nothing touches the keyboard and no key is injected
opens the real device — nothing touches the keyboard and no key is injected
into the focused window. Use a config with `command:` mappings only (a helper
script that dumps its environment is also how you check that a `command`
action sees `DISPLAY`); with `key:` mappings the fake would inject keys into
@@ -401,7 +399,7 @@ over any installed file; the file lookup remains only as a safety net.
the fake `g910_device.h` in an include directory. `#include "g910_device.h"`
searches the *including file's* directory first, so compiling the real
`daemon/main.cpp` would always pick up the real header (its inline
`is_open()` needs libusb).
`is_open()` needs hidraw).
- **Give the fake its own session bus** (`dbus-daemon --session --address=
unix:path=/tmp/…/fake_bus --fork --print-pid=1`, then
`DBUS_SESSION_BUS_ADDRESS=unix:path=…` for the fake). Otherwise it refuses