lock screen: redesign password prompt

This commit is contained in:
end-4
2025-08-26 17:59:37 +07:00
parent 8f2863c02c
commit 79e7f262a7
12 changed files with 215 additions and 91 deletions
@@ -315,25 +315,5 @@ Variants {
}
}
// Password prompt
StyledText {
anchors {
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
bottomMargin: 30
}
opacity: (GlobalStates.screenLocked && !GlobalStates.screenLockContainsCharacters) ? 1 : 0
scale: opacity
visible: opacity > 0
Behavior on opacity {
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
}
text: GlobalStates.screenUnlockFailed ? Translation.tr("Incorrect password") : Translation.tr("Enter password")
color: GlobalStates.screenUnlockFailed ? Appearance.colors.colError : bgRoot.colText
style: Text.Raised
styleColor: Appearance.colors.colShadow
font.pixelSize: Appearance.font.pixelSize.normal
}
}
}
@@ -146,15 +146,15 @@ Singleton {
property color colPrimaryHover: ColorUtils.mix(colors.colPrimary, colLayer1Hover, 0.87)
property color colPrimaryActive: ColorUtils.mix(colors.colPrimary, colLayer1Active, 0.7)
property color colPrimaryContainer: m3colors.m3primaryContainer
property color colPrimaryContainerHover: ColorUtils.mix(colors.colPrimaryContainer, colLayer1Hover, 0.7)
property color colPrimaryContainerActive: ColorUtils.mix(colors.colPrimaryContainer, colLayer1Active, 0.6)
property color colPrimaryContainerHover: ColorUtils.mix(colors.colPrimaryContainer, colors.colOnPrimaryContainer, 0.9)
property color colPrimaryContainerActive: ColorUtils.mix(colors.colPrimaryContainer, colors.colOnPrimaryContainer, 0.8)
property color colOnPrimaryContainer: m3colors.m3onPrimaryContainer
property color colSecondary: m3colors.m3secondary
property color colSecondaryHover: ColorUtils.mix(m3colors.m3secondary, colLayer1Hover, 0.85)
property color colSecondaryActive: ColorUtils.mix(m3colors.m3secondary, colLayer1Active, 0.4)
property color colSecondaryContainer: m3colors.m3secondaryContainer
property color colSecondaryContainerHover: ColorUtils.mix(m3colors.m3secondaryContainer, m3colors.m3onSecondaryContainer, 0.90)
property color colSecondaryContainerActive: ColorUtils.mix(m3colors.m3secondaryContainer, colLayer1Active, 0.54)
property color colSecondaryContainerActive: ColorUtils.mix(m3colors.m3secondaryContainer, m3colors.m3onSecondaryContainer, 0.54)
property color colTertiary: m3colors.m3tertiary
property color colTertiaryHover: ColorUtils.mix(m3colors.m3tertiary, colLayer1Hover, 0.85)
property color colTertiaryActive: ColorUtils.mix(m3colors.m3tertiary, colLayer1Active, 0.4)
@@ -0,0 +1,50 @@
pragma Singleton
import Quickshell
import qs.services
import qs.modules.common
Singleton {
id: root
function closeAllWindows() {
HyprlandData.windowList.map(w => w.pid).forEach(pid => {
Quickshell.execDetached(["kill", pid]);
});
}
function lock() {
Quickshell.execDetached(["loginctl", "lock-session"]);
}
function suspend() {
Quickshell.execDetached(["bash", "-c", "systemctl suspend || loginctl suspend"]);
}
function logout() {
closeAllWindows();
Quickshell.execDetached(["pkill", "Hyprland"]);
}
function launchTaskManager() {
Quickshell.execDetached(["bash", "-c", `${Config.options.apps.taskManager}`]);
}
function hibernate() {
Quickshell.execDetached(["bash", "-c", `systemctl hibernate || loginctl hibernate`]);
}
function poweroff() {
closeAllWindows();
Quickshell.execDetached(["bash", "-c", `systemctl poweroff || loginctl poweroff`]);
}
function reboot() {
closeAllWindows();
Quickshell.execDetached(["bash", "-c", `reboot || loginctl reboot`]);
}
function rebootToFirmware() {
closeAllWindows();
Quickshell.execDetached(["bash", "-c", `systemctl reboot --firmware-setup || loginctl reboot --firmware-setup`]);
}
}
@@ -30,11 +30,11 @@ Button {
property color colRippleToggled: Appearance?.colors.colPrimaryActive ?? "#D6CEE2"
opacity: root.enabled ? 1 : 0.4
property color buttonColor: root.enabled ? (root.toggled ?
property color buttonColor: ColorUtils.transparentize(root.toggled ?
(root.hovered ? colBackgroundToggledHover :
colBackgroundToggled) :
(root.hovered ? colBackgroundHover :
colBackground)) : colBackground
colBackground), root.enabled ? 0 : 1)
property color rippleColor: root.toggled ? colRippleToggled : colRipple
function startRipple(x, y) {
@@ -0,0 +1,39 @@
import QtQuick
import QtQuick.Layouts
import qs.modules.common
import qs.modules.common.widgets
/**
* Material 3 expressive style toolbar.
* https://m3.material.io/components/toolbars
*/
Item {
id: root
property real padding: 6
property alias colBackground: background.color
default property alias data: toolbarLayout.data
implicitWidth: background.implicitWidth
implicitHeight: background.implicitHeight
StyledRectangularShadow {
target: background
}
Rectangle {
id: background
anchors.centerIn: parent
color: Appearance.colors.colLayer2
implicitHeight: toolbarLayout.implicitHeight + root.padding * 2
implicitWidth: toolbarLayout.implicitWidth + root.padding * 2
radius: Appearance.rounding.full
RowLayout {
id: toolbarLayout
anchors {
fill: parent
margins: root.padding
}
}
}
}
@@ -0,0 +1,10 @@
import QtQuick
import QtQuick.Layouts
import qs.modules.common
RippleButton {
Layout.fillHeight: true
Layout.topMargin: 2
Layout.bottomMargin: 2
buttonRadius: Appearance.rounding.full
}
@@ -0,0 +1,30 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import qs.modules.common
import qs.modules.common.widgets
TextField {
id: filterField
property alias colBackground: background.color
Layout.fillHeight: true
Layout.topMargin: 2
Layout.bottomMargin: 2
implicitWidth: 200
padding: 10
placeholderTextColor: Appearance.colors.colSubtext
color: Appearance.colors.colOnLayer1
font.pixelSize: Appearance.font.pixelSize.small
renderType: Text.NativeRendering
selectedTextColor: Appearance.colors.colOnSecondaryContainer
selectionColor: Appearance.colors.colSecondaryContainer
background: Rectangle {
id: background
color: Appearance.colors.colLayer1
radius: Appearance.rounding.full
}
}
@@ -0,0 +1,10 @@
import QtQuick
import QtQuick.Layouts
import qs.modules.common
import qs.modules.common.functions
ToolbarButton {
colBackground: ColorUtils.transparentize(Appearance.colors.colPrimaryContainer)
colBackgroundHover: Appearance.colors.colPrimaryContainerHover
colRipple: Appearance.colors.colPrimaryContainerActive
}
@@ -1,6 +1,7 @@
import QtQuick
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
@@ -27,23 +28,20 @@ MouseArea {
}
}
Keys.onPressed: (event) => { // Esc to clear
// console.log("KEY!!")
Keys.onPressed: event => { // Esc to clear
if (event.key === Qt.Key_Escape) {
root.context.currentText = ""
root.context.currentText = "";
}
forceFieldFocus();
}
hoverEnabled: true
acceptedButtons: Qt.LeftButton
onPressed: (mouse) => {
onPressed: mouse => {
forceFieldFocus();
// console.log("Pressed")
}
onPositionChanged: (mouse) => {
onPositionChanged: mouse => {
forceFieldFocus();
// console.log(JSON.stringify(mouse))
}
anchors.fill: parent
@@ -63,38 +61,57 @@ MouseArea {
// }
// }
// Password entry
Rectangle {
id: passwordBoxContainer
// Controls
Toolbar {
anchors {
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
bottomMargin: root.showInputField ? 20 : -height
bottomMargin: 20
}
Behavior on anchors.bottomMargin {
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
}
radius: Appearance.rounding.full
color: Appearance.m3colors.m3surfaceContainer
implicitWidth: 160
implicitHeight: 44
StyledTextInput {
scale: 0.9
opacity: 0
Component.onCompleted: {
scale = 1
opacity = 1
}
Behavior on scale {
NumberAnimation {
duration: Appearance.animation.elementMove.duration
easing.type: Appearance.animation.elementMove.type
easing.bezierCurve: Appearance.animationCurves.expressiveFastSpatial
}
}
Behavior on opacity {
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
}
ToolbarButton {
id: sleepButton
implicitWidth: height
onClicked: Session.suspend()
contentItem: MaterialSymbol {
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
iconSize: 24
text: "dark_mode"
color: Appearance.colors.colOnPrimaryContainer
}
}
ToolbarTextField {
id: passwordBox
placeholderText: GlobalStates.screenUnlockFailed ? Translation.tr("Incorrect password") : Translation.tr("Enter password")
anchors {
fill: parent
margins: 10
}
// Style
clip: true
horizontalAlignment: TextInput.AlignHCenter
verticalAlignment: TextInput.AlignVCenter
focus: true
onFocusChanged: root.forceFieldFocus();
color: Appearance.colors.colOnLayer2
font {
pixelSize: 10
}
font.pixelSize: Appearance.font.pixelSize.small
// Password
enabled: !root.context.unlockInProgress
@@ -111,30 +128,24 @@ MouseArea {
}
}
}
}
RippleButton {
anchors {
verticalCenter: passwordBoxContainer.verticalCenter
left: passwordBoxContainer.right
leftMargin: 5
}
ToolbarButton {
id: confirmButton
implicitWidth: height
toggled: true
enabled: !root.context.unlockInProgress && root.context.currentText.length > 0
colBackgroundToggled: Appearance.colors.colPrimary
visible: opacity > 0
implicitHeight: passwordBoxContainer.implicitHeight - 12
implicitWidth: implicitHeight
toggled: true
buttonRadius: passwordBoxContainer.radius
colBackground: Appearance.colors.colLayer2
onClicked: root.context.tryUnlock()
onClicked: root.context.tryUnlock()
contentItem: MaterialSymbol {
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
iconSize: 24
text: "arrow_right_alt"
color: Appearance.colors.colOnPrimary
contentItem: MaterialSymbol {
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
iconSize: 24
text: "arrow_right_alt"
color: confirmButton.enabled ? Appearance.colors.colOnPrimary : Appearance.colors.colSubtext
}
}
}
}
@@ -39,12 +39,6 @@ Scope {
}
}
function closeAllWindows() {
HyprlandData.windowList.map(w => w.pid).forEach((pid) => {
Quickshell.execDetached(["kill", pid]);
});
}
function detectRunningStuff() {
packageManagerRunning = false;
downloadRunning = false;
@@ -160,7 +154,7 @@ Scope {
focus: sessionRoot.visible
buttonIcon: "lock"
buttonText: Translation.tr("Lock")
onClicked: { Quickshell.execDetached(["loginctl", "lock-session"]); sessionRoot.hide() }
onClicked: { Session.lock(); sessionRoot.hide() }
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
KeyNavigation.right: sessionSleep
KeyNavigation.down: sessionHibernate
@@ -169,7 +163,7 @@ Scope {
id: sessionSleep
buttonIcon: "dark_mode"
buttonText: Translation.tr("Sleep")
onClicked: { Quickshell.execDetached(["bash", "-c", "systemctl suspend || loginctl suspend"]); sessionRoot.hide() }
onClicked: { Session.suspend(); sessionRoot.hide() }
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
KeyNavigation.left: sessionLock
KeyNavigation.right: sessionLogout
@@ -179,7 +173,7 @@ Scope {
id: sessionLogout
buttonIcon: "logout"
buttonText: Translation.tr("Logout")
onClicked: { root.closeAllWindows(); Quickshell.execDetached(["pkill", "Hyprland"]); sessionRoot.hide() }
onClicked: { Session.logout(); sessionRoot.hide() }
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
KeyNavigation.left: sessionSleep
KeyNavigation.right: sessionTaskManager
@@ -189,7 +183,7 @@ Scope {
id: sessionTaskManager
buttonIcon: "browse_activity"
buttonText: Translation.tr("Task Manager")
onClicked: { Quickshell.execDetached(["bash", "-c", `${Config.options.apps.taskManager}`]); sessionRoot.hide() }
onClicked: { Session.launchTaskManager(); sessionRoot.hide() }
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
KeyNavigation.left: sessionLogout
KeyNavigation.down: sessionFirmwareReboot
@@ -199,7 +193,7 @@ Scope {
id: sessionHibernate
buttonIcon: "downloading"
buttonText: Translation.tr("Hibernate")
onClicked: { Quickshell.execDetached(["bash", "-c", `systemctl hibernate || loginctl hibernate`]); sessionRoot.hide() }
onClicked: { Session.hibernate(); sessionRoot.hide() }
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
KeyNavigation.up: sessionLock
KeyNavigation.right: sessionShutdown
@@ -208,7 +202,7 @@ Scope {
id: sessionShutdown
buttonIcon: "power_settings_new"
buttonText: Translation.tr("Shutdown")
onClicked: { root.closeAllWindows(); Quickshell.execDetached(["bash", "-c", `systemctl poweroff || loginctl poweroff`]); sessionRoot.hide() }
onClicked: { Session.poweroff(); sessionRoot.hide() }
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
KeyNavigation.left: sessionHibernate
KeyNavigation.right: sessionReboot
@@ -218,7 +212,7 @@ Scope {
id: sessionReboot
buttonIcon: "restart_alt"
buttonText: Translation.tr("Reboot")
onClicked: { root.closeAllWindows(); Quickshell.execDetached(["bash", "-c", `reboot || loginctl reboot`]); sessionRoot.hide() }
onClicked: { Session.reboot(); sessionRoot.hide() }
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
KeyNavigation.left: sessionShutdown
KeyNavigation.right: sessionFirmwareReboot
@@ -228,7 +222,7 @@ Scope {
id: sessionFirmwareReboot
buttonIcon: "settings_applications"
buttonText: Translation.tr("Reboot to firmware settings")
onClicked: { root.closeAllWindows(); Quickshell.execDetached(["bash", "-c", `systemctl reboot --firmware-setup || loginctl reboot --firmware-setup`]); sessionRoot.hide() }
onClicked: { Session.rebootToFirmware(); sessionRoot.hide() }
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
KeyNavigation.up: sessionTaskManager
KeyNavigation.left: sessionReboot
+3 -3
View File
@@ -19,7 +19,7 @@ import "./modules/onScreenDisplay/"
import "./modules/onScreenKeyboard/"
import "./modules/overview/"
import "./modules/screenCorners/"
import "./modules/session/"
import "./modules/sessionScreen/"
import "./modules/sidebarLeft/"
import "./modules/sidebarRight/"
import "./modules/verticalBar/"
@@ -45,7 +45,7 @@ ShellRoot {
property bool enableOverview: true
property bool enableReloadPopup: true
property bool enableScreenCorners: true
property bool enableSession: true
property bool enableSessionScreen: true
property bool enableSidebarLeft: true
property bool enableSidebarRight: true
property bool enableVerticalBar: true
@@ -72,7 +72,7 @@ ShellRoot {
LazyLoader { active: enableOverview; component: Overview {} }
LazyLoader { active: enableReloadPopup; component: ReloadPopup {} }
LazyLoader { active: enableScreenCorners; component: ScreenCorners {} }
LazyLoader { active: enableSession; component: Session {} }
LazyLoader { active: enableSessionScreen; component: SessionScreen {} }
LazyLoader { active: enableSidebarLeft; component: SidebarLeft {} }
LazyLoader { active: enableSidebarRight; component: SidebarRight {} }
LazyLoader { active: enableVerticalBar && Config.ready && Config.options.bar.vertical; component: VerticalBar {} }