Embedd assets icons
This commit is contained in:
72
README.md
72
README.md
@@ -3,8 +3,10 @@
|
||||
GTK4 application (C++) for remapping the G keys **G1–G9** of a Logitech **G910**
|
||||
to other keys or commands (Linux Mint / Ubuntu).
|
||||
|
||||
The GUI is complete. A background daemon (`gkeymapper-daemon`) that reads the
|
||||
G-keys from the keyboard is in progress — see `docs/daemon-plan.md`.
|
||||
The GUI is complete. The background daemon (`gkeymapper-daemon`) that reads the
|
||||
G-keys from the keyboard and replays the actions is implemented as well; the
|
||||
GUI and the daemon talk over a small D-Bus channel (status, reload, test) — see
|
||||
`docs/daemon-plan.md`.
|
||||
|
||||
Documentation and source comments are written in English.
|
||||
|
||||
@@ -17,16 +19,18 @@ Documentation and source comments are written in English.
|
||||
- GTK 4 development files
|
||||
- libusb 1.0 development files (for the daemon)
|
||||
- libxkbcommon development files (for the daemon's layout handling)
|
||||
- GLib/GIO development files (for the GUI ↔ daemon D-Bus channel; `libgtk-4-dev`
|
||||
already pulls them in, but they are needed for `make daemon` on its own)
|
||||
|
||||
### Install dependencies
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install -y build-essential gettext libgtk-4-dev libusb-1.0-0-dev libxkbcommon-dev
|
||||
sudo apt install -y build-essential gettext libgtk-4-dev libusb-1.0-0-dev libxkbcommon-dev libglib2.0-dev
|
||||
```
|
||||
|
||||
Afterwards `pkg-config --modversion gtk4` and
|
||||
`pkg-config --modversion libusb-1.0` should print versions.
|
||||
Afterwards `pkg-config --modversion gtk4`, `pkg-config --modversion libusb-1.0`
|
||||
and `pkg-config --modversion gio-2.0` should print versions.
|
||||
|
||||
## Setting up the project
|
||||
|
||||
@@ -46,7 +50,9 @@ make
|
||||
|
||||
This produces the `gkeymapper` GUI binary, the `gkeymapper-daemon` binary and
|
||||
the `.mo` translations under `locale/`. The daemon can also be built on its own
|
||||
with `make daemon`.
|
||||
with `make daemon`. The GUI has its icons (`assets/icon.png`, `assets/icon.svg`)
|
||||
compiled in (`data/icons.gresource.xml` → generated `build/gresources.c`), so the
|
||||
window icon works without an installed `assets/` directory.
|
||||
|
||||
## Rebuild translations
|
||||
|
||||
@@ -70,6 +76,10 @@ LANG=de_DE.UTF-8 GKEYMAPPER_LOCALEDIR=$PWD/locale ./gkeymapper
|
||||
|
||||
Supported languages: German, English, Spanish, French.
|
||||
|
||||
The footer of the window shows the daemon state (`Daemon: running · Device: …`
|
||||
plus the last G key that fired, or `Daemon: not reachable`) and follows it live:
|
||||
start or stop the daemon while the GUI is open and the line updates itself.
|
||||
|
||||
## Running the daemon
|
||||
|
||||
The daemon reads G1–G9 from the keyboard and replays the configured action
|
||||
@@ -101,6 +111,9 @@ The daemon reads G1–G9 from the keyboard and replays the configured action
|
||||
`pgrep -x gkeymapper-daemon` does **not** match.
|
||||
- A failed reload keeps the previous mappings, so a transient read error never
|
||||
silently disables every key.
|
||||
- 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.
|
||||
- Key names are layout-independent: `key:ctrl+z` means the key that produces
|
||||
`z` **on your layout**. The layout is read from `/etc/default/keyboard`
|
||||
(`XKBLAYOUT`); without it, US key positions are used. Because the name is
|
||||
@@ -113,6 +126,34 @@ The daemon reads G1–G9 from the keyboard and replays the configured action
|
||||
|
||||
Stop it with Ctrl+C or `kill`; it reattaches the kernel driver on the way out.
|
||||
|
||||
### Status and control over D-Bus
|
||||
|
||||
The daemon owns the name `dev.rager.gkeymapper.Daemon` on the session bus. The
|
||||
GUI uses that channel for its footer line ("Daemon: running / not reachable",
|
||||
the device and the last G key that fired) and to apply a save immediately.
|
||||
Nothing on this channel is on the keypress path, so a GUI that is slow or absent
|
||||
never delays an action.
|
||||
|
||||
```bash
|
||||
D=dev.rager.gkeymapper.Daemon
|
||||
O=/dev/rager/gkeymapper/Daemon
|
||||
|
||||
gdbus call --session --dest $D --object-path $O --method $D.GetStatus
|
||||
gdbus call --session --dest $D --object-path $O --method $D.Reload
|
||||
gdbus call --session --dest $D --object-path $O --method $D.TestMapping 0
|
||||
gdbus monitor --session --dest $D # KeyPressed / ConfigReloaded / DeviceChanged
|
||||
```
|
||||
|
||||
- `GetStatus` → `(version, running, device, configPath)`.
|
||||
- `Reload` re-reads the mappings file; `ConfigReloaded(ok)` reports the result.
|
||||
- `TestMapping` fires a mapping without touching the keyboard (useful to check a
|
||||
sequence). The index is **0-based**: `0` = G1 … `8` = G9. It runs the same code
|
||||
path as a real keypress.
|
||||
- `KeyPressed(index, action)` is emitted for every G key, real or tested.
|
||||
|
||||
If no session bus is available the daemon still works — it just runs without the
|
||||
GUI channel and logs that.
|
||||
|
||||
## Install (optional)
|
||||
|
||||
```bash
|
||||
@@ -129,6 +170,7 @@ Installs, under `PREFIX` (default `/usr/local`):
|
||||
| `lib/udev/rules.d/60-gkeymapper.rules` | lets your user reach the keyboard and `/dev/uinput` |
|
||||
| `lib/modules-load.d/gkeymapper.conf` | loads the `uinput` module at boot |
|
||||
| `lib/systemd/user/gkeymapper-daemon.service` | systemd user unit (binary path filled in from `PREFIX`) |
|
||||
| `share/dbus-1/services/dev.rager.gkeymapper.Daemon.service` | D-Bus activation: the GUI can start the daemon on demand |
|
||||
|
||||
Then enable the daemon for your session — it then starts automatically at login:
|
||||
|
||||
@@ -138,6 +180,10 @@ systemctl --user enable --now gkeymapper-daemon
|
||||
systemctl --user status gkeymapper-daemon
|
||||
```
|
||||
|
||||
Enabling it is optional: the D-Bus activation file above lets the bus start the
|
||||
daemon as soon as the GUI asks for its status. With both in place the unit is
|
||||
used either way, so the daemon never runs twice.
|
||||
|
||||
It is a **user** service on purpose: it needs your session for `/dev/uinput` and
|
||||
so that a `command` action inherits `DISPLAY`/`WAYLAND_DISPLAY`. The unit does
|
||||
not run as root. `make install` reloads the udev rules for you; on a fresh
|
||||
@@ -149,7 +195,7 @@ machine replug the keyboard (or reboot) once so the ACL applies.
|
||||
make clean
|
||||
```
|
||||
|
||||
Removes the binary and the generated `locale/` directory.
|
||||
Removes the binaries and the generated `locale/` and `build/` directories.
|
||||
|
||||
## Capturing key sequences
|
||||
|
||||
@@ -194,22 +240,26 @@ never sees a half-written file and the watch reloads exactly once per save.
|
||||
## Project structure
|
||||
|
||||
```
|
||||
src/main.cpp # app actions + GUI
|
||||
src/main.cpp # app actions + GUI + daemon status footer
|
||||
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)
|
||||
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
|
||||
shared/ipc_ids.h # app id + D-Bus names shared by GUI and daemon
|
||||
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/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)
|
||||
data/gkeymapper-uinput.conf # modules-load.d fragment for uinput
|
||||
data/gkeymapper-daemon.service# systemd user unit (installed by make install)
|
||||
data/dev.rager.gkeymapper.Daemon.service # D-Bus activation (session bus)
|
||||
docs/daemon-plan.md # daemon plan (reference: g910-gkey-macro-support)
|
||||
po/ # Translations (pot/po/mo targets)
|
||||
Makefile # Build via pkg-config + gettext
|
||||
@@ -244,7 +294,7 @@ export PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/share/pkgconfig:
|
||||
|
||||
## Planned next steps
|
||||
|
||||
- Daemon ↔ GUI channel (D-Bus): reload on save and show the daemon status.
|
||||
- Support the media keys and the M1–M3 / MR keys of the G910.
|
||||
- udev rule and systemd user service so the daemon can autostart.
|
||||
- `make install` for the daemon binary, the udev rule and the service file.
|
||||
- Profiles: swap mapping sets on the fly (the G910's M keys), which is what the
|
||||
reserved `SetProfile` D-Bus method was meant for.
|
||||
- Key sequence timing: per-step delays for recorded macros.
|
||||
|
||||
Reference in New Issue
Block a user