srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/platform
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2026-05-13 19:47:00 +0200
committersrdusr <[email protected]>2026-05-13 19:47:00 +0200
commit670c9845129fc0c4b6e0192d657eea05e1a64b49 (patch)
tree273573d7ed109af3d39e268a6d43787b831c9d47 /crates/platform
parent646b37e7e3aa5931079c6b9e804f420bb43c74d5 (diff)
downloadsrdwm-670c9845129fc0c4b6e0192d657eea05e1a64b49.tar.gz
srdwm-670c9845129fc0c4b6e0192d657eea05e1a64b49.zip
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 <id> 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.
Diffstat (limited to 'crates/platform')
-rw-r--r--crates/platform/src/ipc/dispatch.rs11
-rw-r--r--crates/platform/src/ipc/types.rs14
2 files changed, 25 insertions, 0 deletions
diff --git a/crates/platform/src/ipc/dispatch.rs b/crates/platform/src/ipc/dispatch.rs
index 749b2aa..ad79b98 100644
--- a/crates/platform/src/ipc/dispatch.rs
+++ b/crates/platform/src/ipc/dispatch.rs
@@ -417,6 +417,17 @@ pub(crate) fn handle_request(line: &[u8], wm: &std::rc::Rc<std::cell::RefCell<Wi
// `redraw_decoration`/`apply_geometry` for every visible window
// unconditionally - this only has to mutate the right field and
// let that existing machinery do the rest.
+ // `{"cmd":"keybindings"}` - every binding the loaded config
+ // registered, as `(combo, description)`. Read-only, and the one
+ // way a panel or launcher can show the user what their own keys
+ // do: `srd.bind` lives entirely in the Lua engine, so nothing
+ // outside this process could see a binding at all before this.
+ "keybindings" => {
+ let wm = wm.borrow();
+ let list: Vec<KeybindingInfo> =
+ wm.keybindings.iter().map(|(combo, description)| KeybindingInfo { combo: combo.clone(), description: description.clone() }).collect();
+ (serde_json::to_vec(&KeybindingsResponse { keybindings: list }).unwrap_or_default(), false)
+ }
"set" => handle_set(&req, wm),
_ => (err("unknown command"), false),
}
diff --git a/crates/platform/src/ipc/types.rs b/crates/platform/src/ipc/types.rs
index f9af26c..286df20 100644
--- a/crates/platform/src/ipc/types.rs
+++ b/crates/platform/src/ipc/types.rs
@@ -122,6 +122,20 @@ pub(crate) struct MonitorsResponse {
pub(crate) monitors: Vec<MonitorInfo>,
}
+/// One key binding, for `srd keybindings`. `description` is empty when the
+/// binding did not give one - an empty string rather than `null`, so a
+/// consumer can render it without a branch.
+#[derive(Serialize)]
+pub(crate) struct KeybindingInfo {
+ pub(crate) combo: String,
+ pub(crate) description: String,
+}
+
+#[derive(Serialize)]
+pub(crate) struct KeybindingsResponse {
+ pub(crate) keybindings: Vec<KeybindingInfo>,
+}
+
#[derive(Serialize)]
pub(crate) struct WorkspacesResponse {
pub(crate) workspaces: Vec<WorkspaceInfo>,