feat: session menu
This commit is contained in:
parent
a2c3417675
commit
60858f6f02
11 changed files with 399 additions and 34 deletions
BIN
assets/kurukuru.gif
Normal file
BIN
assets/kurukuru.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 97 KiB |
12
config/SessionConfig.qml
Normal file
12
config/SessionConfig.qml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
readonly property Sizes sizes: Sizes {}
|
||||||
|
|
||||||
|
component Sizes: QtObject {
|
||||||
|
readonly property int button: 80
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import "root:/widgets"
|
import "root:/widgets"
|
||||||
import "root:/services"
|
import "root:/services"
|
||||||
import "root:/config"
|
import "root:/config"
|
||||||
import Quickshell
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
|
|
|
||||||
|
|
@ -80,49 +80,60 @@ Variants {
|
||||||
|
|
||||||
Component.onCompleted: root.winHeight = height
|
Component.onCompleted: root.winHeight = height
|
||||||
|
|
||||||
Background {
|
Item {
|
||||||
id: bg
|
|
||||||
|
|
||||||
visible: false
|
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Drawers.rightExclusion
|
||||||
|
|
||||||
wrapperWidth: Math.min(wrapper.width, content.width)
|
clip: true
|
||||||
wrapperHeight: wrapper.height
|
visible: width > 0
|
||||||
}
|
implicitWidth: wrapper.width
|
||||||
|
implicitHeight: wrapper.height
|
||||||
|
|
||||||
LayerShadow {
|
Background {
|
||||||
source: bg
|
id: bg
|
||||||
}
|
|
||||||
|
|
||||||
Wrapper {
|
visible: false
|
||||||
id: wrapper
|
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
implicitHeight: content.height + bg.rounding * 2
|
wrapperWidth: Math.min(wrapper.width, content.width)
|
||||||
|
wrapperHeight: wrapper.height
|
||||||
osdVisible: root.osdVisible
|
|
||||||
contentWidth: content.width
|
|
||||||
|
|
||||||
Content {
|
|
||||||
id: content
|
|
||||||
|
|
||||||
monitor: root.monitor
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
HoverHandler {
|
LayerShadow {
|
||||||
id: hoverHandler
|
source: bg
|
||||||
|
}
|
||||||
|
|
||||||
onHoveredChanged: {
|
Wrapper {
|
||||||
root.hovered = hovered;
|
id: wrapper
|
||||||
if (hovered)
|
|
||||||
timer.stop();
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
else
|
anchors.right: parent.right
|
||||||
root.osdVisible = false;
|
|
||||||
|
implicitHeight: content.height + bg.rounding * 2
|
||||||
|
|
||||||
|
osdVisible: root.osdVisible
|
||||||
|
contentWidth: content.width
|
||||||
|
|
||||||
|
Content {
|
||||||
|
id: content
|
||||||
|
|
||||||
|
monitor: root.monitor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HoverHandler {
|
||||||
|
id: hoverHandler
|
||||||
|
|
||||||
|
onHoveredChanged: {
|
||||||
|
root.hovered = hovered;
|
||||||
|
if (hovered)
|
||||||
|
timer.stop();
|
||||||
|
else
|
||||||
|
root.osdVisible = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
70
modules/session/Background.qml
Normal file
70
modules/session/Background.qml
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
import "root:/services"
|
||||||
|
import "root:/config"
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Shapes
|
||||||
|
|
||||||
|
Shape {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property real wrapperWidth
|
||||||
|
required property real wrapperHeight
|
||||||
|
readonly property real rounding: BorderConfig.rounding
|
||||||
|
readonly property bool flatten: wrapperWidth < rounding * 2
|
||||||
|
readonly property real roundingX: flatten ? wrapperWidth / 2 : rounding
|
||||||
|
|
||||||
|
preferredRendererType: Shape.CurveRenderer
|
||||||
|
opacity: Colours.transparency.enabled ? Colours.transparency.base : 1
|
||||||
|
|
||||||
|
ShapePath {
|
||||||
|
strokeWidth: -1
|
||||||
|
fillColor: BorderConfig.colour
|
||||||
|
|
||||||
|
startX: root.wrapperWidth - 1
|
||||||
|
|
||||||
|
PathArc {
|
||||||
|
relativeX: -root.roundingX
|
||||||
|
relativeY: root.rounding
|
||||||
|
radiusX: Math.min(root.rounding, root.wrapperWidth)
|
||||||
|
radiusY: root.rounding
|
||||||
|
}
|
||||||
|
PathLine {
|
||||||
|
x: root.roundingX
|
||||||
|
relativeY: 0
|
||||||
|
}
|
||||||
|
PathArc {
|
||||||
|
relativeX: -root.roundingX
|
||||||
|
relativeY: root.rounding
|
||||||
|
radiusX: Math.min(root.rounding, root.wrapperWidth)
|
||||||
|
radiusY: root.rounding
|
||||||
|
direction: PathArc.Counterclockwise
|
||||||
|
}
|
||||||
|
PathLine {
|
||||||
|
y: root.wrapperHeight - root.rounding * 2
|
||||||
|
}
|
||||||
|
PathArc {
|
||||||
|
relativeX: root.roundingX
|
||||||
|
relativeY: root.rounding
|
||||||
|
radiusX: Math.min(root.rounding, root.wrapperWidth)
|
||||||
|
radiusY: root.rounding
|
||||||
|
direction: PathArc.Counterclockwise
|
||||||
|
}
|
||||||
|
PathLine {
|
||||||
|
x: (root.flatten ? root.roundingX : root.wrapperWidth - root.rounding) - 1
|
||||||
|
relativeY: 0
|
||||||
|
}
|
||||||
|
PathArc {
|
||||||
|
relativeX: root.roundingX
|
||||||
|
relativeY: root.rounding
|
||||||
|
radiusX: Math.min(root.rounding, root.wrapperWidth)
|
||||||
|
radiusY: root.rounding
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on fillColor {
|
||||||
|
ColorAnimation {
|
||||||
|
duration: Appearance.anim.durations.normal
|
||||||
|
easing.type: Easing.BezierSpline
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.standard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
118
modules/session/Content.qml
Normal file
118
modules/session/Content.qml
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import "root:/widgets"
|
||||||
|
import "root:/services"
|
||||||
|
import "root:/config"
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property Scope session
|
||||||
|
|
||||||
|
padding: Appearance.padding.large
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
|
||||||
|
spacing: Appearance.spacing.large
|
||||||
|
|
||||||
|
SessionButton {
|
||||||
|
id: logout
|
||||||
|
|
||||||
|
icon: "logout"
|
||||||
|
command: ["uwsm", "stop"]
|
||||||
|
|
||||||
|
KeyNavigation.down: shutdown
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: session
|
||||||
|
|
||||||
|
function onSessionVisibleChanged(): void {
|
||||||
|
if (session.sessionVisible)
|
||||||
|
logout.focus = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionButton {
|
||||||
|
id: shutdown
|
||||||
|
|
||||||
|
icon: "power_settings_new"
|
||||||
|
command: ["systemctl", "poweroff"]
|
||||||
|
|
||||||
|
KeyNavigation.up: logout
|
||||||
|
KeyNavigation.down: hibernate
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatedImage {
|
||||||
|
width: SessionConfig.sizes.button
|
||||||
|
height: SessionConfig.sizes.button
|
||||||
|
sourceSize.width: width
|
||||||
|
sourceSize.height: height
|
||||||
|
|
||||||
|
playing: session.sessionVisible
|
||||||
|
asynchronous: true
|
||||||
|
speed: 0.7
|
||||||
|
source: "root:/assets/kurukuru.gif"
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionButton {
|
||||||
|
id: hibernate
|
||||||
|
|
||||||
|
icon: "downloading"
|
||||||
|
command: ["systemctl", "hibernate"]
|
||||||
|
|
||||||
|
KeyNavigation.up: shutdown
|
||||||
|
KeyNavigation.down: reboot
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionButton {
|
||||||
|
id: reboot
|
||||||
|
|
||||||
|
icon: "cached"
|
||||||
|
command: ["systemctl", "reboot"]
|
||||||
|
|
||||||
|
KeyNavigation.up: hibernate
|
||||||
|
}
|
||||||
|
|
||||||
|
component SessionButton: StyledRect {
|
||||||
|
id: button
|
||||||
|
|
||||||
|
required property string icon
|
||||||
|
required property list<string> command
|
||||||
|
|
||||||
|
implicitWidth: SessionConfig.sizes.button
|
||||||
|
implicitHeight: SessionConfig.sizes.button
|
||||||
|
|
||||||
|
radius: Appearance.rounding.large
|
||||||
|
color: button.activeFocus ? Colours.palette.m3secondaryContainer : Colours.palette.m3surfaceContainer
|
||||||
|
|
||||||
|
Keys.onEnterPressed: proc.startDetached()
|
||||||
|
Keys.onEscapePressed: root.session.sessionVisible = false
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: proc
|
||||||
|
|
||||||
|
command: button.command
|
||||||
|
}
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
radius: parent.radius
|
||||||
|
|
||||||
|
function onClicked(): void {
|
||||||
|
proc.startDetached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
text: button.icon
|
||||||
|
color: button.activeFocus ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
|
||||||
|
font.pointSize: Appearance.font.size.extraLarge
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
87
modules/session/Session.qml
Normal file
87
modules/session/Session.qml
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
import "root:/widgets"
|
||||||
|
import "root:/services"
|
||||||
|
import "root:/config"
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Scope {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property int winHeight
|
||||||
|
property bool sessionVisible
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: Drawers
|
||||||
|
|
||||||
|
function onPosChanged(screen: ShellScreen, x: int, y: int): void {
|
||||||
|
if (x > screen.width - BorderConfig.thickness && y > (screen.height - root.winHeight) / 2 && y < (screen.height + root.winHeight) / 2)
|
||||||
|
root.sessionVisible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LazyLoader {
|
||||||
|
loading: true
|
||||||
|
|
||||||
|
StyledWindow {
|
||||||
|
id: win
|
||||||
|
|
||||||
|
name: "osd"
|
||||||
|
keyboardFocus: root.sessionVisible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
|
||||||
|
visible: wrapper.shouldBeVisible
|
||||||
|
|
||||||
|
mask: Region {
|
||||||
|
item: wrapper
|
||||||
|
}
|
||||||
|
|
||||||
|
anchors.left: true
|
||||||
|
anchors.right: true
|
||||||
|
height: wrapper.height
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
root.winHeight = height;
|
||||||
|
Drawers.rightExclusion = Qt.binding(() => bg.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
Background {
|
||||||
|
id: bg
|
||||||
|
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
wrapperWidth: Math.min(wrapper.width, content.width)
|
||||||
|
wrapperHeight: wrapper.height
|
||||||
|
}
|
||||||
|
|
||||||
|
LayerShadow {
|
||||||
|
source: bg
|
||||||
|
}
|
||||||
|
|
||||||
|
Wrapper {
|
||||||
|
id: wrapper
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
implicitHeight: content.height + bg.rounding * 2
|
||||||
|
|
||||||
|
sessionVisible: root.sessionVisible
|
||||||
|
contentWidth: content.width
|
||||||
|
|
||||||
|
Content {
|
||||||
|
id: content
|
||||||
|
|
||||||
|
session: root
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomShortcut {
|
||||||
|
name: "session"
|
||||||
|
description: "Toggle session menu"
|
||||||
|
onPressed: root.sessionVisible = !root.sessionVisible
|
||||||
|
}
|
||||||
|
}
|
||||||
62
modules/session/Wrapper.qml
Normal file
62
modules/session/Wrapper.qml
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
import "root:/config"
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property bool sessionVisible
|
||||||
|
required property real contentWidth
|
||||||
|
property bool shouldBeVisible
|
||||||
|
|
||||||
|
visible: width > 0
|
||||||
|
width: 0
|
||||||
|
|
||||||
|
states: State {
|
||||||
|
name: "visible"
|
||||||
|
when: root.sessionVisible
|
||||||
|
|
||||||
|
PropertyChanges {
|
||||||
|
root.width: contentWidth
|
||||||
|
root.shouldBeVisible: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transitions: [
|
||||||
|
Transition {
|
||||||
|
from: ""
|
||||||
|
to: "visible"
|
||||||
|
|
||||||
|
SequentialAnimation {
|
||||||
|
PropertyAction {
|
||||||
|
target: root
|
||||||
|
property: "shouldBeVisible"
|
||||||
|
}
|
||||||
|
NumberAnimation {
|
||||||
|
target: root
|
||||||
|
property: "width"
|
||||||
|
duration: Appearance.anim.durations.large
|
||||||
|
easing.type: Easing.BezierSpline
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.emphasizedDecel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Transition {
|
||||||
|
from: "visible"
|
||||||
|
to: ""
|
||||||
|
|
||||||
|
SequentialAnimation {
|
||||||
|
NumberAnimation {
|
||||||
|
target: root
|
||||||
|
property: "width"
|
||||||
|
duration: Appearance.anim.durations.normal
|
||||||
|
easing.type: Easing.BezierSpline
|
||||||
|
easing.bezierCurve: Appearance.anim.curves.emphasizedAccel
|
||||||
|
}
|
||||||
|
PropertyAction {
|
||||||
|
target: root
|
||||||
|
property: "shouldBeVisible"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ Singleton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property var positions: ({})
|
property var positions: ({})
|
||||||
|
property int rightExclusion
|
||||||
|
|
||||||
signal posChanged(screen: ShellScreen, x: int, y: int)
|
signal posChanged(screen: ShellScreen, x: int, y: int)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import "modules/bar"
|
||||||
import "modules/launcher"
|
import "modules/launcher"
|
||||||
import "modules/osd"
|
import "modules/osd"
|
||||||
import "modules/notifications"
|
import "modules/notifications"
|
||||||
|
import "modules/session"
|
||||||
import "modules/drawers"
|
import "modules/drawers"
|
||||||
import "modules/background"
|
import "modules/background"
|
||||||
import Quickshell
|
import Quickshell
|
||||||
|
|
@ -13,4 +14,5 @@ ShellRoot {
|
||||||
Background {}
|
Background {}
|
||||||
Drawers {}
|
Drawers {}
|
||||||
Notifications {}
|
Notifications {}
|
||||||
|
Session {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@ import QtQuick
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
readonly property alias hovered: mouse.hovered
|
||||||
|
readonly property alias pressed: mouse.pressed
|
||||||
|
|
||||||
function onClicked(event: MouseEvent): void {
|
function onClicked(event: MouseEvent): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue