Say why the overlay closed, and document focusing both kinds of tile

--verbose now reports whether the overlay was picked from, cancelled, or
closed by the compositor. Chasing a "keys do nothing" symptom that turned
out to be a locked session, that distinction was the piece of information
I kept lacking: an exit code of 1 cannot tell a cancel from a surface the
compositor took away.

README now shows the two commands a caller needs — [con_id=N] focus for a
window, focus output NAME for a display — and that --focus runs them.
This commit is contained in:
Milad Alizadeh
2026-08-23 13:26:54 +01:00
parent 5b1f0f74e8
commit 6d8ae655b9
2 changed files with 29 additions and 6 deletions
+14 -4
View File
@@ -54,13 +54,23 @@ caller. The pick goes to stdout, nothing does if you cancel, and the exit status
is 0 for a pick and 1 for a cancel.
```sh
# sway scripting: act on the con_id
swaymsg "[con_id=$(wlgrid | cut -f2)] focus"
# or let wlgrid do it, for a bare keybinding
# Simplest: let wlgrid do the focusing, for a bare keybinding.
bindsym $mod+Tab exec wlgrid --focus
# Windows only, in a script:
swaymsg "[con_id=$(wlgrid --no-outputs | cut -f2)] focus"
# Both windows and displays: the TYPE column says which command to use.
IFS=$'\t' read -r type id toplevel app title < <(wlgrid) || exit 0
case $type in
window) swaymsg "[con_id=$id] focus" ;;
output) swaymsg "focus output $id" ;;
esac
```
`--focus` runs exactly those two commands for you. (Focusing a display only does
something visible when you have more than one.)
Three formats, because the identifiers different consumers need differ:
| `--format` | output |
+15 -2
View File
@@ -217,6 +217,8 @@ struct App {
configured: bool,
quit: bool,
/// Why the overlay closed, for --verbose.
quit_why: &'static str,
activate: Option<Target>,
/// Frame-callback ticks, for diagnosing the live clock.
ticks: u32,
@@ -265,6 +267,7 @@ impl App {
chrome_buffers: Vec::new(),
configured: false,
quit: false,
quit_why: "",
activate: None,
ticks: 0,
releases: 0,
@@ -645,9 +648,13 @@ impl App {
fn key(&mut self, code: u32) {
match code {
KEY_LEFTSHIFT | KEY_RIGHTSHIFT => self.shift = true,
KEY_ESC | KEY_Q => self.quit = true,
KEY_ESC | KEY_Q => {
self.quit_why = "cancelled";
self.quit = true;
}
KEY_ENTER | KEY_KPENTER => {
self.activate = self.tiles.get(self.sel).map(|t| t.target.clone());
self.quit_why = "picked";
self.quit = true;
}
KEY_TAB if self.shift => self.move_sel(-1),
@@ -976,6 +983,9 @@ fn run() -> Result<ExitCode, Box<dyn Error>> {
// wlgrid is a chooser: it reports the pick and leaves acting on it to the
// caller (--focus is a convenience for a bare keybinding).
if args.verbose {
eprintln!("wlgrid: {}", app.quit_why);
}
let Some(target) = app.activate else {
return Ok(ExitCode::FAILURE); // cancelled: nothing on stdout
};
@@ -1138,7 +1148,10 @@ impl Dispatch<ZwlrLayerSurfaceV1, ()> for App {
layer.ack_configure(serial);
app.configured = true;
}
zwlr_layer_surface_v1::Event::Closed => app.quit = true,
zwlr_layer_surface_v1::Event::Closed => {
app.quit_why = "the compositor closed the overlay";
app.quit = true;
}
_ => {}
}
}