summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-05-04 22:11:03 +1000
committer2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-05-04 22:11:03 +1000
commita575245d7b9f084110ce062b35d908ceeda260ab (patch)
tree72e727d41577c99126f94421681eb0f17592c93d
parentfeat: audio osd (diff)
downloadcaelestia-shell-a575245d7b9f084110ce062b35d908ceeda260ab.tar.gz
caelestia-shell-a575245d7b9f084110ce062b35d908ceeda260ab.tar.bz2
caelestia-shell-a575245d7b9f084110ce062b35d908ceeda260ab.zip
feat: brightness osd
-rw-r--r--config/OsdConfig.qml2
-rw-r--r--modules/osd/Content.qml4
-rw-r--r--modules/osd/Osd.qml60
-rw-r--r--services/Brightness.qml113
4 files changed, 151 insertions, 28 deletions
diff --git a/config/OsdConfig.qml b/config/OsdConfig.qml
index 1bfdbd6..467d8e7 100644
--- a/config/OsdConfig.qml
+++ b/config/OsdConfig.qml
@@ -4,7 +4,7 @@ import Quickshell
import QtQuick
Singleton {
- readonly property int hideDelay: 1500
+ readonly property int hideDelay: 2000
readonly property Sizes sizes: Sizes {}
component Sizes: QtObject {
diff --git a/modules/osd/Content.qml b/modules/osd/Content.qml
index daab4e2..b224bf6 100644
--- a/modules/osd/Content.qml
+++ b/modules/osd/Content.qml
@@ -7,7 +7,7 @@ import QtQuick
Column {
id: root
- required property ShellScreen screen
+ required property Brightness.Monitor monitor
padding: Appearance.padding.large
@@ -35,6 +35,8 @@ Column {
VerticalSlider {
icon: "brightness_6"
+ value: root.monitor?.brightness ?? 0
+ onMoved: root.monitor?.setBrightness(value)
implicitWidth: OsdConfig.sizes.sliderWidth
implicitHeight: OsdConfig.sizes.sliderHeight
diff --git a/modules/osd/Osd.qml b/modules/osd/Osd.qml
index 4d744f6..4d6ab7e 100644
--- a/modules/osd/Osd.qml
+++ b/modules/osd/Osd.qml
@@ -4,47 +4,55 @@ import "root:/config"
import Quickshell
import QtQuick
-Scope {
- id: root
+Variants {
+ model: Quickshell.screens
- property bool osdVisible
+ Scope {
+ id: root
- function show(): void {
- root.osdVisible = true;
- timer.restart();
- }
-
- Connections {
- target: Audio
+ required property ShellScreen modelData
+ readonly property Brightness.Monitor monitor: Brightness.getMonitorForScreen(modelData)
+ property bool osdVisible
- function onMutedChanged(): void {
- root.show();
+ function show(): void {
+ root.osdVisible = true;
+ timer.restart();
}
- function onVolumeChanged(): void {
- root.show();
+ Connections {
+ target: Audio
+
+ function onMutedChanged(): void {
+ root.show();
+ }
+
+ function onVolumeChanged(): void {
+ root.show();
+ }
}
- }
- Timer {
- id: timer
+ Connections {
+ target: root.monitor
- interval: OsdConfig.hideDelay
- onTriggered: root.osdVisible = false
- }
+ function onBrightnessChanged(): void {
+ root.show();
+ }
+ }
- Variants {
- model: Quickshell.screens
+ Timer {
+ id: timer
+
+ interval: OsdConfig.hideDelay
+ onTriggered: root.osdVisible = false
+ }
LazyLoader {
loading: true
- required property ShellScreen modelData
-
StyledWindow {
id: win
- screen: parent.modelData
+ screen: root.modelData
name: "osd"
visible: wrapper.shouldBeVisible
@@ -80,7 +88,7 @@ Scope {
Content {
id: content
- screen: parent.modelData
+ monitor: root.monitor
}
}
}
diff --git a/services/Brightness.qml b/services/Brightness.qml
new file mode 100644
index 0000000..dd51376
--- /dev/null
+++ b/services/Brightness.qml
@@ -0,0 +1,113 @@
+pragma Singleton
+pragma ComponentBehavior: Bound
+
+import "root:/widgets"
+import Quickshell
+import Quickshell.Io
+import QtQuick
+
+Singleton {
+ id: root
+
+ property var ddcMonitors: []
+ readonly property list<Monitor> monitors: Quickshell.screens.map(screen => monitorComp.createObject(root, {
+ screen
+ }))
+
+ function getMonitorForScreen(screen: ShellScreen): var {
+ return monitors.find(m => m.screen === screen);
+ }
+
+ function increaseBrightness(): void {
+ const focusedName = Hyprland.focusedMonitor.name;
+ const monitor = monitors.find(m => focusedName === m.screen.name);
+ if (monitor)
+ monitor.setBrightness(monitor.brightness + 0.1);
+ }
+
+ function decreaseBrightness(): void {
+ const focusedName = Hyprland.focusedMonitor.name;
+ const monitor = monitors.find(m => focusedName === m.screen.name);
+ if (monitor)
+ monitor.setBrightness(monitor.brightness - 0.1);
+ }
+
+ reloadableId: "brightness"
+
+ onMonitorsChanged: {
+ ddcMonitors = [];
+ ddcProc.running = true;
+ }
+
+ Process {
+ id: ddcProc
+
+ command: ["ddcutil", "detect", "--brief"]
+ stdout: SplitParser {
+ splitMarker: "\n\n"
+ onRead: data => {
+ if (data.startsWith("Display ")) {
+ const lines = data.split("\n").map(l => l.trim());
+ root.ddcMonitors.push({
+ model: lines.find(l => l.startsWith("Monitor:")).split(":")[2],
+ busNum: lines.find(l => l.startsWith("I2C bus:")).split("/dev/i2c-")[1]
+ });
+ }
+ }
+ }
+ onExited: root.ddcMonitorsChanged()
+ }
+
+ Process {
+ id: setProc
+ }
+
+ CustomShortcut {
+ name: "brightnessUp"
+ onPressed: root.increaseBrightness()
+ }
+
+ CustomShortcut {
+ name: "brightnessDown"
+ onPressed: root.decreaseBrightness()
+ }
+
+ component Monitor: QtObject {
+ id: monitor
+
+ required property ShellScreen screen
+ readonly property bool isDdc: root.ddcMonitors.some(m => m.model === screen.model)
+ readonly property string busNum: root.ddcMonitors.find(m => m.model === screen.model)?.busNum ?? ""
+ property real brightness
+
+ readonly property Process initProc: Process {
+ stdout: SplitParser {
+ onRead: data => {
+ const [, , , current, max] = data.split(" ");
+ monitor.brightness = parseInt(current) / parseInt(max);
+ }
+ }
+ }
+
+ function setBrightness(value: real): void {
+ value = Math.max(0, Math.min(1, value));
+ const rounded = Math.round(value * 100);
+ if (Math.round(brightness * 100) === rounded)
+ return;
+ brightness = value;
+ setProc.command = isDdc ? ["ddcutil", "-b", busNum, "setvcp", "10", rounded] : ["brightnessctl", "s", rounded];
+ setProc.startDetached();
+ }
+
+ onBusNumChanged: {
+ initProc.command = isDdc ? ["ddcutil", "-b", busNum, "getvcp", "10", "--brief"] : ["sh", "-c", `echo "a b c $(brightnessctl g) $(brightnessctl m)"`];
+ initProc.running = true;
+ }
+ }
+
+ Component {
+ id: monitorComp
+
+ Monitor {}
+ }
+}