Compare commits

...

14 Commits

8 changed files with 497 additions and 26 deletions

10
Bar.qml
View File

@@ -23,7 +23,7 @@ Scope {
PanelWindow {
id: win
property double barExclusionZone: 15
property double barExclusionZone: IpcManager.tabletMode ? 35 : 15
property double barMaxHeight: modelData.height
required property var modelData
property HyprlandMonitor monitor: Hyprland.monitorFor(modelData)
@@ -55,6 +55,10 @@ Scope {
Region {
id: maskRegion
Region {
item: launcher
}
Region {
item: left
}
@@ -101,6 +105,10 @@ Scope {
top: parent.top
}
Launcher {
id: launcher
}
Row {
id: left

View File

@@ -22,7 +22,7 @@ Container {
boxHeightOpened: root.batteryDisplayHeight
boxRadius: radius
boxWidth: 60
boxWidthOpened: 410
boxWidthOpened: 450
defaultItem: icon
exclusiveMonitor: root.monitor
exclusiveToScreen: true

194
Bar/Launcher.qml Normal file
View File

@@ -0,0 +1,194 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Hyprland
import "../Color.js" as Colors
import "../Components/"
import "../Services/"
Item {
id: root
property var buttons: [
{
icon: "",
color: Colors.surface1,
action: function () {}
},
{
icon: "",
color: Colors.yellow,
action: function () {
Quickshell.execDetached("nemo");
}
},
{
icon: "󰪶",
color: Colors.green,
action: function () {
Hyprland.dispatch("hl.dsp.exec_cmd('firefox --new-window \"https://office.voidarc.co.uk\"')");
}
},
{
icon: "󰊻",
color: Colors.sky,
action: function () {
Hyprland.dispatch("hl.dsp.exec_cmd('firefox --new-window \"https://teams.cloud.microsoft\"')");
}
},
{
icon: "",
color: Colors.mauve,
action: function () {
Hyprland.dispatch("hl.dsp.exec_cmd('kitty')");
}
},
{
icon: "󰼁",
color: Colors.red,
action: function () {}
},
{
icon: "󰈹",
color: Colors.peach,
action: function () {
Hyprland.dispatch("hl.dsp.exec_cmd('firefox')");
}
}
]
property real cx: width / 2
property real cy: height / 2
property bool hidden: !IpcManager.launcherOpen
property real r: 120
property double topMargin: 50
implicitHeight: 300
implicitWidth: 300
states: [
State {
name: "hidden"
when: root.hidden == true
PropertyChanges {
root.r: 0
root.topMargin: -300
}
},
State {
name: "shown"
when: root.hidden == false
PropertyChanges {
root.r: 120
root.topMargin: 50
}
}
]
transitions: [
Transition {
from: "hidden"
to: "shown"
ParallelAnimation {
SpringAnimation {
damping: 0.3
property: "topMargin"
spring: 5
target: root
}
SequentialAnimation {
PauseAnimation {
duration: 220
}
SpringAnimation {
damping: 0.3
property: "r"
spring: 4
target: root
}
}
}
},
Transition {
from: "shown"
to: "hidden"
ParallelAnimation {
SpringAnimation {
damping: 0.3
property: "r"
spring: 4
target: root
}
SequentialAnimation {
PauseAnimation {
duration: 130
}
NumberAnimation {
duration: 250
easing.type: Easing.InBack
property: "topMargin"
target: root
}
}
}
}
]
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.top
topMargin: root.topMargin
}
Repeater {
model: root.buttons
delegate: Item {
id: itemRoot
required property int index
required property var modelData
x: index === 0 ? root.cx - width / 2 : root.cx + root.r * Math.cos((index - 1) * Math.PI / 3)
- width / 2
y: index === 0 ? root.cy - height / 2 : root.cy + root.r * Math.sin((index - 1) * Math.PI / 3)
- height / 2
z: index === 0 ? 10 : 0
Rectangle {
color: itemRoot.modelData.color
implicitHeight: 80 + (itemRoot.index === 0 ? 2 : 0)
implicitWidth: 80 + (itemRoot.index === 0 ? 2 : 0)
radius: 10
TapHandler {
onTapped: {
itemRoot.modelData.action();
IpcManager.toggleLauncher();
}
}
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
CenteredText {
color: itemRoot.index === 0 ? Colors.text : Colors.surface0
fontSize: 32
propo: true
text: itemRoot.modelData.icon
}
}
}
}
}

View File

@@ -29,7 +29,8 @@ Container {
property bool notified: false
boxColor: Colors.mauve
defaultItem: time
boxWidth: IpcManager.tabletMode ? 600 : 100
defaultItem: IpcManager.tabletMode ? tabletTime : time
exclusiveMonitor: root.monitor
exclusiveToScreen: true
@@ -66,7 +67,9 @@ Container {
StateChangeScript {
script: {
root.stack.replace(mprisToast);
mprisTimer.restart();
if (root.hovered != true) {
mprisTimer.restart();
}
}
}
},
@@ -91,12 +94,20 @@ Container {
]
onHoveredChanged: {
if (root.hovered == true && MprisManager.getPlaying() == true) {
root.overriden = true;
root.mpris = true;
} else {
root.overriden = false;
root.mpris = true;
if (root.hovered == true) {
if (root.logout == false) {
if (MprisManager.getPlaying() == true) {
root.overriden = true;
root.mpris = true;
}
}
} else { // Hovered == false
if (root.logout == true) {
IpcManager.closeLogoutMenu();
} else {
root.overriden = false;
root.mpris = false;
}
}
}
@@ -107,6 +118,11 @@ Container {
}
function onLogoutMenu() {
root.overriden = false;
root.mpris = false;
mprisTimer.stop();
root.notified = false;
notificationTimer.stop();
if (root.monitor.focused == true) {
root.overriden = true;
root.logout = true;
@@ -132,9 +148,10 @@ Container {
Connections {
function onTrackChanged() {
root.overriden = true;
root.mpris = true;
console.log("track changed");
if (root.overriden != true && root.hovered != true) {
root.overriden = true;
root.mpris = true;
}
}
target: MprisManager.defaultPlayer
@@ -143,7 +160,7 @@ Container {
Timer {
id: notificationTimer
interval: 2000
interval: 5000
repeat: false
running: false
@@ -183,7 +200,7 @@ Container {
color: Colors.peach,
text: "󰗽",
key: Qt.Key_E,
command: ["hyprctl", "dispatch", "'hl.dsp.exit()'"]
command: ["hyprctl", "dispatch", "hl.dsp.exit()"]
},
{
color: Colors.yellow,
@@ -241,24 +258,59 @@ Container {
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
HoverHandler {
id: logoutHoverHandler
onHoveredChanged: {
if (logoutHoverHandler.hovered == true) {
buttonBackground.color = Colors.surface1;
logoutButtonText.color = logoutButtonRoot.modelData.color;
} else {
buttonBackground.color = logoutButtonRoot.modelData.color;
logoutButtonText.color = Colors.base;
}
}
}
TapHandler {
onTapped: {
Quickshell.execDetached(logoutButtonRoot.modelData.command);
}
}
Rectangle {
id: buttonBackground
anchors.fill: parent
color: logoutButtonRoot.modelData.color
radius: 7
Behavior on color {
ColorAnimation {
duration: 100
}
}
StyledText {
id: logoutButtonText
anchors.fill: parent
fontSize: 25
horizontalAlignment: Qt.AlignHCenter
propo: true
text: logoutButtonRoot.modelData.text
verticalAlignment: Qt.AlignVCenter
Behavior on color {
ColorAnimation {
duration: 100
}
}
}
}
}
@@ -279,6 +331,140 @@ Container {
}
}
Component {
id: tabletTime
Item {
property string component: "tabletTime"
Rectangle {
color: Colors.surface1
radius: root.boxRadius - 2
anchors {
fill: parent
margins: 3
topMargin: 3
}
Component {
id: tabletButton
Rectangle {
id: tabletButtonRoot
required property var modelData
color: Colors.overlay0
implicitWidth: 25
radius: root.boxRadius - 4
Behavior on color {
ColorAnimation {
duration: 60
}
}
anchors {
bottom: parent.bottom
top: parent.top
}
TapHandler {
onTapped: {
tabletButtonRoot.modelData.onTapped();
tabletButtonRoot.color = Colors.text;
tapAnimationTimer.restart();
}
}
Timer {
id: tapAnimationTimer
interval: 80
repeat: false
running: false
onTriggered: {
tabletButtonRoot.color = Colors.overlay0;
}
}
StyledText {
anchors.fill: parent
color: Colors.mauve
fontSize: 14
fontWeight: 10
horizontalAlignment: Qt.AlignHCenter
propo: true
text: tabletButtonRoot.modelData.text
verticalAlignment: Qt.AlignVCenter
}
}
}
Row {
anchors {
bottom: parent.bottom
bottomMargin: 3
left: parent.left
leftMargin: 4
top: parent.top
topMargin: 3
}
Repeater {
delegate: tabletButton
model: [
{
text: "󱗿",
onTapped: function () {
IpcManager.toggleLauncher();
}
},
]
}
}
CenteredText {
color: Colors.mauve
text: TimeManager.time
}
Row {
spacing: 3
anchors {
bottom: parent.bottom
bottomMargin: 3
right: parent.right
rightMargin: 4
top: parent.top
topMargin: 3
}
Repeater {
delegate: tabletButton
model: [
{
text: "",
onTapped: function () {
WorkspaceManager.activateWorkspaceById("-1");
}
},
{
text: "",
onTapped: function () {
Hyprland.dispatch(`hl.dsp.focus({workspace = "+1"})`);
}
},
]
}
}
}
}
}
Component {
id: notification
@@ -315,7 +501,7 @@ Container {
IconImage {
anchors.fill: parent
anchors.margins: 10
source: root.latestNotif.image
source: "file://" + root.latestNotif.appIcon
}
}
@@ -367,6 +553,18 @@ Container {
return fullHeight - (fullMargin * 2);
}
TapHandler {
acceptedButtons: Qt.RightButton
onTapped: MprisManager.skip()
}
TapHandler {
acceptedButtons: Qt.LeftButton
onTapped: MprisManager.prev()
}
Rectangle {
color: Colors.surface1
radius: 9
@@ -384,9 +582,22 @@ Container {
implicitWidth: mprisToastRoot.getInnerHeight()
radius: 5
IconImage {
anchors.fill: parent
source: mprisToastRoot.trackInfo["albumArt"]
Image {
anchors.centerIn: parent
// Non-blocking load for local or remote track art
asynchronous: true
// Optional: clips the overflowing parts of the cropped image to the 1:1 box
clip: true
// Zoom and crop from the center to fill the square completely
fillMode: Image.PreserveAspectCrop
height: width
source: mprisToastRoot.trackInfo["albumArt"] ?? ""
// Force a 1:1 square target area based on the parent container
width: Math.min(parent.width, parent.height)
}
}

View File

@@ -5,6 +5,7 @@ import Quickshell
import Quickshell.Hyprland
import "../Color.js" as Colors
import "../Services/"
Item {
id: root
@@ -78,6 +79,7 @@ Item {
State {
name: "closed"
when: root.hovered == false && root.boxOpened == false && root.overriden == false
&& IpcManager.tabletMode == false
PropertyChanges {
container.radius: root.boxRadius
@@ -91,19 +93,38 @@ Item {
}
}
},
State {
name: "tablet"
when: ( root.hovered == false || IpcManager.tabletMode == true ) && root.boxOpened == false && root.overriden == false
&& IpcManager.tabletMode == true
PropertyChanges {
container.radius: root.boxRadius
root.implicitHeight: 33
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.implicitHeight: IpcManager.tabletMode ? 35 : root.boxHeight + 2
root.implicitWidth: root.boxWidth + 2
}
StateChangeScript {
script: {
stack.replace(root.defaultItem);
if (IpcManager.tabletMode == false) {
stack.replace(root.defaultItem);
}
}
}
},
@@ -182,8 +203,11 @@ Item {
} else {
root.hovered = false;
root.boxOpened = false;
if (root.state == "closed") {
root.stack.replace(root.defaultItem);
if (root.state == "closed" || root.state == "tablet") {
if (IpcManager.tabletMode == false) {
root.stack.replace(root.defaultItem);
console.log("some");
}
}
}
}
@@ -199,6 +223,24 @@ Item {
}
}
TapHandler {
id: touchScreenTapHandler
acceptedDevices: PointerDevice.TouchScreen
onGrabChanged: state => {
if (state == 1) {
if (root.openedItem) {
root.hovered = true;
root.boxOpened = true;
}
} else if (state == 2) {
root.hovered = false;
root.boxOpened = false;
}
}
}
Rectangle {
id: container

View File

@@ -9,17 +9,35 @@ Singleton {
id: root
property var focusState: WlrKeyboardFocus.None
property bool launcherOpen: false
property bool logoutMenuOpen: false
property bool tabletMode: false
signal closeLogoutMenu
signal enableTabletMode
signal logoutMenu
signal normalMode
signal toggleLauncher
onCloseLogoutMenu: {
root.focusState = WlrKeyboardFocus.None;
root.logoutMenuOpen = false;
}
onToggleLauncher: {
root.launcherOpen = root.launcherOpen == true ? false : true;
}
IpcHandler {
function disableTabletMode(): void {
root.normalMode();
root.tabletMode = false;
}
function enableTabletMode(): void {
root.enableTabletMode();
root.tabletMode = true;
}
function openLogoutMenu(): void {
root.logoutMenu();
root.focusState = WlrKeyboardFocus.Exclusive;

View File

@@ -95,7 +95,6 @@ Singleton {
} else if (adapter.type == DeviceType.Wired) {
return false;
} else {
console.log(adapter.type);
return false;
}
}

View File

@@ -1,6 +1,5 @@
import QtQuick
import Quickshell
import Quickshell.Hyprland
Scope {
Bar {}