Compare commits

..

8 Commits

10 changed files with 280 additions and 209 deletions

20
Bar.qml
View File

@@ -1,9 +1,12 @@
pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Effects import QtQuick.Effects
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell import Quickshell
import Quickshell.Hyprland import Quickshell.Hyprland
import Quickshell.Wayland
import "./Bar" import "./Bar"
import "./Services/"
import "Color.js" as Colors import "Color.js" as Colors
Scope { Scope {
@@ -25,6 +28,8 @@ Scope {
required property var modelData required property var modelData
property HyprlandMonitor monitor: Hyprland.monitorFor(modelData) property HyprlandMonitor monitor: Hyprland.monitorFor(modelData)
WlrLayershell.keyboardFocus: monitor.focused == true ? IpcManager.focusState :
WlrKeyboardFocus.None
color: "transparent" color: "transparent"
exclusionMode: ExclusionMode.Normal exclusionMode: ExclusionMode.Normal
exclusiveZone: barExclusionZone exclusiveZone: barExclusionZone
@@ -32,6 +37,21 @@ Scope {
mask: maskRegion mask: maskRegion
screen: modelData screen: modelData
Rectangle {
id: blurOverlay
color: Colors.base
implicitHeight: win.modelData.height
implicitWidth: win.modelData.width
opacity: IpcManager.logoutMenuOpen == true ? 0.8 : 0
Behavior on opacity {
NumberAnimation {
duration: 200
}
}
}
Region { Region {
id: maskRegion id: maskRegion

View File

@@ -18,61 +18,16 @@ Container {
animOffset: 150 animOffset: 150
boxColor: Colors.green boxColor: Colors.green
boxHeight: 25
boxHeightOpened: root.batteryDisplayHeight
boxRadius: radius boxRadius: radius
boxWidth: 60
boxWidthOpened: 410
defaultItem: icon defaultItem: icon
exclusiveMonitor: root.monitor exclusiveMonitor: root.monitor
exclusiveToScreen: true exclusiveToScreen: true
forceHidden: !BatteryManager.hasLaptopBattery forceHidden: !BatteryManager.hasLaptopBattery
openedItem: batteryDisplay
states: [
State {
name: "closed"
when: root.hovered == false && root.opened == false
PropertyChanges {
root.boxHeight: 25
root.boxRadius: root.radius
root.boxWidth: 60
}
},
State {
name: "hovered"
when: root.hovered == true && root.opened == false
PropertyChanges {
root.boxHeight: 28
root.boxWidth: 64
}
},
State {
name: "opened"
when: root.opened == true && root.hovered == true
PropertyChanges {
root.boxHeight: root.batteryDisplayHeight
root.boxRadius: 12
root.boxWidth: 450
}
StateChangeScript {
script: {
stack.replace(batteryDisplay);
}
}
}
]
hover.onHoveredChanged: {
if (hover.hovered == false) {
root.opened = false;
if (root.state != "icon") {
root.stack.replace(icon);
}
}
}
tap.onTapped: {
root.opened = true;
}
Component { Component {
id: icon id: icon

View File

@@ -14,67 +14,19 @@ Container {
property double devicePlaqueHeight: 60 property double devicePlaqueHeight: 60
property double devicePlaqueSpacing: 4 property double devicePlaqueSpacing: 4
required property HyprlandMonitor monitor required property HyprlandMonitor monitor
property bool opened: false
animOffset: 200 animOffset: 200
boxColor: Colors.peach boxColor: Colors.peach
boxHeight: 25 boxHeight: 25
boxHeightOpened: (root.devicePlaqueHeight * BluetoothManager.getConnectedDevicesList().length) + (
root.devicePlaqueSpacing * (BluetoothManager.getConnectedDevicesList().length + 1)) + 2
boxWidth: 33 boxWidth: 33
boxWidthOpened: 350
defaultItem: icon defaultItem: icon
exclusiveMonitor: root.monitor exclusiveMonitor: root.monitor
exclusiveToScreen: true exclusiveToScreen: true
forceHidden: !BluetoothManager.anyConnected forceHidden: !BluetoothManager.anyConnected
openedItem: deviceList
states: [
State {
name: "closed"
when: root.hovered == false && root.opened == false
PropertyChanges {
root.boxHeight: 25
root.boxRadius: 9
root.boxWidth: 33
}
},
State {
name: "hovered"
when: root.hovered == true && root.opened == false
PropertyChanges {
root.boxHeight: 28
root.boxWidth: 35
}
},
State {
name: "opened"
when: root.opened == true && root.hovered == true
PropertyChanges {
root.boxHeight: (root.devicePlaqueHeight * BluetoothManager.getConnectedDevicesList().length) + (
root.devicePlaqueSpacing * (BluetoothManager.getConnectedDevicesList().length + 1)) + 2
root.boxRadius: 12
root.boxWidth: 350
}
StateChangeScript {
script: {
stack.replace(deviceList);
}
}
}
]
hover.onHoveredChanged: {
if (hover.hovered == false) {
root.opened = false;
if (root.state != "icon") {
root.stack.replace(icon);
}
}
}
tap.onTapped: {
root.opened = true;
}
Component { Component {
id: icon id: icon

View File

@@ -13,66 +13,18 @@ Container {
required property HyprlandMonitor monitor required property HyprlandMonitor monitor
property double networkDisplayHeight: 80 property double networkDisplayHeight: 80
property bool opened: false
animOffset: 250 animOffset: 250
boxColor: Colors.red boxColor: Colors.red
boxHeight: 25 boxHeight: 25
boxHeightOpened: root.networkDisplayHeight
boxWidth: 33 boxWidth: 33
boxWidthOpened: 350
defaultItem: icon defaultItem: icon
exclusiveMonitor: root.monitor exclusiveMonitor: root.monitor
exclusiveToScreen: true exclusiveToScreen: true
forceHidden: !NetworkManager.connectedWifi forceHidden: !NetworkManager.connectedWifi
openedItem: networkDisplay
states: [
State {
name: "closed"
when: root.hovered == false && root.opened == false
PropertyChanges {
root.boxHeight: 25
root.boxRadius: 9
root.boxWidth: 33
}
},
State {
name: "hovered"
when: root.hovered == true && root.opened == false
PropertyChanges {
root.boxHeight: 28
root.boxWidth: 35
}
},
State {
name: "opened"
when: root.opened == true && root.hovered == true
PropertyChanges {
root.boxHeight: root.networkDisplayHeight
root.boxRadius: 12
root.boxWidth: 350
}
StateChangeScript {
script: {
stack.replace(wifiInfo);
}
}
}
]
hover.onHoveredChanged: {
if (hover.hovered == false) {
root.opened = false;
if (root.state != "icon") {
root.stack.replace(icon);
}
}
}
tap.onTapped: {
root.opened = true;
}
Component { Component {
id: icon id: icon
@@ -86,7 +38,7 @@ Container {
} }
Component { Component {
id: wifiInfo id: networkDisplay
Item { Item {
id: networkDisplayRoot id: networkDisplayRoot

View File

@@ -15,6 +15,10 @@ Container {
id: root id: root
property Notification latestNotif property Notification latestNotif
property bool logout: false
property double logoutHeight: 100
property double logoutMargin: 7
property double logoutSpacing: 5
required property HyprlandMonitor monitor required property HyprlandMonitor monitor
property bool mpris: false property bool mpris: false
property double mprisHeight: 60 property double mprisHeight: 60
@@ -22,7 +26,6 @@ Container {
property double notificationHeight: 100 property double notificationHeight: 100
property double notificationWidth: 350 property double notificationWidth: 350
property bool notified: false property bool notified: false
property bool overriden: false
boxColor: Colors.mauve boxColor: Colors.mauve
defaultItem: time defaultItem: time
@@ -30,43 +33,6 @@ Container {
exclusiveToScreen: true exclusiveToScreen: true
states: [ states: [
State {
name: "closed"
when: root.hovered == false && root.overriden == false
PropertyChanges {
root.boxHeight: 28
root.boxRadius: 9
root.boxWidth: 100
}
StateChangeScript {
script: {
if (!root.stack.currentItem) {
return;
}
if (root.stack.currentItem.component != "time") {
root.stack.replace(time);
}
}
}
},
State {
name: "hovered"
when: root.hovered == true && root.overriden == false
PropertyChanges {
root.boxHeight: MprisManager.getPlaying() == false ? 32 : root.mprisHeight
root.boxRadius: 12
root.boxWidth: MprisManager.getPlaying() == false ? 107 : root.mprisWidth
}
StateChangeScript {
script: {
root.stack.replace(MprisManager.getPlaying() == true ? mprisToast : time);
}
}
},
State { State {
name: "notified" name: "notified"
when: root.notified == true when: root.notified == true
@@ -93,7 +59,7 @@ Container {
root.boxHeight: root.mprisHeight root.boxHeight: root.mprisHeight
root.boxRadius: 12 root.boxRadius: 12
root.boxWidth: root.mprisWidth root.boxWidth: root.mprisWidth
root.visibleTopMargin: 5 root.visibleTopMargin: root.hovered == true ? 0 : 5
} }
StateChangeScript { StateChangeScript {
@@ -102,9 +68,51 @@ Container {
mprisTimer.restart(); mprisTimer.restart();
} }
} }
},
State {
name: "logout"
when: root.logout == true
PropertyChanges {
root.boxHeight: root.logoutHeight
root.boxRadius: 13
root.boxWidth: ((root.logoutHeight - (root.logoutMargin * 2)) * 5) + (root.logoutMargin * 2) + (
root.logoutSpacing * 4)
root.visibleTopMargin: 10
}
StateChangeScript {
script: {
root.stack.replace(logoutMenu);
}
}
} }
] ]
onHoveredChanged: {
if (root.hovered == true && MprisManager.getPlaying() == true) {
root.overriden = true;
root.mpris = true;
} else {
root.overriden = false;
root.mpris = true;
}
}
Connections {
function onCloseLogoutMenu() {
root.overriden = false;
root.logout = false;
}
function onLogoutMenu() {
root.overriden = true;
root.logout = true;
}
target: IpcManager
}
Connections { Connections {
function onNewNotification() { function onNewNotification() {
notification => { notification => {
@@ -155,6 +163,98 @@ Container {
} }
} }
Component {
id: logoutMenu
Item {
id: logoutMenuRoot
property var logoutModel: [
{
color: Colors.red,
text: "s",
key: Qt.Key_S
},
{
color: Colors.peach,
text: "e",
key: Qt.Key_E
},
{
color: Colors.yellow,
text: "r",
key: Qt.Key_R
},
{
color: Colors.green,
text: "l",
key: Qt.Key_L
},
{
color: Colors.sky,
text: "u",
key: Qt.Key_U
},
]
Component.onCompleted: {
forceActiveFocus();
}
Keys.onPressed: event => {
if (event.key == Qt.Key_Escape) {
IpcManager.closeLogoutMenu();
} else {
for (let button of logoutMenuRoot.logoutModel) {
if (button.key == event.key) {
event.accepted = true;
}
}
}
}
RowLayout {
spacing: root.logoutSpacing
anchors {
fill: parent
margins: root.logoutMargin
}
Repeater {
delegate: logoutButton
model: logoutMenuRoot.logoutModel
}
Component {
id: logoutButton
Item {
id: logoutButtonRoot
// Key yen isn't on my keyboard, acts as an errorless analog for no bind
required property var modelData
Layout.fillHeight: true
Layout.fillWidth: true
Rectangle {
anchors.fill: parent
color: logoutButtonRoot.modelData.color
radius: 7
StyledText {
anchors.fill: parent
horizontalAlignment: Qt.AlignHCenter
text: logoutButtonRoot.modelData.text
verticalAlignment: Qt.AlignVCenter
}
}
}
}
}
}
}
Component { Component {
id: time id: time
@@ -162,7 +262,7 @@ Container {
property string component: "time" property string component: "time"
horizontalAlignment: Qt.AlignCenter horizontalAlignment: Qt.AlignCenter
text: Time.time text: TimeManager.time
verticalAlignment: Qt.AlignVCenter verticalAlignment: Qt.AlignVCenter
} }
} }

View File

@@ -25,18 +25,6 @@ Container {
defaultItem: placeholder defaultItem: placeholder
exclusiveMonitor: monitor exclusiveMonitor: monitor
states: [
State {
name: "hovered"
when: root.hovered
PropertyChanges {
root.barHeight: 30
root.workspaceWidth: 20
}
}
]
Component { Component {
id: placeholder id: placeholder

View File

@@ -14,8 +14,12 @@ Item {
property double animOffset: 0 property double animOffset: 0
property color boxColor: Colors.surface0 property color boxColor: Colors.surface0
property double boxHeight: 28 property double boxHeight: 28
property double boxHeightOpened: 150
property bool boxOpened: false
property double boxRadius: 9 property double boxRadius: 9
property double boxRadiusOpened: 12
property double boxWidth: 100 property double boxWidth: 100
property double boxWidthOpened: 200
readonly property double calculatedTopMargin: { readonly property double calculatedTopMargin: {
if (!root.exclusiveToScreen) { if (!root.exclusiveToScreen) {
return visibleTopMargin; return visibleTopMargin;
@@ -38,6 +42,8 @@ Item {
property alias hover: hoverHandler property alias hover: hoverHandler
property bool hoverableWhenHidden: false property bool hoverableWhenHidden: false
property bool hovered: false property bool hovered: false
property Component openedItem
property bool overriden: false
property alias rect: container property alias rect: container
property alias stack: containerContent property alias stack: containerContent
property alias tap: tapHandler property alias tap: tapHandler
@@ -50,13 +56,13 @@ Item {
Behavior on anchors.topMargin { Behavior on anchors.topMargin {
animation: defaultCurve animation: defaultCurve
} }
Behavior on boxHeight { Behavior on boxRadius {
SpringAnimation { SpringAnimation {
damping: 0.3 damping: 0.3
spring: 4 spring: 4
} }
} }
Behavior on boxRadius { Behavior on implicitHeight {
SpringAnimation { SpringAnimation {
damping: 0.3 damping: 0.3
spring: 4 spring: 4
@@ -68,6 +74,56 @@ Item {
spring: 4 spring: 4
} }
} }
states: [
State {
name: "closed"
when: root.hovered == false && root.boxOpened == false && root.overriden == false
PropertyChanges {
container.radius: root.boxRadius
root.implicitHeight: root.boxHeight
root.implicitWidth: root.boxWidth
}
StateChangeScript {
script: {
stack.replace(root.defaultItem);
}
}
},
State {
name: "hovered"
when: root.hovered == true && root.boxOpened == false && root.overriden == false
PropertyChanges {
container.radius: root.boxRadius + 3
root.implicitHeight: root.boxHeight + 2
root.implicitWidth: root.boxWidth + 2
}
StateChangeScript {
script: {
stack.replace(root.defaultItem);
}
}
},
State {
name: "opened"
when: root.boxOpened == true && root.hovered == true && root.overriden == false
PropertyChanges {
container.radius: root.boxRadiusOpened
root.implicitHeight: root.boxHeightOpened
root.implicitWidth: root.boxWidthOpened
}
StateChangeScript {
script: {
stack.replace(root.openedItem);
}
}
}
]
onForceHiddenChanged: { onForceHiddenChanged: {
if (root.forceHidden == true) { if (root.forceHidden == true) {
@@ -125,12 +181,22 @@ Item {
root.hovered = true; root.hovered = true;
} else { } else {
root.hovered = false; root.hovered = false;
root.boxOpened = false;
if (root.state == "closed") {
root.stack.replace(root.defaultItem);
}
} }
} }
} }
TapHandler { TapHandler {
id: tapHandler id: tapHandler
onTapped: {
if (root.openedItem) {
root.boxOpened = true;
}
}
} }
Rectangle { Rectangle {
@@ -141,6 +207,12 @@ Item {
color: root.boxColor color: root.boxColor
radius: root.boxRadius radius: root.boxRadius
Behavior on radius {
NumberAnimation {
duration: 300
}
}
StackView { StackView {
id: containerContent id: containerContent

31
Services/IpcManager.qml Normal file
View File

@@ -0,0 +1,31 @@
pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
Singleton {
id: root
property var focusState: WlrKeyboardFocus.None
property bool logoutMenuOpen: false
signal closeLogoutMenu
signal logoutMenu
onCloseLogoutMenu: {
root.focusState = WlrKeyboardFocus.None;
root.logoutMenuOpen = false;
}
IpcHandler {
function openLogoutMenu(): void {
root.logoutMenu();
root.focusState = WlrKeyboardFocus.Exclusive;
root.logoutMenuOpen = true;
}
target: "root"
}
}

View File

@@ -1,8 +1,9 @@
module Services module Services
singleton Time 1.0 Time.qml singleton TimeManager 1.0 TimeManager.qml
singleton NotificationManager 1.0 NotificationManager.qml singleton NotificationManager 1.0 NotificationManager.qml
singleton WorkspaceManager 1.0 WorkspaceManager.qml singleton WorkspaceManager 1.0 WorkspaceManager.qml
singleton BluetoothManager 1.0 BluetoothManager.qml singleton BluetoothManager 1.0 BluetoothManager.qml
singleton MprisManager 1.0 MprisManager.qml singleton MprisManager 1.0 MprisManager.qml
singleton BatteryManager 1.0 BatteryManager.qml singleton BatteryManager 1.0 BatteryManager.qml
singleton NetworkManager 1.0 NetworkManager.qml singleton NetworkManager 1.0 NetworkManager.qml
singleton IpcManager 1.0 IpcManager.qml