// The quick settings popover — GNOME's system menu (Super+S). // // A layer-shell surface rather than a PopupWindow because it needs keyboard // focus for the wifi password field, and because the bar it hangs from is // owned by a different module. import QtQuick import Quickshell import Quickshell.Wayland import Quickshell.Hyprland import qs.config import qs.services import qs.widgets PanelWindow { id: root visible: ShellState.quickSettingsOpen color: "transparent" // Hangs directly beneath the top-right status cluster. Two logical pixels // preserve the Prism edge without making the surface feel detached. // // The margin is the gap ALONE, not the bar height plus the gap. An // exclusiveZone of 0 means "reserve nothing, but respect what others // reserved", so this surface already begins below the bar's 36px zone; // adding the bar height here counted it twice and left the panel floating // 38px under the bar instead of 2px. It also means the panel follows the // bar on its own -- if the bar ever stops reserving space, this closes up // against the top edge rather than hanging under nothing. anchors.top: true anchors.right: true // The same gap every other popover uses. This had its own constant set to // 2, which left the widest surface in the shell hanging ten pixels higher // than the date menu beside it -- an early value nothing else converged on // rather than a decision; it carried no reason, while barGap does. margins.top: Theme.barGap * 2 margins.right: Theme.barSideMargin exclusiveZone: 0 implicitWidth: Theme.controlCenterWidth implicitHeight: panel.implicitHeight readonly property string expandedSection: panel.expandedSection function expand(name: string): void { panel.expand(name); } // The `qs-popover` prefix is matched by a layerrule in hypr/rules.lua. WlrLayershell.namespace: "qs-popover-quicksettings" WlrLayershell.layer: WlrLayer.Overlay // OnDemand rather than Exclusive: the panel must be able to take typing for // the wifi password field, but must not steal it while merely visible. WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand onVisibleChanged: { if (root.visible) { KdeConnect.refresh(); HomeAssistant.refresh(); // The daemon owns the power profile and anything on the system can // change it, so the panel asks rather than trusting what it last saw. PowerProfiles.refresh(); openAnim.restart(); } else { panel.reset(); } } // Closes the panel when a click lands anywhere else on the desktop. HyprlandFocusGrab { windows: [root] active: root.visible onCleared: ShellState.close() } Rectangle { id: surface anchors.fill: parent radius: Theme.popoverRadius color: Theme.alpha(Theme.bgPopover, Theme.popoverAlpha) border.width: 1 border.color: Theme.alpha(Theme.fg, 0.08) // The prism edge — see widgets/PrismEdge.qml. Sits just inside the 1px // border so the two don't fight for the same row of pixels. PrismEdge { anchors.top: parent.top anchors.topMargin: 1 anchors.left: parent.left anchors.right: parent.right inset: parent.radius } transform: Scale { id: openScale origin.x: surface.width origin.y: 0 xScale: 1 yScale: 1 } // Escape reaches here by propagating up from whatever holds focus // (usually the password field), so it works in every sub-state. Item { anchors.fill: parent focus: true Keys.onEscapePressed: ShellState.close() QuickSettingsPanel { id: panel anchors.fill: parent } } } NumberAnimation { id: openAnim target: openScale property: "yScale" from: 0.94 to: 1.0 duration: Theme.durNormal easing.type: Easing.OutCubic } }