diff options
| author | user <user@clank> | 2026-08-12 15:18:33 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-12 15:18:33 +0200 |
| commit | 549f052ae5451d57b58f5de22de57b2a586e6d23 (patch) | |
| tree | b24bb9565eac6b068886328afbf0644d25b53e82 /zellij-utils/src/plugin_api/action.rs | |
| parent | sl0p: serialise the pane status bar for resurrection (diff) | |
| download | sl0ppij-549f052ae5451d57b58f5de22de57b2a586e6d23.tar.gz sl0ppij-549f052ae5451d57b58f5de22de57b2a586e6d23.tar.xz sl0ppij-549f052ae5451d57b58f5de22de57b2a586e6d23.zip | |
sl0p: clickable action buttons in the pane status bar
Second slice of the status/action frame. A program declares buttons, and a click
is reported back to it:
printf '\033]5577;1;buttons;approve:Approve;reject:Reject\033\\'
-> click -> program's stdin receives OSC 5577 ; 1 ; click ; approve ST
The report is a FIXED format carrying only the id, never bytes the payload chose,
and ids are restricted to [A-Za-z0-9_-]. The sequence that creates a button is
in-band and untrusted -- `cat` of a hostile file emits it as readily as a
cooperating program -- so a click that could send arbitrary bytes would let
viewing a file inject into the stdin of whatever is running, a shell included.
Labels are '%'-escaped since the wire format is ';'-separated, and both the
button count and id length are capped because the list lives as long as the pane.
Positions come from one layout_status_bar function that the renderer draws from
and the hit-test resolves against. Computing that geometry twice is how the
stacked-pane picker once selected the wrong pane; a test asserts every drawn
column resolves back to the button drawn there, across 100 widths.
Two things the drive caught that unit tests could not:
- The first delivery path pushed onto grid.pending_messages_to_pty, which is
only drained when the PANE produces output -- so a click on an idle program sat
in the queue forever. The write now happens at the tab level, which owns the
senders.
- The hit-test derived the frame row from the pane's raw geometry, but this fork
draws the frame inset by gap_offset, so with `gap 1` every click missed by one
row. It now derives from the CONTENT rect, which is by definition the inside of
the drawn frame and therefore the same columns the renderer lays out.
Buttons serialise with the session like the status text, so a resurrected pane
comes back with its buttons intact.
Diffstat (limited to '')
| -rw-r--r-- | zellij-utils/src/plugin_api/action.rs | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs index 3ee610d4..edc9ce66 100644 --- a/zellij-utils/src/plugin_api/action.rs +++ b/zellij-utils/src/plugin_api/action.rs @@ -3116,6 +3116,7 @@ impl TryFrom<ProtobufTiledPaneLayout> for TiledPaneLayout { // no protobuf representation, same as default_fg/default_bg above // no protobuf representation, same as children_arrangement status_bar: None, + status_bar_buttons: None, children_arrangement: None, }) } |
