diff options
25 files changed, 666 insertions, 223 deletions
diff --git a/accounts/gkleen@sif/niri/default.nix b/accounts/gkleen@sif/niri/default.nix index e1eca4c4..10b85169 100644 --- a/accounts/gkleen@sif/niri/default.nix +++ b/accounts/gkleen@sif/niri/default.nix | |||
@@ -10,7 +10,6 @@ let | |||
10 | makoctl = lib.getExe' config.services.mako.package "makoctl"; | 10 | makoctl = lib.getExe' config.services.mako.package "makoctl"; |
11 | loginctl = lib.getExe' hostConfig.systemd.package "loginctl"; | 11 | loginctl = lib.getExe' hostConfig.systemd.package "loginctl"; |
12 | systemctl = lib.getExe' hostConfig.systemd.package "systemctl"; | 12 | systemctl = lib.getExe' hostConfig.systemd.package "systemctl"; |
13 | swayosd-client = lib.getExe' config.services.swayosd.package "swayosd-client"; | ||
14 | 13 | ||
15 | focus_or_spawn = pkgs.writeShellApplication { | 14 | focus_or_spawn = pkgs.writeShellApplication { |
16 | name = "focus-or-spawn"; | 15 | name = "focus-or-spawn"; |
@@ -168,7 +167,6 @@ in { | |||
168 | imports = [ | 167 | imports = [ |
169 | ./waybar.nix | 168 | ./waybar.nix |
170 | ./mako.nix | 169 | ./mako.nix |
171 | ./swayosd.nix | ||
172 | ]; | 170 | ]; |
173 | 171 | ||
174 | options = { | 172 | options = { |
@@ -939,31 +937,6 @@ in { | |||
939 | allow-when-locked = true; | 937 | allow-when-locked = true; |
940 | }; | 938 | }; |
941 | 939 | ||
942 | "XF86MonBrightnessUp" = { | ||
943 | action = spawn swayosd-client "--brightness" "raise"; | ||
944 | allow-when-locked = true; | ||
945 | }; | ||
946 | "XF86MonBrightnessDown" = { | ||
947 | action = spawn swayosd-client "--brightness" "lower"; | ||
948 | allow-when-locked = true; | ||
949 | }; | ||
950 | "XF86AudioRaiseVolume" = { | ||
951 | action = spawn swayosd-client "--output-volume" "raise"; | ||
952 | allow-when-locked = true; | ||
953 | }; | ||
954 | "XF86AudioLowerVolume" = { | ||
955 | action = spawn swayosd-client "--output-volume" "lower"; | ||
956 | allow-when-locked = true; | ||
957 | }; | ||
958 | "XF86AudioMute" = { | ||
959 | action = spawn swayosd-client "--output-volume" "mute-toggle"; | ||
960 | allow-when-locked = true; | ||
961 | }; | ||
962 | "XF86AudioMicMute" = { | ||
963 | action = spawn swayosd-client "--input-volume" "mute-toggle"; | ||
964 | allow-when-locked = true; | ||
965 | }; | ||
966 | |||
967 | "Mod+Semicolon".action = spawn makoctl "dismiss" "--group"; | 940 | "Mod+Semicolon".action = spawn makoctl "dismiss" "--group"; |
968 | "Mod+Shift+Semicolon".action = spawn makoctl "dismiss" "--all"; | 941 | "Mod+Shift+Semicolon".action = spawn makoctl "dismiss" "--all"; |
969 | "Mod+Period".action = spawn makoctl "menu" "--" (lib.getExe config.programs.fuzzel.package) "--dmenu"; | 942 | "Mod+Period".action = spawn makoctl "menu" "--" (lib.getExe config.programs.fuzzel.package) "--dmenu"; |
@@ -982,6 +955,37 @@ in { | |||
982 | "Mod+K".action = spawn (lib.getExe' pkgs.worktime "worktime-ui"); | 955 | "Mod+K".action = spawn (lib.getExe' pkgs.worktime "worktime-ui"); |
983 | "Mod+Shift+K".action = spawn (lib.getExe' pkgs.worktime "worktime-stop"); | 956 | "Mod+Shift+K".action = spawn (lib.getExe' pkgs.worktime "worktime-stop"); |
984 | })) | 957 | })) |
958 | (lib.mapAttrsToList (name: cfg: node name [(lib.removeAttrs cfg ["action"])] [cfg.action]) (let | ||
959 | shell = obj: leaf "send-unix" [ | ||
960 | { path = ''''${XDG_RUNTIME_DIR}/shell.sock''; } | ||
961 | (builtins.toJSON obj + "\n") | ||
962 | ]; | ||
963 | in { | ||
964 | "XF86AudioRaiseVolume" = { | ||
965 | allow-when-locked = true; | ||
966 | action = shell { Volume.volume = "up"; }; | ||
967 | }; | ||
968 | "XF86AudioLowerVolume" = { | ||
969 | allow-when-locked = true; | ||
970 | action = shell { Volume.volume = "down"; }; | ||
971 | }; | ||
972 | "XF86AudioMute" = { | ||
973 | allow-when-locked = true; | ||
974 | action = shell { Volume.muted = "toggle"; }; | ||
975 | }; | ||
976 | "XF86AudioMicMute" = { | ||
977 | allow-when-locked = true; | ||
978 | action = shell { Volume."mic-muted" = "toggle"; }; | ||
979 | }; | ||
980 | "XF86MonBrightnessUp" = { | ||
981 | action = shell { Brightness = "up"; }; | ||
982 | allow-when-locked = true; | ||
983 | }; | ||
984 | "XF86MonBrightnessDown" = { | ||
985 | action = shell { Brightness = "down"; }; | ||
986 | allow-when-locked = true; | ||
987 | }; | ||
988 | })) | ||
985 | (map ({ name, selector, spawn, key, ...}: if key != null && selector != null && spawn != null then bind key { action = focus-or-spawn-action selector name spawn; } else null) cfg.scratchspaces) | 989 | (map ({ name, selector, spawn, key, ...}: if key != null && selector != null && spawn != null then bind key { action = focus-or-spawn-action selector name spawn; } else null) cfg.scratchspaces) |
986 | (map ({ name, moveKey, ...}: if moveKey != null then bind moveKey { action = kdl.magic-leaf "move-column-to-workspace" name; } else null) cfg.scratchspaces) | 990 | (map ({ name, moveKey, ...}: if moveKey != null then bind moveKey { action = kdl.magic-leaf "move-column-to-workspace" name; } else null) cfg.scratchspaces) |
987 | ] | 991 | ] |
diff --git a/accounts/gkleen@sif/niri/swayosd.nix b/accounts/gkleen@sif/niri/swayosd.nix deleted file mode 100644 index 54ebb302..00000000 --- a/accounts/gkleen@sif/niri/swayosd.nix +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | { pkgs, ... }: | ||
2 | { | ||
3 | config = { | ||
4 | services.swayosd = { | ||
5 | enable = true; | ||
6 | topMargin = 0.4769706078; | ||
7 | stylePath = pkgs.runCommand "style.css" { | ||
8 | passAsFile = [ "src" ]; | ||
9 | src = '' | ||
10 | window#osd { | ||
11 | padding: 12px 20px; | ||
12 | border-radius: 999px; | ||
13 | border: none; | ||
14 | background: rgba(0, 0, 0, 0.87); | ||
15 | |||
16 | #container { | ||
17 | margin: 16px; | ||
18 | } | ||
19 | |||
20 | image, | ||
21 | label { | ||
22 | color: rgb(255, 255, 255); | ||
23 | |||
24 | &:disabled { | ||
25 | opacity: 1; | ||
26 | color: rgb(84, 84, 84); | ||
27 | } | ||
28 | } | ||
29 | |||
30 | progressbar { | ||
31 | min-height: 6px; | ||
32 | border-radius: 999px; | ||
33 | background: transparent; | ||
34 | border: none; | ||
35 | |||
36 | trough, progress { | ||
37 | min-height: inherit; | ||
38 | border-radius: inherit; | ||
39 | border: none; | ||
40 | } | ||
41 | |||
42 | trough { | ||
43 | background: rgb(127, 127, 127); | ||
44 | } | ||
45 | progress { | ||
46 | background: rgb(255, 255, 255); | ||
47 | } | ||
48 | |||
49 | &:disabled { | ||
50 | opacity: 1; | ||
51 | |||
52 | trough { | ||
53 | background: rgb(19, 19, 19); | ||
54 | } | ||
55 | progress { | ||
56 | background: rgb(38, 38, 38); | ||
57 | } | ||
58 | } | ||
59 | } | ||
60 | } | ||
61 | ''; | ||
62 | buildInputs = with pkgs; [sass]; | ||
63 | } "scss -C --sourcemap=none --style=compact $srcPath $out"; | ||
64 | }; | ||
65 | }; | ||
66 | } | ||
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.cpp b/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.cpp index 9ccd8ba0..5e607709 100644 --- a/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.cpp +++ b/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.cpp | |||
@@ -9,8 +9,16 @@ void Systemd::stopUserUnit(const QString& unit, const QString& mode) { | |||
9 | "/org/freedesktop/systemd1", | 9 | "/org/freedesktop/systemd1", |
10 | "org.freedesktop.systemd1.Manager", | 10 | "org.freedesktop.systemd1.Manager", |
11 | "StopUnit" | 11 | "StopUnit" |
12 | ); | 12 | ) << unit << mode; |
13 | m << unit; | ||
14 | m << mode; | ||
15 | QDBusConnection::sessionBus().send(m); | 13 | QDBusConnection::sessionBus().send(m); |
16 | } | 14 | } |
15 | |||
16 | void Systemd::setBrightness(const QString& subsystem, const QString& name, quint32 brightness) { | ||
17 | QDBusMessage m = QDBusMessage::createMethodCall( | ||
18 | "org.freedesktop.login1", | ||
19 | "/org/freedesktop/login1/session/auto", | ||
20 | "org.freedesktop.login1.Session", | ||
21 | "SetBrightness" | ||
22 | ) << subsystem << name << brightness; | ||
23 | QDBusConnection::systemBus().send(m); | ||
24 | } | ||
diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.hpp b/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.hpp index 883a96f3..f8841518 100644 --- a/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.hpp +++ b/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.hpp | |||
@@ -10,4 +10,5 @@ class Systemd : public QObject { | |||
10 | 10 | ||
11 | public: | 11 | public: |
12 | Q_INVOKABLE void stopUserUnit(const QString& unit, const QString& mode); | 12 | Q_INVOKABLE void stopUserUnit(const QString& unit, const QString& mode); |
13 | Q_INVOKABLE void setBrightness(const QString& subsystem, const QString& name, quint32 brightness); | ||
13 | }; | 14 | }; |
diff --git a/accounts/gkleen@sif/shell/quickshell/Bar.qml b/accounts/gkleen@sif/shell/quickshell/Bar.qml index 3652af54..d52740b2 100644 --- a/accounts/gkleen@sif/shell/quickshell/Bar.qml +++ b/accounts/gkleen@sif/shell/quickshell/Bar.qml | |||
@@ -1,7 +1,6 @@ | |||
1 | import Quickshell | 1 | import Quickshell |
2 | import QtQuick | 2 | import QtQuick |
3 | 3 | ||
4 | |||
5 | PanelWindow { | 4 | PanelWindow { |
6 | id: bar | 5 | id: bar |
7 | 6 | ||
@@ -64,25 +63,39 @@ PanelWindow { | |||
64 | anchors.verticalCenter: parent.verticalCenter | 63 | anchors.verticalCenter: parent.verticalCenter |
65 | spacing: 0 | 64 | spacing: 0 |
66 | 65 | ||
67 | PipewireWidget {} | 66 | PrivacyWidget { |
67 | id: privacy | ||
68 | } | ||
68 | 69 | ||
69 | Item { | 70 | Item { |
71 | enabled: privacy.active | ||
70 | height: parent.height | 72 | height: parent.height |
71 | width: 4 | 73 | width: 8 |
72 | } | 74 | } |
73 | 75 | ||
74 | SystemTray {} | 76 | BatteryWidget {} |
77 | |||
78 | Item { | ||
79 | height: parent.height | ||
80 | width: 8 | ||
81 | } | ||
82 | |||
83 | BrightnessWidget {} | ||
75 | 84 | ||
76 | Item { | 85 | Item { |
77 | height: parent.height | 86 | height: parent.height |
78 | width: 4 | 87 | width: 4 |
79 | } | 88 | } |
80 | 89 | ||
90 | PipewireWidget {} | ||
91 | |||
92 | SystemTray {} | ||
93 | |||
81 | KeyboardLayout {} | 94 | KeyboardLayout {} |
82 | 95 | ||
83 | Item { | 96 | Item { |
84 | height: parent.height | 97 | height: parent.height |
85 | width: 4 | 98 | width: 8 - 4 |
86 | } | 99 | } |
87 | 100 | ||
88 | Clock {} | 101 | Clock {} |
diff --git a/accounts/gkleen@sif/shell/quickshell/BatteryWidget.qml b/accounts/gkleen@sif/shell/quickshell/BatteryWidget.qml new file mode 100644 index 00000000..896440f1 --- /dev/null +++ b/accounts/gkleen@sif/shell/quickshell/BatteryWidget.qml | |||
@@ -0,0 +1,61 @@ | |||
1 | import QtQuick | ||
2 | import Quickshell | ||
3 | import Quickshell.Widgets | ||
4 | import Quickshell.Services.UPower | ||
5 | |||
6 | Item { | ||
7 | id: root | ||
8 | |||
9 | height: parent.height | ||
10 | width: batteryIcon.width | ||
11 | anchors.verticalCenter: parent.verticalCenter | ||
12 | |||
13 | property var batteryDevice: Array.from(UPower.devices.values).find(dev => dev.isLaptopBattery) | ||
14 | |||
15 | WrapperMouseArea { | ||
16 | id: widgetMouseArea | ||
17 | |||
18 | anchors.fill: parent | ||
19 | |||
20 | hoverEnabled: true | ||
21 | |||
22 | Item { | ||
23 | anchors.fill: parent | ||
24 | |||
25 | MaterialDesignIcon { | ||
26 | id: batteryIcon | ||
27 | |||
28 | implicitSize: 14 | ||
29 | anchors.centerIn: parent | ||
30 | |||
31 | icon: { | ||
32 | if (!root.batteryDevice?.ready) | ||
33 | return "battery-unknown"; | ||
34 | |||
35 | if (root.batteryDevice.state == UPowerDeviceState.FullyCharged) | ||
36 | return "power-plug-battery"; | ||
37 | |||
38 | const perdec = 10 * Math.max(1, Math.ceil(root.batteryDevice.percentage * 10)); | ||
39 | if (root.batteryDevice.state == UPowerDeviceState.Charging) | ||
40 | return `battery-charging-${perdec}`; | ||
41 | if (perdec == 100) | ||
42 | return "battery"; | ||
43 | return `battery-${perdec}`; | ||
44 | } | ||
45 | color: { | ||
46 | if (!root.batteryDevice?.ready) | ||
47 | return "#555"; | ||
48 | |||
49 | if (root.batteryDevice.state != UPowerDeviceState.FullyCharged && root.batteryDevice.state != UPowerDeviceState.Charging && root.batteryDevice.timeToEmpty < 20 * 60) | ||
50 | return "#f2201f"; | ||
51 | if (root.batteryDevice.state != UPowerDeviceState.FullyCharged && root.batteryDevice.state != UPowerDeviceState.Charging && root.batteryDevice.timeToEmpty < 40 * 60) | ||
52 | return "#f28a21"; | ||
53 | if (root.batteryDevice.state != UPowerDeviceState.FullyCharged) | ||
54 | return "#fff"; | ||
55 | return "#555"; | ||
56 | } | ||
57 | } | ||
58 | |||
59 | } | ||
60 | } | ||
61 | } | ||
diff --git a/accounts/gkleen@sif/shell/quickshell/BrightnessOSD.qml b/accounts/gkleen@sif/shell/quickshell/BrightnessOSD.qml new file mode 100644 index 00000000..a432179e --- /dev/null +++ b/accounts/gkleen@sif/shell/quickshell/BrightnessOSD.qml | |||
@@ -0,0 +1,117 @@ | |||
1 | import QtQuick | ||
2 | import QtQuick.Layouts | ||
3 | import Quickshell | ||
4 | import Quickshell.Widgets | ||
5 | import qs.Services | ||
6 | |||
7 | Scope { | ||
8 | id: root | ||
9 | |||
10 | property bool show: false | ||
11 | property bool inhibited: true | ||
12 | |||
13 | Connections { | ||
14 | target: Brightness | ||
15 | |||
16 | function onCurrBrightnessChanged() { | ||
17 | root.show = true; | ||
18 | hideTimer.restart(); | ||
19 | } | ||
20 | } | ||
21 | |||
22 | onShowChanged: { | ||
23 | if (show) | ||
24 | hideTimer.restart(); | ||
25 | } | ||
26 | |||
27 | Timer { | ||
28 | id: hideTimer | ||
29 | interval: 1000 | ||
30 | onTriggered: root.show = false | ||
31 | } | ||
32 | |||
33 | Timer { | ||
34 | id: startInhibit | ||
35 | interval: 100 | ||
36 | running: true | ||
37 | onTriggered: { | ||
38 | root.show = false; | ||
39 | root.inhibited = false; | ||
40 | } | ||
41 | } | ||
42 | |||
43 | LazyLoader { | ||
44 | active: root.show && !root.inhibited | ||
45 | |||
46 | Variants { | ||
47 | model: Quickshell.screens | ||
48 | |||
49 | delegate: Scope { | ||
50 | id: screenScope | ||
51 | |||
52 | required property var modelData | ||
53 | |||
54 | PanelWindow { | ||
55 | id: window | ||
56 | |||
57 | screen: screenScope.modelData | ||
58 | |||
59 | anchors.top: true | ||
60 | margins.top: screen.height / 2 - 50 + 3.5 | ||
61 | exclusiveZone: 0 | ||
62 | exclusionMode: ExclusionMode.Ignore | ||
63 | |||
64 | implicitWidth: 400 | ||
65 | implicitHeight: 50 | ||
66 | |||
67 | mask: Region {} | ||
68 | |||
69 | color: "transparent" | ||
70 | |||
71 | Rectangle { | ||
72 | anchors.fill: parent | ||
73 | color: Qt.rgba(0, 0, 0, 0.75) | ||
74 | } | ||
75 | |||
76 | RowLayout { | ||
77 | id: layout | ||
78 | |||
79 | anchors.centerIn: parent | ||
80 | |||
81 | height: 50 - 8*2 | ||
82 | width: 400 - 8*2 | ||
83 | |||
84 | MaterialDesignIcon { | ||
85 | id: volumeIcon | ||
86 | |||
87 | implicitWidth: parent.height | ||
88 | implicitHeight: parent.height | ||
89 | |||
90 | icon: `brightness-${Math.min(7, Math.floor(Brightness.currBrightness * 7) + 1)}` | ||
91 | } | ||
92 | |||
93 | Rectangle { | ||
94 | Layout.fillWidth: true | ||
95 | |||
96 | implicitHeight: 10 | ||
97 | |||
98 | color: "#50ffffff" | ||
99 | |||
100 | Rectangle { | ||
101 | anchors { | ||
102 | left: parent.left | ||
103 | top: parent.top | ||
104 | bottom: parent.bottom | ||
105 | } | ||
106 | |||
107 | color: "white" | ||
108 | |||
109 | implicitWidth: parent.width * Brightness.currBrightness | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | } | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | } | ||
diff --git a/accounts/gkleen@sif/shell/quickshell/BrightnessWidget.qml b/accounts/gkleen@sif/shell/quickshell/BrightnessWidget.qml new file mode 100644 index 00000000..664b28e2 --- /dev/null +++ b/accounts/gkleen@sif/shell/quickshell/BrightnessWidget.qml | |||
@@ -0,0 +1,33 @@ | |||
1 | import QtQuick | ||
2 | import Quickshell | ||
3 | import Quickshell.Widgets | ||
4 | import qs.Services | ||
5 | |||
6 | Item { | ||
7 | height: parent.height | ||
8 | width: brightnessIcon.width | ||
9 | anchors.verticalCenter: parent.verticalCenter | ||
10 | |||
11 | WrapperMouseArea { | ||
12 | id: widgetMouseArea | ||
13 | |||
14 | anchors.fill: parent | ||
15 | |||
16 | property real sensitivity: (1 / 50) / 120 | ||
17 | onWheel: event => Brightness.currBrightness += event.angleDelta.y * sensitivity | ||
18 | |||
19 | Item { | ||
20 | anchors.fill: parent | ||
21 | |||
22 | MaterialDesignIcon { | ||
23 | id: brightnessIcon | ||
24 | |||
25 | implicitSize: 14 | ||
26 | anchors.centerIn: parent | ||
27 | |||
28 | icon: `brightness-${Math.min(7, Math.floor(Brightness.currBrightness * 7) + 1)}` | ||
29 | color: "#555" | ||
30 | } | ||
31 | } | ||
32 | } | ||
33 | } | ||
diff --git a/accounts/gkleen@sif/shell/quickshell/MaterialDesignIcon.qml b/accounts/gkleen@sif/shell/quickshell/MaterialDesignIcon.qml index 387dcc8b..155a009e 100644 --- a/accounts/gkleen@sif/shell/quickshell/MaterialDesignIcon.qml +++ b/accounts/gkleen@sif/shell/quickshell/MaterialDesignIcon.qml | |||
@@ -2,15 +2,26 @@ import QtQuick | |||
2 | import QtQuick.Effects | 2 | import QtQuick.Effects |
3 | 3 | ||
4 | Item { | 4 | Item { |
5 | id: icon | 5 | id: root |
6 | 6 | ||
7 | required property string icon | 7 | required property string icon |
8 | property color color: "white" | 8 | property color color: "white" |
9 | 9 | ||
10 | property real implicitSize: 0 | ||
11 | |||
12 | readonly property real actualSize: Math.min(root.width, root.height) | ||
13 | |||
14 | implicitWidth: root.implicitSize | ||
15 | implicitHeight: root.implicitSize | ||
16 | |||
10 | Image { | 17 | Image { |
11 | id: sourceImage | 18 | id: sourceImage |
12 | source: "file://" + @mdi@ + "/svg/" + icon.icon + ".svg" | 19 | source: "file://" + @mdi@ + "/svg/" + root.icon + ".svg" |
13 | anchors.fill: parent | 20 | anchors.fill: parent |
21 | fillMode: Image.PreserveAspectFit | ||
22 | |||
23 | sourceSize.width: root.actualSize | ||
24 | sourceSize.height: root.actualSize | ||
14 | 25 | ||
15 | layer.enabled: true | 26 | layer.enabled: true |
16 | layer.effect: MultiEffect { | 27 | layer.effect: MultiEffect { |
@@ -18,7 +29,7 @@ Item { | |||
18 | 29 | ||
19 | brightness: 1 | 30 | brightness: 1 |
20 | colorization: 1 | 31 | colorization: 1 |
21 | colorizationColor: icon.color | 32 | colorizationColor: root.color |
22 | } | 33 | } |
23 | } | 34 | } |
24 | } | 35 | } |
diff --git a/accounts/gkleen@sif/shell/quickshell/PipewireWidget.qml b/accounts/gkleen@sif/shell/quickshell/PipewireWidget.qml index 7fdb5006..007ce100 100644 --- a/accounts/gkleen@sif/shell/quickshell/PipewireWidget.qml +++ b/accounts/gkleen@sif/shell/quickshell/PipewireWidget.qml | |||
@@ -50,8 +50,7 @@ Item { | |||
50 | MaterialDesignIcon { | 50 | MaterialDesignIcon { |
51 | id: volumeIcon | 51 | id: volumeIcon |
52 | 52 | ||
53 | width: 16 | 53 | implicitSize: 14 |
54 | height: 16 | ||
55 | anchors.centerIn: parent | 54 | anchors.centerIn: parent |
56 | 55 | ||
57 | icon: { | 56 | icon: { |
diff --git a/accounts/gkleen@sif/shell/quickshell/PrivacyWidget.qml b/accounts/gkleen@sif/shell/quickshell/PrivacyWidget.qml new file mode 100644 index 00000000..bb02528b --- /dev/null +++ b/accounts/gkleen@sif/shell/quickshell/PrivacyWidget.qml | |||
@@ -0,0 +1,49 @@ | |||
1 | import QtQuick | ||
2 | import QtQuick.Layouts | ||
3 | import Quickshell | ||
4 | import Quickshell.Widgets | ||
5 | import qs.Services | ||
6 | |||
7 | Item { | ||
8 | height: parent.height | ||
9 | width: layout.childrenRect.width | ||
10 | anchors.verticalCenter: parent.verticalCenter | ||
11 | |||
12 | readonly property bool active: Boolean(Privacy.activeItems) | ||
13 | |||
14 | RowLayout { | ||
15 | id: layout | ||
16 | |||
17 | anchors.fill: parent | ||
18 | |||
19 | spacing: 8 | ||
20 | |||
21 | Repeater { | ||
22 | model: Privacy.activeItems | ||
23 | |||
24 | Item { | ||
25 | id: privacyItem | ||
26 | |||
27 | required property var modelData; | ||
28 | |||
29 | height: parent.height | ||
30 | width: icon.width | ||
31 | |||
32 | MaterialDesignIcon { | ||
33 | id: icon | ||
34 | |||
35 | implicitSize: 14 | ||
36 | anchors.centerIn: parent | ||
37 | |||
38 | icon: { | ||
39 | if (privacyItem.modelData == Privacy.Item.Microphone) | ||
40 | return "microphone"; | ||
41 | if (privacyItem.modelData == Privacy.Item.Screensharing) | ||
42 | return "monitor-share"; | ||
43 | } | ||
44 | color: "#f2201f" | ||
45 | } | ||
46 | } | ||
47 | } | ||
48 | } | ||
49 | } | ||
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..87c7c05b --- /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 | function onLoaded() { root.currBrightness = root.calcCurrBrightness(); } | ||
30 | } | ||
31 | Connections { | ||
32 | target: maxFile | ||
33 | function 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 | } | ||
diff --git a/accounts/gkleen@sif/shell/quickshell/SystemTray.qml b/accounts/gkleen@sif/shell/quickshell/SystemTray.qml index 55b1690e..6f70be29 100644 --- a/accounts/gkleen@sif/shell/quickshell/SystemTray.qml +++ b/accounts/gkleen@sif/shell/quickshell/SystemTray.qml | |||
@@ -47,7 +47,7 @@ Item { | |||
47 | return "" | 47 | return "" |
48 | } | 48 | } |
49 | 49 | ||
50 | width: 16 | 50 | width: icon.width + 6 |
51 | height: parent.height | 51 | height: parent.height |
52 | anchors.verticalCenter: parent.verticalCenter | 52 | anchors.verticalCenter: parent.verticalCenter |
53 | 53 | ||
@@ -83,14 +83,24 @@ Item { | |||
83 | } | 83 | } |
84 | } | 84 | } |
85 | 85 | ||
86 | IconImage { | 86 | Rectangle { |
87 | anchors.centerIn: parent | 87 | anchors.fill: parent |
88 | width: parent.width | 88 | color: { |
89 | height: parent.width | 89 | if (trayItemArea.containsMouse) |
90 | source: trayItemWrapper.iconSource | 90 | return "#33808080"; |
91 | asynchronous: true | 91 | return "transparent"; |
92 | smooth: true | 92 | } |
93 | mipmap: true | 93 | |
94 | IconImage { | ||
95 | id: icon | ||
96 | |||
97 | anchors.centerIn: parent | ||
98 | implicitSize: 16 | ||
99 | source: trayItemWrapper.iconSource | ||
100 | asynchronous: true | ||
101 | smooth: true | ||
102 | mipmap: true | ||
103 | } | ||
94 | } | 104 | } |
95 | } | 105 | } |
96 | 106 | ||
@@ -116,7 +126,7 @@ Item { | |||
116 | color: "black" | 126 | color: "black" |
117 | 127 | ||
118 | implicitWidth: Math.max(tooltipTitle.contentWidth, tooltipDescription.contentWidth) + 16 | 128 | implicitWidth: Math.max(tooltipTitle.contentWidth, tooltipDescription.contentWidth) + 16 |
119 | implicitHeight: tooltipTitle.contentHeight + tooltipDescription.contentHeight + 16 | 129 | implicitHeight: (trayItem.tooltipTitle ? tooltipTitle.contentHeight : 0) + (trayItem.tooltipDescription ? tooltipDescription.contentHeight : 0) + 16 |
120 | 130 | ||
121 | WrapperMouseArea { | 131 | WrapperMouseArea { |
122 | id: tooltipMouseArea | 132 | id: tooltipMouseArea |
@@ -130,6 +140,8 @@ Item { | |||
130 | Text { | 140 | Text { |
131 | id: tooltipTitle | 141 | id: tooltipTitle |
132 | 142 | ||
143 | enabled: trayItem.tooltipTitle | ||
144 | |||
133 | font.pointSize: 10 | 145 | font.pointSize: 10 |
134 | font.family: "Fira Sans" | 146 | font.family: "Fira Sans" |
135 | font.bold: true | 147 | font.bold: true |
@@ -141,6 +153,8 @@ Item { | |||
141 | Text { | 153 | Text { |
142 | id: tooltipDescription | 154 | id: tooltipDescription |
143 | 155 | ||
156 | enabled: trayItem.tooltipDescription | ||
157 | |||
144 | font.pointSize: 10 | 158 | font.pointSize: 10 |
145 | font.family: "Fira Sans" | 159 | font.family: "Fira Sans" |
146 | color: "white" | 160 | color: "white" |
diff --git a/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml b/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml new file mode 100644 index 00000000..742ef4f5 --- /dev/null +++ b/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml | |||
@@ -0,0 +1,59 @@ | |||
1 | import Quickshell | ||
2 | import Quickshell.Io | ||
3 | import Quickshell.Services.Pipewire | ||
4 | import qs.Services | ||
5 | |||
6 | Scope { | ||
7 | id: root | ||
8 | |||
9 | SocketServer { | ||
10 | active: true | ||
11 | path: `${Quickshell.env("XDG_RUNTIME_DIR")}/shell.sock` | ||
12 | handler: Socket { | ||
13 | parser: SplitParser { | ||
14 | onRead: line => { | ||
15 | try { | ||
16 | const command = JSON.parse(line); | ||
17 | |||
18 | if (command.Volume) | ||
19 | root.onCommandVolume(command.Volume); | ||
20 | else if (command.Brightness) | ||
21 | root.onCommandBrightness(command.Brightness); | ||
22 | else | ||
23 | console.warn("UnixIPC: Command not handled:", JSON.stringify(command)); | ||
24 | } catch (e) { | ||
25 | console.warn("UnixIPC: Failed to parse command:", line, e); | ||
26 | } | ||
27 | } | ||
28 | } | ||
29 | |||
30 | onError: e => { | ||
31 | if (e == 1) | ||
32 | return; | ||
33 | console.warn("QLocalSocket::LocalSocketError", e); | ||
34 | } | ||
35 | } | ||
36 | } | ||
37 | |||
38 | PwObjectTracker { | ||
39 | objects: [ Pipewire.defaultAudioSink, Pipewire.defaultAudioSource ] | ||
40 | } | ||
41 | function onCommandVolume(command) { | ||
42 | if (command.muted === "toggle") | ||
43 | Pipewire.defaultAudioSink.audio.muted = !Pipewire.defaultAudioSink.audio.muted; | ||
44 | if (command.volume === "up") | ||
45 | Pipewire.defaultAudioSink.audio.volume += 0.02; | ||
46 | if (command.volume === "down") | ||
47 | Pipewire.defaultAudioSink.audio.volume -= 0.02; | ||
48 | |||
49 | if (command["mic-muted"] === "toggle") | ||
50 | Pipewire.defaultAudioSource.audio.muted = !Pipewire.defaultAudioSource.audio.muted; | ||
51 | } | ||
52 | |||
53 | function onCommandBrightness(command) { | ||
54 | if (command === "up") | ||
55 | Brightness.currBrightness += 0.02 | ||
56 | if (command === "down") | ||
57 | Brightness.currBrightness -= 0.02 | ||
58 | } | ||
59 | } | ||
diff --git a/accounts/gkleen@sif/shell/quickshell/VolumeOSD.qml b/accounts/gkleen@sif/shell/quickshell/VolumeOSD.qml index 02dcf227..16fb5dea 100644 --- a/accounts/gkleen@sif/shell/quickshell/VolumeOSD.qml +++ b/accounts/gkleen@sif/shell/quickshell/VolumeOSD.qml | |||
@@ -7,11 +7,11 @@ import Quickshell.Widgets | |||
7 | Scope { | 7 | Scope { |
8 | id: root | 8 | id: root |
9 | 9 | ||
10 | property bool show: false | 10 | property string show: "" |
11 | property bool inhibited: true | 11 | property bool inhibited: true |
12 | 12 | ||
13 | PwObjectTracker { | 13 | PwObjectTracker { |
14 | objects: [ Pipewire.defaultAudioSink ] | 14 | objects: [ Pipewire.defaultAudioSink, Pipewire.defaultAudioSource ] |
15 | } | 15 | } |
16 | 16 | ||
17 | Connections { | 17 | Connections { |
@@ -19,11 +19,25 @@ Scope { | |||
19 | target: Pipewire.defaultAudioSink?.audio | 19 | target: Pipewire.defaultAudioSink?.audio |
20 | 20 | ||
21 | function onVolumeChanged() { | 21 | function onVolumeChanged() { |
22 | root.show = true; | 22 | root.show = "sink"; |
23 | hideTimer.restart(); | 23 | hideTimer.restart(); |
24 | } | 24 | } |
25 | function onMutedChanged() { | 25 | function onMutedChanged() { |
26 | root.show = true; | 26 | root.show = "sink"; |
27 | hideTimer.restart(); | ||
28 | } | ||
29 | } | ||
30 | |||
31 | Connections { | ||
32 | enabled: Pipewire.defaultAudioSource | ||
33 | target: Pipewire.defaultAudioSource?.audio | ||
34 | |||
35 | function onVolumeChanged() { | ||
36 | root.show = "source"; | ||
37 | hideTimer.restart(); | ||
38 | } | ||
39 | function onMutedChanged() { | ||
40 | root.show = "source"; | ||
27 | hideTimer.restart(); | 41 | hideTimer.restart(); |
28 | } | 42 | } |
29 | } | 43 | } |
@@ -36,7 +50,7 @@ Scope { | |||
36 | Timer { | 50 | Timer { |
37 | id: hideTimer | 51 | id: hideTimer |
38 | interval: 1000 | 52 | interval: 1000 |
39 | onTriggered: root.show = false | 53 | onTriggered: root.show = "" |
40 | } | 54 | } |
41 | 55 | ||
42 | Timer { | 56 | Timer { |
@@ -44,7 +58,7 @@ Scope { | |||
44 | interval: 100 | 58 | interval: 100 |
45 | running: true | 59 | running: true |
46 | onTriggered: { | 60 | onTriggered: { |
47 | root.show = false; | 61 | root.show = ""; |
48 | root.inhibited = false; | 62 | root.inhibited = false; |
49 | } | 63 | } |
50 | } | 64 | } |
@@ -97,13 +111,20 @@ Scope { | |||
97 | implicitHeight: parent.height | 111 | implicitHeight: parent.height |
98 | 112 | ||
99 | icon: { | 113 | icon: { |
100 | if (!Pipewire.defaultAudioSink || Pipewire.defaultAudioSink.audio.muted) | 114 | if (root.show == "sink") { |
101 | return "volume-off"; | 115 | if (!Pipewire.defaultAudioSink || Pipewire.defaultAudioSink.audio.muted) |
102 | if (Pipewire.defaultAudioSink.audio.volume <= 0.33) | 116 | return "volume-off"; |
103 | return "volume-low"; | 117 | if (Pipewire.defaultAudioSink.audio.volume <= 0.33) |
104 | if (Pipewire.defaultAudioSink.audio.volume <= 0.67) | 118 | return "volume-low"; |
105 | return "volume-medium"; | 119 | if (Pipewire.defaultAudioSink.audio.volume <= 0.67) |
106 | return "volume-high"; | 120 | return "volume-medium"; |
121 | return "volume-high"; | ||
122 | } else if (root.show == "source") { | ||
123 | if (!Pipewire.defaultAudioSource || Pipewire.defaultAudioSource.audio.muted) | ||
124 | return "microphone-off"; | ||
125 | return "microphone"; | ||
126 | } | ||
127 | return "volume-high"; | ||
107 | } | 128 | } |
108 | } | 129 | } |
109 | 130 | ||
@@ -123,7 +144,13 @@ Scope { | |||
123 | 144 | ||
124 | color: Pipewire.defaultAudioSink?.audio.muted ? "#70ffffff" : "white" | 145 | color: Pipewire.defaultAudioSink?.audio.muted ? "#70ffffff" : "white" |
125 | 146 | ||
126 | implicitWidth: parent.width * (Pipewire.defaultAudioSink?.audio.volume ?? 0) | 147 | implicitWidth: { |
148 | if (root.show == "sink") | ||
149 | return parent.width * (Pipewire.defaultAudioSink?.audio.volume ?? 0); | ||
150 | else if (root.show == "source") | ||
151 | return parent.width * (Pipewire.defaultAudioSource?.audio.volume ?? 0); | ||
152 | return 0; | ||
153 | } | ||
127 | } | 154 | } |
128 | } | 155 | } |
129 | } | 156 | } |
diff --git a/accounts/gkleen@sif/shell/quickshell/shell.qml b/accounts/gkleen@sif/shell/quickshell/shell.qml index 3657f77f..0fa45f79 100644 --- a/accounts/gkleen@sif/shell/quickshell/shell.qml +++ b/accounts/gkleen@sif/shell/quickshell/shell.qml | |||
@@ -43,4 +43,7 @@ ShellRoot { | |||
43 | Lockscreen {} | 43 | Lockscreen {} |
44 | 44 | ||
45 | VolumeOSD {} | 45 | VolumeOSD {} |
46 | BrightnessOSD {} | ||
47 | |||
48 | UnixIPC {} | ||
46 | } | 49 | } |
@@ -507,11 +507,11 @@ | |||
507 | "xwayland-satellite-unstable": "xwayland-satellite-unstable" | 507 | "xwayland-satellite-unstable": "xwayland-satellite-unstable" |
508 | }, | 508 | }, |
509 | "locked": { | 509 | "locked": { |
510 | "lastModified": 1755424351, | 510 | "lastModified": 1757437545, |
511 | "narHash": "sha256-xcorYLNdtLpb0wH5CPlUcpmYQUxeK95j1X855xQw+DY=", | 511 | "narHash": "sha256-7ssbrFnmSrqtCtOySiu5ncyOBxPrR6p2nhNHrg6D+fo=", |
512 | "owner": "sodiboo", | 512 | "owner": "sodiboo", |
513 | "repo": "niri-flake", | 513 | "repo": "niri-flake", |
514 | "rev": "9aa137af01f05386e5bb5050e983750017007a66", | 514 | "rev": "ef694b996daeeb8684c0adfaa9b7067a6e709054", |
515 | "type": "github" | 515 | "type": "github" |
516 | }, | 516 | }, |
517 | "original": { | 517 | "original": { |
@@ -524,16 +524,16 @@ | |||
524 | "niri-stable": { | 524 | "niri-stable": { |
525 | "flake": false, | 525 | "flake": false, |
526 | "locked": { | 526 | "locked": { |
527 | "lastModified": 1748151941, | 527 | "lastModified": 1756556321, |
528 | "narHash": "sha256-z4viQZLgC2bIJ3VrzQnR+q2F3gAOEQpU1H5xHtX/2fs=", | 528 | "narHash": "sha256-RLD89dfjN0RVO86C/Mot0T7aduCygPGaYbog566F0Qo=", |
529 | "owner": "YaLTeR", | 529 | "owner": "YaLTeR", |
530 | "repo": "niri", | 530 | "repo": "niri", |
531 | "rev": "8ba57fcf25d2fc9565131684a839d58703f1dae7", | 531 | "rev": "01be0e65f4eb91a9cd624ac0b76aaeab765c7294", |
532 | "type": "github" | 532 | "type": "github" |
533 | }, | 533 | }, |
534 | "original": { | 534 | "original": { |
535 | "owner": "YaLTeR", | 535 | "owner": "YaLTeR", |
536 | "ref": "v25.05.1", | 536 | "ref": "v25.08", |
537 | "repo": "niri", | 537 | "repo": "niri", |
538 | "type": "github" | 538 | "type": "github" |
539 | } | 539 | } |
@@ -541,15 +541,16 @@ | |||
541 | "niri-unstable": { | 541 | "niri-unstable": { |
542 | "flake": false, | 542 | "flake": false, |
543 | "locked": { | 543 | "locked": { |
544 | "lastModified": 1755419373, | 544 | "lastModified": 1757438446, |
545 | "narHash": "sha256-EFH3zbpyLYjEboNV2Lmkxf9joEuFCmeYX+MMLRPStpg=", | 545 | "narHash": "sha256-4NN+weI4isQCFB+A36J+CU8tb251maVlBO9usuzgMQ8=", |
546 | "owner": "YaLTeR", | 546 | "owner": "gkleen", |
547 | "repo": "niri", | 547 | "repo": "niri", |
548 | "rev": "a6febb86aa5af0df7bf2792ca027ef95a503d599", | 548 | "rev": "2c7f7053ce360279160a9e2366d54980def848ad", |
549 | "type": "github" | 549 | "type": "github" |
550 | }, | 550 | }, |
551 | "original": { | 551 | "original": { |
552 | "owner": "YaLTeR", | 552 | "owner": "gkleen", |
553 | "ref": "feat/unix-sockets", | ||
553 | "repo": "niri", | 554 | "repo": "niri", |
554 | "type": "github" | 555 | "type": "github" |
555 | } | 556 | } |
@@ -780,11 +781,11 @@ | |||
780 | }, | 781 | }, |
781 | "nixpkgs-stable_3": { | 782 | "nixpkgs-stable_3": { |
782 | "locked": { | 783 | "locked": { |
783 | "lastModified": 1755274400, | 784 | "lastModified": 1757408970, |
784 | "narHash": "sha256-rTInmnp/xYrfcMZyFMH3kc8oko5zYfxsowaLv1LVobY=", | 785 | "narHash": "sha256-aSgK4BLNFFGvDTNKPeB28lVXYqVn8RdyXDNAvgGq+k0=", |
785 | "owner": "NixOS", | 786 | "owner": "NixOS", |
786 | "repo": "nixpkgs", | 787 | "repo": "nixpkgs", |
787 | "rev": "ad7196ae55c295f53a7d1ec39e4a06d922f3b899", | 788 | "rev": "d179d77c139e0a3f5c416477f7747e9d6b7ec315", |
788 | "type": "github" | 789 | "type": "github" |
789 | }, | 790 | }, |
790 | "original": { | 791 | "original": { |
@@ -1280,16 +1281,16 @@ | |||
1280 | "xwayland-satellite-stable": { | 1281 | "xwayland-satellite-stable": { |
1281 | "flake": false, | 1282 | "flake": false, |
1282 | "locked": { | 1283 | "locked": { |
1283 | "lastModified": 1748488455, | 1284 | "lastModified": 1755491097, |
1284 | "narHash": "sha256-IiLr1alzKFIy5tGGpDlabQbe6LV1c9ABvkH6T5WmyRI=", | 1285 | "narHash": "sha256-m+9tUfsmBeF2Gn4HWa6vSITZ4Gz1eA1F5Kh62B0N4oE=", |
1285 | "owner": "Supreeeme", | 1286 | "owner": "Supreeeme", |
1286 | "repo": "xwayland-satellite", | 1287 | "repo": "xwayland-satellite", |
1287 | "rev": "3ba30b149f9eb2bbf42cf4758d2158ca8cceef73", | 1288 | "rev": "388d291e82ffbc73be18169d39470f340707edaa", |
1288 | "type": "github" | 1289 | "type": "github" |
1289 | }, | 1290 | }, |
1290 | "original": { | 1291 | "original": { |
1291 | "owner": "Supreeeme", | 1292 | "owner": "Supreeeme", |
1292 | "ref": "v0.6", | 1293 | "ref": "v0.7", |
1293 | "repo": "xwayland-satellite", | 1294 | "repo": "xwayland-satellite", |
1294 | "type": "github" | 1295 | "type": "github" |
1295 | } | 1296 | } |
@@ -1297,11 +1298,11 @@ | |||
1297 | "xwayland-satellite-unstable": { | 1298 | "xwayland-satellite-unstable": { |
1298 | "flake": false, | 1299 | "flake": false, |
1299 | "locked": { | 1300 | "locked": { |
1300 | "lastModified": 1755219541, | 1301 | "lastModified": 1757179758, |
1301 | "narHash": "sha256-yKV6xHaPbEbh5RPxAJnb9yTs1wypr7do86hFFGQm1w8=", | 1302 | "narHash": "sha256-TIvyWzRt1miQj6Cf5Wy8Qz43XIZX7c4vTVwRLAT5S4Y=", |
1302 | "owner": "Supreeeme", | 1303 | "owner": "Supreeeme", |
1303 | "repo": "xwayland-satellite", | 1304 | "repo": "xwayland-satellite", |
1304 | "rev": "5a184d435927c3423f0ad189ea2b490578450fb7", | 1305 | "rev": "970728d0d9d1eada342bb8860af214b601139e58", |
1305 | "type": "github" | 1306 | "type": "github" |
1306 | }, | 1307 | }, |
1307 | "original": { | 1308 | "original": { |
@@ -209,7 +209,12 @@ | |||
209 | ref = "main"; | 209 | ref = "main"; |
210 | inputs = { | 210 | inputs = { |
211 | nixpkgs.follows = "nixpkgs"; | 211 | nixpkgs.follows = "nixpkgs"; |
212 | # niri-unstable.url = "github:gkleen/niri"; | 212 | niri-unstable = { |
213 | type = "github"; | ||
214 | owner = "gkleen"; | ||
215 | repo = "niri"; | ||
216 | ref = "feat/unix-sockets"; | ||
217 | }; | ||
213 | }; | 218 | }; |
214 | }; | 219 | }; |
215 | nix-monitored = { | 220 | nix-monitored = { |
diff --git a/overlays/niri.nix b/overlays/niri.nix index 9188ed7d..95a918b0 100644 --- a/overlays/niri.nix +++ b/overlays/niri.nix | |||
@@ -3,6 +3,7 @@ | |||
3 | (final: prev: { | 3 | (final: prev: { |
4 | niri-unstable = prev.niri-unstable.overrideAttrs (oldAttrs: { | 4 | niri-unstable = prev.niri-unstable.overrideAttrs (oldAttrs: { |
5 | buildInputs = (oldAttrs.buildInputs or []) ++ [ final.libgbm ]; | 5 | buildInputs = (oldAttrs.buildInputs or []) ++ [ final.libgbm ]; |
6 | doCheck = false; | ||
6 | }); | 7 | }); |
7 | }) | 8 | }) |
8 | final prev | 9 | final prev |
diff --git a/overlays/quickshell/default.nix b/overlays/quickshell/default.nix index 622d69a3..d806753f 100644 --- a/overlays/quickshell/default.nix +++ b/overlays/quickshell/default.nix | |||
@@ -5,6 +5,7 @@ | |||
5 | ./greetd-response.patch | 5 | ./greetd-response.patch |
6 | ./lock-state-changed.patch | 6 | ./lock-state-changed.patch |
7 | ./pipewire.patch | 7 | ./pipewire.patch |
8 | ./io.patch | ||
8 | ]; | 9 | ]; |
9 | }); | 10 | }); |
10 | } | 11 | } |
diff --git a/overlays/quickshell/io.patch b/overlays/quickshell/io.patch new file mode 100644 index 00000000..961bdcaf --- /dev/null +++ b/overlays/quickshell/io.patch | |||
@@ -0,0 +1,13 @@ | |||
1 | diff --git i/src/io/socket.cpp w/src/io/socket.cpp | ||
2 | index 371f687..d12eaeb 100644 | ||
3 | --- i/src/io/socket.cpp | ||
4 | +++ w/src/io/socket.cpp | ||
5 | @@ -66,7 +66,7 @@ void Socket::onSocketDisconnected() { | ||
6 | } | ||
7 | |||
8 | void Socket::onSocketError(QLocalSocket::LocalSocketError error) { | ||
9 | - qCWarning(logSocket) << "Socket error for" << this << error; | ||
10 | + // qCWarning(logSocket) << "Socket error for" << this << error; | ||
11 | emit this->error(error); | ||
12 | } | ||
13 | |||
diff --git a/overlays/quickshell/pipewire.patch b/overlays/quickshell/pipewire.patch index 33025d8b..2d98eefc 100644 --- a/overlays/quickshell/pipewire.patch +++ b/overlays/quickshell/pipewire.patch | |||
@@ -211,6 +211,34 @@ index 1a1f705..ee64858 100644 | |||
211 | bool | 211 | bool |
212 | setRouteProps(qint32 routeDevice, const std::function<void*(spa_pod_builder*)>& propsCallback); | 212 | setRouteProps(qint32 routeDevice, const std::function<void*(spa_pod_builder*)>& propsCallback); |
213 | 213 | ||
214 | diff --git i/src/services/pipewire/node.cpp w/src/services/pipewire/node.cpp | ||
215 | index 3e68149..4721a58 100644 | ||
216 | --- i/src/services/pipewire/node.cpp | ||
217 | +++ w/src/services/pipewire/node.cpp | ||
218 | @@ -145,6 +145,10 @@ void PwNode::initProps(const spa_dict* props) { | ||
219 | this->type = PwNodeType::VideoSink; | ||
220 | } else if (strcmp(mediaClass, "Video/Source") == 0) { | ||
221 | this->type = PwNodeType::VideoSource; | ||
222 | + } else if (strcmp(mediaClass, "Stream/Output/Video") == 0) { | ||
223 | + this->type = PwNodeType::VideoOutStream; | ||
224 | + } else if (strcmp(mediaClass, "Stream/Input/Video") == 0) { | ||
225 | + this->type = PwNodeType::VideoInStream; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | diff --git i/src/services/pipewire/node.hpp w/src/services/pipewire/node.hpp | ||
230 | index 0d4c92e..ee6f223 100644 | ||
231 | --- i/src/services/pipewire/node.hpp | ||
232 | +++ w/src/services/pipewire/node.hpp | ||
233 | @@ -144,6 +144,8 @@ public: | ||
234 | // This is equivalent to the media class `Video/Sink` and is composed of the | ||
235 | // @@PwNodeType.Video and @@PwNodeType.Sink flags. | ||
236 | VideoSink = Video | Sink, | ||
237 | + VideoOutStream = Video | Sink | Stream, | ||
238 | + VideoInStream = Video | Source | Stream, | ||
239 | }; | ||
240 | Q_ENUM(Flag); | ||
241 | Q_DECLARE_FLAGS(Flags, Flag); | ||
214 | diff --git i/src/services/pipewire/qml.cpp w/src/services/pipewire/qml.cpp | 242 | diff --git i/src/services/pipewire/qml.cpp w/src/services/pipewire/qml.cpp |
215 | index 9efb17e..921d12a 100644 | 243 | index 9efb17e..921d12a 100644 |
216 | --- i/src/services/pipewire/qml.cpp | 244 | --- i/src/services/pipewire/qml.cpp |
diff --git a/overlays/swayosd/default.nix b/overlays/swayosd/default.nix deleted file mode 100644 index 5e715dae..00000000 --- a/overlays/swayosd/default.nix +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | { final, prev, sources, ... }: { | ||
2 | swayosd = prev.swayosd.overrideAttrs (oldAttrs: rec { | ||
3 | inherit (sources.swayosd) version src; | ||
4 | cargoDeps = prev.rustPlatform.fetchCargoVendor { | ||
5 | inherit (oldAttrs) pname; | ||
6 | inherit version src; | ||
7 | hash = "sha256-J2sl6/4+bRWlkvaTJtFsMqvvOxYtWLRjJcYWcu0loRE="; | ||
8 | }; | ||
9 | patches = (oldAttrs.patches or []) ++ [ | ||
10 | ./exponential.patch | ||
11 | ]; | ||
12 | }); | ||
13 | } | ||
diff --git a/overlays/swayosd/exponential.patch b/overlays/swayosd/exponential.patch deleted file mode 100644 index eb90d739..00000000 --- a/overlays/swayosd/exponential.patch +++ /dev/null | |||
@@ -1,57 +0,0 @@ | |||
1 | diff --git a/src/brightness_backend/brightnessctl.rs b/src/brightness_backend/brightnessctl.rs | ||
2 | index ccb0e11..740fdb6 100644 | ||
3 | --- a/src/brightness_backend/brightnessctl.rs | ||
4 | +++ b/src/brightness_backend/brightnessctl.rs | ||
5 | @@ -107,10 +107,21 @@ impl VirtualDevice { | ||
6 | } | ||
7 | } | ||
8 | |||
9 | - fn set_percent(&mut self, mut val: u32) -> anyhow::Result<()> { | ||
10 | - val = val.clamp(0, 100); | ||
11 | - self.current = self.max.map(|max| val * max / 100); | ||
12 | - let _: String = self.run(("set", &*format!("{val}%")))?; | ||
13 | + fn val_to_percent(&mut self, val: u32) -> u32 { | ||
14 | + return ((val as f64 / self.get_max() as f64).powf(0.25) * 100_f64).round() as u32; | ||
15 | + } | ||
16 | + fn percent_to_val(&mut self, perc: u32) -> u32 { | ||
17 | + return ((perc as f64 / 100_f64).powf(4_f64) * self.get_max() as f64).round() as u32; | ||
18 | + } | ||
19 | + | ||
20 | + fn set_percent(&mut self, val: u32) -> anyhow::Result<()> { | ||
21 | + let new = self.percent_to_val(val); | ||
22 | + self.set_val(new) | ||
23 | + } | ||
24 | + fn set_val(&mut self, val: u32) -> anyhow::Result<()> { | ||
25 | + let curr = val.clamp(0, self.get_max()); | ||
26 | + self.current = Some(curr); | ||
27 | + let _: String = self.run(("set", &*format!("{curr}")))?; | ||
28 | Ok(()) | ||
29 | } | ||
30 | } | ||
31 | @@ -134,20 +145,18 @@ impl BrightnessBackend for BrightnessCtl { | ||
32 | |||
33 | fn lower(&mut self, by: u32) -> anyhow::Result<()> { | ||
34 | let curr = self.get_current(); | ||
35 | - let max = self.get_max(); | ||
36 | - | ||
37 | - let curr = curr * 100 / max; | ||
38 | + let mut new = self.device.val_to_percent(curr).saturating_sub(by); | ||
39 | + new = self.device.percent_to_val(new).min(curr.saturating_sub(1)); | ||
40 | |||
41 | - self.device.set_percent(curr.saturating_sub(by)) | ||
42 | + self.device.set_val(new) | ||
43 | } | ||
44 | |||
45 | fn raise(&mut self, by: u32) -> anyhow::Result<()> { | ||
46 | let curr = self.get_current(); | ||
47 | - let max = self.get_max(); | ||
48 | - | ||
49 | - let curr = curr * 100 / max; | ||
50 | + let mut new = self.device.val_to_percent(curr) + by; | ||
51 | + new = self.device.percent_to_val(new).max(curr + 1); | ||
52 | |||
53 | - self.device.set_percent(curr + by) | ||
54 | + self.device.set_val(new) | ||
55 | } | ||
56 | |||
57 | fn set(&mut self, val: u32) -> anyhow::Result<()> { | ||