fix(notifications, terminal): desktop notification delivery and rendering fixes - #49
Merged
Conversation
…livery Desktop notifications reached Notification Center on macOS but never popped up a banner, and OSC-triggered notifications (e.g. "Claude is waiting for your input") never fired at all, even though the scanner and app-side plumbing for them were designed and documented (docs/guide/16-notifications.md, docs/guide/07-osc-notifications.md) but never actually wired together — TerminalPane fed PTY bytes to the terminal grid only, dropping them on the floor as far as notifications were concerned. - rmux-terminal/osc.rs: OSC 9 is overloaded — iTerm2/ConEmu also use it for progress bars (`OSC 9;4;<state>[;<percent>]`), which is why this was disabled previously (produced junk notifications like "4;0;"). Add a targeted filter that recognizes and drops only that exact shape, so real notification text is unaffected. - rmux-app: give TerminalPane its own OscScanner over the same PTY bytes it feeds to TermState (scanning never mutates the stream), and thread completed notifications up through PaneNode -> Workspace -> WorkspaceManager -> RmuxApp, tagged with (workspace_id, pane_id), to the same NotificationManager::add() path the CLI's `notification.create` already used. - notifications/mod.rs: on macOS, mac-notification-sys silently posts every notification as com.apple.Finder when the running binary isn't inside a registered bundle (i.e. any dev/debug build) — delivery "succeeds" so it lands in Notification Center's history, but no banner ever animates, since most users have long muted Finder's routine trash/eject alerts. Explicitly claim rmux's own identity (matching the bundle id scripts/install.sh registers), falling back to Terminal's when rmux.app was never installed. Also set appname/icon on Linux so notifications group under "rmux" instead of a blank/PID-derived name. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…he pane Two separate rendering bugs, both cross-platform (macOS + Linux) since neither depends on OS-specific code paths: - Scrambled/garbled text after resume from sleep: our own per-glyph Arc<Galley> cache holds mesh vertices with UV coordinates baked in for egui's font texture atlas. egui rebuilds that atlas whole (DPI change, max_texture_side change, or simply filling past ~80% over a long session) — and in practice, the GPU context getting recreated after the OS suspends/resumes triggers the same rebuild. Our cached galleys kept pointing at the old atlas's packing, so painting them against the freshly repacked (differently laid out) atlas sampled whatever now happened to sit at those old coordinates: scrambled glyphs. Fix: track the atlas's Arc identity and drop the whole glyph cache whenever it changes, for any reason, on any platform — no sleep/wake-specific detection needed. - Full-screen TUIs (nvim, lazygit, btop, etc.) leaving a gap below and sometimes beside their content: row height was a flat `font_size * 1.15` guess, chosen to keep block-element TUIs (LazyVim's logo) looking tight. That guess ran ~13-15% taller than JetBrains Mono's real line height, so the cols/rows we told the PTY (and thus the TUI) was consistently undercounted versus the pane's actual pixel size. A full-screen TUI queries its size once at startup and only repaints on SIGWINCH, so it latched onto geometry smaller than the pane and never grew to fill it. Fix: measure the font's real row height instead of guessing. The original guess's actual job — making sure adjacent rows of block-drawing / box-drawing characters tile without seams — is now handled directly by rendering those characters as geometry sized to the cell (already true for block elements; extended here to the common single-line box-drawing set: ─│┌┐└┘├┤┬┴┼, used by nvim splits, nvim-tree, lazygit, btop borders), so it no longer depends on how a specific font's glyphs sit inside its own line metrics. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
docs/guide/16-notifications.md,docs/guide/07-osc-notifications.md) but never actually wired up —TerminalPanefed PTY bytes to the terminal grid only. WiredOscScannerthroughPaneNode→Workspace→WorkspaceManager→RmuxApp, with a targeted filter so iTerm2/ConEmu progress-bar OSC 9 sequences (OSC 9;4;<state>[;<percent>]) don't produce junk notifications (the reason this was disabled previously).mac-notification-syssilently posts ascom.apple.Finderwhen the binary isn't in a registered bundle (any dev build) — delivery "succeeds" but no banner shows, since most users have muted Finder's routine alerts. Now claims rmux's own identity (matchingscripts/install.sh's bundle id), falling back tocom.apple.Terminal. Also setsappname/iconon Linux so notifications group under "rmux".Arc<Galley>cache bakes in mesh UVs pointing into egui's font texture atlas. egui rebuilds that atlas whole on DPI change, fill-ratio overflow, or — in practice — GPU context recreation after OS suspend/resume. Cached galleys kept pointing at the old atlas packing, painting garbage from wherever the new atlas happened to repack. Now tracks the atlas'sArcidentity and drops the glyph cache whenever it changes, for any reason, on any platform.font_size * 1.15guess, ~13-15% taller than JetBrains Mono's real line height, so rmux consistently undercounted how many rows/cols fit the pane. A TUI queries its size once at startup and only redraws onSIGWINCH, so it latched onto the undercounted geometry. Now measures the font's real row height; the original guess's actual job (keeping block/box-drawing TUI art tiling without seams) is handled directly by rendering those characters as geometry sized to the cell — already true for block elements, now extended to the common single-line box-drawing set (─│┌┐└┘├┤┬┴┼).Test plan
cargo clippy --workspace --all-targets— cleancargo test --workspace— all passing (377 tests, several new: OSC progress-bar filtering, glyph-cache atlas invalidation, box-drawing geometry classification)rmux-cli notification create— no panics/warnings in logs🤖 Generated with Claude Code