Krolyxon
Commit a215858

Branches

Refs →

aurora.configquickshellaurorashell.qml

167 lines · 6.1 KB · QML

1import QtQuick
2import Quickshell
3import Quickshell.Io
4import Quickshell.Hyprland
5import Quickshell.Services.Pipewire
6
7// aurora: bar + control panel + notifications, themed from pywal16.
8ShellRoot {
9 id: root
10
11 property bool opened: false
12 property int tab: 0
13 property double closedAt: 0
14 property string lastTab: ""
15 property string lastScreen: ""
16 property var panelScreen: focusedScreen()
17 readonly property var focusedScr: focusedScreen()
18 // centered overlay windows (wallpaper picker, clipboard, ...): one at a time, on the focused monitor
19 property string overlay: ""
20 property var overlayScreen: focusedScreen()
21 readonly property var tabNames: ["home", "audio", "net", "bt", "sys", "notif", "settings"]
22
23 // screen of the monitor that currently has focus (falls back to the first screen)
24 function focusedScreen() {
25 var m = Hyprland.focusedMonitor
26 var l = Quickshell.screens
27 if (m) for (var i = 0; i < l.length; i++) if (l[i].name === m.name) return l[i]
28 return l.length ? l[0] : null
29 }
30 function close() {
31 if (!opened) return
32 opened = false
33 closedAt = Date.now()
34 lastTab = tabNames[tab]
35 lastScreen = panelScreen ? panelScreen.name : ""
36 }
37 property double overlayClosedAt: 0
38 property string lastOverlay: ""
39 function closeOverlay() {
40 if (overlay === "") return
41 lastOverlay = overlay
42 overlayClosedAt = Date.now()
43 overlay = ""
44 }
45 // scr: where to open (defaults to the focused monitor). Same instant re-open guard as togglePanel.
46 function toggleOverlay(name, scr) {
47 if (overlay === name) { closeOverlay(); return }
48 if (lastOverlay === name && Date.now() - overlayClosedAt < 250) return
49 close()
50 overlayScreen = scr ? scr : focusedScreen()
51 overlay = name
52 }
53 function openTab(name) {
54 var i = tabNames.indexOf(name)
55 if (i >= 0) tab = i
56 panelScreen = focusedScreen()
57 opened = true
58 }
59 // bar buttons: click once to open that tab, again to close.
60 // (the focus grab already closed the panel on the press, so guard against instant re-open)
61 // scr = the screen whose bar was clicked, so the panel opens on that monitor
62 function togglePanel(name, scr) {
63 var i = tabNames.indexOf(name)
64 var sn = scr ? scr.name : ""
65 if (opened && tab === i && panelScreen && panelScreen.name === sn) { close(); return }
66 if (!opened && lastTab === name && lastScreen === sn && Date.now() - closedAt < 250) return
67 tab = i
68 panelScreen = scr
69 opened = true
70 }
71
72 // keep every pipewire node bound so volume / mute / properties are readable
73 PwObjectTracker { objects: Pipewire.nodes.values }
74
75 Variants {
76 model: Quickshell.screens
77 Desktop {}
78 }
79
80 Variants {
81 model: Quickshell.screens
82 Dock {}
83 }
84
85 Variants {
86 model: Quickshell.screens
87 Bar {
88 onTogglePanel: (name, scr) => root.togglePanel(name, scr)
89 onToggleOverlay: (name, scr) => root.toggleOverlay(name, scr)
90 }
91 }
92
93 ControlPanel {
94 screen: root.panelScreen
95 opened: root.opened
96 tab: root.tab
97 onTabRequested: i => root.tab = i
98 onCloseRequested: root.close()
99 onOverlayRequested: name => { root.close(); root.toggleOverlay(name) }
100 }
101
102 Overview {
103 screen: root.overlayScreen
104 opened: root.overlay === "overview"
105 onCloseRequested: root.closeOverlay()
106 }
107
108 CalPopup {
109 screen: root.overlayScreen
110 opened: root.overlay === "cal"
111 onCloseRequested: root.closeOverlay()
112 }
113
114 ClipWindow {
115 screen: root.overlayScreen
116 opened: root.overlay === "clip"
117 onCloseRequested: root.closeOverlay()
118 }
119
120 WallPicker {
121 screen: root.overlayScreen
122 opened: root.overlay === "wall"
123 onCloseRequested: root.closeOverlay()
124 }
125
126 PowerMenu {
127 screen: root.overlayScreen
128 opened: root.overlay === "power"
129 onCloseRequested: root.closeOverlay()
130 }
131
132 NotifPopups { screen: root.focusedScr; suppressed: root.opened }
133
134 Osd { id: osd; screen: root.focusedScr; suppressed: root.opened }
135 Connections {
136 target: Bright
137 // brightnessctl only knows the laptop panel; external monitors go through ddcutil (no readback)
138 function onStepped() {
139 var m = Hyprland.focusedMonitor
140 if (Bright.available && (!m || m.name.indexOf("eDP") === 0))
141 osd.show(Theme.iBright, Bright.percent / 100, false)
142 }
143 }
144
145 IpcHandler {
146 target: "shell"
147 function toggle(): void { if (root.opened) root.close(); else root.openTab(root.tabNames[root.tab]) }
148 function open(): void { root.openTab(root.tabNames[root.tab]) }
149 function close(): void { root.close() }
150 function show(name: string): void { root.openTab(name) }
151 // `qs ipc call shell show x` is swallowed by the qs CLI (it has its own `show`), so use this
152 function tab(name: string): void { root.openTab(name) }
153 function dnd(): void { Notifs.dnd = !Notifs.dnd }
154 function shot(mode: string): void { root.close(); Shot.take(mode) } // region | window | output | ocr
155 function shotsave(): void { Shot.save = !Shot.save }
156 function overview(): void { root.toggleOverlay("overview") }
157 function cal(): void { root.toggleOverlay("cal") }
158 function clip(): void { root.toggleOverlay("clip") }
159 function wall(): void { root.toggleOverlay("wall") }
160 function power(): void { root.toggleOverlay("power") }
161 function wallrandom(): void { Wall.random() }
162 function wallset(path: string): void { Wall.apply(path) } // absolute path (setwall resolves it)
163 function rec(mode: string): void { root.close(); Rec.toggle(mode === "region" ? "region" : "screen") } // screen (default) | region
164 function caffeine(): void { Toggles.caffeine = !Toggles.caffeine }
165 function bright(dir: string): void { Bright.step(dir === "down" ? -1 : 1) } // up | down
166 }
167}