notifications: re-apply toast click-through after the surface::apply migration

feature/theme-spotlight branched before main's 297207a ('notifications:
stop toast popups from stealing focus or blocking clicks') and the
notification popup was rewritten in this branch to use
surface::apply() for its layer-shell setup, which sets only
anchor/margin/width/layer — no input region — and left the window on
KeyboardMode::OnDemand. Merging this branch would have silently
reintroduced the original bug with no merge conflict to flag it.

Re-apply the fix on top of surface::apply(): add surface::click_through(),
an opt-in helper that sets an empty layer-shell input region on map so
every pointer event passes through to whatever's underneath, and call
it from the toast's create_window(). history.rs's window (the genuinely
interactive notification-history view) is untouched and correctly
keeps OnDemand and normal hit-testing.

Also switch the toast itself from KeyboardMode::OnDemand to
KeyboardMode::None. The toast's card layout does build action buttons
and, when a notification carries an inline-reply hint, a GtkEntry —
but with an empty input region nothing on the toast is ever clickable
or focusable regardless of keyboard mode, so OnDemand only offered a
focus capability with no way to trigger it. Those controls remain
reachable from the history window, which is opened deliberately and
keeps real hit-testing.
This commit is contained in:
Breadway 2026-08-25 16:19:49 +08:00
parent 1d30818510
commit 110ad2c6f9
2 changed files with 40 additions and 3 deletions

View file

@ -86,3 +86,28 @@ pub fn apply(window: &gtk4::Window, namespace: &str) {
window.set_size_request(px, -1);
}
}
/// Makes `window` fully click-through: an empty layer-shell input region
/// means every pointer event passes to whatever is underneath instead of
/// being consumed by this surface. Deliberately opt-in, not part of
/// `apply()` — like `exclusive` zone and `keyboard` mode (see the module
/// doc comment), this isn't a `[surfaces.*]` schema concept, and most of
/// breadbar's satellites (history, the panel, the dismiss-scrim) genuinely
/// need real hit-testing. Only a purely-informational surface — today just
/// the notification toast — should call this.
///
/// Must be applied in a `connect_map` handler: the surface (and therefore
/// `window.surface()`) doesn't exist until the window is mapped.
///
/// This exists so a future migration of a surface's window-setup code
/// (like the one from hand-rolled layer-shell calls to this module) can't
/// silently drop a click-through requirement the way `breadbar-notif` did
/// once already — see the git history of `notifications/popup.rs` around
/// the "stop toast popups from stealing focus or blocking clicks" fix.
pub fn click_through(window: &gtk4::Window) {
window.connect_map(|win| {
if let Some(surface) = win.surface() {
surface.set_input_region(Some(&gtk4::cairo::Region::create()));
}
});
}