Krolyxon
Commit a5716dc

Branches

Refs →

auroraa5716dc

aurora: add caffeine, airplane, colour picker and screen recording toggles

Author
krolyxon
Date
2026-10-17 15:05 +0530
Parent
229376d
Commit
a5716dc528a79b5081079d81271542989c899914

+162 −1

7 files changed

  1. M .config/quickshell/aurora/Bar.qml +22 −0
  2. M .config/quickshell/aurora/ControlPanel.qml +1 −1
  3. M .config/quickshell/aurora/HomePage.qml +33 −0
  4. A .config/quickshell/aurora/Rec.qml +45 −0
  5. M .config/quickshell/aurora/Theme.qml +9 −0
  6. A .config/quickshell/aurora/Toggles.qml +50 −0
  7. M .config/quickshell/aurora/shell.qml +2 −0
M .config/quickshell/aurora/Bar.qml View
@@ -20,6 +20,12 @@ PanelWindow {
2020
2121 SystemClock { id: clock; precision: SystemClock.Minutes }
2222
23+ // caffeine: one inhibitor is enough, keep it on the first screen's bar
24+ IdleInhibitor {
25+ window: bar
26+ enabled: Toggles.caffeine && bar.modelData === Quickshell.screens[0]
27+ }
28+
2329 // ---- state ----
2430 readonly property var audio: Pipewire.defaultAudioSink ? Pipewire.defaultAudioSink.audio : null
2531 readonly property var mic: Pipewire.defaultAudioSource ? Pipewire.defaultAudioSource.audio : null
@@ -89,6 +95,22 @@ PanelWindow {
8995
9096 Tray { show: bar.monFocused }
9197
98+ BarPill {
99+ visible: Rec.running
100+ icon: Theme.iRec
101+ text: Theme.fmtClock(Rec.elapsed)
102+ tint: Theme.err
103+ underline: Theme.err
104+ onActivated: Rec.stop()
105+ }
106+
107+ BarPill {
108+ visible: Toggles.caffeine || Toggles.airplane
109+ icon: (Toggles.caffeine ? Theme.iCoffee : "") + (Toggles.caffeine && Toggles.airplane ? " " : "")
110+ + (Toggles.airplane ? Theme.iPlane : "")
111+ onActivated: bar.togglePanel("home", bar.modelData)
112+ }
113+
92114 BarPill {
93115 visible: bar.headset !== null
94116 icon: Theme.iHeadphones
M .config/quickshell/aurora/ControlPanel.qml View
@@ -16,7 +16,7 @@ PanelWindow {
1616 anchors { top: true; right: true }
1717 margins { top: 6; right: 8 } // sits just under the bar (bar's exclusive zone is respected)
1818 implicitWidth: 440
19− implicitHeight: 640
19+ implicitHeight: 720
2020 exclusiveZone: 0
2121 color: "transparent"
2222 WlrLayershell.layer: WlrLayer.Overlay
M .config/quickshell/aurora/HomePage.qml View
@@ -95,6 +95,39 @@ ColumnLayout {
9595 onClicked: if (audio) audio.muted = !audio.muted
9696 }
9797 }
98+ RowLayout {
99+ Layout.fillWidth: true
100+ spacing: 6
101+ IconBtn {
102+ Layout.fillWidth: true
103+ icon: Theme.iCoffee
104+ label: "caffeine"
105+ active: Toggles.caffeine
106+ onClicked: Toggles.caffeine = !Toggles.caffeine
107+ }
108+ IconBtn {
109+ Layout.fillWidth: true
110+ icon: Theme.iPlane
111+ label: "airplane"
112+ active: Toggles.airplane
113+ onClicked: Toggles.setAirplane(!Toggles.airplane)
114+ }
115+ IconBtn {
116+ Layout.fillWidth: true
117+ visible: Toggles.hasPicker
118+ icon: Theme.iPicker
119+ label: "colour"
120+ onClicked: { page.closeRequested(); Toggles.pickColour() }
121+ }
122+ IconBtn { // click: record a region; while recording: stop
123+ Layout.fillWidth: true
124+ visible: Rec.available
125+ icon: Rec.running ? Theme.iStop : Theme.iRec
126+ label: Rec.running ? Theme.fmtClock(Rec.elapsed) : "rec"
127+ active: Rec.running
128+ onClicked: { if (!Rec.running) page.closeRequested(); Rec.toggle("region") }
129+ }
130+ }
98131
99132 SectionLabel { text: "desktop" }
100133
A .config/quickshell/aurora/Rec.qml View
@@ -0,0 +1,45 @@
1+pragma Singleton
2+import QtQuick
3+import Quickshell
4+import Quickshell.Io
5+import Quickshell.Hyprland
6+
7+// Screen recording with wf-recorder (region via slurp, or the focused monitor), saved to ~/vids/rec.
8+// Everything is hidden if wf-recorder isn't installed.
9+Singleton {
10+ id: root
11+ property bool available: false
12+ readonly property bool running: proc.running
13+ property string dir: Quickshell.env("HOME") + "/vids/rec"
14+ property string file: ""
15+ property int elapsed: 0 // seconds
16+
17+ function start(mode) { // "region" | "screen"
18+ if (!available || proc.running) return
19+ file = dir + "/" + Qt.formatDateTime(new Date(), "yyyy-MM-dd_HH-mm-ss") + ".mp4"
20+ var m = Hyprland.focusedMonitor
21+ // exec so the Process pid is wf-recorder itself and SIGINT reaches it
22+ proc.command = mode === "region"
23+ ? ["sh", "-c", 'mkdir -p "${1%/*}"; g=$(slurp) || exit 1; exec wf-recorder -g "$g" -f "$1"', "sh", file]
24+ : ["sh", "-c", 'mkdir -p "${1%/*}"; exec wf-recorder -o "$2" -f "$1"', "sh", file, m ? m.name : ""]
25+ elapsed = 0
26+ proc.running = true
27+ }
28+ function stop() { if (proc.running) proc.signal(2) } // SIGINT: wf-recorder finalises the file
29+ function toggle(mode) { if (proc.running) stop(); else start(mode) }
30+
31+ Process {
32+ id: proc
33+ onExited: code => {
34+ Quickshell.execDetached(["sh", "-c",
35+ '[ -s "$1" ] && notify-send -a aurora "recording saved" "$1"', "sh", root.file])
36+ }
37+ }
38+ Timer { interval: 1000; repeat: true; running: proc.running; onTriggered: root.elapsed++ }
39+
40+ Process {
41+ command: ["sh", "-c", "command -v wf-recorder && command -v slurp"]
42+ running: true
43+ onExited: code => root.available = code === 0
44+ }
45+}
M .config/quickshell/aurora/Theme.qml View
@@ -151,6 +151,11 @@ Singleton {
151151 readonly property string iBatCharge: cp(0xF0084)
152152 readonly property string iShuffle: cp(0xF049D)
153153 readonly property string iImage: cp(0xF02E9)
154+ readonly property string iCoffee: cp(0xF0176)
155+ readonly property string iPlane: cp(0xF001D)
156+ readonly property string iPicker: cp(0xF020A)
157+ readonly property string iRec: cp(0xF044A)
158+ readonly property string iStop: cp(0xF04DB)
154159
155160 // workspace icons: the exact Font Awesome glyphs from your waybar config.
156161 // 1 browser, 2 code, 3 book, 4 cog, 5 chat, 6 file, 7 folder, 8 terminal, 9 flask, 10 image
@@ -176,6 +181,10 @@ Singleton {
176181 return h > 0 ? h + "h " + m + "m" : m + "m"
177182 }
178183
184+ function fmtClock(s) { // 75 -> "1:15"
185+ var m = Math.floor(s / 60), r = s % 60
186+ return m + ":" + (r < 10 ? "0" : "") + r
187+ }
179188 function volIcon(v, muted) {
180189 if (muted || v <= 0) return iVolOff
181190 return v < 0.34 ? iVolLow : (v < 0.67 ? iVolMed : iVolHigh)
A .config/quickshell/aurora/Toggles.qml View
@@ -0,0 +1,50 @@
1+pragma Singleton
2+import QtQuick
3+import Quickshell
4+import Quickshell.Io
5+import Quickshell.Bluetooth
6+
7+// Small session toggles used by the Home tab and the bar.
8+Singleton {
9+ id: root
10+
11+ // ---- caffeine: an IdleInhibitor on the bar (see Bar.qml) keeps hypridle from dimming/locking
12+ property bool caffeine: false
13+
14+ // ---- airplane: wifi + bluetooth off, previous state restored when turned off again
15+ property bool airplane: false
16+ property bool hadWifi: true
17+ property bool hadBt: false
18+ function setAirplane(on) {
19+ var ad = Bluetooth.defaultAdapter
20+ if (on) {
21+ hadWifi = Net.wifiEnabled
22+ hadBt = ad ? ad.enabled : false
23+ Net.setWifi(false)
24+ if (ad) ad.enabled = false
25+ } else {
26+ if (hadWifi) Net.setWifi(true)
27+ if (ad && hadBt) ad.enabled = true
28+ }
29+ airplane = on
30+ }
31+
32+ // ---- colour picker: hyprpicker copies the hex itself, we just show it as a notification
33+ property bool hasPicker: false
34+ function pickColour() { if (!picker.running) picker.running = true }
35+ Process {
36+ id: picker
37+ command: ["hyprpicker", "-a", "-f", "hex"]
38+ stdout: StdioCollector {
39+ onStreamFinished: {
40+ var c = text.trim()
41+ if (c !== "") Quickshell.execDetached(["notify-send", "-a", "aurora", "colour copied", c])
42+ }
43+ }
44+ }
45+ Process {
46+ command: ["sh", "-c", "command -v hyprpicker"]
47+ running: true
48+ onExited: code => root.hasPicker = code === 0
49+ }
50+}
M .config/quickshell/aurora/shell.qml View
@@ -145,6 +145,8 @@ ShellRoot {
145145 function clip(): void { root.toggleOverlay("clip") }
146146 function wall(): void { root.toggleOverlay("wall") }
147147 function wallrandom(): void { Wall.random() }
148+ function rec(mode: string): void { root.close(); Rec.toggle(mode === "screen" ? "screen" : "region") } // region | screen
149+ function caffeine(): void { Toggles.caffeine = !Toggles.caffeine }
148150 function bright(dir: string): void { Bright.step(dir === "down" ? -1 : 1) } // up | down
149151 }
150152 }