From bfe97c1c053fccaaef4d93df723bf02d1fc06871 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 8 Dec 2025 14:48:44 +0100 Subject: [PATCH] refractor lock screen --- .../panels}/lock/LockContext.qml | 0 .../modules/common/panels/lock/LockScreen.qml | 157 ++++++++++++++++ .../panels}/lock/pam/fprintd.conf | 0 .../quickshell/ii/modules/ii/lock/Lock.qml | 172 ++---------------- .../ii/modules/ii/lock/LockSurface.qml | 1 + dots/.config/quickshell/ii/shell.qml | 2 +- 6 files changed, 177 insertions(+), 155 deletions(-) rename dots/.config/quickshell/ii/modules/{ii => common/panels}/lock/LockContext.qml (100%) create mode 100644 dots/.config/quickshell/ii/modules/common/panels/lock/LockScreen.qml rename dots/.config/quickshell/ii/modules/{ii => common/panels}/lock/pam/fprintd.conf (100%) diff --git a/dots/.config/quickshell/ii/modules/ii/lock/LockContext.qml b/dots/.config/quickshell/ii/modules/common/panels/lock/LockContext.qml similarity index 100% rename from dots/.config/quickshell/ii/modules/ii/lock/LockContext.qml rename to dots/.config/quickshell/ii/modules/common/panels/lock/LockContext.qml diff --git a/dots/.config/quickshell/ii/modules/common/panels/lock/LockScreen.qml b/dots/.config/quickshell/ii/modules/common/panels/lock/LockScreen.qml new file mode 100644 index 000000000..9e4b9bd94 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/panels/lock/LockScreen.qml @@ -0,0 +1,157 @@ +pragma ComponentBehavior: Bound +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import QtQuick +import Quickshell +import Quickshell.Io +import Quickshell.Wayland +import Quickshell.Hyprland + +Scope { + id: root + + required property Component lockSurface + property alias context: lockContext + property Component sessionLockSurface: WlSessionLockSurface { + id: sessionLockSurface + color: "transparent" + Loader { + active: GlobalStates.screenLocked + anchors.fill: parent + opacity: active ? 1 : 0 + Behavior on opacity { + animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this) + } + sourceComponent: root.lockSurface + } + } + + Process { + id: unlockKeyringProc + onExited: (exitCode, exitStatus) => { + KeyringStorage.fetchKeyringData(); + } + } + function unlockKeyring() { + unlockKeyringProc.exec({ + environment: ({ + "UNLOCK_PASSWORD": lockContext.currentText + }), + command: ["bash", "-c", Quickshell.shellPath("scripts/keyring/unlock.sh")] + }) + } + + // This stores all the information shared between the lock surfaces on each screen. + // https://github.com/quickshell-mirror/quickshell-examples/tree/master/lockscreen + LockContext { + id: lockContext + + Connections { + target: GlobalStates + function onScreenLockedChanged() { + if (GlobalStates.screenLocked) { + lockContext.reset(); + lockContext.tryFingerUnlock(); + } + } + } + + onUnlocked: (targetAction) => { + // Perform the target action if it's not just unlocking + if (targetAction == LockContext.ActionEnum.Poweroff) { + Session.poweroff(); + return; + } else if (targetAction == LockContext.ActionEnum.Reboot) { + Session.reboot(); + return; + } + + // Unlock the keyring if configured to do so + if (Config.options.lock.security.unlockKeyring) root.unlockKeyring(); // Async + + // Unlock the screen before exiting, or the compositor will display a + // fallback lock you can't interact with. + GlobalStates.screenLocked = false; + + // Refocus last focused window on unlock (hack) + Quickshell.execDetached(["bash", "-c", `sleep 0.2; hyprctl --batch "dispatch togglespecialworkspace; dispatch togglespecialworkspace"`]) + + // Reset + lockContext.reset(); + + // Post-unlock actions + if (lockContext.alsoInhibitIdle) { + lockContext.alsoInhibitIdle = false; + Idle.toggleInhibit(true); + } + } + } + + WlSessionLock { + id: lock + locked: GlobalStates.screenLocked + + surface: root.sessionLockSurface + } + + function lock() { + if (Config.options.lock.useHyprlock) { + Quickshell.execDetached(["bash", "-c", "pidof hyprlock || hyprlock"]); + return; + } + GlobalStates.screenLocked = true; + } + + IpcHandler { + target: "lock" + + function activate(): void { + root.lock(); + } + function focus(): void { + lockContext.shouldReFocus(); + } + } + + GlobalShortcut { + name: "lock" + description: "Locks the screen" + + onPressed: { + root.lock() + } + } + + GlobalShortcut { + name: "lockFocus" + description: "Re-focuses the lock screen. This is because Hyprland after waking up for whatever reason" + + "decides to keyboard-unfocus the lock screen" + + onPressed: { + lockContext.shouldReFocus(); + } + } + + function initIfReady() { + if (!Config.ready || !Persistent.ready) return; + if (Config.options.lock.launchOnStartup && Persistent.isNewHyprlandInstance) { + root.lock(); + } else { + KeyringStorage.fetchKeyringData(); + } + } + Connections { + target: Config + function onReadyChanged() { + root.initIfReady(); + } + } + Connections { + target: Persistent + function onReadyChanged() { + root.initIfReady(); + } + } +} diff --git a/dots/.config/quickshell/ii/modules/ii/lock/pam/fprintd.conf b/dots/.config/quickshell/ii/modules/common/panels/lock/pam/fprintd.conf similarity index 100% rename from dots/.config/quickshell/ii/modules/ii/lock/pam/fprintd.conf rename to dots/.config/quickshell/ii/modules/common/panels/lock/pam/fprintd.conf diff --git a/dots/.config/quickshell/ii/modules/ii/lock/Lock.qml b/dots/.config/quickshell/ii/modules/ii/lock/Lock.qml index 3d6506c54..3aae6ef7b 100644 --- a/dots/.config/quickshell/ii/modules/ii/lock/Lock.qml +++ b/dots/.config/quickshell/ii/modules/ii/lock/Lock.qml @@ -3,116 +3,39 @@ import qs import qs.services import qs.modules.common import qs.modules.common.functions +import qs.modules.common.panels.lock import QtQuick import Quickshell import Quickshell.Io import Quickshell.Wayland import Quickshell.Hyprland -Scope { +LockScreen { id: root - Process { - id: unlockKeyringProc - onExited: (exitCode, exitStatus) => { - KeyringStorage.fetchKeyringData(); - } - } - function unlockKeyring() { - unlockKeyringProc.exec({ - environment: ({ - "UNLOCK_PASSWORD": lockContext.currentText - }), - command: ["bash", "-c", Quickshell.shellPath("scripts/keyring/unlock.sh")] - }) + lockSurface: LockSurface { + context: root.context } + // Push everything down property var windowData: [] function saveWindowPositionAndTile() { - Quickshell.execDetached(["hyprctl", "keyword", "dwindle:pseudotile", "true"]) - root.windowData = HyprlandData.windowList.filter(w => (w.floating && w.workspace.id === HyprlandData.activeWorkspace.id)) + Quickshell.execDetached(["hyprctl", "keyword", "dwindle:pseudotile", "true"]); + root.windowData = HyprlandData.windowList.filter(w => (w.floating && w.workspace.id === HyprlandData.activeWorkspace.id)); root.windowData.forEach(w => { - Hyprland.dispatch(`pseudo address:${w.address}`) - Hyprland.dispatch(`settiled address:${w.address}`) - Hyprland.dispatch(`movetoworkspacesilent ${w.workspace.id},address:${w.address}`) - }) + Hyprland.dispatch(`pseudo address:${w.address}`); + Hyprland.dispatch(`settiled address:${w.address}`); + Hyprland.dispatch(`movetoworkspacesilent ${w.workspace.id},address:${w.address}`); + }); } function restoreWindowPositionAndTile() { root.windowData.forEach(w => { - Hyprland.dispatch(`setfloating address:${w.address}`) - Hyprland.dispatch(`movewindowpixel exact ${w.at[0]} ${w.at[1]}, address:${w.address}`) - Hyprland.dispatch(`pseudo address:${w.address}`) - }) - Quickshell.execDetached(["hyprctl", "keyword", "dwindle:pseudotile", "false"]) + Hyprland.dispatch(`setfloating address:${w.address}`); + Hyprland.dispatch(`movewindowpixel exact ${w.at[0]} ${w.at[1]}, address:${w.address}`); + Hyprland.dispatch(`pseudo address:${w.address}`); + }); + Quickshell.execDetached(["hyprctl", "keyword", "dwindle:pseudotile", "false"]); } - - // This stores all the information shared between the lock surfaces on each screen. - // https://github.com/quickshell-mirror/quickshell-examples/tree/master/lockscreen - LockContext { - id: lockContext - - Connections { - target: GlobalStates - function onScreenLockedChanged() { - if (GlobalStates.screenLocked) { - lockContext.reset(); - lockContext.tryFingerUnlock(); - } - } - } - - onUnlocked: (targetAction) => { - // Perform the target action if it's not just unlocking - if (targetAction == LockContext.ActionEnum.Poweroff) { - Session.poweroff(); - return; - } else if (targetAction == LockContext.ActionEnum.Reboot) { - Session.reboot(); - return; - } - - // Unlock the keyring if configured to do so - if (Config.options.lock.security.unlockKeyring) root.unlockKeyring(); // Async - - // Unlock the screen before exiting, or the compositor will display a - // fallback lock you can't interact with. - GlobalStates.screenLocked = false; - - // Refocus last focused window on unlock (hack) - Quickshell.execDetached(["bash", "-c", `sleep 0.2; hyprctl --batch "dispatch togglespecialworkspace; dispatch togglespecialworkspace"`]) - - // Reset - lockContext.reset(); - - // Post-unlock actions - if (lockContext.alsoInhibitIdle) { - lockContext.alsoInhibitIdle = false; - Idle.toggleInhibit(true); - } - } - } - - WlSessionLock { - id: lock - locked: GlobalStates.screenLocked - - WlSessionLockSurface { - color: "transparent" - Loader { - active: GlobalStates.screenLocked - anchors.fill: parent - opacity: active ? 1 : 0 - Behavior on opacity { - animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this) - } - sourceComponent: LockSurface { - context: lockContext - } - } - } - } - - // Blur layer hack Variants { model: Quickshell.screens delegate: Scope { @@ -124,71 +47,12 @@ Scope { onShouldPushChanged: { if (shouldPush) { root.saveWindowPositionAndTile(); - Quickshell.execDetached(["bash", "-c", `hyprctl keyword monitor ${targetMonitorName}, addreserved, ${verticalMovementDistance}, ${-verticalMovementDistance}, ${horizontalSqueeze}, ${horizontalSqueeze}`]) + Quickshell.execDetached(["bash", "-c", `hyprctl keyword monitor ${targetMonitorName}, addreserved, ${verticalMovementDistance}, ${-verticalMovementDistance}, ${horizontalSqueeze}, ${horizontalSqueeze}`]); } else { - Quickshell.execDetached(["bash", "-c", `hyprctl keyword monitor ${targetMonitorName}, addreserved, 0, 0, 0, 0`]) + Quickshell.execDetached(["bash", "-c", `hyprctl keyword monitor ${targetMonitorName}, addreserved, 0, 0, 0, 0`]); root.restoreWindowPositionAndTile(); } } } } - - function lock() { - if (Config.options.lock.useHyprlock) { - Quickshell.execDetached(["bash", "-c", "pidof hyprlock || hyprlock"]); - return; - } - GlobalStates.screenLocked = true; - } - - IpcHandler { - target: "lock" - - function activate(): void { - root.lock(); - } - function focus(): void { - lockContext.shouldReFocus(); - } - } - - GlobalShortcut { - name: "lock" - description: "Locks the screen" - - onPressed: { - root.lock() - } - } - - GlobalShortcut { - name: "lockFocus" - description: "Re-focuses the lock screen. This is because Hyprland after waking up for whatever reason" - + "decides to keyboard-unfocus the lock screen" - - onPressed: { - lockContext.shouldReFocus(); - } - } - - function initIfReady() { - if (!Config.ready || !Persistent.ready) return; - if (Config.options.lock.launchOnStartup && Persistent.isNewHyprlandInstance) { - root.lock(); - } else { - KeyringStorage.fetchKeyringData(); - } - } - Connections { - target: Config - function onReadyChanged() { - root.initIfReady(); - } - } - Connections { - target: Persistent - function onReadyChanged() { - root.initIfReady(); - } - } } diff --git a/dots/.config/quickshell/ii/modules/ii/lock/LockSurface.qml b/dots/.config/quickshell/ii/modules/ii/lock/LockSurface.qml index e44eecacb..b2482132d 100644 --- a/dots/.config/quickshell/ii/modules/ii/lock/LockSurface.qml +++ b/dots/.config/quickshell/ii/modules/ii/lock/LockSurface.qml @@ -7,6 +7,7 @@ import qs.services import qs.modules.common import qs.modules.common.widgets import qs.modules.common.functions +import qs.modules.common.panels.lock import qs.modules.ii.bar as Bar import Quickshell import Quickshell.Services.SystemTray diff --git a/dots/.config/quickshell/ii/shell.qml b/dots/.config/quickshell/ii/shell.qml index eebd15e22..6ed6480a6 100644 --- a/dots/.config/quickshell/ii/shell.qml +++ b/dots/.config/quickshell/ii/shell.qml @@ -100,7 +100,7 @@ ShellRoot { property list families: ["ii", "waffle"] property var panelFamilies: ({ "ii": ["iiBar", "iiBackground", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiScreenCorners", "iiSessionScreen", "iiSidebarLeft", "iiSidebarRight", "iiVerticalBar", "iiWallpaperSelector"], - "waffle": ["wActionCenter", "wBar", "wBackground", "wNotificationCenter", "wOnScreenDisplay", "wPolkit", "wStartMenu", "iiCheatsheet", "iiLock", "iiNotificationPopup", "iiOnScreenKeyboard", "iiOverlay", "iiRegionSelector", "wSessionScreen", "iiWallpaperSelector"], + "waffle": ["wActionCenter", "wBar", "wBackground", "wNotificationCenter", "wOnScreenDisplay", "wPolkit", "wSessionScreen", "wStartMenu", "iiCheatsheet", "iiLock", "iiNotificationPopup", "iiOnScreenKeyboard", "iiOverlay", "iiRegionSelector", "iiWallpaperSelector"], }) function cyclePanelFamily() { const currentIndex = families.indexOf(Config.options.panelFamily)