lock: add session buttons

This commit is contained in:
2 * r + 2 * t 2025-06-25 17:45:26 +10:00
parent 173738c0be
commit 7a27d4126f
4 changed files with 191 additions and 0 deletions

View file

@ -19,5 +19,7 @@ JsonObject {
property int mediaCoverBorder: 3 property int mediaCoverBorder: 3
property int largeScreenWidth: 2560 property int largeScreenWidth: 2560
property int smallScreenWidth: 1080 property int smallScreenWidth: 1080
property int buttonsWidth: 500
property int buttonsWidthSmall: 300
} }
} }

View file

@ -10,6 +10,8 @@ Item {
required property bool locked required property bool locked
required property real weatherWidth required property real weatherWidth
required property real buttonsWidth
required property real buttonsHeight
required property bool isNormal required property bool isNormal
required property bool isLarge required property bool isLarge
@ -17,6 +19,8 @@ Item {
readonly property real inputTop: innerMask.anchors.margins + inputPath.height readonly property real inputTop: innerMask.anchors.margins + inputPath.height
readonly property real weatherTop: innerMask.anchors.margins + weatherPath.height readonly property real weatherTop: innerMask.anchors.margins + weatherPath.height
readonly property real weatherRight: innerMask.anchors.margins + weatherPath.width readonly property real weatherRight: innerMask.anchors.margins + weatherPath.width
readonly property real buttonsTop: innerMask.anchors.margins + buttonsPath.height
readonly property real buttonsLeft: innerMask.anchors.margins + buttonsPath.width
readonly property real mediaX: innerMask.anchors.margins + mediaPath.width readonly property real mediaX: innerMask.anchors.margins + mediaPath.width
readonly property real mediaY: innerMask.anchors.margins + mediaPath.height readonly property real mediaY: innerMask.anchors.margins + mediaPath.height
@ -331,6 +335,71 @@ Item {
} }
} }
} }
ShapePath {
id: buttonsPath
property int width: root.locked ? root.buttonsWidth - Config.lock.sizes.border / 4 : 0
property real height: root.locked ? root.buttonsHeight - Config.lock.sizes.border / 4 : 0
readonly property real rounding: Appearance.rounding.large * 2
readonly property real roundingX: width < rounding * 2 ? width / 2 : rounding
readonly property real roundingY: height < rounding * 2 ? height / 2 : rounding
strokeWidth: -1
fillColor: root.isLarge ? Config.border.colour : "transparent"
startX: Math.ceil(innerMask.width)
startY: Math.ceil(innerMask.height) - height - roundingY
PathArc {
relativeX: -buttonsPath.roundingX
relativeY: buttonsPath.roundingY
radiusX: Math.min(buttonsPath.rounding, buttonsPath.width)
radiusY: Math.min(buttonsPath.rounding, buttonsPath.height)
}
PathLine {
relativeX: -(buttonsPath.width - buttonsPath.roundingX * 2)
relativeY: 0
}
PathArc {
relativeX: -buttonsPath.roundingX
relativeY: buttonsPath.roundingY
radiusX: Math.min(buttonsPath.rounding, buttonsPath.width)
radiusY: Math.min(buttonsPath.rounding, buttonsPath.height)
direction: PathArc.Counterclockwise
}
PathLine {
relativeX: 0
relativeY: buttonsPath.height - buttonsPath.roundingY * 2
}
PathArc {
relativeX: -buttonsPath.roundingX
relativeY: buttonsPath.roundingY
radiusX: Math.min(buttonsPath.rounding, buttonsPath.width)
radiusY: Math.min(buttonsPath.rounding, buttonsPath.height)
}
PathLine {
relativeX: buttonsPath.width + buttonsPath.roundingX
relativeY: 0
}
Behavior on width {
Anim {}
}
Behavior on height {
Anim {}
}
Behavior on fillColor {
ColorAnimation {
duration: Appearance.anim.durations.normal
easing.type: Easing.BezierSpline
easing.bezierCurve: Appearance.anim.curves.standard
}
}
}
} }
component Anim: NumberAnimation { component Anim: NumberAnimation {

111
modules/lock/Buttons.qml Normal file
View file

@ -0,0 +1,111 @@
import "root:/widgets"
import "root:/services"
import "root:/config"
import Quickshell.Widgets
import QtQuick
import QtQuick.Layouts
WrapperItem {
readonly property real nonAnimMargin: handler.hovered ? Appearance.padding.large * 2 : Appearance.padding.large * 1.2
readonly property real nonAnimWidth: handler.hovered ? Config.lock.sizes.buttonsWidth : Config.lock.sizes.buttonsWidthSmall
readonly property real nonAnimHeight: (nonAnimWidth + nonAnimMargin * 2) / 4
margin: nonAnimMargin
rightMargin: 0
bottomMargin: 0
implicitWidth: nonAnimWidth
implicitHeight: nonAnimHeight
Behavior on margin {
NumberAnimation {
duration: Appearance.anim.durations.large
easing.type: Easing.BezierSpline
easing.bezierCurve: Appearance.anim.curves.emphasized
}
}
Behavior on implicitWidth {
NumberAnimation {
duration: Appearance.anim.durations.large
easing.type: Easing.BezierSpline
easing.bezierCurve: Appearance.anim.curves.emphasized
}
}
Behavior on implicitHeight {
NumberAnimation {
duration: Appearance.anim.durations.large
easing.type: Easing.BezierSpline
easing.bezierCurve: Appearance.anim.curves.emphasized
}
}
HoverHandler {
id: handler
target: parent
}
RowLayout {
id: layout
spacing: Appearance.spacing.normal
SessionButton {
icon: "logout"
command: ["loginctl", "terminate-user", ""]
}
SessionButton {
icon: "power_settings_new"
command: ["systemctl", "poweroff"]
}
SessionButton {
icon: "downloading"
command: ["systemctl", "hibernate"]
}
SessionButton {
icon: "cached"
command: ["systemctl", "reboot"]
}
}
component SessionButton: StyledRect {
required property string icon
required property list<string> command
Layout.fillWidth: true
Layout.preferredHeight: width
radius: stateLayer.containsMouse ? Appearance.rounding.large * 2 : Appearance.rounding.large * 1.2
color: Colours.palette.m3secondaryContainer
StateLayer {
id: stateLayer
color: Colours.palette.m3onSecondaryContainer
function onClicked(): void {
Quickshell.execDetached(parent.command);
}
}
MaterialIcon {
anchors.centerIn: parent
text: parent.icon
color: Colours.palette.m3onSecondaryContainer
font.pointSize: (parent.width * 0.4) || 1
}
Behavior on radius {
NumberAnimation {
duration: Appearance.anim.durations.normal
easing.type: Easing.BezierSpline
easing.bezierCurve: Appearance.anim.curves.standard
}
}
}
}

View file

@ -73,6 +73,8 @@ WlSessionLockSurface {
locked: root.locked locked: root.locked
weatherWidth: weather.implicitWidth weatherWidth: weather.implicitWidth
buttonsWidth: buttons.item?.nonAnimWidth ?? 0
buttonsHeight: buttons.item?.nonAnimHeight ?? 0
isNormal: root.screen.width > Config.lock.sizes.smallScreenWidth isNormal: root.screen.width > Config.lock.sizes.smallScreenWidth
isLarge: root.screen.width > Config.lock.sizes.largeScreenWidth isLarge: root.screen.width > Config.lock.sizes.largeScreenWidth
visible: false visible: false
@ -153,9 +155,16 @@ WlSessionLockSurface {
} }
Loader { Loader {
id: buttons
active: root.screen.width > Config.lock.sizes.largeScreenWidth active: root.screen.width > Config.lock.sizes.largeScreenWidth
asynchronous: true asynchronous: true
anchors.top: parent.bottom
anchors.left: parent.right
anchors.topMargin: -backgrounds.buttonsTop
anchors.leftMargin: -backgrounds.buttonsLeft
sourceComponent: Buttons {} sourceComponent: Buttons {}
} }