This commit is contained in:
2026-09-18 20:39:06 +02:00
parent b3c3cc38f0
commit f7b12bc7cd
24 changed files with 1474 additions and 240 deletions
@@ -6,6 +6,8 @@ import Quickshell.Wayland
import qs.HyprChrome.Widgets.Bar
import qs.HyprChrome.Widgets
import qs.HyprChrome.Widgets.Polkit
import qs.HyprChrome.Widgets.Launcher
import qs.HyprChrome.Widgets.Askpass
// The hyprchrome shell: owns everything the rail's surfaces have to agree on,
// and instantiates them.
@@ -17,10 +19,11 @@ import qs.HyprChrome.Widgets.Polkit
// * which monitor the shell lives on — every surface has to pick the same one
// * the density — the whole rail expands and collapses as one, so the toggle
// and the shortcut that drives it belong to the shell, not to the bar
// * whether an authorization prompt is up — it raises the same scrim the rail
// uses and freezes the density while it is open, so two surfaces read it.
// That is why the agent lives here rather than as a sibling of the
// launchers in shell.qml
// * whether a MODAL is open — the polkit prompt, the launcher, or the sudo
// askpass dialog. Each raises the same scrim the rail uses, freezes the
// density, lands on the focused monitor and takes the keyboard off the
// rail, so several surfaces read it. That is why they live here rather than
// as siblings of the remaining launcher variants in shell.qml
// * the layer PAIR — the backdrop must sit exactly one layer below the bar in
// both densities. Two surfaces on the same layer stack by creation order,
// which is not something to rely on; one layer apart is a guarantee. Split
@@ -96,24 +99,30 @@ Scope {
// Frozen while a prompt is up, and dropped rather than queued: SUPER A
// during a prompt does nothing at all, instead of arming a change that
// springs the rail open or shut the moment the dialog goes.
if (polkit.prompting)
if (shell.modalOpen)
return;
shell.expanded = !shell.expanded;
}
// Whether the scrim is up, from EITHER cause. This is the fact the surfaces
// actually share — the rail's density is only one of the two things that
// can raise it — so the backdrop and the layer pair below key off this
// rather than off `expanded`.
// The surfaces that take over the screen: they dim EVERY output, land on the
// focused one, and take the keyboard off the rail. Grouped because
// everything below treats them alike, so a fourth one joins by being named
// here and nowhere else.
readonly property bool modalOpen: polkit.prompting || launcher.active || askpass.active
// Whether the scrim is up, from ANY cause. This is the fact the surfaces
// actually share — the rail's density is only one of the things that can
// raise it — so the backdrop and the layer pair below key off this rather
// than off `expanded`.
//
// One backdrop instance serves both. A prompt arriving over an already
// expanded rail therefore changes nothing about the scrim: it is already up,
// already full height, and the dialog simply appears above it. A prompt over
// a COLLAPSED rail expands that same scrim from its bar-height band to the
// whole output, using the animation it already has, and the rail stays
// collapsed throughout.
readonly property bool scrimUp: shell.expanded || polkit.prompting
// One backdrop instance serves all of them. A modal opening over an already
// expanded rail therefore changes nothing about the scrim on that monitor:
// it is already up, already full height, and the modal simply appears above
// it. Over a COLLAPSED rail the same scrim expands from its bar-height band
// to the whole output, using the animation it already has, and the rail
// stays collapsed throughout.
readonly property bool scrimUp: shell.expanded || shell.modalOpen
// Scrim up, the rail is over everything; scrim down, it drops below ordinary
// windows. BOTTOM rather than BACKGROUND for the lowered bar: it is the
@@ -174,7 +183,7 @@ Scope {
required property var modelData
screen: modelData
active: polkit.prompting
active: shell.modalOpen
wlrLayer: WlrLayer.Top
barHeight: 0
}
@@ -196,7 +205,7 @@ Scope {
// the rail. Withheld rather than left to the compositor to arbitrate
// between two exclusive surfaces, which would decide by stacking and
// silently swap the order the day the layers change.
grabsKeyboard: shell.expanded && !polkit.prompting
grabsKeyboard: shell.expanded && !shell.modalOpen
onDismissed: shell.expanded = false
}
@@ -220,4 +229,23 @@ Scope {
screen: shell.focusedScreen
}
// Primary application launcher — SUPER_L. Migrated out of
// widgets/launcher/; the ten remaining variants are still evaluation copies
// and stay in shell.qml. Declared after the bar for the same reason the
// prompt is: while it is open the bar is on Overlay too, and there is no
// layer above Overlay to escape to.
AppLauncher {
id: launcher
screen: shell.focusedScreen
}
// GUI password prompt for `sudo -A`. Not the polkit agent — sudo cannot use
// one — but it renders the same dialog. See the file for the flow.
AskpassPrompt {
id: askpass
screen: shell.focusedScreen
}
}