Regenerated
This commit is contained in:
@@ -2964,6 +2964,7 @@ bind = , XF86Sleep, exec, systemctl suspend
|
||||
bind = , XF86PowerOff, exec, systemctl poweroff
|
||||
bind = , XF86WakeUp, exec, systemctl suspend
|
||||
bind = , XF86ScreenSaver, exec, loginctl lock-session
|
||||
bind = $mainMod, P, exec, qs -c powermgmt
|
||||
|
||||
#########################
|
||||
# Start apps
|
||||
@@ -3657,6 +3658,640 @@ ShellRoot {
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
** =generated/.config/quickshell/powermgmt/shell.qml=
|
||||
Provides powermanagement settings
|
||||
#+BEGIN_SRC qml :tangle generated/.config/quickshell/powermgmt/shell.qml :noweb yes :mkdirp yes :eval never
|
||||
// --- Power Management Panel for NixOS + Hyprland ---
|
||||
// Launch with: bind=$MAINMOD,p,exec,qs powermgmt
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
ShellRoot {
|
||||
// ── Catppuccin Mocha — full palette from colors.css ───────────────────
|
||||
QtObject {
|
||||
id: colors
|
||||
// Base layers
|
||||
readonly property color crust: "#11111b"
|
||||
readonly property color mantle: "#181825"
|
||||
readonly property color base: "#1e1e2e"
|
||||
// Surfaces
|
||||
readonly property color surface0: "#313244"
|
||||
readonly property color surface1: "#45475a"
|
||||
readonly property color surface2: "#585b70"
|
||||
// Overlays
|
||||
readonly property color overlay0: "#6c7086"
|
||||
readonly property color overlay1: "#7f849c"
|
||||
readonly property color overlay2: "#9399b2"
|
||||
// Text
|
||||
readonly property color subtext0: "#a6adc8"
|
||||
readonly property color subtext1: "#bac2de"
|
||||
readonly property color text: "#cdd6f4"
|
||||
// Accent colours
|
||||
readonly property color border: "#96cdd2"
|
||||
readonly property color rosewater: "#f5e0dc"
|
||||
readonly property color flamingo: "#f2cdcd"
|
||||
readonly property color pink: "#f5c2e7"
|
||||
readonly property color mauve: "#cba6f7"
|
||||
readonly property color red: "#f38ba8"
|
||||
readonly property color maroon: "#eba0ac"
|
||||
readonly property color peach: "#fab387"
|
||||
readonly property color yellow: "#f9e2af"
|
||||
readonly property color green: "#a6e3a1"
|
||||
readonly property color teal: "#94e2d5"
|
||||
readonly property color sapphire: "#74c7ec"
|
||||
readonly property color blue: "#89b4fa"
|
||||
readonly property color lavender: "#b4befe"
|
||||
// Convenience: semi-transparent base
|
||||
readonly property color baseAlpha: Qt.rgba(0.118, 0.118, 0.180, 0.8)
|
||||
}
|
||||
|
||||
// ── State ──────────────────────────────────────────────────────────────
|
||||
property string activeProfile: "balanced" // performance | balanced | powersave
|
||||
property bool lidClose: true
|
||||
property bool wifiPower: true
|
||||
property bool bluetoothOff: false
|
||||
property string statusMsg: ""
|
||||
property bool statusOk: true
|
||||
|
||||
// Hypridle timeouts — initialised from current hypridle.conf values:
|
||||
// lock @ 600s = 10 min
|
||||
// dpms @ 900s = 15 min
|
||||
// suspend @ 1200s = 20 min
|
||||
property int lockTimeout: 10 // minutes (0 = disabled)
|
||||
property int dpmsTimeout: 15 // minutes (0 = disabled)
|
||||
property int suspendTimeout: 20 // minutes (0 = disabled)
|
||||
|
||||
property int brightnessLevel: 80 // percent
|
||||
|
||||
// ── hypridle config writer ─────────────────────────────────────────────
|
||||
// Mirrors the structure of the original hypridle.conf exactly,
|
||||
// preserving: after_sleep_cmd, ignore_dbus_inhibit, on-resume for dpms.
|
||||
function buildHypridleConf() {
|
||||
var s =
|
||||
"# --- managed by quickshell powermgmt panel ---\n" +
|
||||
"general {\n" +
|
||||
" lock_cmd = hyprlock\n" +
|
||||
" before_sleep_cmd = hyprlock\n" +
|
||||
" after_sleep_cmd = hyprctl dispatch dpms on\n" +
|
||||
" ignore_dbus_inhibit = false\n" +
|
||||
"}\n"
|
||||
|
||||
if (lockTimeout > 0) {
|
||||
s +=
|
||||
"\nlistener {\n" +
|
||||
" timeout = " + (lockTimeout * 60) + "\n" +
|
||||
" on-timeout = hyprlock\n" +
|
||||
"}\n"
|
||||
}
|
||||
|
||||
if (dpmsTimeout > 0) {
|
||||
s +=
|
||||
"\nlistener {\n" +
|
||||
" timeout = " + (dpmsTimeout * 60) + "\n" +
|
||||
" on-timeout = hyprctl dispatch dpms off\n" +
|
||||
" on-resume = hyprctl dispatch dpms on\n" +
|
||||
"}\n"
|
||||
}
|
||||
|
||||
if (suspendTimeout > 0) {
|
||||
s +=
|
||||
"\nlistener {\n" +
|
||||
" timeout = " + (suspendTimeout * 60) + "\n" +
|
||||
" on-timeout = systemctl suspend\n" +
|
||||
"}\n"
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
function applyHypridle() {
|
||||
var conf = buildHypridleConf()
|
||||
// Use printf to avoid shell interpretation of special chars in the conf
|
||||
writeProc.command = ["bash", "-c",
|
||||
"printf '%s' " + JSON.stringify(conf) +
|
||||
" > ~/.config/hypr/hypridle.conf && pkill hypridle; hypridle &"]
|
||||
writeProc.running = true
|
||||
}
|
||||
|
||||
// ── Helpers ────────────────────────────────────────────────────────────
|
||||
function run(cmd) {
|
||||
runnerProc.command = cmd
|
||||
runnerProc.running = true
|
||||
}
|
||||
|
||||
function showStatus(msg, ok) {
|
||||
statusMsg = msg
|
||||
statusOk = ok
|
||||
statusTimer.restart()
|
||||
}
|
||||
|
||||
function applyProfile(p) {
|
||||
activeProfile = p
|
||||
if (p === "performance") run(["powerprofilesctl", "set", "performance"])
|
||||
else if (p === "balanced") run(["powerprofilesctl", "set", "balanced"])
|
||||
else run(["powerprofilesctl", "set", "power-saver"])
|
||||
showStatus("Profile → " + p, true)
|
||||
}
|
||||
|
||||
function applyBrightness(v) {
|
||||
brightnessLevel = v
|
||||
run(["brightnessctl", "set", v + "%"])
|
||||
}
|
||||
|
||||
function setLockTimeout(mins) {
|
||||
lockTimeout = mins
|
||||
applyHypridle()
|
||||
showStatus(mins === 0 ? "Auto-lock disabled" : "Lock after " + mins + " min", true)
|
||||
}
|
||||
|
||||
function setDpmsTimeout(mins) {
|
||||
dpmsTimeout = mins
|
||||
applyHypridle()
|
||||
showStatus(mins === 0 ? "Screen timeout disabled" : "Screen off after " + mins + " min", true)
|
||||
}
|
||||
|
||||
function setSuspendTimeout(mins) {
|
||||
suspendTimeout = mins
|
||||
applyHypridle()
|
||||
showStatus(mins === 0 ? "Auto-suspend disabled" : "Suspend after " + mins + " min", true)
|
||||
}
|
||||
|
||||
function toggleWifiPower(v) {
|
||||
wifiPower = v
|
||||
// Replace wlan0 with your actual interface if different (check: ip link)
|
||||
run(v ? ["iw", "dev", "wlan0", "set", "power_save", "on"]
|
||||
: ["iw", "dev", "wlan0", "set", "power_save", "off"])
|
||||
showStatus("WiFi power save " + (v ? "on" : "off"), true)
|
||||
}
|
||||
|
||||
function toggleBluetooth(v) {
|
||||
bluetoothOff = v
|
||||
run(v ? ["rfkill", "block", "bluetooth"]
|
||||
: ["rfkill", "unblock", "bluetooth"])
|
||||
showStatus("Bluetooth " + (v ? "disabled" : "enabled"), true)
|
||||
}
|
||||
|
||||
function toggleLid(v) {
|
||||
lidClose = v
|
||||
run(["bash", "-c",
|
||||
"loginctl set-handle-lid-switch " + (v ? "suspend" : "ignore")])
|
||||
showStatus("Lid close → " + (v ? "suspend" : "ignore"), true)
|
||||
}
|
||||
|
||||
// ── Processes ──────────────────────────────────────────────────────────
|
||||
Process {
|
||||
id: runnerProc
|
||||
onExited: (code) => {
|
||||
if (code !== 0)
|
||||
showStatus("Command failed (exit " + code + ")", false)
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: writeProc
|
||||
onExited: (code) => {
|
||||
if (code !== 0)
|
||||
showStatus("hypridle reload failed (exit " + code + ")", false)
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: statusTimer
|
||||
interval: 3000
|
||||
onTriggered: statusMsg = ""
|
||||
}
|
||||
|
||||
// ── Window ─────────────────────────────────────────────────────────────
|
||||
FloatingWindow {
|
||||
title: "quickshell-powermgmt"
|
||||
visible: true
|
||||
width: 540
|
||||
height: mainCol.implicitHeight + 40
|
||||
color: "transparent"
|
||||
|
||||
Shortcut { sequence: "Escape"; onActivated: Qt.quit() }
|
||||
|
||||
// Gradient border — uses border colour from colors.css as midpoint
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: -2
|
||||
radius: 20
|
||||
z: -1
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
GradientStop { position: 0.0; color: colors.mauve }
|
||||
GradientStop { position: 0.5; color: colors.border }
|
||||
GradientStop { position: 1.0; color: colors.blue }
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: 18
|
||||
color: colors.base
|
||||
|
||||
ColumnLayout {
|
||||
id: mainCol
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
margins: 20
|
||||
}
|
||||
spacing: 14
|
||||
|
||||
// ── Header ─────────────────────────────────────────────
|
||||
RowLayout {
|
||||
Layout.topMargin: 4
|
||||
spacing: 10
|
||||
|
||||
Text { text: "⚡"; font.pixelSize: 18 }
|
||||
|
||||
Text {
|
||||
text: "Power Management"
|
||||
color: colors.text
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
}
|
||||
Item { Layout.fillWidth: true }
|
||||
Text {
|
||||
text: "✕"
|
||||
color: colors.surface2
|
||||
font.pixelSize: 14
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: Qt.quit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Power Profile ───────────────────────────────────────
|
||||
SectionLabel { label: "Power Profile" }
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 8
|
||||
|
||||
ProfileButton {
|
||||
label: "Performance"
|
||||
icon: "🚀"
|
||||
accent: colors.peach
|
||||
active: activeProfile === "performance"
|
||||
onClicked: applyProfile("performance")
|
||||
}
|
||||
ProfileButton {
|
||||
label: "Balanced"
|
||||
icon: "⚖"
|
||||
accent: colors.blue
|
||||
active: activeProfile === "balanced"
|
||||
onClicked: applyProfile("balanced")
|
||||
}
|
||||
ProfileButton {
|
||||
label: "Power Save"
|
||||
icon: "🌿"
|
||||
accent: colors.green
|
||||
active: activeProfile === "powersave"
|
||||
onClicked: applyProfile("powersave")
|
||||
}
|
||||
}
|
||||
|
||||
// ── Brightness ──────────────────────────────────────────
|
||||
SectionLabel { label: "Screen Brightness" }
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 10
|
||||
|
||||
Text { text: "🔅"; font.pixelSize: 13 }
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
height: 6
|
||||
radius: 3
|
||||
color: colors.surface0
|
||||
|
||||
Rectangle {
|
||||
width: parent.width * (brightnessLevel / 100)
|
||||
height: parent.height
|
||||
radius: parent.radius
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
GradientStop { position: 0.0; color: colors.yellow }
|
||||
GradientStop { position: 1.0; color: colors.peach }
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: (mouse) => {
|
||||
var v = Math.round((mouse.x / width) * 100)
|
||||
applyBrightness(Math.max(5, Math.min(100, v)))
|
||||
}
|
||||
onPositionChanged: (mouse) => {
|
||||
if (pressed) {
|
||||
var v = Math.round((mouse.x / width) * 100)
|
||||
applyBrightness(Math.max(5, Math.min(100, v)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text { text: "🔆"; font.pixelSize: 13 }
|
||||
|
||||
Text {
|
||||
text: brightnessLevel + "%"
|
||||
color: colors.subtext0
|
||||
font.pixelSize: 12
|
||||
width: 32
|
||||
}
|
||||
}
|
||||
|
||||
// ── Hypridle Timeouts ───────────────────────────────────
|
||||
// These three rows map 1-to-1 to the three listeners in
|
||||
// hypridle.conf and rewrite + reload the daemon on change.
|
||||
SectionLabel { label: "Idle Timeouts (hypridle)" }
|
||||
|
||||
TimeoutRow {
|
||||
label: "Auto-lock"
|
||||
icon: "🔒"
|
||||
accent: colors.lavender
|
||||
value: lockTimeout
|
||||
options: [5, 10, 15, 30, 0]
|
||||
onPicked: (v) => setLockTimeout(v)
|
||||
}
|
||||
TimeoutRow {
|
||||
label: "Screen off"
|
||||
icon: "🖥"
|
||||
accent: colors.sapphire
|
||||
value: dpmsTimeout
|
||||
options: [5, 10, 15, 30, 0]
|
||||
onPicked: (v) => setDpmsTimeout(v)
|
||||
}
|
||||
TimeoutRow {
|
||||
label: "Suspend"
|
||||
icon: "💤"
|
||||
accent: colors.mauve
|
||||
value: suspendTimeout
|
||||
options: [15, 20, 30, 60, 0]
|
||||
onPicked: (v) => setSuspendTimeout(v)
|
||||
}
|
||||
|
||||
// ── Toggles ─────────────────────────────────────────────
|
||||
SectionLabel { label: "Settings" }
|
||||
|
||||
ToggleRow {
|
||||
label: "Suspend on lid close"
|
||||
icon: "💻"
|
||||
checked: lidClose
|
||||
onToggled: (v) => toggleLid(v)
|
||||
}
|
||||
ToggleRow {
|
||||
label: "WiFi power saving"
|
||||
icon: "📶"
|
||||
checked: wifiPower
|
||||
onToggled: (v) => toggleWifiPower(v)
|
||||
}
|
||||
ToggleRow {
|
||||
label: "Bluetooth off"
|
||||
icon: "🔵"
|
||||
checked: bluetoothOff
|
||||
onToggled: (v) => toggleBluetooth(v)
|
||||
}
|
||||
|
||||
// ── Status bar ──────────────────────────────────────────
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
height: visible ? 32 : 0
|
||||
visible: statusMsg !== ""
|
||||
radius: 8
|
||||
color: statusOk
|
||||
? Qt.rgba(colors.green.r, colors.green.g, colors.green.b, 0.12)
|
||||
: Qt.rgba(colors.red.r, colors.red.g, colors.red.b, 0.12)
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: statusMsg
|
||||
color: statusOk ? colors.green : colors.red
|
||||
font.pixelSize: 12
|
||||
}
|
||||
}
|
||||
|
||||
// ── Actions ─────────────────────────────────────────────
|
||||
SectionLabel { label: "Actions" }
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: 8
|
||||
spacing: 8
|
||||
|
||||
ActionButton { label: "Lock"; icon: "🔒"; accent: colors.blue; onClicked: run(["hyprlock"]) }
|
||||
ActionButton { label: "Suspend"; icon: "💤"; accent: colors.mauve; onClicked: run(["systemctl", "suspend"]) }
|
||||
ActionButton { label: "Hibernate"; icon: "🌙"; accent: colors.sapphire; onClicked: run(["systemctl", "hibernate"]) }
|
||||
ActionButton { label: "Reboot"; icon: "🔄"; accent: colors.peach; onClicked: run(["systemctl", "reboot"]) }
|
||||
ActionButton { label: "Shutdown"; icon: "⏻"; accent: colors.red; onClicked: run(["systemctl", "poweroff"]) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Inline components ──────────────────────────────────────────────────
|
||||
|
||||
component SectionLabel: Text {
|
||||
required property string label
|
||||
text: label.toUpperCase()
|
||||
color: colors.overlay0
|
||||
font.pixelSize: 10
|
||||
font.bold: true
|
||||
letterSpacing: 1.2
|
||||
}
|
||||
|
||||
component ProfileButton: Rectangle {
|
||||
required property string label
|
||||
required property string icon
|
||||
required property color accent
|
||||
required property bool active
|
||||
signal clicked
|
||||
|
||||
Layout.fillWidth: true
|
||||
height: 56
|
||||
radius: 10
|
||||
color: active ? Qt.rgba(accent.r, accent.g, accent.b, 0.15) : colors.surface0
|
||||
border.color: active ? accent : "transparent"
|
||||
border.width: 1
|
||||
|
||||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
spacing: 2
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: icon
|
||||
font.pixelSize: 18
|
||||
}
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: label
|
||||
color: active ? accent : colors.subtext0
|
||||
font.pixelSize: 11
|
||||
font.bold: active
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: parent.clicked()
|
||||
}
|
||||
}
|
||||
|
||||
component TimeoutRow: RowLayout {
|
||||
required property string label
|
||||
required property string icon
|
||||
required property color accent
|
||||
required property int value
|
||||
required property var options
|
||||
signal picked(int v)
|
||||
|
||||
Layout.fillWidth: true
|
||||
spacing: 8
|
||||
|
||||
Text { text: icon; font.pixelSize: 14 }
|
||||
|
||||
Text {
|
||||
text: label
|
||||
color: colors.subtext1
|
||||
font.pixelSize: 12
|
||||
Layout.preferredWidth: 100
|
||||
}
|
||||
|
||||
Item { Layout.fillWidth: true }
|
||||
|
||||
Repeater {
|
||||
model: options
|
||||
delegate: Rectangle {
|
||||
readonly property int mins: modelData
|
||||
readonly property bool sel: value === mins
|
||||
|
||||
width: mins === 0 ? 40 : 36
|
||||
height: 24
|
||||
radius: 6
|
||||
color: sel ? Qt.rgba(accent.r, accent.g, accent.b, 0.2) : colors.surface0
|
||||
border.color: sel ? accent : "transparent"
|
||||
border.width: 1
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: mins === 0 ? "off" : mins + "m"
|
||||
color: sel ? accent : colors.subtext0
|
||||
font.pixelSize: 10
|
||||
font.bold: sel
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: picked(mins)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component ToggleRow: RowLayout {
|
||||
required property string label
|
||||
required property string icon
|
||||
required property bool checked
|
||||
signal toggled(bool v)
|
||||
|
||||
Layout.fillWidth: true
|
||||
spacing: 8
|
||||
|
||||
Text { text: icon; font.pixelSize: 14 }
|
||||
|
||||
Text {
|
||||
text: label
|
||||
color: colors.subtext1
|
||||
font.pixelSize: 12
|
||||
}
|
||||
|
||||
Item { Layout.fillWidth: true }
|
||||
|
||||
Rectangle {
|
||||
width: 42
|
||||
height: 22
|
||||
radius: 11
|
||||
color: checked ? Qt.rgba(colors.green.r, colors.green.g, colors.green.b, 0.3) : colors.surface1
|
||||
border.color: checked ? colors.green : colors.surface2
|
||||
border.width: 1
|
||||
|
||||
Behavior on color { ColorAnimation { duration: 150 } }
|
||||
|
||||
Rectangle {
|
||||
x: checked ? parent.width - width - 3 : 3
|
||||
y: 3
|
||||
width: 16; height: 16; radius: 8
|
||||
color: checked ? colors.green : colors.surface2
|
||||
|
||||
Behavior on x { NumberAnimation { duration: 150; easing.type: Easing.OutCubic } }
|
||||
Behavior on color { ColorAnimation { duration: 150 } }
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: toggled(!checked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component ActionButton: Rectangle {
|
||||
required property string label
|
||||
required property string icon
|
||||
required property color accent
|
||||
signal clicked
|
||||
|
||||
Layout.fillWidth: true
|
||||
height: 52
|
||||
radius: 10
|
||||
color: colors.surface0
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
spacing: 2
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: icon
|
||||
font.pixelSize: 16
|
||||
}
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: label
|
||||
color: colors.subtext0
|
||||
font.pixelSize: 10
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: hoverBorder
|
||||
anchors.fill: parent
|
||||
radius: parent.radius
|
||||
color: "transparent"
|
||||
border.color: accent
|
||||
border.width: 0
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
onEntered: hoverBorder.border.width = 1
|
||||
onExited: hoverBorder.border.width = 0
|
||||
onClicked: parent.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
** =generated/.config/quickshell/powermenu/shell.qml=
|
||||
Provides a powermenu
|
||||
#+BEGIN_SRC qml :tangle generated/.config/quickshell/powermenu/shell.qml :noweb yes :mkdirp yes :eval never
|
||||
|
||||
Reference in New Issue
Block a user