From 446d83ce2cb17e8b3aa61c402f879b56623cdde8 Mon Sep 17 00:00:00 2001 From: kossLAN Date: Tue, 5 Aug 2025 12:12:32 -0400 Subject: [PATCH] still broken but getting there --- .gitignore | 3 +- shell/.qmlls.ini | 1 + shell/ShellSettings.qml | 83 +---- shell/bar/ActiveWindow.qml | 2 +- shell/bar/Bar.qml | 45 ++- .../MenuWindow.qml => PopupHandler.qml} | 81 +---- .../{HyprWorkspaces.qml => Workspaces.qml} | 39 ++- shell/bar/control/Button.qml | 33 -- shell/bar/control/ControlPanel.qml | 308 ------------------ shell/bar/control/MediaPlayer.qml | 248 -------------- shell/bar/control/ProfileImage.qml | 33 -- shell/bar/control/volume/Card.qml | 79 ----- shell/bar/control/volume/Mixer.qml | 176 ---------- shell/bar/systray/SysTray.qml | 37 +-- shell/bar/systray/TrayMenuEntry.qml | 11 +- shell/bar/systray/TrayMenuItem.qml | 6 +- shell/volume-osd/Controller.qml | 126 ++----- shell/widgets/IconButton.qml | 8 +- shell/widgets/StyledMouseArea.qml | 4 +- shell/widgets/StyledPopup.qml | 39 ++- 20 files changed, 143 insertions(+), 1219 deletions(-) create mode 120000 shell/.qmlls.ini rename shell/bar/{popups/MenuWindow.qml => PopupHandler.qml} (59%) rename shell/bar/{HyprWorkspaces.qml => Workspaces.qml} (81%) delete mode 100644 shell/bar/control/Button.qml delete mode 100644 shell/bar/control/ControlPanel.qml delete mode 100644 shell/bar/control/MediaPlayer.qml delete mode 100644 shell/bar/control/ProfileImage.qml delete mode 100644 shell/bar/control/volume/Card.qml delete mode 100644 shell/bar/control/volume/Mixer.qml diff --git a/.gitignore b/.gitignore index 2237ec8..ab66c2f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -.stfolder -.stversions +./shell/.qmlls.ini diff --git a/shell/.qmlls.ini b/shell/.qmlls.ini new file mode 120000 index 0000000..826dc3d --- /dev/null +++ b/shell/.qmlls.ini @@ -0,0 +1 @@ +/run/user/1000/quickshell/vfs/99445c8565c70898bc0c842af0f02bb1/.qmlls.ini \ No newline at end of file diff --git a/shell/ShellSettings.qml b/shell/ShellSettings.qml index a6fc0cf..a4fa7b0 100644 --- a/shell/ShellSettings.qml +++ b/shell/ShellSettings.qml @@ -12,17 +12,15 @@ Singleton { FileView { path: `${Quickshell.dataPath("settings")}/quickshell/settings.json` watchChanges: true - onFileChanged: reload() - onAdapterUpdated: writeAdapter() + // onFileChanged: reload() + // onAdapterUpdated: writeAdapter() blockLoading: true JsonAdapter { id: jsonAdapter property JsonObject settings: JsonObject { - property string wallpaperUrl: Qt.resolvedUrl("root:resources/wallpapers/pixelart0.jpg") - property string colorScheme: "scheme-fruit-salad" property string screenshotPath: "/home/koss/Pictures" property real opacity: 0.55 } @@ -32,73 +30,18 @@ Singleton { } property JsonObject colors: JsonObject { - property color surface: "#111111" - property color surface_container: "#191919" - property color primary: "#52DBCB" - property color active: "#FFFFFF" - property color inactive: "#6F6F6F" + property color surface: Qt.rgba(1.0, 1.0, 1.0, 1.0) + property color surface_translucent: Qt.rgba(0.0, 0.0, 0.0, 0.15) + property color surface_container: Qt.rgba(0.25, 0.25, 0.25, 1.0) + property color surface_container_translucent: Qt.rgba(0.25, 0.25, 0.25, 0.25) + property color highlight: Qt.rgba(1.0, 1.0, 1.0, 0.85) + // property color primary: "#2EADC6" + property color active: Qt.rgba(1.0, 1.0, 1.0, 1.0) + property color active_translucent: Qt.rgba(1.0, 1.0, 1.0, 0.15) + property color border_translucent: Qt.rgba(1.0, 1.0, 1.0, 0.05) + property color inactive: Qt.rgba(0.25, 0.25, 0.25, 1.0) + property color inactive_translucent: Qt.rgba(0.25, 0.25, 0.25, 0.15) } - - // property var colors: { - // "surface": "#111111", - // "surface_container": "#191919", - // "primary": "#52DBCB", - // "active": "#FFFFFF", - // "inactive": "#6F6F6F", - // } - - // property var colors: { - // "background": "#131313", - // "error": "#ffb4ab", - // "error_container": "#93000a", - // "inverse_on_surface": "#303030", - // "inverse_primary": "#9c4236", - // "inverse_surface": "#e2e2e2", - // "on_background": "#e2e2e2", - // "on_error": "#690005", - // "on_error_container": "#ffdad6", - // "on_primary": "#5f150d", - // "on_primary_container": "#ffdad4", - // "on_primary_fixed": "#410000", - // "on_primary_fixed_variant": "#7d2b21", - // "on_secondary": "#442925", - // "on_secondary_container": "#ffdad4", - // "on_secondary_fixed": "#2c1512", - // "on_secondary_fixed_variant": "#5d3f3b", - // "on_surface": "#e2e2e2", - // "on_surface_variant": "#c6c6c6", - // "on_tertiary": "#3e2e04", - // "on_tertiary_container": "#fbdfa6", - // "on_tertiary_fixed": "#251a00", - // "on_tertiary_fixed_variant": "#564419", - // "outline": "#919191", - // "outline_variant": "#474747", - // "primary": "#ffb4a8", - // "primary_container": "#7d2b21", - // "primary_fixed": "#ffdad4", - // "primary_fixed_dim": "#ffb4a8", - // "scrim": "#000000", - // "secondary": "#e7bdb6", - // "secondary_container": "#5d3f3b", - // "secondary_fixed": "#ffdad4", - // "secondary_fixed_dim": "#e7bdb6", - // "shadow": "#000000", - // "source_color": "#df4332", - // "surface": "#131313", - // "surface_bright": "#393939", - // "surface_container": "#1f1f1f", - // "surface_container_high": "#2a2a2a", - // "surface_container_highest": "#353535", - // "surface_container_low": "#1b1b1b", - // "surface_container_lowest": "#0e0e0e", - // "surface_dim": "#131313", - // "surface_tint": "#ffb4a8", - // "surface_variant": "#474747", - // "tertiary": "#dec38c", - // "tertiary_container": "#564419", - // "tertiary_fixed": "#fbdfa6", - // "tertiary_fixed_dim": "#dec38c" - // } } } } diff --git a/shell/bar/ActiveWindow.qml b/shell/bar/ActiveWindow.qml index ecf7b46..4e5e126 100644 --- a/shell/bar/ActiveWindow.qml +++ b/shell/bar/ActiveWindow.qml @@ -5,7 +5,7 @@ import ".." Text { id: windowText text: ToplevelManager.activeToplevel?.title ?? "" - color: ShellSettings.colors["inverse_surface"] + color: ShellSettings.colors.active font.pointSize: 11 visible: text !== "" elide: Text.ElideRight diff --git a/shell/bar/Bar.qml b/shell/bar/Bar.qml index 929c829..00d7ccf 100644 --- a/shell/bar/Bar.qml +++ b/shell/bar/Bar.qml @@ -1,18 +1,17 @@ import QtQuick import QtQuick.Layouts import Quickshell -import "power" +// import "power" // import "volume" -import "systray" as SysTray -import "popups" as Popup -import "../widgets" as Widgets -import ".." +import "systray" +// import qs.widgets +import qs PanelWindow { id: root - color: "transparent" + color: "transparent" implicitHeight: ShellSettings.sizing.barHeight - property alias popup: popupWindow + property alias popup: popupHandler anchors { top: true @@ -21,14 +20,12 @@ PanelWindow { } Rectangle { - color: ShellSettings.colors.surface - opacity: 0.15 + color: ShellSettings.colors.surface_translucent anchors.fill: parent } - // Popup window for all popups - Popup.MenuWindow { - id: popupWindow + PopupHandler { + id: popupHandler bar: root } @@ -47,15 +44,15 @@ PanelWindow { Layout.fillWidth: true Layout.fillHeight: true - // HyprWorkspaces { - // screen: root.screen - // Layout.fillHeight: true - // } + Workspaces { + screen: root.screen + Layout.fillHeight: true + } - // ActiveWindow { - // id: activeWindow - // Layout.preferredWidth: 400 - // } + ActiveWindow { + id: activeWindow + Layout.preferredWidth: 400 + } } // Right side of bar @@ -65,10 +62,10 @@ PanelWindow { Layout.fillHeight: true Layout.alignment: Qt.AlignRight - SysTray.SysTray { + SysTray { id: sysTray - // popup: root.popup - bar: root + popup: root.popup + // bar: root Layout.fillHeight: true } @@ -94,7 +91,7 @@ PanelWindow { Clock { id: clock - color: ShellSettings.colors["active"] + color: ShellSettings.colors.active } } } diff --git a/shell/bar/popups/MenuWindow.qml b/shell/bar/PopupHandler.qml similarity index 59% rename from shell/bar/popups/MenuWindow.qml rename to shell/bar/PopupHandler.qml index 3b41f74..8424265 100644 --- a/shell/bar/popups/MenuWindow.qml +++ b/shell/bar/PopupHandler.qml @@ -2,8 +2,7 @@ import Quickshell import Quickshell.Hyprland import Quickshell.Widgets import QtQuick -import QtQuick.Effects -import "../.." +import qs PopupWindow { id: root @@ -37,8 +36,6 @@ PopupWindow { let itemPos = item.mapToItem(root.bar.contentItem, 0, root.bar.height, item.width, 0).x; position(itemPos); - // popupContainer.opacity = 0; - // popupContent.opacity = 0; popupContainer.visible = false; } @@ -67,16 +64,12 @@ PopupWindow { isOpen = true; root.visible = true; // set and leave open root.content.visible = true; - // popupContainer.opacity = 1; - // popupContent.opacity = 1; popupContainer.visible = true; } function hide() { grab.active = false; isOpen = false; - // popupContainer.opacity = 0; - // popupContent.opacity = 0; popupContainer.visible = false; root.item = undefined; @@ -92,18 +85,8 @@ PopupWindow { } } - // RectangularShadow { - // radius: popupContainer.radius - // anchors.fill: popupContainer - // opacity: popupContainer.opacity - // visible: popupContainer.visible - // blur: 10 - // spread: 2 - // } - Rectangle { - color: ShellSettings.colors.surface - // opacity: ShellSettings.settings.opacity + color: ShellSettings.colors.surface_translucent opacity: 0.15 radius: 12 anchors.fill: popupContainer @@ -112,19 +95,9 @@ PopupWindow { WrapperItem { id: popupContainer - - // color: ShellSettings.colors.surface - // radius: 12 margin: 8 clip: true - // opacity: 0.5 - // visible: opacity > 0 x: root.bar.width - - // spooky, likely to cause problems lol - width: implicitWidth - height: implicitHeight - onVisibleChanged: root.visible = visible // needed to handle occurences where items are resized while open @@ -140,28 +113,8 @@ PopupWindow { id: popupContent implicitWidth: Math.max(root.content?.width, 60) implicitHeight: Math.max(childrenRect.height, 60) - - Behavior on opacity { - NumberAnimation { - duration: 200 - easing.type: Easing.InOutQuad - from: 0 - to: 1 - } - } } - // broken for elements in the popup that have hover/mousearea's - // HoverHandler { - // id: hover - // enabled: true - // acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad - // onHoveredChanged: { - // if (hovered == false) - // root.hide(); - // } - // } - HyprlandFocusGrab { id: grab windows: [root, root.bar] @@ -169,35 +122,5 @@ PopupWindow { root.hide(); } } - - // Behavior on opacity { - // NumberAnimation { - // duration: 200 - // easing.type: Easing.Linear - // } - // } - - Behavior on width { - enabled: root.isOpen - SmoothedAnimation { - duration: 200 - easing.type: Easing.InOutQuad - } - } - - Behavior on height { - SmoothedAnimation { - duration: 200 - easing.type: Easing.InOutQuad - } - } - - Behavior on x { - enabled: root.isOpen - SmoothedAnimation { - duration: 200 - easing.type: Easing.InOutQuad - } - } } } diff --git a/shell/bar/HyprWorkspaces.qml b/shell/bar/Workspaces.qml similarity index 81% rename from shell/bar/HyprWorkspaces.qml rename to shell/bar/Workspaces.qml index ee70c79..ab14fa9 100644 --- a/shell/bar/HyprWorkspaces.qml +++ b/shell/bar/Workspaces.qml @@ -2,7 +2,7 @@ import QtQuick import QtQuick.Layouts import Quickshell import Quickshell.Hyprland -import ".." +import qs RowLayout { spacing: 6 @@ -14,15 +14,27 @@ RowLayout { id: workspaceButtons model: ScriptModel { - values: Hyprland.workspaces.values.slice().filter( - workspace => workspace.monitor === Hyprland.monitorFor(screen) - ) + values: Hyprland.workspaces.values.slice().filter(workspace => workspace.monitor === Hyprland.monitorFor(screen)) } Rectangle { - required property var modelData - radius: height / 2 + + color: { + let value = ShellSettings.colors.active_translucent; + + if (!modelData?.id || !Hyprland.focusedMonitor?.activeWorkspace?.id) + return value; + + if (workspaceButton.containsMouse) { + value = ShellSettings.colors.highlight; + } else if (Hyprland.focusedMonitor.activeWorkspace.id === modelData.id) { + value = ShellSettings.colors.highlight; + } + + return value; + } + Layout.alignment: Qt.AlignVCenter Layout.preferredHeight: 12 Layout.preferredWidth: { @@ -32,20 +44,7 @@ RowLayout { return 12; } - color: { - let value = Qt.color(ShellSettings.colors["secondary"]).darker(2); - - if (!modelData?.id || !Hyprland.focusedMonitor?.activeWorkspace?.id) - return value; - - if (workspaceButton.containsMouse) { - value = ShellSettings.colors["on_primary"]; - } else if (Hyprland.focusedMonitor.activeWorkspace.id === modelData.id) { - value = ShellSettings.colors["primary"]; - } - - return value; - } + required property var modelData Behavior on Layout.preferredWidth { SmoothedAnimation { diff --git a/shell/bar/control/Button.qml b/shell/bar/control/Button.qml deleted file mode 100644 index 65cd859..0000000 --- a/shell/bar/control/Button.qml +++ /dev/null @@ -1,33 +0,0 @@ -import Quickshell -import QtQuick -import "../../widgets/" as Widgets - -Widgets.IconButton { - id: root - required property var bar - required property var screen - - implicitSize: 20 - source: "root:/resources/general/nixos.svg" - padding: 2 - - onClicked: { - if (controlPanel.visible) { - controlPanel.hide(); - } else { - controlPanel.show(); - } - } - - ControlPanel { - id: controlPanel - - anchor { - window: root.screen - - onAnchoring: { - anchor.rect = mapToItem(root.screen.contentItem, 0, root.screen.height, width, 0); - } - } - } -} diff --git a/shell/bar/control/ControlPanel.qml b/shell/bar/control/ControlPanel.qml deleted file mode 100644 index 9342dec..0000000 --- a/shell/bar/control/ControlPanel.qml +++ /dev/null @@ -1,308 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import QtQuick.Layouts -import Quickshell -import Quickshell.Hyprland -import Quickshell.Io -import Quickshell.Services.Mpris -import Qt5Compat.GraphicalEffects -import "volume" as Volume -import "../../widgets/" as Widgets -import "../.." - -// Change to PopupWindow -PopupWindow { - id: root - implicitWidth: 400 - implicitHeight: container.height + 10 - color: "transparent" - visible: container.opacity > 0 - - anchor.rect.x: 0 - anchor.rect.y: parentWindow.implicitHeight - - // anchors { - // top: true - // left: true - // } - - function show() { - container.opacity = 1; - grab.active = true; - } - - function hide() { - container.opacity = 0; - grab.active = false; - } - - HyprlandFocusGrab { - id: grab - windows: [root] - onCleared: { - root.hide(); - } - } - - // Add drop shadow effect - // Rectangle { - // id: shadowSource - // color: ShellSettings.colors["surface"] - // radius: 8 - // opacity: container.opacity - // width: container.width - // height: container.height - // - // anchors { - // top: parent.top - // left: parent.left - // margins: 5 - // } - // - // layer.enabled: true - // layer.effect: DropShadow { - // horizontalOffset: 0 - // verticalOffset: 2 - // radius: 8.0 - // samples: 17 - // color: Qt.rgba(0, 0, 0, 0.5) - // transparentBorder: true - // } - // visible: false // Hide the source rectangle - // } - - Item { - id: shadowItem - anchors.fill: container - z: container.z - 1 - opacity: container.opacity - - Rectangle { - id: shadowRect - anchors.fill: parent - color: "transparent" - - layer.enabled: true - layer.effect: DropShadow { - horizontalOffset: 0 - verticalOffset: 2 - radius: 8.0 - samples: 17 - color: Qt.rgba(0, 0, 0, 0.5) - source: container - } - } - } - - Rectangle { - id: container - color: ShellSettings.colors["surface"] - radius: 18 - opacity: 0 - width: parent.width - 10 - height: contentColumn.implicitHeight + 20 - - anchors { - top: parent.top - left: parent.left - margins: 5 - } - - Behavior on opacity { - NumberAnimation { - duration: 300 - easing.type: Easing.OutCubic - } - } - - ColumnLayout { - id: contentColumn - spacing: 10 - - anchors { - top: parent.top - left: parent.left - right: parent.right - margins: 10 - } - - // RowLayout { - // Layout.fillWidth: true - // Layout.preferredHeight: 40 - // - // Rectangle { - // radius: 20 - // color: ShellSettings.colors["surface_container_high"] - // Layout.fillWidth: true - // Layout.fillHeight: true - // - // RowLayout { - // anchors { - // fill: parent - // leftMargin: 6 - // } - // - // ProfileImage { - // id: profileImage - // Layout.preferredWidth: 25 - // Layout.preferredHeight: 25 - // // implicitWidth: 30 - // // implicitHeight: 30 - // } - // - // Text { - // text: "kossLAN" - // color: ShellSettings.colors["inverse_surface"] - // font.pointSize: 12 - // verticalAlignment: Text.AlignVCenter - // Layout.fillWidth: true - // Layout.fillHeight: true - // Layout.margins: 4 - // } - // } - // } - // - // Rectangle { - // radius: 20 - // color: ShellSettings.colors["surface_container_high"] - // Layout.preferredWidth: powerButtons.implicitWidth + 10 - // Layout.fillHeight: true - // - // RowLayout { - // id: powerButtons - // spacing: 10 - // - // anchors { - // fill: parent - // leftMargin: 5 - // rightMargin: 5 - // } - // - // Widgets.IconButton { - // id: sleepButton - // implicitSize: 24 - // radius: 20 - // source: "root:resources/control/sleep.svg" - // onClicked: sleepProcess.running = true - // } - // - // Process { - // id: sleepProcess - // running: false - // command: ["hyprctl", "dispatch", "dpms", "off"] - // } - // - // Rectangle { - // radius: 20 - // color: ShellSettings.colors["surface_bright"] - // Layout.preferredWidth: 2 - // Layout.fillHeight: true - // Layout.topMargin: 4 - // Layout.bottomMargin: 4 - // } - // - // Widgets.IconButton { - // id: powerButton - // implicitSize: 24 - // radius: 20 - // source: "root:resources/control/shutdown.svg" - // } - // } - // } - // } - - RowLayout { - spacing: 15 - Layout.fillWidth: true - - Rectangle { - color: ShellSettings.colors["surface_container_high"] - radius: 12 - Layout.fillWidth: true - Layout.preferredHeight: 30 - } - } - - RowLayout { - spacing: 15 - Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter - - Repeater { - model: [1, 2, 3, 4, 5] - delegate: Rectangle { - color: ShellSettings.colors["surface_container_high"] - radius: width / 2 - Layout.preferredWidth: 45 - Layout.preferredHeight: 45 - } - } - } - - ColumnLayout { - spacing: 10 - Layout.fillWidth: true - - RowLayout { - spacing: 10 - Layout.fillWidth: true - Layout.preferredHeight: 55 - - Rectangle { - color: ShellSettings.colors["primary"] - radius: width / 2 - Layout.fillWidth: true - Layout.fillHeight: true - } - - Rectangle { - color: ShellSettings.colors["primary"] - radius: width / 2 - Layout.fillWidth: true - Layout.fillHeight: true - } - } - - RowLayout { - spacing: 10 - Layout.fillWidth: true - Layout.preferredHeight: 55 - - Rectangle { - color: ShellSettings.colors["surface_container_high"] - radius: width / 2 - Layout.fillWidth: true - Layout.fillHeight: true - } - - Rectangle { - color: ShellSettings.colors["surface_container_high"] - radius: width / 2 - Layout.fillWidth: true - Layout.fillHeight: true - } - } - } - - Volume.Mixer { - id: sinkMixer - isSink: true - Layout.fillWidth: true - } - - Volume.Mixer { - id: sourceMixer - isSink: false - Layout.fillWidth: true - } - - MediaPlayer { - player: Mpris.players?.values[0] - visible: Mpris.players?.values.length != 0 - Layout.fillWidth: true - Layout.preferredHeight: 150 - } - } - } -} diff --git a/shell/bar/control/MediaPlayer.qml b/shell/bar/control/MediaPlayer.qml deleted file mode 100644 index 4580283..0000000 --- a/shell/bar/control/MediaPlayer.qml +++ /dev/null @@ -1,248 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import QtQuick.Layouts -import Qt5Compat.GraphicalEffects -import Quickshell -import Quickshell.Services.Mpris -import "../.." -import "../../widgets" as Widgets - -Item { - id: root - required property var player - layer.enabled: true - layer.effect: OpacityMask { - maskSource: Rectangle { - width: root.width - height: root.height - radius: 14 - color: "black" - } - } - - ColorQuantizer { - id: gradientQuantizer - source: root.player?.trackArtUrl ?? "" - depth: 2 - rescaleSize: 64 - } - - ColorQuantizer { - id: accentQuantizer - source: root.player?.trackArtUrl ?? "" - depth: 0 - rescaleSize: 64 - } - - ShaderEffect { - property color topLeftColor: gradientQuantizer?.colors[0] ?? "white" - property color topRightColor: gradientQuantizer?.colors[1] ?? "black" - property color bottomLeftColor: gradientQuantizer?.colors[2] ?? "white" - property color bottomRightColor: gradientQuantizer?.colors[3] ?? "black" - - anchors.fill: parent - fragmentShader: "root:/shaders/vertexgradient.frag.qsb" - vertexShader: "root:/shaders/vertexgradient.vert.qsb" - - Behavior on topLeftColor { - ColorAnimation { - duration: 500 - easing.type: Easing.InOutQuad - } - } - - Behavior on topRightColor { - ColorAnimation { - duration: 500 - easing.type: Easing.InOutQuad - } - } - - Behavior on bottomLeftColor { - ColorAnimation { - duration: 500 - easing.type: Easing.InOutQuad - } - } - - Behavior on bottomRightColor { - ColorAnimation { - duration: 500 - easing.type: Easing.InOutQuad - } - } - } - - RowLayout { - id: cardLayout - spacing: 15 - - anchors { - fill: parent - margins: 10 - } - - ColumnLayout { - Layout.fillWidth: true - Layout.fillHeight: true - spacing: 5 - - RowLayout { - Rectangle { - id: mprisImage - color: "transparent" - radius: 10 - width: 50 - height: 50 - Layout.alignment: Qt.AlignVCenter - visible: true - - layer.enabled: true - layer.effect: DropShadow { - transparentBorder: true - spread: 0.02 - samples: 25 - color: "#80000000" - } - - Image { - anchors.fill: parent - source: root.player?.trackArtUrl ?? "" - sourceSize.width: 1024 - sourceSize.height: 1024 - fillMode: Image.PreserveAspectFit - - layer.enabled: true - layer.effect: OpacityMask { - source: Rectangle { - width: mprisImage.width - height: mprisImage.height - radius: 10 - color: "white" - } - - maskSource: Rectangle { - width: mprisImage.width - height: mprisImage.height - radius: 10 - color: "black" - } - } - } - } - - ColumnLayout { - Layout.leftMargin: 7.5 - Layout.alignment: Qt.AlignBottom - - Text { - text: root.player?.trackArtist ?? "NA" - color: "white" - font.pointSize: 13 - font.bold: true - horizontalAlignment: Text.AlignLeft - Layout.fillWidth: true - elide: Text.ElideRight - } - - Text { - text: root.player?.trackTitle ?? "NA" - color: "white" - font.pointSize: 13 - horizontalAlignment: Text.AlignLeft - Layout.fillWidth: true - elide: Text.ElideRight - } - } - } - - RowLayout { - spacing: 6 - - Text { - text: timeStr(root.player?.position) - color: "white" - - font { - pointSize: 9 - bold: true - } - } - - FrameAnimation { - running: root.player?.playbackState == MprisPlaybackState.Playing - onTriggered: root.player?.positionChanged() - } - - Widgets.RoundSlider { - id: positionSlider - implicitHeight: 7 - from: 0 - to: root.player?.length - accentColor: accentQuantizer.colors[0]?.darker(1.2) ?? "purple" - value: root.player?.position ?? 0 - Layout.fillWidth: true - - onMoved: { - if (root.player == null) - return; - - root.player.position = value; - } - } - - Text { - text: timeStr(root.player?.length) - color: "white" - - font { - pointSize: 9 - bold: true - } - } - } - - // Music Controls - RowLayout { - spacing: 2 - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - - Widgets.IconButton { - implicitSize: 40 - activeRectangle: false - padding: 4 - source: "root:resources/mpris/previous.svg" - onClicked: root.player?.previous() - } - - Widgets.IconButton { - implicitSize: 40 - activeRectangle: false - padding: 4 - source: root.player?.isPlaying ? "root:resources/mpris/pause.svg" : "root:resources/mpris/play.svg" - onClicked: { - if (!root.player?.canPlay) - return; - player.isPlaying ? player.pause() : player.play(); - } - } - - Widgets.IconButton { - implicitSize: 40 - activeRectangle: false - padding: 4 - source: "root:resources/mpris/next.svg" - onClicked: root.player?.next() - } - } - } - } - - function timeStr(time: int): string { - const seconds = time % 60; - const minutes = Math.floor(time / 60); - - return `${minutes}:${seconds.toString().padStart(2, '0')}`; - } -} diff --git a/shell/bar/control/ProfileImage.qml b/shell/bar/control/ProfileImage.qml deleted file mode 100644 index b7f33d1..0000000 --- a/shell/bar/control/ProfileImage.qml +++ /dev/null @@ -1,33 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import Qt5Compat.GraphicalEffects - -Rectangle { - id: profileImage - color: "transparent" - - Image { - anchors.fill: parent - source: "root:resources/general/pfp.png" - sourceSize.width: 100 - sourceSize.height: 100 - - layer.enabled: true - layer.effect: OpacityMask { - source: Rectangle { - width: profileImage.width - height: profileImage.height - radius: 10 - color: "white" - } - - maskSource: Rectangle { - width: profileImage.width - height: profileImage.height - radius: 10 - color: "black" - } - } - } -} diff --git a/shell/bar/control/volume/Card.qml b/shell/bar/control/volume/Card.qml deleted file mode 100644 index fd6f561..0000000 --- a/shell/bar/control/volume/Card.qml +++ /dev/null @@ -1,79 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import Quickshell -import Quickshell.Services.Pipewire -import "../../.." -import "../../../widgets" as Widgets - -Rectangle { - id: root - required property PwNode node - required property var isSink - color: ShellSettings.colors["surface_container_high"] - - PwObjectTracker { - id: defaultSourceTracker - objects: [root.node] - } - - RowLayout { - anchors.fill: parent - spacing: 8 - - ColumnLayout { - Layout.fillWidth: true - Layout.fillHeight: true - Layout.leftMargin: 2 - spacing: 10 - - Text { - color: ShellSettings.colors["inverse_surface"] - text: { - - // Taken from quickshell-examples - const app = root.node?.properties["application.name"] ?? (root.node?.description != "" ? root.node?.description : root.node?.name); - const media = root.node?.properties["media.name"]; - const title = media != undefined ? `${app} - ${media}` : app; - - return title != undefined ? title : "null"; - } - - font.bold: true - - elide: Text.ElideRight - Layout.fillWidth: true - Layout.topMargin: 5 - Layout.rightMargin: 5 - } - - Widgets.RoundSlider { - implicitHeight: 7 - from: 0 - to: 1 - value: root.node?.audio.volume ?? 0 - onValueChanged: root.node.audio.volume = value - Layout.fillWidth: true - Layout.bottomMargin: 7.5 - } - } - - Widgets.IconButton { - source: { - if (!root.isSink) - return root.node?.audio.muted ? "root:resources/volume/microphone-mute.svg" : "root:resources/volume/microphone-full.svg"; - - return root.node?.audio.muted ? "root:resources/volume/volume-mute.svg" : "root:resources/volume/volume-full.svg"; - } - - implicitSize: 36 - padding: 4 - radius: implicitSize / 2 - Layout.rightMargin: 10 - Layout.alignment: Qt.AlignLeft - - onClicked: { - root.node.audio.muted = !root.node.audio.muted; - } - } - } -} diff --git a/shell/bar/control/volume/Mixer.qml b/shell/bar/control/volume/Mixer.qml deleted file mode 100644 index 729af1d..0000000 --- a/shell/bar/control/volume/Mixer.qml +++ /dev/null @@ -1,176 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import QtQuick.Layouts -import Qt5Compat.GraphicalEffects -import Quickshell.Widgets -import Quickshell.Services.Pipewire -import "../../../widgets/" as Widgets -import "../../.." - -// TODO: refactor this trash -Rectangle { - id: root - required property var isSink - color: "transparent" - radius: 10 - - property bool expanded: false - property int baseHeight: 60 - property int contentHeight: expanded ? (applicationVolumes.count * baseHeight) : 0 - - implicitHeight: baseHeight + contentHeight - - layer.enabled: true - layer.effect: OpacityMask { - maskSource: Rectangle { - width: root.width - height: root.height - radius: root.baseHeight / 2 - color: "black" - } - } - - Item { - id: headerSection - width: parent.width - height: root.baseHeight - anchors.top: parent.top - - RowLayout { - spacing: 0 - anchors.fill: parent - - Rectangle { - color: ShellSettings.colors["surface_container_high"] - - Widgets.IconButton { - id: arrowButton - implicitSize: 44 - activeRectangle: false - source: "root:resources/general/right-arrow.svg" - padding: 4 - rotation: root.expanded ? 90 : 0 - anchors.centerIn: parent - - Behavior on rotation { - NumberAnimation { - duration: 150 - easing.type: Easing.OutCubic - } - } - - onClicked: { - root.expanded = !root.expanded; - } - } - - Layout.preferredWidth: 40 - Layout.preferredHeight: root.baseHeight - } - - Card { - node: root.isSink ? Pipewire.defaultAudioSink : Pipewire.defaultAudioSource - isSink: root.isSink - Layout.fillWidth: true - Layout.preferredHeight: root.baseHeight - } - } - } - - Rectangle { - id: divider - color: ShellSettings.colors["surface_bright"] - height: 2 - width: parent.width - anchors.top: headerSection.bottom - - opacity: root.expanded ? 1.0 : 0.0 - - // Behavior on opacity { - // NumberAnimation { - // duration: 150 - // easing.type: Easing.OutCubic - // } - // } - } - - Item { - id: contentSection - width: parent.width - anchors.top: divider.bottom - height: root.contentHeight - clip: true - - // Behavior on height { - // SmoothedAnimation { - // duration: 150 - // velocity: 200 - // easing.type: Easing.OutCubic - // } - // } - - Column { - id: applicationsColumn - width: parent.width - anchors.top: parent.top - opacity: root.expanded ? 1.0 : 0.0 - - // Behavior on opacity { - // NumberAnimation { - // duration: 100 - // easing.type: Easing.OutCubic - // } - // } - - PwNodeLinkTracker { - id: linkTracker - node: root.isSink ? Pipewire.defaultAudioSink : Pipewire.defaultAudioSource - } - - Repeater { - id: applicationVolumes - model: linkTracker.linkGroups - - delegate: RowLayout { - id: cardRow - required property PwLinkGroup modelData - spacing: 0 - width: applicationsColumn.width - height: root.baseHeight - - Rectangle { - color: ShellSettings.colors["surface_container_high"] - - IconImage { - implicitSize: 32 - source: { - if (cardRow.modelData.source?.properties["application.icon-name"] == null) { - return "root:resources/general/placeholder.svg"; - } - - return `image://icon/${cardRow.modelData.source?.properties["application.icon-name"]}`; - } - - anchors { - fill: parent - leftMargin: 8 - rightMargin: 8 - } - } - - Layout.preferredWidth: 40 - Layout.preferredHeight: root.baseHeight - } - - Card { - node: cardRow.modelData.source - isSink: root.isSink - Layout.fillWidth: true - Layout.preferredHeight: root.baseHeight - } - } - } - } - } -} diff --git a/shell/bar/systray/SysTray.qml b/shell/bar/systray/SysTray.qml index b4f956c..56c2a40 100644 --- a/shell/bar/systray/SysTray.qml +++ b/shell/bar/systray/SysTray.qml @@ -5,15 +5,14 @@ import QtQuick.Layouts import Quickshell import Quickshell.Widgets import Quickshell.Services.SystemTray -import "../../widgets" as Widgets +import qs.widgets RowLayout { id: root spacing: 5 visible: SystemTray.items.values.length > 0 - // required property var popup - required property var bar + required property var popup Repeater { model: SystemTray.items @@ -24,32 +23,29 @@ RowLayout { Layout.fillHeight: true required property SystemTrayItem modelData - Widgets.StyledMouseArea { + StyledMouseArea { id: trayButton hoverEnabled: true onClicked: { menuOpener.menu = trayField.modelData.menu; - if (trayMenu.visible) { - trayMenu.visible = false; - // root.popup.hide(); - + if (root.popup.content == trayMenu) { + root.popup.hide(); return; } - trayMenu.visible = true; - - // root.popup.set(this, trayMenu); - // root.popup.show(); + root.popup.set(this, trayMenu); + root.popup.show(); } anchors { fill: parent - // margins: 2 + margins: 2 } IconImage { id: trayIcon + anchors.fill: parent source: { // console.log(trayField.modelData.id); switch (trayField.modelData.id) { @@ -59,11 +55,6 @@ RowLayout { return trayField.modelData.icon; } } - - anchors { - fill: parent - margins: 2 - } } } @@ -71,19 +62,13 @@ RowLayout { id: menuOpener } - Widgets.StyledPopup { + WrapperItem { id: trayMenu - // visible: false + visible: false property var leftItem: false property var rightItem: false - anchor { - window: root.bar - item: trayButton - margins.top: root.bar.height + 5 - } - ColumnLayout { id: menuContainer spacing: 2 diff --git a/shell/bar/systray/TrayMenuEntry.qml b/shell/bar/systray/TrayMenuEntry.qml index 83cf29c..6f178ab 100644 --- a/shell/bar/systray/TrayMenuEntry.qml +++ b/shell/bar/systray/TrayMenuEntry.qml @@ -31,8 +31,7 @@ ColumnLayout { return "transparent"; if (entryArea.containsMouse) { - let base = ShellSettings.colors.active; - return Qt.rgba(base.r, base.g, base.b, 0.15); + return ShellSettings.colors.active_translucent; } return "transparent"; @@ -141,9 +140,15 @@ ColumnLayout { WrapperRectangle { id: subTrayMenu - color: ShellSettings.colors.surface_container + color: ShellSettings.colors.surface_container_translucent radius: 8 visible: false + + border { + width: 1 + color: ShellSettings.colors.active_translucent + } + Layout.fillWidth: true QsMenuOpener { diff --git a/shell/bar/systray/TrayMenuItem.qml b/shell/bar/systray/TrayMenuItem.qml index 69fcc32..685d4d5 100644 --- a/shell/bar/systray/TrayMenuItem.qml +++ b/shell/bar/systray/TrayMenuItem.qml @@ -1,7 +1,7 @@ import Quickshell import QtQuick import QtQuick.Layouts -import "../.." +import qs ColumnLayout { id: root @@ -12,8 +12,8 @@ ColumnLayout { Rectangle { visible: (root.modelData?.isSeparator ?? false) - color: ShellSettings.colors.inactive - opacity: 0.1 + color: ShellSettings.colors.inactive_translucent + // opacity: 0.1 Layout.fillWidth: true Layout.preferredHeight: 2 Layout.leftMargin: 8 diff --git a/shell/volume-osd/Controller.qml b/shell/volume-osd/Controller.qml index 96b59c8..b381574 100644 --- a/shell/volume-osd/Controller.qml +++ b/shell/volume-osd/Controller.qml @@ -33,15 +33,10 @@ Scope { onTriggered: root.shouldShowOsd = false } - // The OSD window will be created and destroyed based on shouldShowOsd. - // PanelWindow.visible could be set instead of using a loader, but using - // a loader will reduce the memory overhead when the window isn't open. LazyLoader { active: root.shouldShowOsd - PanelWindow { - anchors.right: true - margins.right: 5 + PopupWindow { implicitWidth: 50 implicitHeight: 275 color: "transparent" @@ -51,124 +46,57 @@ Scope { Rectangle { anchors.fill: parent - radius: width / 2 - color: ShellSettings.colors["surface"] - - ColumnLayout { - spacing: 10 + radius: 8 + color: { + let color = ShellSettings.colors["surface"]; + return Qt.rgba(color.r, color.g, color.b, 0.8); + } + RowLayout { anchors { fill: parent - margins: 8 + leftMargin: 10 + rightMargin: 15 + } + + IconImage { + implicitSize: 30 + source: "root:resources/volume/volume-full.svg" } Rectangle { - radius: width / 2 + id: sliderBackground Layout.fillWidth: true - Layout.preferredHeight: width - } - - Rectangle { - id: sliderContainer - color: "gray" - Layout.fillWidth: true - Layout.fillHeight: true + implicitHeight: 10 + radius: 20 + color: { + let color = ShellSettings.colors["inverse_surface"]; + return Qt.rgba(color.r, color.g, color.b, 0.5); + } layer.enabled: true layer.effect: OpacityMask { - source: Rectangle { - width: sliderContainer.width - height: sliderContainer.height - radius: sliderContainer.width / 2 - color: "white" - } - maskSource: Rectangle { - width: sliderContainer.width - height: sliderContainer.height - radius: sliderContainer.width / 2 + width: sliderBackground.width + height: sliderBackground.height + radius: sliderBackground.radius color: "black" } } Rectangle { - radius: width / 2 color: ShellSettings.colors["primary"] - implicitHeight: Math.max(parent.width, parent.height * (Pipewire.defaultAudioSink?.audio.volume ?? 0)) - anchors { - bottom: parent.bottom left: parent.left - right: parent.right + top: parent.top + bottom: parent.bottom } - // replace with material icon - // IconImage { - // implicitSize: parent.width - 4 - // source: "root:resources/volume/volume-full.svg" - // - // anchors { - // horizontalCenter: parent.horizontalCenter - // } - // } + implicitWidth: parent.width * (Pipewire.defaultAudioSink?.audio.volume ?? 0) } } } } - - // Rectangle { - // anchors.fill: parent - // radius: 8 - // color: { - // let color = ShellSettings.colors["surface"]; - // return Qt.rgba(color.r, color.g, color.b, 0.8); - // } - // - // RowLayout { - // anchors { - // fill: parent - // leftMargin: 10 - // rightMargin: 15 - // } - // - // IconImage { - // implicitSize: 30 - // source: "root:resources/volume/volume-full.svg" - // } - // - // Rectangle { - // id: sliderBackground - // Layout.fillWidth: true - // implicitHeight: 10 - // radius: 20 - // color: { - // let color = ShellSettings.colors["inverse_surface"]; - // return Qt.rgba(color.r, color.g, color.b, 0.5); - // } - // - // layer.enabled: true - // layer.effect: OpacityMask { - // maskSource: Rectangle { - // width: sliderBackground.width - // height: sliderBackground.height - // radius: sliderBackground.radius - // color: "black" - // } - // } - // - // Rectangle { - // color: ShellSettings.colors["primary"] - // anchors { - // left: parent.left - // top: parent.top - // bottom: parent.bottom - // } - // - // implicitWidth: parent.width * (Pipewire.defaultAudioSink?.audio.volume ?? 0) - // } - // } - // } - // } } } } diff --git a/shell/widgets/IconButton.qml b/shell/widgets/IconButton.qml index 8f7ca52..16cba83 100644 --- a/shell/widgets/IconButton.qml +++ b/shell/widgets/IconButton.qml @@ -1,6 +1,6 @@ import QtQuick import Quickshell.Widgets -import ".." +import qs Item { id: root @@ -9,8 +9,8 @@ Item { property var padding: 0 property var radius: 20 property var activeRectangle: true - property var color: ShellSettings.colors["inverse_surface"] - property var activeColor: ShellSettings.colors["inverse_primary"] + property var color: ShellSettings.colors.inactive_translucent + property var activeColor: ShellSettings.colors.active_translucent signal clicked implicitWidth: implicitSize @@ -18,7 +18,7 @@ Item { Rectangle { id: iconBackground - color: ShellSettings.colors["primary"] + color: ShellSettings.colors.active_translucent radius: root.radius visible: iconButton.containsMouse && root.activeRectangle anchors.fill: parent diff --git a/shell/widgets/StyledMouseArea.qml b/shell/widgets/StyledMouseArea.qml index a9786a9..d7c694a 100644 --- a/shell/widgets/StyledMouseArea.qml +++ b/shell/widgets/StyledMouseArea.qml @@ -1,5 +1,5 @@ import QtQuick -import ".." +import qs MouseArea { id: root @@ -7,7 +7,7 @@ MouseArea { property real radius: width / 2 property bool checked: false - property var activeColor: ShellSettings.colors["primary"] + property var activeColor: ShellSettings.colors.active_translucent property var inactiveColor: "transparent" Rectangle { diff --git a/shell/widgets/StyledPopup.qml b/shell/widgets/StyledPopup.qml index 8afa616..71883f5 100644 --- a/shell/widgets/StyledPopup.qml +++ b/shell/widgets/StyledPopup.qml @@ -1,6 +1,7 @@ import QtQuick import Quickshell import Quickshell.Widgets +import Quickshell.Hyprland import ".." PopupWindow { @@ -11,22 +12,42 @@ PopupWindow { default property alias contentItem: container.children + function open() { + // root.anchor.rect.y = -root.implicitHeight; + root.visible = true; + grab.active = true; + // slideAnimation.start(); + } + + function hide() { + root.visible = false; + grab.active = false; + } + + // PropertyAnimation { + // id: slideAnimation + // target: root.anchor.rect + // property: "y" + // from: -root.implicitHeight // Off-screen position + // to: 0 // On-screen position + // duration: 300 // Animation duration in milliseconds + // } + + HyprlandFocusGrab { + id: grab + windows: [root] + onCleared: root.hide() + } + WrapperRectangle { id: container margin: 5 radius: 12 - - color: { - let base = ShellSettings.colors.surface; - return Qt.rgba(base.r, base.g, base.b, 0.15); - } + color: ShellSettings.colors.surface_translucent border { width: 1 - color: { - let base = ShellSettings.colors.active; - return Qt.rgba(base.r, base.g, base.b, 0.05); - } + color: ShellSettings.colors.active_translucent } } }