gtk: wire up occlusionCallback for non-focused tabs (#12760) master
As discussed in #12745, there has been an outstanding plan to make rendering behavior for non-focused surfaces consistent across platforms. This PR does that for Linux/GTK using the same patterns as OSX. The change in `src/apprt/gtk/class/surface.zig` piggybacks on the existing `glareaMap` / `glareaUnmap` callbacks (added by `e59e27f8b`) by also calling a new `updateOcclusion(bool)` helper. If you don't like the helper, or want the helper lifted up further and used on other paths, let me know and I can revise. The changes in `src/renderer/Thread.zig` bail on `renderCallback` when not visible and then block on `drainMailbox` to complete the "catch up" before trying to draw again. I want to note that this is more granular than the original #1512, which was just focused on the top level window state. I can look at that as well if you want, but given the complexity around how `XDG_TOPLEVEL_STATE_SUSPENDED` event is fired, I would want to make sure we discussed things like transparency and single-instance properly first (e.g., do we render when behind another transparent window). ## Testing Here's a summary of what I tested: Tested on Linux/GTK (Ubuntu 26.04, GTK 4.22.2, libadwaita 1.9.0, Wayland), built `ReleaseFast`. The patched binary has been daily-driven for ~24 hours as my primary terminal. | Test | Workload | Result | |---|---|---| | Daily drive | byobu × multiple SSH sessions, Claude Code and Codex producing sustained streaming output, `top` / `btop` redrawing on 1 s intervals, frequent tab switching | No observed issues over ~24 hours of mixed use | | Bell on hidden tab | `sleep 5 && printf '\a'` in background tab | Bell + needs-attention indicator both fire; confirms IO-thread → GTK-signal path is untouched | | Search highlight survives hide/show | Open search w/ matches highlighted in tab B → switch to tab A for ~10 s → switch back | Highlights restored instantly with no stale state; confirms deferred-replay path (`updateFrame` on `.visible → true`) works correctly | | Selection persistence | Select text in tab B → switch tabs → switch back | Selection preserved exactly | | Lifecycle (close-all) | Opened 8 surfaces, closed them one at a time, then process exit + systemd restart | Zero `glib-CRITICAL`, zero `error in occlusion callback ...` warnings, clean teardown per `journalctl --user -u app-com.mitchellh.ghostty` | | Per-thread CPU during workload | `pidstat -t -p <pid>` 30 s with 1 byobu surface focused, 1 background | Hidden surface's renderer thread sits at 0.00 % every sample; focused surface's renderer shows ~1 % blips on byobu status ticks | ## AI usage Claude Code (Opus 4.7) helped review my patch and monitor / summarize the jorunald log and pidstat entries.