From 9fab3828698199718a3d2f2faf8826f77d9258f7 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Tue, 9 Sep 2025 21:40:07 +0200 Subject: ... --- accounts/gkleen@sif/niri/default.nix | 39 ++++++++------- accounts/gkleen@sif/shell/quickshell/UnixIPC.qml | 49 +++++++++++++++++++ accounts/gkleen@sif/shell/quickshell/VolumeOSD.qml | 55 ++++++++++++++++------ accounts/gkleen@sif/shell/quickshell/shell.qml | 2 + flake.lock | 45 +++++++++--------- flake.nix | 7 ++- overlays/niri.nix | 1 + overlays/quickshell/default.nix | 1 + overlays/quickshell/io.patch | 13 +++++ 9 files changed, 159 insertions(+), 53 deletions(-) create mode 100644 accounts/gkleen@sif/shell/quickshell/UnixIPC.qml create mode 100644 overlays/quickshell/io.patch diff --git a/accounts/gkleen@sif/niri/default.nix b/accounts/gkleen@sif/niri/default.nix index e1eca4c4..1ff149bc 100644 --- a/accounts/gkleen@sif/niri/default.nix +++ b/accounts/gkleen@sif/niri/default.nix @@ -947,22 +947,6 @@ in { action = spawn swayosd-client "--brightness" "lower"; allow-when-locked = true; }; - "XF86AudioRaiseVolume" = { - action = spawn swayosd-client "--output-volume" "raise"; - allow-when-locked = true; - }; - "XF86AudioLowerVolume" = { - action = spawn swayosd-client "--output-volume" "lower"; - allow-when-locked = true; - }; - "XF86AudioMute" = { - action = spawn swayosd-client "--output-volume" "mute-toggle"; - allow-when-locked = true; - }; - "XF86AudioMicMute" = { - action = spawn swayosd-client "--input-volume" "mute-toggle"; - allow-when-locked = true; - }; "Mod+Semicolon".action = spawn makoctl "dismiss" "--group"; "Mod+Shift+Semicolon".action = spawn makoctl "dismiss" "--all"; @@ -982,6 +966,29 @@ in { "Mod+K".action = spawn (lib.getExe' pkgs.worktime "worktime-ui"); "Mod+Shift+K".action = spawn (lib.getExe' pkgs.worktime "worktime-stop"); })) + (lib.mapAttrsToList (name: cfg: node name [(lib.removeAttrs cfg ["action"])] [cfg.action]) (let + shell = obj: leaf "send-unix" [ + { path = ''''${XDG_RUNTIME_DIR}/shell.sock''; } + (builtins.toJSON obj + "\n") + ]; + in { + "XF86AudioRaiseVolume" = { + allow-when-locked = true; + action = shell { Volume.volume = "up"; }; + }; + "XF86AudioLowerVolume" = { + allow-when-locked = true; + action = shell { Volume.volume = "down"; }; + }; + "XF86AudioMute" = { + allow-when-locked = true; + action = shell { Volume.muted = "toggle"; }; + }; + "XF86AudioMicMute" = { + allow-when-locked = true; + action = shell { Volume."mic-muted" = "toggle"; }; + }; + })) (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) (map ({ name, moveKey, ...}: if moveKey != null then bind moveKey { action = kdl.magic-leaf "move-column-to-workspace" name; } else null) cfg.scratchspaces) ] diff --git a/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml b/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml new file mode 100644 index 00000000..7b308ec0 --- /dev/null +++ b/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml @@ -0,0 +1,49 @@ +import Quickshell +import Quickshell.Io +import Quickshell.Services.Pipewire + +Scope { + id: root + + SocketServer { + active: true + path: `${Quickshell.env("XDG_RUNTIME_DIR")}/shell.sock` + handler: Socket { + parser: SplitParser { + onRead: line => { + try { + const command = JSON.parse(line); + + if (command.Volume) + root.onCommandVolume(command.Volume); + else + console.warn("UnixIPC: Command not handled:", JSON.stringify(command)); + } catch (e) { + console.warn("UnixIPC: Failed to parse command:", line, e); + } + } + } + + onError: e => { + if (e == 1) + return; + console.warn("QLocalSocket::LocalSocketError", e); + } + } + } + + PwObjectTracker { + objects: [ Pipewire.defaultAudioSink, Pipewire.defaultAudioSource ] + } + function onCommandVolume(command) { + if (command.muted === "toggle") + Pipewire.defaultAudioSink.audio.muted = !Pipewire.defaultAudioSink.audio.muted; + if (command.volume === "up") + Pipewire.defaultAudioSink.audio.volume += 0.02; + if (command.volume === "down") + Pipewire.defaultAudioSink.audio.volume -= 0.02; + + if (command["mic-muted"] === "toggle") + Pipewire.defaultAudioSource.audio.muted = !Pipewire.defaultAudioSource.audio.muted; + } +} 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 Scope { id: root - property bool show: false + property string show: "" property bool inhibited: true PwObjectTracker { - objects: [ Pipewire.defaultAudioSink ] + objects: [ Pipewire.defaultAudioSink, Pipewire.defaultAudioSource ] } Connections { @@ -19,11 +19,25 @@ Scope { target: Pipewire.defaultAudioSink?.audio function onVolumeChanged() { - root.show = true; + root.show = "sink"; hideTimer.restart(); } function onMutedChanged() { - root.show = true; + root.show = "sink"; + hideTimer.restart(); + } + } + + Connections { + enabled: Pipewire.defaultAudioSource + target: Pipewire.defaultAudioSource?.audio + + function onVolumeChanged() { + root.show = "source"; + hideTimer.restart(); + } + function onMutedChanged() { + root.show = "source"; hideTimer.restart(); } } @@ -36,7 +50,7 @@ Scope { Timer { id: hideTimer interval: 1000 - onTriggered: root.show = false + onTriggered: root.show = "" } Timer { @@ -44,7 +58,7 @@ Scope { interval: 100 running: true onTriggered: { - root.show = false; + root.show = ""; root.inhibited = false; } } @@ -97,13 +111,20 @@ Scope { implicitHeight: parent.height icon: { - if (!Pipewire.defaultAudioSink || Pipewire.defaultAudioSink.audio.muted) - return "volume-off"; - if (Pipewire.defaultAudioSink.audio.volume <= 0.33) - return "volume-low"; - if (Pipewire.defaultAudioSink.audio.volume <= 0.67) - return "volume-medium"; - return "volume-high"; + if (root.show == "sink") { + if (!Pipewire.defaultAudioSink || Pipewire.defaultAudioSink.audio.muted) + return "volume-off"; + if (Pipewire.defaultAudioSink.audio.volume <= 0.33) + return "volume-low"; + if (Pipewire.defaultAudioSink.audio.volume <= 0.67) + return "volume-medium"; + return "volume-high"; + } else if (root.show == "source") { + if (!Pipewire.defaultAudioSource || Pipewire.defaultAudioSource.audio.muted) + return "microphone-off"; + return "microphone"; + } + return "volume-high"; } } @@ -123,7 +144,13 @@ Scope { color: Pipewire.defaultAudioSink?.audio.muted ? "#70ffffff" : "white" - implicitWidth: parent.width * (Pipewire.defaultAudioSink?.audio.volume ?? 0) + implicitWidth: { + if (root.show == "sink") + return parent.width * (Pipewire.defaultAudioSink?.audio.volume ?? 0); + else if (root.show == "source") + return parent.width * (Pipewire.defaultAudioSource?.audio.volume ?? 0); + return 0; + } } } } diff --git a/accounts/gkleen@sif/shell/quickshell/shell.qml b/accounts/gkleen@sif/shell/quickshell/shell.qml index 3657f77f..3bb2ae00 100644 --- a/accounts/gkleen@sif/shell/quickshell/shell.qml +++ b/accounts/gkleen@sif/shell/quickshell/shell.qml @@ -43,4 +43,6 @@ ShellRoot { Lockscreen {} VolumeOSD {} + + UnixIPC {} } diff --git a/flake.lock b/flake.lock index 6046d92f..05385ecd 100644 --- a/flake.lock +++ b/flake.lock @@ -507,11 +507,11 @@ "xwayland-satellite-unstable": "xwayland-satellite-unstable" }, "locked": { - "lastModified": 1755424351, - "narHash": "sha256-xcorYLNdtLpb0wH5CPlUcpmYQUxeK95j1X855xQw+DY=", + "lastModified": 1757437545, + "narHash": "sha256-7ssbrFnmSrqtCtOySiu5ncyOBxPrR6p2nhNHrg6D+fo=", "owner": "sodiboo", "repo": "niri-flake", - "rev": "9aa137af01f05386e5bb5050e983750017007a66", + "rev": "ef694b996daeeb8684c0adfaa9b7067a6e709054", "type": "github" }, "original": { @@ -524,16 +524,16 @@ "niri-stable": { "flake": false, "locked": { - "lastModified": 1748151941, - "narHash": "sha256-z4viQZLgC2bIJ3VrzQnR+q2F3gAOEQpU1H5xHtX/2fs=", + "lastModified": 1756556321, + "narHash": "sha256-RLD89dfjN0RVO86C/Mot0T7aduCygPGaYbog566F0Qo=", "owner": "YaLTeR", "repo": "niri", - "rev": "8ba57fcf25d2fc9565131684a839d58703f1dae7", + "rev": "01be0e65f4eb91a9cd624ac0b76aaeab765c7294", "type": "github" }, "original": { "owner": "YaLTeR", - "ref": "v25.05.1", + "ref": "v25.08", "repo": "niri", "type": "github" } @@ -541,15 +541,16 @@ "niri-unstable": { "flake": false, "locked": { - "lastModified": 1755419373, - "narHash": "sha256-EFH3zbpyLYjEboNV2Lmkxf9joEuFCmeYX+MMLRPStpg=", - "owner": "YaLTeR", + "lastModified": 1757438446, + "narHash": "sha256-4NN+weI4isQCFB+A36J+CU8tb251maVlBO9usuzgMQ8=", + "owner": "gkleen", "repo": "niri", - "rev": "a6febb86aa5af0df7bf2792ca027ef95a503d599", + "rev": "2c7f7053ce360279160a9e2366d54980def848ad", "type": "github" }, "original": { - "owner": "YaLTeR", + "owner": "gkleen", + "ref": "feat/unix-sockets", "repo": "niri", "type": "github" } @@ -780,11 +781,11 @@ }, "nixpkgs-stable_3": { "locked": { - "lastModified": 1755274400, - "narHash": "sha256-rTInmnp/xYrfcMZyFMH3kc8oko5zYfxsowaLv1LVobY=", + "lastModified": 1757408970, + "narHash": "sha256-aSgK4BLNFFGvDTNKPeB28lVXYqVn8RdyXDNAvgGq+k0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ad7196ae55c295f53a7d1ec39e4a06d922f3b899", + "rev": "d179d77c139e0a3f5c416477f7747e9d6b7ec315", "type": "github" }, "original": { @@ -1280,16 +1281,16 @@ "xwayland-satellite-stable": { "flake": false, "locked": { - "lastModified": 1748488455, - "narHash": "sha256-IiLr1alzKFIy5tGGpDlabQbe6LV1c9ABvkH6T5WmyRI=", + "lastModified": 1755491097, + "narHash": "sha256-m+9tUfsmBeF2Gn4HWa6vSITZ4Gz1eA1F5Kh62B0N4oE=", "owner": "Supreeeme", "repo": "xwayland-satellite", - "rev": "3ba30b149f9eb2bbf42cf4758d2158ca8cceef73", + "rev": "388d291e82ffbc73be18169d39470f340707edaa", "type": "github" }, "original": { "owner": "Supreeeme", - "ref": "v0.6", + "ref": "v0.7", "repo": "xwayland-satellite", "type": "github" } @@ -1297,11 +1298,11 @@ "xwayland-satellite-unstable": { "flake": false, "locked": { - "lastModified": 1755219541, - "narHash": "sha256-yKV6xHaPbEbh5RPxAJnb9yTs1wypr7do86hFFGQm1w8=", + "lastModified": 1757179758, + "narHash": "sha256-TIvyWzRt1miQj6Cf5Wy8Qz43XIZX7c4vTVwRLAT5S4Y=", "owner": "Supreeeme", "repo": "xwayland-satellite", - "rev": "5a184d435927c3423f0ad189ea2b490578450fb7", + "rev": "970728d0d9d1eada342bb8860af214b601139e58", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index b9382c6f..0b2ce0a8 100644 --- a/flake.nix +++ b/flake.nix @@ -209,7 +209,12 @@ ref = "main"; inputs = { nixpkgs.follows = "nixpkgs"; - # niri-unstable.url = "github:gkleen/niri"; + niri-unstable = { + type = "github"; + owner = "gkleen"; + repo = "niri"; + ref = "feat/unix-sockets"; + }; }; }; 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 @@ (final: prev: { niri-unstable = prev.niri-unstable.overrideAttrs (oldAttrs: { buildInputs = (oldAttrs.buildInputs or []) ++ [ final.libgbm ]; + doCheck = false; }); }) 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 @@ ./greetd-response.patch ./lock-state-changed.patch ./pipewire.patch + ./io.patch ]; }); } 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 @@ +diff --git i/src/io/socket.cpp w/src/io/socket.cpp +index 371f687..d12eaeb 100644 +--- i/src/io/socket.cpp ++++ w/src/io/socket.cpp +@@ -66,7 +66,7 @@ void Socket::onSocketDisconnected() { + } + + void Socket::onSocketError(QLocalSocket::LocalSocketError error) { +- qCWarning(logSocket) << "Socket error for" << this << error; ++ // qCWarning(logSocket) << "Socket error for" << this << error; + emit this->error(error); + } + -- cgit v1.2.3