Add a watchdog that keeps the notch in the topmost z-order band - #322
Conversation
|
Thanks @abrahaofv. The idea is sound — a notch that loses its z-order band is a real bug — but the implementation needs two changes. Blocker: it logs forever when the notch is hidden. Should-fix: it shouldn't be a poller at all. The comment at If the hook turns out to miss a case in practice, a slow backstop poll (30s+) behind the same visibility gate would be a fair compromise — but let's try the hook first. |
Replaces the 2-second watchdog poll with EVENT_SYSTEM_FOREGROUND on a dedicated message-loop thread. A shared visible-window and drag gate keeps hidden notches completely silent, and a 30-second backstop covers a topmost window that appears without becoming foreground. The watchdog records one line per excursion and serializes the foreground callback with the backstop so overlapping checks cannot duplicate that diagnosis. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: Codex <322868195+abrahaofvcodex@users.noreply.github.com>
bd8d66a to
fcd3f11
Compare
|
Addressed both review points in fcd3f11. The watchdog now returns before any z-order enumeration when the notch is hidden, so The 2-second poll is replaced by an Validated with the notch hidden for over five minutes, repeated foreground changes, forced loss/recovery of |
|
Thank you @vinzdg/codenotch ***@***.***> for the
detailed review — I’ve updated the PR to address both points.
- The watchdog now returns before enumerating or reasserting when the
notch is hidden, so notch_visible = false produces no topmost watchdog
log entries.
- The 2-second poll has been replaced by an EVENT_SYSTEM_FOREGROUND hook
running on its own message-loop thread, so foreground changes drive the
normal recovery path at no idle cost.
- Logging is deduplicated to one entry per z-order excursion, including
when the hook and fallback overlap.
I also kept a 30-second backstop behind the same visibility and drag gates,
solely for the case where another application creates or changes a topmost
window without receiving foreground. I understand your preference to start
hook-only; I’m happy to remove the backstop if you’d rather keep this
revision strictly event-driven.
I validated the hidden-window case, repeated foreground changes, forced
loss/recovery of WS_EX_TOPMOST, and dragging across positions. All CI
checks are green.
And thank you again for merging #318 and #319.
Em ter., 22 de set. de 2026 às 22:02, Vinz ***@***.***>
escreveu:
… *vinzdg* left a comment (vinzdg/codenotch#322)
<#322 (comment)>
Thanks @abrahaofv <https://github.com/abrahaofv>. The idea is sound — a
notch that loses its z-order band is a real bug — but the implementation
needs two changes.
*Blocker: it logs forever when the notch is hidden.* topmost.rs:44,62 —
when the notch is switched off via notch_visible, the window is never
found, so the watchdog reasserts and logs every 2 seconds indefinitely.
run.log is capped at 1 MB, so that rotates away everything useful; the
first thing anyone attaches to a bug report would be nothing but this. Gate
it on the notch actually being shown.
*Should-fix: it shouldn't be a poller at all.* TOPMOST_POLL_MS = 2000 is
about 43,000 unconditional wake-ups a day, gated only by DRAGGING,
sitting beside the existing 1-second work-area watch. The CPU cost is
negligible (~0.01%) and that isn't really the point — it's a timer that
exists because nothing was subscribed to.
The comment at :101-102 says there's nothing to subscribe to, and that
isn't so: SetWinEventHook(EVENT_SYSTEM_FOREGROUND) delivers precisely
this event, at zero idle cost. That's the shape I'd want — react when the
foreground window changes, rather than ask every two seconds whether it did.
If the hook turns out to miss a case in practice, a slow backstop poll
(30s+) behind the same visibility gate would be a fair compromise — but
let's try the hook first.
Thanks for #318 <#318> and #319
<#319>, both merged.
—
Reply to this email directly, view it on GitHub
<#322?email_source=notifications&email_token=AS72XGAW3JRR6KY3C6YEKN35QMOKRA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKNZYG4YTMOBRGE22M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-5787168115>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AS72XGHACMSRTW2S3LJNVYD5QMOKRAVCNFSNUABGKJSXA33TNF2G64TZHMYTGNJYGI4TKMZVGM5US43TOVSTWNJVGQZTGNRXGIYTNILWAI>
.
Triage notifications, keep track of coding agent tasks and review pull
requests on the go with GitHub Mobile for iOS
<https://github.com/notifications/mobile/ios/AS72XGFRRMQVQZTO2ZUYKTD5QMOKRA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKNZYG4YTMOBRGE22M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJKTGN5XXIZLSL5UW64Y>
and Android
<https://github.com/notifications/mobile/android/AS72XGBOZGF5ITJV247EGFL5QMOKRA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKNZYG4YTMOBRGE22M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLTGN5XXIZLSL5QW4ZDSN5UWI>.
Download it today!
You are receiving this because you were mentioned.Message ID:
***@***.***>
--
Grato.
Abrahão Vendramini.
(21) 98313-2197
|
|
Merged — thanks for turning this round so quickly. Everything I asked for is in, and I checked each one rather than taking it on trust.
All four CI workflows green. |
Summary
Implements the fix already agreed on #304 between @PedroMendes22 (who diagnosed and measured this) and @RawJat (who confirmed the cause and the click-through interaction) — not a new direction of my own.
Root cause, as measured on the issue:
tao(Tauri 2's windowing crate) only callsSetWindowPoswhen its ownALWAYS_ON_TOPflag changes value.tauri.conf.jsonsetsalwaysOnTop: trueat window creation, so that flag never changes again — any laterwindow.set_always_on_top(true)is a no-op that never reasserts anything with the OS.WS_EX_TOPMOSTcan stay set on the notch while the real z-order has sunk it behind ordinary windows anyway (60/60 samples behind Chrome on the issue, despite the bit being set).Two spots were already identified as affected:
main.rs'sset_click_through, called on every pointer enter/exit over the notch, triggerstao's style rewrite withSWP_NOZORDER— explicitly not reordering.dropzones.rs's drag-carry lift (notch.set_always_on_top(true), meant to raise the notch back over the drop-zone overlay) was the same no-op.What this does
topmost.rs:is_out_of_topmost_bandunifies the two failure modes the issue describes into one check — the notch's ownWS_EX_TOPMOSTbit cleared outright, or the bit set but a visible ordinary window found ahead of it in a top-to-bottomEnumWindowswalk.reassertdoes the directSetWindowPos(HWND_TOPMOST, ...)that bypassestao's diff.start_watchdogpolls every 2s — the cadence @PedroMendes22 already validated ("logged 3 assertions" over a session, not one per tick) — modelled on the existingstart_work_area_watch(same bare-thread-plus-sleep shape, sameDRAGGINGskip-guard so it doesn't fight the carry).dropzones.rs: routes the drag-carry lift through the sametopmost::reasserthelper instead of the no-op, per @RawJat's specific ask on the issue.main.rs: wirestopmost::start_watchdogalongside the other two watchdogs;DRAGGINGneeded to go from private topub(crate)fortopmost.rsto read it.One implementation detail not spelled out in the issue:
window.hwnd()on atauri::WebviewWindowcomes back typed against whateverwindowscrate version Tauri itself pulled in (0.61.2 here), which differs from the one this crate depends on directly (0.58, pinned inCargo.toml). Same workaroundnotchmenu.rs'sgive_backalready uses: the raw pointer is carried across as an integer and rebuilt into this crate's ownHWNDbefore touching any Win32 call.Test plan
cargo build --releaseandcargo test --locked— 131 passed, 0 failed, no regressionscargo clippy --release— 6 pre-existing warnings elsewhere (tray.rs,glm.rs), none in the touched filesSetWindowPos(notch, HWND_NOTOPMOST, …)"): a throwaway script calledSetWindowPos(HWND_NOTOPMOST)on the running dev build's notch window. ConfirmedWS_EX_TOPMOSTwent from set to cleared.run.logprinted"topmost watchdog: notch had left the topmost band, reasserted", and a follow-up check confirmedWS_EX_TOPMOSTwas set again — no restart needed. Visually confirmed with another window brought to front over the notch: stayed on top.🤖 Generated with Claude Code