lock: add caps/num lock indicator

Closes #485
This commit is contained in:
2 * r + 2 * t 2025-08-28 15:13:40 +10:00
parent be4047201f
commit f2b79757e2
2 changed files with 193 additions and 105 deletions

View file

@ -213,6 +213,63 @@ ColumnLayout {
}
}
Item {
Layout.fillWidth: true
Layout.topMargin: -Appearance.spacing.large
implicitHeight: stateMessage.implicitHeight
StyledText {
id: stateMessage
readonly property string msg: {
if (Hypr.capsLock && Hypr.numLock)
return qsTr("Caps lock and Num lock are ON.");
if (Hypr.capsLock)
return qsTr("Caps lock is ON.");
if (Hypr.numLock)
return qsTr("Num lock is ON.");
return "";
}
property bool shouldBeVisible
onMsgChanged: {
if (msg) {
if (opacity > 0) {
animate = true;
text = msg;
animate = false;
} else {
text = msg;
}
shouldBeVisible = true;
} else {
shouldBeVisible = false;
}
}
anchors.left: parent.left
anchors.right: parent.right
scale: shouldBeVisible && !message.msg ? 1 : 0.7
opacity: shouldBeVisible && !message.msg ? 1 : 0
color: Colours.palette.m3onSurfaceVariant
animateProp: "opacity"
font.family: Appearance.font.family.mono
horizontalAlignment: Qt.AlignHCenter
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
Behavior on scale {
Anim {}
}
Behavior on opacity {
Anim {}
}
}
StyledText {
id: message
@ -247,8 +304,8 @@ ColumnLayout {
return "";
}
Layout.fillWidth: true
Layout.topMargin: -Appearance.spacing.large
anchors.left: parent.left
anchors.right: parent.right
scale: 0.7
opacity: 0
@ -334,6 +391,7 @@ ColumnLayout {
}
}
}
}
component FlashAnim: NumberAnimation {
target: message

View file

@ -1,5 +1,6 @@
pragma Singleton
import qs.components.misc
import Quickshell
import Quickshell.Hyprland
import Quickshell.Io
@ -15,11 +16,14 @@ Singleton {
readonly property HyprlandToplevel activeToplevel: Hyprland.activeToplevel?.wayland?.activated ? Hyprland.activeToplevel : null
readonly property HyprlandWorkspace focusedWorkspace: Hyprland.focusedWorkspace
readonly property HyprlandMonitor focusedMonitor: Hyprland.focusedMonitor
readonly property int activeWsId: focusedWorkspace?.id ?? 1
property var keyboard
readonly property bool capsLock: keyboard?.capsLock ?? false
readonly property bool numLock: keyboard?.numLock ?? false
readonly property string kbLayoutFull: keyboard?.active_keymap ?? "?"
readonly property string kbLayout: kbMap.get(kbLayoutFull) ?? "??"
property string kbLayoutFull: "?"
property var kbMap: new Map()
readonly property var kbMap: new Map()
function dispatch(request: string): void {
Hyprland.dispatch(request);
@ -37,8 +41,10 @@ Singleton {
if (n.endsWith("v2"))
return;
if (n === "activelayout") {
root.kbLayoutFull = event.parse(2)[1];
if (n === "configreloaded") {
setDynamicConfsProc.running = true;
} else if (n === "activelayout") {
devicesProc.running = true;
} else if (["workspace", "moveworkspace", "activespecial", "focusedmon"].includes(n)) {
Hyprland.refreshWorkspaces();
Hyprland.refreshMonitors();
@ -73,10 +79,34 @@ Singleton {
}
Process {
id: devicesProc
running: true
command: ["hyprctl", "-j", "devices"]
stdout: StdioCollector {
onStreamFinished: root.kbLayoutFull = JSON.parse(text).keyboards.find(k => k.main).active_keymap
onStreamFinished: root.keyboard = JSON.parse(text).keyboards.find(k => k.main)
}
}
Process {
id: setDynamicConfsProc
running: true
command: ["hyprctl", "--batch", "keyword bindln ,Caps_Lock,global,caelestia:reloadDevices;keyword bindln ,Num_Lock,global,caelestia:reloadDevices"]
}
IpcHandler {
target: "hypr"
function reloadDevices(): void {
devicesProc.running = true;
}
}
CustomShortcut {
name: "reloadDevices"
description: "Reload devices"
onPressed: devicesProc.running = true
onReleased: devicesProc.running = true
}
}