From 670c9845129fc0c4b6e0192d657eea05e1a64b49 Mon Sep 17 00:00:00 2001 From: srdusr <99972264+srdusr@users.noreply.github.com> Date: Wed, 13 May 2026 19:47:00 +0200 Subject: Expose key bindings over IPC so a launcher can list them Asked whether srdwm's bindings show in the AGS launcher. They could not: srd.bind lives entirely in the Lua engine, and nothing published a binding anywhere a client could read it. There was no IPC command, no field in any response, and bound_keys() was used only by main.rs to register grabs. srd.bind now takes an optional third argument, a description, and the loaded set is copied into the WindowManager after the initial load and after every reload. Core neither owns nor interprets them - it has no Lua state and never dispatches a key - it holds them so the IPC layer, which is handed a WindowManager and nothing else, can serve them. New `srd keybindings` returns combo and description pairs, sorted so a UI listing them does not reshuffle on every refresh. Every binding in the shipped config now carries a description, so the feature is useful without the user writing any. Verified live in a nested instance: 46 bindings published, 0 without a description, and editing the config file updated the list without a restart (which also exercised reload-on-write again). Also verified, for the separate report that windows cannot be moved to another workspace from the AGS workspace pills: the compositor side works. `srd dispatch move workspace 2` moved a window from workspace 1 to 2 and correctly hid it, since workspace 1 was active. Nothing to fix here; the missing piece is on the shell side. 515 tests pass, clippy clean. --- crates/core/src/manager/mod.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'crates/core/src/manager') diff --git a/crates/core/src/manager/mod.rs b/crates/core/src/manager/mod.rs index 2ca2bf9..a225220 100644 --- a/crates/core/src/manager/mod.rs +++ b/crates/core/src/manager/mod.rs @@ -439,6 +439,17 @@ pub struct WindowManager { /// above it. A top bar's own reservation is always honoured either /// way. Default `true` - see `input::layers::maximize_geometry_for`. pub maximize_covers_dock: bool, + /// Every key binding as `(combo, description)`, published by the main + /// loop after the config loads and after every reload. + /// + /// Core neither owns nor interprets these - it has no Lua state and + /// never dispatches a key itself. It holds them so the IPC layer, which + /// is handed a `WindowManager` and nothing else, can serve them to a + /// panel or launcher that wants to show the user what their keys do. + /// Asked for as whether "our bindings show in ags's launcher": they + /// could not, because nothing published them anywhere a client could + /// read. + pub keybindings: Vec<(String, String)>, /// Set by `request_refresh`, drained by the main loop. Same /// cross-boundary queued-request shape as `lock_requested`. refresh_requested: bool, @@ -628,6 +639,7 @@ impl WindowManager { auto_raise: false, theme: ThemeConfig::default(), lock: LockConfig::default(), + keybindings: Vec::new(), maximize_covers_dock: true, refresh_requested: false, live_settings: std::collections::BTreeMap::new(), -- cgit v1.2.3