panel: extend the dismiss-scrim pattern for the capsule's click-away (item B)
PanelSet's shared breadbar-dismiss surface already handles click-away for the wifi/control/media popovers; this adds the pieces the capsule needs to reuse it rather than a second mechanism: an extra on_dismiss callback invoked alongside hide_all() on every dismiss click, and show_capsule_dismiss/hide_dismiss, which show the scrim with its clickable region starting at a caller-given top margin instead of the popover default. That margin matters: breadbar-dismiss's layer (overlay) always renders above the bar's own (top), so if its clickable region ever reached up into where the drawer is actually drawn, it would swallow clicks meant for a result row instead of the click-away. The capsule's own call site (main.rs, not part of this commit) always passes a margin sized to the drawer's maximum possible height, never its live one, so this can never happen regardless of how tall the drawer currently is. Not yet wired into the capsule's open/close — PanelSet's three new methods are unused until that follow-up commit, hence the transient dead_code warnings.
This commit is contained in:
parent
33181a7461
commit
c68ed0d7e9
1 changed files with 62 additions and 1 deletions
63
src/panel.rs
63
src/panel.rs
|
|
@ -5,18 +5,31 @@
|
|||
//! *below* the exclusive zone, and Hyprland slides `breadbar-panel` in from
|
||||
//! the right.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use gtk4::gdk::Key;
|
||||
use gtk4::prelude::*;
|
||||
use gtk4_layer_shell::{KeyboardMode, LayerShell};
|
||||
use gtk4_layer_shell::{Edge, KeyboardMode, LayerShell};
|
||||
|
||||
use crate::{bind_layer_monitor, theme};
|
||||
|
||||
/// A boxed, ref-counted, optionally-unset click-away callback — see
|
||||
/// `PanelSet::on_dismiss`'s own doc comment.
|
||||
type DismissCallback = Rc<RefCell<Option<Rc<dyn Fn()>>>>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PanelSet {
|
||||
pub connectivity: gtk4::Window,
|
||||
pub control: gtk4::Window,
|
||||
pub media: gtk4::Window,
|
||||
dismiss: gtk4::Window,
|
||||
// Theme 04/spotlight's capsule (plan §7 phase 6c): an extra click-away
|
||||
// callback invoked alongside the popover-dismiss path below, so the
|
||||
// SAME `breadbar-dismiss` surface/click-catcher also collapses the
|
||||
// capsule's drawer — see `show_capsule_dismiss`/`hide_dismiss` and
|
||||
// `set_on_dismiss`. `None` under every other theme (never set).
|
||||
on_dismiss: DismissCallback,
|
||||
}
|
||||
|
||||
impl PanelSet {
|
||||
|
|
@ -36,6 +49,7 @@ impl PanelSet {
|
|||
control,
|
||||
media,
|
||||
dismiss,
|
||||
on_dismiss: Rc::new(RefCell::new(None)),
|
||||
};
|
||||
set.wire_dismiss();
|
||||
set.wire_escape();
|
||||
|
|
@ -52,6 +66,10 @@ impl PanelSet {
|
|||
|
||||
pub fn show(&self, which: >k4::Window) {
|
||||
self.hide_panels();
|
||||
// A prior capsule search (see `show_capsule_dismiss`) may have left
|
||||
// the shared dismiss surface's top margin pushed down past its
|
||||
// popover-shaped default — restore it before this popover uses it.
|
||||
self.reset_dismiss_margin();
|
||||
// Dismiss first so the panel maps above it (same Overlay layer).
|
||||
self.dismiss.set_visible(true);
|
||||
self.dismiss.present();
|
||||
|
|
@ -70,12 +88,55 @@ impl PanelSet {
|
|||
self.media.set_visible(false);
|
||||
}
|
||||
|
||||
/// Theme 04/spotlight's capsule (plan §7 phase 6c): registers `cb` to
|
||||
/// run whenever the shared dismiss surface is clicked, alongside the
|
||||
/// popovers' own `hide_all`. `cb` is expected to no-op when the capsule
|
||||
/// isn't actually open (matching `close_fn`'s own guard in main.rs), so
|
||||
/// this firing on an ordinary popover click-away is harmless.
|
||||
pub fn set_on_dismiss(&self, cb: impl Fn() + 'static) {
|
||||
*self.on_dismiss.borrow_mut() = Some(Rc::new(cb));
|
||||
}
|
||||
|
||||
/// Shows the dismiss scrim with its clickable region starting at
|
||||
/// `top_margin` px from the screen top, rather than the theme's own
|
||||
/// popover-shaped default. See the call site in main.rs's capsule
|
||||
/// `open_fn` for why this needs to be at least the capsule's own row
|
||||
/// height plus the drawer's maximum possible height: the dismiss
|
||||
/// surface's layer (`overlay`) always renders above the bar's own
|
||||
/// (`top`), so if its clickable region ever reached up into where the
|
||||
/// drawer is actually drawn, it would swallow clicks meant for a
|
||||
/// result row instead of forwarding them.
|
||||
pub fn show_capsule_dismiss(&self, top_margin: i32) {
|
||||
self.dismiss.set_margin(Edge::Top, top_margin);
|
||||
self.dismiss.set_visible(true);
|
||||
self.dismiss.present();
|
||||
}
|
||||
|
||||
/// Hides the dismiss scrim and restores its margin to the theme's own
|
||||
/// popover default, so a later popover `show()` isn't left with a
|
||||
/// leftover capsule-sized gap.
|
||||
pub fn hide_dismiss(&self) {
|
||||
self.reset_dismiss_margin();
|
||||
self.dismiss.set_visible(false);
|
||||
}
|
||||
|
||||
fn reset_dismiss_margin(&self) {
|
||||
let theme = theme::shell_theme();
|
||||
if let Some(surf) = theme.surfaces().get("breadbar-dismiss") {
|
||||
let top = surf.offset.first().copied().unwrap_or(0.0) as i32;
|
||||
self.dismiss.set_margin(Edge::Top, top);
|
||||
}
|
||||
}
|
||||
|
||||
fn wire_dismiss(&self) {
|
||||
let set = self.clone();
|
||||
let click = gtk4::GestureClick::new();
|
||||
click.set_button(0);
|
||||
click.connect_pressed(move |_, _, _, _| {
|
||||
set.hide_all();
|
||||
if let Some(cb) = set.on_dismiss.borrow().as_ref() {
|
||||
cb();
|
||||
}
|
||||
});
|
||||
if let Some(child) = self.dismiss.child() {
|
||||
child.add_controller(click);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue