diff options
| author | Laurens Duin <85798751+Laurens256@users.noreply.github.com> | 2025-08-13 06:31:48 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-13 14:31:48 +1000 |
| commit | 3710df29f588c2aa430d9797a36afa1cbd85b128 (patch) | |
| tree | 5f804118369ab2db0dbffbbd604b4ddc33af93ed /modules/bar/Bar.qml | |
| parent | nix: add home manager module (#402) (diff) | |
| download | caelestia-shell-3710df29f588c2aa430d9797a36afa1cbd85b128.tar.gz caelestia-shell-3710df29f588c2aa430d9797a36afa1cbd85b128.tar.bz2 caelestia-shell-3710df29f588c2aa430d9797a36afa1cbd85b128.zip | |
bar: allow hiding items and reordering (#379)
* feat: reorder bar, no popout yet
* chore: cleanup
* refactor: use DelegateChooser
* feat: popouts
* chore: cleanup
* better popout check + fix async stuff + bar interaction
+ a bunch of other fixes
* fix activewindow and bar vertical padding
* readme: add config opt
* bar: fix top/bottom padding
* bar: better wheel behaviour
---------
Co-authored-by: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>
Diffstat (limited to 'modules/bar/Bar.qml')
| -rw-r--r-- | modules/bar/Bar.qml | 270 |
1 files changed, 138 insertions, 132 deletions
diff --git a/modules/bar/Bar.qml b/modules/bar/Bar.qml index 22f21dd..cc191de 100644 --- a/modules/bar/Bar.qml +++ b/modules/bar/Bar.qml @@ -1,5 +1,5 @@ -import qs.components -import qs.components.controls +pragma ComponentBehavior: Bound + import qs.services import qs.config import "popouts" as BarPopouts @@ -7,170 +7,176 @@ import "components" import "components/workspaces" import Quickshell import QtQuick +import QtQuick.Layouts -Item { +ColumnLayout { id: root required property ShellScreen screen required property PersistentProperties visibilities required property BarPopouts.Wrapper popouts + readonly property int padding: Math.max(Appearance.padding.smaller, Config.border.thickness) + readonly property int vPadding: Appearance.padding.large function checkPopout(y: real): void { - const spacing = Appearance.spacing.small; - const aw = activeWindow.child; - const awy = activeWindow.y + aw.y; - - const ty = tray.y; - const th = tray.implicitHeight; - const trayItems = tray.items; - - // Check status icons hover areas - let statusIconFound = false; - for (const area of statusIconsInner.hoverAreas) { - if (!area.enabled) - continue; + const ch = childAt(width / 2, y) as WrappedLoader; + if (!ch) { + popouts.hasCurrent = false; + return; + } - const item = area.item; - const itemY = statusIcons.y + statusIconsInner.y + item.y - spacing / 2; - const itemHeight = item.implicitHeight + spacing; + const id = ch.id; + const top = ch.y; + const item = ch.item; + const itemHeight = item.implicitHeight; - if (y >= itemY && y <= itemY + itemHeight) { - popouts.currentName = area.name; - popouts.currentCenter = Qt.binding(() => statusIcons.y + statusIconsInner.y + item.y + item.implicitHeight / 2); + if (id === "statusIcons") { + const items = item.items; + const icon = items.childAt(items.width / 2, mapToItem(items, 0, y).y); + if (icon) { + popouts.currentName = icon.name; + popouts.currentCenter = Qt.binding(() => icon.mapToItem(root, 0, icon.implicitHeight / 2).y); popouts.hasCurrent = true; - statusIconFound = true; - break; } - } - - if (y >= awy && y <= awy + aw.implicitHeight) { - popouts.currentName = "activewindow"; - popouts.currentCenter = Qt.binding(() => activeWindow.y + aw.y + aw.implicitHeight / 2); - popouts.hasCurrent = true; - } else if (y > ty && y < ty + th) { - const index = Math.floor(((y - ty) / th) * trayItems.count); - const item = trayItems.itemAt(index); - - popouts.currentName = `traymenu${index}`; - popouts.currentCenter = Qt.binding(() => tray.y + item.y + item.implicitHeight / 2); + } else if (id === "tray") { + const index = Math.floor(((y - top) / itemHeight) * item.items.count); + const trayItem = item.items.itemAt(index); + if (trayItem) { + popouts.currentName = `traymenu${index}`; + popouts.currentCenter = Qt.binding(() => trayItem.mapToItem(root, 0, trayItem.implicitHeight / 2).y); + popouts.hasCurrent = true; + } + } else if (id === "activeWindow") { + popouts.currentName = id.toLowerCase(); + popouts.currentCenter = item.mapToItem(root, 0, itemHeight / 2).y; popouts.hasCurrent = true; - } else if (!statusIconFound) { - popouts.hasCurrent = false; } } - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.left: parent.left - - implicitWidth: child.implicitWidth + Math.max(Appearance.padding.smaller, Config.border.thickness) * 2 - - Item { - id: child - - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.horizontalCenter: parent.horizontalCenter - - implicitWidth: Math.max(osIcon.implicitWidth, workspaces.implicitWidth, activeWindow.implicitWidth, tray.implicitWidth, clock.implicitWidth, statusIcons.implicitWidth, power.implicitWidth) - - OsIcon { - id: osIcon - - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - anchors.topMargin: Appearance.padding.large + function handleWheel(y: real, angleDelta: point): void { + const ch = childAt(width / 2, y) as WrappedLoader; + if (ch?.id === "workspaces") { + // Workspace scroll + const activeWs = Hyprland.activeToplevel?.workspace?.name; + if (activeWs?.startsWith("special:")) + Hyprland.dispatch(`togglespecialworkspace ${activeWs.slice(8)}`); + else if (angleDelta.y < 0 || Hyprland.activeWsId > 1) + Hyprland.dispatch(`workspace r${angleDelta.y > 0 ? "-" : "+"}1`); + } else if (y < screen.height / 2) { + // Volume scroll on top half + if (angleDelta.y > 0) + Audio.incrementVolume(); + else if (angleDelta.y < 0) + Audio.decrementVolume(); + } else { + // Brightness scroll on bottom half + const monitor = Brightness.getMonitorForScreen(screen); + if (angleDelta.y > 0) + monitor.setBrightness(monitor.brightness + 0.1); + else if (angleDelta.y < 0) + monitor.setBrightness(monitor.brightness - 0.1); } + } - StyledRect { - id: workspaces - - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: osIcon.bottom - anchors.topMargin: Appearance.spacing.normal + spacing: Appearance.spacing.normal - radius: Appearance.rounding.full - color: Colours.tPalette.m3surfaceContainer + Repeater { + id: repeater - implicitWidth: workspacesInner.implicitWidth + Appearance.padding.small * 2 - implicitHeight: workspacesInner.implicitHeight + Appearance.padding.small * 2 + model: Config.bar.entries - CustomMouseArea { - anchors.fill: parent - anchors.leftMargin: -Math.max(Appearance.padding.smaller, Config.border.thickness) - anchors.rightMargin: -Math.max(Appearance.padding.smaller, Config.border.thickness) + DelegateChooser { + role: "id" - function onWheel(event: WheelEvent): void { - const activeWs = Hyprland.activeToplevel?.workspace?.name; - if (activeWs?.startsWith("special:")) - Hyprland.dispatch(`togglespecialworkspace ${activeWs.slice(8)}`); - else if (event.angleDelta.y < 0 || Hyprland.activeWsId > 1) - Hyprland.dispatch(`workspace r${event.angleDelta.y > 0 ? "-" : "+"}1`); + DelegateChoice { + roleValue: "spacer" + delegate: WrappedLoader { + Layout.fillHeight: enabled } } - - Workspaces { - id: workspacesInner - - anchors.centerIn: parent + DelegateChoice { + roleValue: "logo" + delegate: WrappedLoader { + sourceComponent: OsIcon {} + } + } + DelegateChoice { + roleValue: "workspaces" + delegate: WrappedLoader { + sourceComponent: Workspaces {} + } + } + DelegateChoice { + roleValue: "activeWindow" + delegate: WrappedLoader { + sourceComponent: ActiveWindow { + bar: root + monitor: Brightness.getMonitorForScreen(root.screen) + } + } + } + DelegateChoice { + roleValue: "tray" + delegate: WrappedLoader { + sourceComponent: Tray {} + } + } + DelegateChoice { + roleValue: "clock" + delegate: WrappedLoader { + sourceComponent: Clock {} + } + } + DelegateChoice { + roleValue: "statusIcons" + delegate: WrappedLoader { + sourceComponent: StatusIcons {} + } + } + DelegateChoice { + roleValue: "power" + delegate: WrappedLoader { + sourceComponent: Power { + visibilities: root.visibilities + } + } } } + } - ActiveWindow { - id: activeWindow - - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: workspaces.bottom - anchors.bottom: tray.top - anchors.margins: Appearance.spacing.large - - monitor: Brightness.getMonitorForScreen(root.screen) - } - - Tray { - id: tray - - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: clock.top - anchors.bottomMargin: Appearance.spacing.larger - } - - Clock { - id: clock + component WrappedLoader: Loader { + required property bool enabled + required property string id + required property int index - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: statusIcons.top - anchors.bottomMargin: Appearance.spacing.normal + function findFirstEnabled(): Item { + const count = repeater.count; + for (let i = 0; i < count; i++) { + const item = repeater.itemAt(i); + if (item?.enabled) + return item; + } + return null; } - StyledRect { - id: statusIcons - - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: power.top - anchors.bottomMargin: Appearance.spacing.normal - - radius: Appearance.rounding.full - color: Colours.tPalette.m3surfaceContainer - - implicitHeight: statusIconsInner.implicitHeight + Appearance.padding.normal * 2 - - StatusIcons { - id: statusIconsInner - - anchors.centerIn: parent + function findLastEnabled(): Item { + for (let i = repeater.count - 1; i >= 0; i--) { + const item = repeater.itemAt(i); + if (item?.enabled) + return item; } + return null; } - Power { - id: power + Layout.alignment: Qt.AlignHCenter + Layout.leftMargin: root.padding + Layout.rightMargin: root.padding - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: parent.bottom - anchors.bottomMargin: Appearance.padding.large + // Cursed ahh thing to add padding to first and last enabled components + Layout.topMargin: findFirstEnabled() === this ? root.vPadding : 0 + Layout.bottomMargin: findLastEnabled() === this ? root.vPadding : 0 - visibilities: root.visibilities - } + visible: enabled + active: enabled } } |