diff options
Diffstat (limited to 'accounts')
16 files changed, 469 insertions, 90 deletions
diff --git a/accounts/gkleen@sif/niri/default.nix b/accounts/gkleen@sif/niri/default.nix index 1ff149bc..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,15 +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 | |||
| 951 | "Mod+Semicolon".action = spawn makoctl "dismiss" "--group"; | 940 | "Mod+Semicolon".action = spawn makoctl "dismiss" "--group"; |
| 952 | "Mod+Shift+Semicolon".action = spawn makoctl "dismiss" "--all"; | 941 | "Mod+Shift+Semicolon".action = spawn makoctl "dismiss" "--all"; |
| 953 | "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"; |
| @@ -988,6 +977,14 @@ in { | |||
| 988 | allow-when-locked = true; | 977 | allow-when-locked = true; |
| 989 | action = shell { Volume."mic-muted" = "toggle"; }; | 978 | action = shell { Volume."mic-muted" = "toggle"; }; |
| 990 | }; | 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 | }; | ||
| 991 | })) | 988 | })) |
| 992 | (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) |
| 993 | (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) |
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..399b566f 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,49 @@ 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 | } | ||
| 69 | |||
| 70 | Item { | ||
| 71 | enabled: privacy.active | ||
| 72 | height: parent.height | ||
| 73 | width: 8 | ||
| 74 | } | ||
| 75 | |||
| 76 | BatteryWidget {} | ||
| 77 | |||
| 78 | Item { | ||
| 79 | height: parent.height | ||
| 80 | width: 8 | ||
| 81 | } | ||
| 82 | |||
| 83 | BrightnessWidget {} | ||
| 68 | 84 | ||
| 69 | Item { | 85 | Item { |
| 70 | height: parent.height | 86 | height: parent.height |
| 71 | width: 4 | 87 | width: 4 |
| 72 | } | 88 | } |
| 73 | 89 | ||
| 90 | PipewireWidget {} | ||
| 91 | |||
| 92 | Item { | ||
| 93 | height: parent.height | ||
| 94 | width: 2 | ||
| 95 | } | ||
| 96 | |||
| 74 | SystemTray {} | 97 | SystemTray {} |
| 75 | 98 | ||
| 76 | Item { | 99 | Item { |
| 77 | height: parent.height | 100 | height: parent.height |
| 78 | width: 4 | 101 | width: 2 |
| 79 | } | 102 | } |
| 80 | 103 | ||
| 81 | KeyboardLayout {} | 104 | KeyboardLayout {} |
| 82 | 105 | ||
| 83 | Item { | 106 | Item { |
| 84 | height: parent.height | 107 | height: parent.height |
| 85 | width: 4 | 108 | width: 8 - 4 |
| 86 | } | 109 | } |
| 87 | 110 | ||
| 88 | Clock {} | 111 | 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..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 | } | ||
diff --git a/accounts/gkleen@sif/shell/quickshell/SystemTray.qml b/accounts/gkleen@sif/shell/quickshell/SystemTray.qml index 55b1690e..956f3995 100644 --- a/accounts/gkleen@sif/shell/quickshell/SystemTray.qml +++ b/accounts/gkleen@sif/shell/quickshell/SystemTray.qml | |||
| @@ -116,7 +116,7 @@ Item { | |||
| 116 | color: "black" | 116 | color: "black" |
| 117 | 117 | ||
| 118 | implicitWidth: Math.max(tooltipTitle.contentWidth, tooltipDescription.contentWidth) + 16 | 118 | implicitWidth: Math.max(tooltipTitle.contentWidth, tooltipDescription.contentWidth) + 16 |
| 119 | implicitHeight: tooltipTitle.contentHeight + tooltipDescription.contentHeight + 16 | 119 | implicitHeight: (trayItem.tooltipTitle ? tooltipTitle.contentHeight : 0) + (trayItem.tooltipDescription ? tooltipDescription.contentHeight : 0) + 16 |
| 120 | 120 | ||
| 121 | WrapperMouseArea { | 121 | WrapperMouseArea { |
| 122 | id: tooltipMouseArea | 122 | id: tooltipMouseArea |
| @@ -130,6 +130,8 @@ Item { | |||
| 130 | Text { | 130 | Text { |
| 131 | id: tooltipTitle | 131 | id: tooltipTitle |
| 132 | 132 | ||
| 133 | enabled: trayItem.tooltipTitle | ||
| 134 | |||
| 133 | font.pointSize: 10 | 135 | font.pointSize: 10 |
| 134 | font.family: "Fira Sans" | 136 | font.family: "Fira Sans" |
| 135 | font.bold: true | 137 | font.bold: true |
| @@ -141,6 +143,8 @@ Item { | |||
| 141 | Text { | 143 | Text { |
| 142 | id: tooltipDescription | 144 | id: tooltipDescription |
| 143 | 145 | ||
| 146 | enabled: trayItem.tooltipDescription | ||
| 147 | |||
| 144 | font.pointSize: 10 | 148 | font.pointSize: 10 |
| 145 | font.family: "Fira Sans" | 149 | font.family: "Fira Sans" |
| 146 | color: "white" | 150 | color: "white" |
diff --git a/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml b/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml index 7b308ec0..742ef4f5 100644 --- a/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml +++ b/accounts/gkleen@sif/shell/quickshell/UnixIPC.qml | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | import Quickshell | 1 | import Quickshell |
| 2 | import Quickshell.Io | 2 | import Quickshell.Io |
| 3 | import Quickshell.Services.Pipewire | 3 | import Quickshell.Services.Pipewire |
| 4 | import qs.Services | ||
| 4 | 5 | ||
| 5 | Scope { | 6 | Scope { |
| 6 | id: root | 7 | id: root |
| @@ -16,6 +17,8 @@ Scope { | |||
| 16 | 17 | ||
| 17 | if (command.Volume) | 18 | if (command.Volume) |
| 18 | root.onCommandVolume(command.Volume); | 19 | root.onCommandVolume(command.Volume); |
| 20 | else if (command.Brightness) | ||
| 21 | root.onCommandBrightness(command.Brightness); | ||
| 19 | else | 22 | else |
| 20 | console.warn("UnixIPC: Command not handled:", JSON.stringify(command)); | 23 | console.warn("UnixIPC: Command not handled:", JSON.stringify(command)); |
| 21 | } catch (e) { | 24 | } catch (e) { |
| @@ -46,4 +49,11 @@ Scope { | |||
| 46 | if (command["mic-muted"] === "toggle") | 49 | if (command["mic-muted"] === "toggle") |
| 47 | Pipewire.defaultAudioSource.audio.muted = !Pipewire.defaultAudioSource.audio.muted; | 50 | Pipewire.defaultAudioSource.audio.muted = !Pipewire.defaultAudioSource.audio.muted; |
| 48 | } | 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 | } | ||
| 49 | } | 59 | } |
diff --git a/accounts/gkleen@sif/shell/quickshell/shell.qml b/accounts/gkleen@sif/shell/quickshell/shell.qml index 3bb2ae00..0fa45f79 100644 --- a/accounts/gkleen@sif/shell/quickshell/shell.qml +++ b/accounts/gkleen@sif/shell/quickshell/shell.qml | |||
| @@ -43,6 +43,7 @@ ShellRoot { | |||
| 43 | Lockscreen {} | 43 | Lockscreen {} |
| 44 | 44 | ||
| 45 | VolumeOSD {} | 45 | VolumeOSD {} |
| 46 | BrightnessOSD {} | ||
| 46 | 47 | ||
| 47 | UnixIPC {} | 48 | UnixIPC {} |
| 48 | } | 49 | } |
