summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/kurukuru.gifbin0 -> 99006 bytes
-rw-r--r--config/SessionConfig.qml12
-rw-r--r--modules/osd/Content.qml1
-rw-r--r--modules/osd/Osd.qml71
-rw-r--r--modules/session/Background.qml70
-rw-r--r--modules/session/Content.qml118
-rw-r--r--modules/session/Session.qml87
-rw-r--r--modules/session/Wrapper.qml62
-rw-r--r--services/Drawers.qml1
-rw-r--r--shell.qml2
-rw-r--r--widgets/StateLayer.qml3
11 files changed, 396 insertions, 31 deletions
diff --git a/assets/kurukuru.gif b/assets/kurukuru.gif
new file mode 100644
index 0000000..38d203d
--- /dev/null
+++ b/assets/kurukuru.gif
Binary files differ
diff --git a/config/SessionConfig.qml b/config/SessionConfig.qml
new file mode 100644
index 0000000..ba4db0c
--- /dev/null
+++ b/config/SessionConfig.qml
@@ -0,0 +1,12 @@
+pragma Singleton
+
+import Quickshell
+import QtQuick
+
+Singleton {
+ readonly property Sizes sizes: Sizes {}
+
+ component Sizes: QtObject {
+ readonly property int button: 80
+ }
+}
diff --git a/modules/osd/Content.qml b/modules/osd/Content.qml
index 25ba7b8..6814966 100644
--- a/modules/osd/Content.qml
+++ b/modules/osd/Content.qml
@@ -1,7 +1,6 @@
import "root:/widgets"
import "root:/services"
import "root:/config"
-import Quickshell
import QtQuick
Column {
diff --git a/modules/osd/Osd.qml b/modules/osd/Osd.qml
index 8f93ae9..7774bab 100644
--- a/modules/osd/Osd.qml
+++ b/modules/osd/Osd.qml
@@ -80,49 +80,60 @@ Variants {
Component.onCompleted: root.winHeight = height
- Background {
- id: bg
-
- visible: false
-
+ Item {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
+ anchors.rightMargin: Drawers.rightExclusion
- wrapperWidth: Math.min(wrapper.width, content.width)
- wrapperHeight: wrapper.height
- }
+ clip: true
+ visible: width > 0
+ implicitWidth: wrapper.width
+ implicitHeight: wrapper.height
- LayerShadow {
- source: bg
- }
+ Background {
+ id: bg
- Wrapper {
- id: wrapper
+ visible: false
- anchors.verticalCenter: parent.verticalCenter
- anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ 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
+ LayerShadow {
+ source: bg
+ }
+
+ Wrapper {
+ id: wrapper
+
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: parent.right
- Content {
- id: content
+ implicitHeight: content.height + bg.rounding * 2
- monitor: root.monitor
+ osdVisible: root.osdVisible
+ contentWidth: content.width
+
+ Content {
+ id: content
+
+ monitor: root.monitor
+ }
}
- }
- HoverHandler {
- id: hoverHandler
+ HoverHandler {
+ id: hoverHandler
- onHoveredChanged: {
- root.hovered = hovered;
- if (hovered)
- timer.stop();
- else
- root.osdVisible = false;
+ onHoveredChanged: {
+ root.hovered = hovered;
+ if (hovered)
+ timer.stop();
+ else
+ root.osdVisible = false;
+ }
}
}
}
diff --git a/modules/session/Background.qml b/modules/session/Background.qml
new file mode 100644
index 0000000..4b4b92e
--- /dev/null
+++ b/modules/session/Background.qml
@@ -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
+ }
+ }
+ }
+}
diff --git a/modules/session/Content.qml b/modules/session/Content.qml
new file mode 100644
index 0000000..d1a2c38
--- /dev/null
+++ b/modules/session/Content.qml
@@ -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
+ }
+ }
+}
diff --git a/modules/session/Session.qml b/modules/session/Session.qml
new file mode 100644
index 0000000..0f8a0d5
--- /dev/null
+++ b/modules/session/Session.qml
@@ -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
+ }
+}
diff --git a/modules/session/Wrapper.qml b/modules/session/Wrapper.qml
new file mode 100644
index 0000000..5806972
--- /dev/null
+++ b/modules/session/Wrapper.qml
@@ -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"
+ }
+ }
+ }
+ ]
+}
diff --git a/services/Drawers.qml b/services/Drawers.qml
index 1f524ab..ac88b6c 100644
--- a/services/Drawers.qml
+++ b/services/Drawers.qml
@@ -6,6 +6,7 @@ Singleton {
id: root
property var positions: ({})
+ property int rightExclusion
signal posChanged(screen: ShellScreen, x: int, y: int)
diff --git a/shell.qml b/shell.qml
index bca6feb..f6a83d2 100644
--- a/shell.qml
+++ b/shell.qml
@@ -2,6 +2,7 @@ import "modules/bar"
import "modules/launcher"
import "modules/osd"
import "modules/notifications"
+import "modules/session"
import "modules/drawers"
import "modules/background"
import Quickshell
@@ -13,4 +14,5 @@ ShellRoot {
Background {}
Drawers {}
Notifications {}
+ Session {}
}
diff --git a/widgets/StateLayer.qml b/widgets/StateLayer.qml
index de15b16..bebf230 100644
--- a/widgets/StateLayer.qml
+++ b/widgets/StateLayer.qml
@@ -6,6 +6,9 @@ import QtQuick
Rectangle {
id: root
+ readonly property alias hovered: mouse.hovered
+ readonly property alias pressed: mouse.pressed
+
function onClicked(event: MouseEvent): void {
}