waffles: add action center window

This commit is contained in:
end-4
2025-11-16 23:52:07 +01:00
parent 71e0538cf5
commit 2d65af70ad
14 changed files with 321 additions and 43 deletions
@@ -0,0 +1,77 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs
import qs.services
import qs.modules.common
import qs.modules.common.functions
import qs.modules.waffle.looks
WBarAttachedPanelContent {
id: root
contentItem: ColumnLayout {
anchors.centerIn: parent
spacing: 0
Rectangle {
Layout.fillHeight: true
Layout.fillWidth: true
topLeftRadius: root.border.radius - root.border.border.width
topRightRadius: topLeftRadius
color: Looks.colors.bgPanelBody
implicitWidth: 360
implicitHeight: 380
}
Rectangle {
Layout.fillHeight: false
Layout.fillWidth: true
color: Looks.colors.bgPanelSeparator
implicitHeight: 1
}
Rectangle {
Layout.fillHeight: false
Layout.fillWidth: true
bottomLeftRadius: root.border.radius - root.border.border.width
bottomRightRadius: bottomLeftRadius
color: Looks.colors.bgPanelFooter
implicitWidth: 360
implicitHeight: 47
// Battery button
WPanelFooterButton {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 12
contentItem: Row {
spacing: 4
FluentIcon {
anchors.verticalCenter: parent.verticalCenter
icon: WIcons.batteryIcon
}
WText {
anchors.verticalCenter: parent.verticalCenter
text: `${Math.round(Battery.percentage * 100) || 0}%`
}
}
}
// Settings button
WPanelFooterButton {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 12
contentItem: FluentIcon {
icon: "settings"
}
}
}
}
}
@@ -0,0 +1,85 @@
import QtQuick
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import Quickshell.Hyprland
import qs
import qs.services
import qs.modules.common
import qs.modules.common.widgets
Scope {
id: root
Connections {
target: GlobalStates
function onSidebarLeftOpenChanged() {
if (GlobalStates.sidebarLeftOpen) barLoader.active = true;
}
}
Loader {
id: barLoader
active: GlobalStates.sidebarLeftOpen
sourceComponent: PanelWindow {
id: panelWindow
exclusiveZone: 0
WlrLayershell.namespace: "quickshell:actionCenter"
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
color: "transparent"
anchors {
bottom: Config.options.waffles.bar.bottom
top: !Config.options.waffles.bar.bottom
right: true
}
implicitWidth: content.implicitWidth + content.visualMargin * 2
implicitHeight: content.implicitHeight + content.visualMargin * 2
HyprlandFocusGrab {
id: focusGrab
active: true
windows: [panelWindow]
onCleared: content.close();
}
Connections {
target: GlobalStates
function onSidebarLeftOpenChanged() {
if (!GlobalStates.sidebarLeftOpen) content.close();
}
}
ActionCenterContent {
id: content
anchors.centerIn: parent
onClosed: {
barLoader.active = false;
GlobalStates.sidebarLeftOpen = false;
}
}
}
}
function toggleOpen() {
GlobalStates.sidebarLeftOpen = !GlobalStates.sidebarLeftOpen;
}
IpcHandler {
target: "sidebarLeft"
function toggle() {
root.toggleOpen();
}
}
GlobalShortcut {
name: "sidebarLeftToggle"
description: "Toggles left sidebar on press"
onPressed: root.toggleOpen();
}
}
@@ -70,8 +70,8 @@ Loader {
focusGrab.active = true; // Doesn't work
}
implicitWidth: realContent.implicitWidth + (ambientShadow.border.width * 2) + (root.visualMargin * 2)
implicitHeight: realContent.implicitHeight + (ambientShadow.border.width * 2) + (root.visualMargin * 2)
implicitWidth: realContent.implicitWidth + (root.ambientShadowWidth * 2) + (root.visualMargin * 2)
implicitHeight: realContent.implicitHeight + (root.ambientShadowWidth * 2) + (root.visualMargin * 2)
property real sourceEdgeMargin: -implicitHeight
PropertyAnimation {
@@ -101,17 +101,8 @@ Loader {
}
color: "transparent"
Rectangle {
id: ambientShadow
z: 0
anchors {
fill: realContent
margins: -border.width
}
border.color: ColorUtils.transparentize(Looks.colors.ambientShadow, Looks.shadowTransparency)
border.width: root.ambientShadowWidth
color: "transparent"
radius: realContent.radius + border.width
WAmbientShadow {
target: realContent
}
Rectangle {
@@ -8,9 +8,9 @@ import qs.modules.waffle.looks
BarButton {
id: root
checked: GlobalStates.sidebarRightOpen
checked: GlobalStates.sidebarLeftOpen
onClicked: {
GlobalStates.sidebarRightOpen = !GlobalStates.sidebarRightOpen; // For now...
GlobalStates.sidebarLeftOpen = !GlobalStates.sidebarLeftOpen;
}
contentItem: Item {
@@ -9,9 +9,8 @@ import qs.modules.common
import qs.modules.common.widgets
Scope {
id: bar
property bool showBarBackground: Config.options.bar.showBackground
id: root
LazyLoader {
id: barLoader
active: GlobalStates.barOpen && !GlobalStates.screenLocked
@@ -36,7 +36,7 @@ PopupWindow {
///////////////////// Internals /////////////////////
readonly property bool bottom: Config.options.waffles.bar.bottom
property real visualMargin: 12
property alias ambientShadowWidth: ambientShadow.border.width
property real ambientShadowWidth: 1
visible: false
color: "transparent"
@@ -64,16 +64,8 @@ PopupWindow {
hoverEnabled: true
// Shadow
Rectangle {
id: ambientShadow
anchors {
fill: contentItem
margins: -border.width
}
border.color: ColorUtils.transparentize(Looks.colors.ambientShadow, Looks.shadowTransparency)
border.width: 1
color: "transparent"
radius: Looks.radius.large + border.width
WAmbientShadow {
target: contentItem
}
Rectangle {
@@ -17,10 +17,12 @@ Singleton {
property real backgroundTransparency: 0.17
property real contentTransparency: 0.25
property real shadowTransparency: 0.6
colors: QtObject {
id: colors
property color ambientShadow: ColorUtils.transparentize("#000000", 0.4)
property color ambientShadow: ColorUtils.transparentize("#000000", 0.75)
property color bgPanelFooter: root.dark ? "#1C1C1C" : "#EEEEEE"
property color bgPanelBody: root.dark ? "#242424" : "#F2F2F2"
property color bgPanelSeparator: root.dark ? "#191919" : "#E0E0E0"
property color bg0: root.dark ? "#1C1C1C" : "#EEEEEE"
property color bg0Border: root.dark ? "#404040" : "#BEBEBE"
property color bg1: root.dark ? "#2C2C2C" : "#F7F7F7"
@@ -0,0 +1,25 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Hyprland
import qs.modules.common
import qs.modules.common.functions
import qs.modules.waffle.looks
Rectangle {
id: root
required property var target
z: 0
anchors {
fill: target
margins: -border.width
}
border.color: Looks.colors.ambientShadow
border.width: 1
color: "transparent"
radius: target.radius + border.width
}
@@ -0,0 +1,79 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs
import qs.services
import qs.modules.common
import qs.modules.waffle.looks
Item {
id: root
signal closed()
property alias border: borderRect
required default property Item contentItem
property real visualMargin: 12
function close() {
closeAnim.start();
}
readonly property bool barAtBottom: Config.options.waffles.bar.bottom
implicitHeight: borderRect.implicitHeight
implicitWidth: borderRect.implicitWidth
Rectangle {
id: borderRect
color: "transparent"
radius: Looks.radius.large
border.color: Looks.colors.bg2Border
border.width: 1
implicitWidth: contentItem.implicitWidth + border.width * 2
implicitHeight: contentItem.implicitHeight + border.width * 2
children: [root.contentItem]
anchors {
left: parent.left
right: parent.right
top: root.barAtBottom ? undefined : parent.top
bottom: root.barAtBottom ? parent.bottom : undefined
// Opening anim
bottomMargin: root.barAtBottom ? sourceEdgeMargin : 0
topMargin: root.barAtBottom ? 0 : sourceEdgeMargin
}
Component.onCompleted: {
openAnim.start();
}
property real sourceEdgeMargin: -(implicitHeight + root.visualMargin)
PropertyAnimation {
id: openAnim
target: borderRect
property: "sourceEdgeMargin"
to: 0
duration: 200
easing.type: Easing.BezierSpline
easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn
}
SequentialAnimation {
id: closeAnim
PropertyAnimation {
target: borderRect
property: "sourceEdgeMargin"
to: -(implicitHeight + root.visualMargin)
duration: 150
easing.type: Easing.BezierSpline
easing.bezierCurve: Looks.transition.easing.bezierCurve.easeOut
}
ScriptAction {
script: {
root.closed();
}
}
}
}
}
@@ -0,0 +1,32 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import qs.modules.common
import qs.modules.common.functions
import qs.modules.waffle.looks
Button {
id: root
implicitHeight: 36
property color colBackground: ColorUtils.transparentize(Looks.colors.bg1)
property color colBackgroundHover: Looks.colors.bg1Hover
property color colBackgroundActive: Looks.colors.bg1Active
property color color
property color colForeground: Looks.colors.fg
color: {
if (root.down) {
return root.colBackgroundActive
} else if ((root.hovered && !root.down) || root.checked) {
return root.colBackgroundHover
} else {
return root.colBackground
}
}
background: Rectangle {
radius: Looks.radius.medium
color: root.color
}
}
@@ -27,17 +27,8 @@ PopupToolTip {
implicitWidth: realContent.implicitWidth + 2 * 2
implicitHeight: realContent.implicitHeight + 2 * 2
Rectangle {
id: ambientShadow
z: 0
anchors {
fill: realContent
margins: -border.width
}
border.color: ColorUtils.transparentize(Looks.colors.ambientShadow, Looks.shadowTransparency)
border.width: 1
color: "transparent"
radius: realContent.radius + border.width
WAmbientShadow {
target: realContent
}
Rectangle {