// The top bar: edge-to-edge system chrome with no surface of its own. Content // floats directly over the desktop, while individual controls still provide // hover and press feedback. The entire bar is a hit target so the top-left // corner remains a dependable workspace-scroll gesture. // // Instantiate one per screen: // // Variants { // model: Quickshell.screens // Bar {} // } // // Layout mirrors GNOME's: workspaces + vitals left, clock + weather center, // media + tray + status cluster right. import Quickshell import Quickshell.Wayland import QtQuick import QtQuick.Effects import qs.config import qs.modules.clipboard import qs.modules.focus PanelWindow { id: root // Set by Variants. Left as a plain property (not `required`) so the bar can // also be instantiated standalone on the default screen while testing. property var modelData: null // Raised when the status cluster is clicked; the shell wires this to the // quick settings panel, which this module does not own. signal requestQuickSettings // Bound by the shell when an idle inhibitor is held, so the cluster can // show the caffeine glyph. property alias idleInhibited: statusCluster.idleInhibited screen: root.modelData anchors { top: true left: true right: true } // PanelWindow defaults to an opaque white background. color: "transparent" implicitHeight: Theme.barHeight exclusiveZone: Theme.barHeight // Stable namespace for compositor inspection and shell diagnostics. WlrLayershell.namespace: "qs-bar" WlrLayershell.layer: WlrLayer.Top WlrLayershell.keyboardFocus: WlrKeyboardFocus.None // The full-width region is intentional: unlike a floating island, a menu // bar owns the screen edge. In particular, Workspaces starts at x=0 and // spans the full height so scrolling at the literal corner always works. mask: Region { item: barContent } // A scrim for wallpapers the bar cannot win against on tone alone. Drawn // behind the content rows, fading out downward so the bar still has no // hard edge of its own — the point is to darken what is under the text, // not to give the bar a surface. Static: a gradient that never changes // costs one paint, and this one has nothing to animate. Rectangle { anchors.fill: parent visible: Settings.barBackdrop gradient: Gradient { GradientStop { position: 0.0 color: Theme.alpha("#0c0e18", 0.55) } GradientStop { position: 1.0 color: "transparent" } } } Item { id: barContent anchors.fill: parent // One shadow for the whole bar rather than one per widget: the content // is flattened into a single layer and the halo is drawn under it, so // every glyph and label picks it up and nothing has to opt in. Off by // default — it only earns its layer on a busy wallpaper. layer.enabled: Settings.barTextShadow layer.effect: MultiEffect { shadowEnabled: true shadowColor: "#0a0c14" shadowBlur: 0.6 shadowVerticalOffset: 1 } // ── Left ──────────────────────────────────────────────────────────── Row { anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter spacing: Theme.itemSpacing Workspaces { anchors.verticalCenter: parent.verticalCenter screen: root.screen } AgentUsageWidget { anchors.verticalCenter: parent.verticalCenter } VitalsWidget { anchors.verticalCenter: parent.verticalCenter } } // ── Center ────────────────────────────────────────────────────────── Row { anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter spacing: 2 Clock { anchors.verticalCenter: parent.verticalCenter } WeatherWidget { anchors.verticalCenter: parent.verticalCenter } } // ── Right ─────────────────────────────────────────────────────────── Row { anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter spacing: Theme.itemSpacing CalendarIndicator { anchors.verticalCenter: parent.verticalCenter } HealthIndicator { anchors.verticalCenter: parent.verticalCenter } ActivityIndicator { anchors.verticalCenter: parent.verticalCenter } WallpaperIndicator { anchors.verticalCenter: parent.verticalCenter } FocusIndicator { anchors.verticalCenter: parent.verticalCenter } MediaWidget { anchors.verticalCenter: parent.verticalCenter } ClipboardWidget { anchors.verticalCenter: parent.verticalCenter } Tray { anchors.verticalCenter: parent.verticalCenter } StatusCluster { id: statusCluster anchors.verticalCenter: parent.verticalCenter onRequestQuickSettings: root.requestQuickSettings() } } } }