diff options
Diffstat (limited to 'accounts/gkleen@sif/shell/quickshell/Services')
-rw-r--r-- | accounts/gkleen@sif/shell/quickshell/Services/Brightness.qml | 68 | ||||
-rw-r--r-- | accounts/gkleen@sif/shell/quickshell/Services/Privacy.qml | 63 |
2 files changed, 131 insertions, 0 deletions
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/Brightness.qml b/accounts/gkleen@sif/shell/quickshell/Services/Brightness.qml new file mode 100644 index 00000000..545ef24f --- /dev/null +++ b/accounts/gkleen@sif/shell/quickshell/Services/Brightness.qml | |||
@@ -0,0 +1,68 @@ | |||
1 | pragma Singleton | ||
2 | |||
3 | import QtQml | ||
4 | import Quickshell | ||
5 | import Quickshell.Io | ||
6 | import Custom as Custom | ||
7 | |||
8 | Singleton { | ||
9 | id: root | ||
10 | |||
11 | property string subsystem: "backlight" | ||
12 | property string device: "intel_backlight" | ||
13 | |||
14 | property real currBrightness | ||
15 | property real exponent: 4 | ||
16 | |||
17 | function calcCurrBrightness() { | ||
18 | if (!currFile.loaded || !maxFile.loaded) | ||
19 | return undefined; | ||
20 | const curr = Number(currFile.text()); | ||
21 | const max = Number(maxFile.text()); | ||
22 | const val = Math.pow(curr / max, 1 / root.exponent); | ||
23 | return val; | ||
24 | } | ||
25 | |||
26 | Component.onCompleted: root.currBrightness = root.calcCurrBrightness() | ||
27 | Connections { | ||
28 | target: currFile | ||
29 | onLoaded: root.currBrightness = root.calcCurrBrightness() | ||
30 | } | ||
31 | Connections { | ||
32 | target: maxFile | ||
33 | onLoaded: root.currBrightness = root.calcCurrBrightness() | ||
34 | } | ||
35 | |||
36 | onCurrBrightnessChanged: { | ||
37 | root.currBrightness = Math.max(0, Math.min(1, root.currBrightness)); | ||
38 | |||
39 | const prev = root.calcCurrBrightness(); | ||
40 | if (typeof prev === 'undefined' || Math.abs(root.currBrightness - prev) < 0.01) | ||
41 | return; | ||
42 | |||
43 | const max = Number(maxFile.text()); | ||
44 | const actual = Number(currFile.text()); | ||
45 | let curr = Math.max(0, Math.min(max, Math.pow(root.currBrightness, root.exponent) * max)); | ||
46 | if (Math.round(curr) == actual && curr < actual) | ||
47 | curr = Math.max(0, actual - 1); | ||
48 | else if (Math.round(curr) == actual && curr > actual) | ||
49 | curr = Math.min(max, actual + 1); | ||
50 | // root.currBrightness = Math.pow(curr / max, 1 / root.exponent); | ||
51 | Custom.Systemd.setBrightness(root.subsystem, root.device, Math.round(curr)); | ||
52 | } | ||
53 | |||
54 | FileView { | ||
55 | id: currFile | ||
56 | path: `/sys/class/${root.subsystem}/${root.device}/brightness` | ||
57 | blockAllReads: true | ||
58 | watchChanges: true | ||
59 | onFileChanged: reload() | ||
60 | } | ||
61 | FileView { | ||
62 | id: maxFile | ||
63 | path: `/sys/class/${root.subsystem}/${root.device}/max_brightness` | ||
64 | blockAllReads: true | ||
65 | watchChanges: true | ||
66 | onFileChanged: reload() | ||
67 | } | ||
68 | } | ||
diff --git a/accounts/gkleen@sif/shell/quickshell/Services/Privacy.qml b/accounts/gkleen@sif/shell/quickshell/Services/Privacy.qml new file mode 100644 index 00000000..9c813e49 --- /dev/null +++ b/accounts/gkleen@sif/shell/quickshell/Services/Privacy.qml | |||
@@ -0,0 +1,63 @@ | |||
1 | pragma Singleton | ||
2 | |||
3 | import QtQml | ||
4 | import Quickshell | ||
5 | import Quickshell.Services.Pipewire | ||
6 | |||
7 | Singleton { | ||
8 | id: root | ||
9 | |||
10 | PwObjectTracker { | ||
11 | objects: Pipewire.nodes.values | ||
12 | } | ||
13 | |||
14 | enum Item { | ||
15 | Microphone, | ||
16 | Screensharing | ||
17 | } | ||
18 | |||
19 | readonly property list<var> activeItems: { | ||
20 | var items = []; | ||
21 | if (microphoneActive) | ||
22 | items.push(Privacy.Item.Microphone); | ||
23 | if (screensharingActive) | ||
24 | items.push(Privacy.Item.Screensharing); | ||
25 | return items; | ||
26 | } | ||
27 | |||
28 | readonly property bool microphoneActive: { | ||
29 | if (!Pipewire.ready || !Pipewire.nodes?.values) { | ||
30 | return false | ||
31 | } | ||
32 | |||
33 | for (const node of Pipewire.nodes.values) { | ||
34 | if (!node || (node.type & PwNodeType.AudioInStream) != PwNodeType.AudioInStream) | ||
35 | continue; | ||
36 | |||
37 | if (node.properties?.["stream.monitor"] === "true") | ||
38 | continue; | ||
39 | |||
40 | if (node.audio?.muted) | ||
41 | continue; | ||
42 | |||
43 | return true; | ||
44 | } | ||
45 | |||
46 | return false; | ||
47 | } | ||
48 | |||
49 | readonly property bool screensharingActive: { | ||
50 | if (!Pipewire.ready || !Pipewire.nodes?.values) { | ||
51 | return false | ||
52 | } | ||
53 | |||
54 | for (const node of Pipewire.nodes.values) { | ||
55 | if (!node || (node.type & PwNodeType.VideoInStream) != PwNodeType.VideoInStream) | ||
56 | continue; | ||
57 | |||
58 | return true; | ||
59 | } | ||
60 | |||
61 | return false; | ||
62 | } | ||
63 | } | ||