From ef1170c770ec7c8186f906298516cee0008b5bc1 Mon Sep 17 00:00:00 2001 From: _xB <65196493+xBiei@users.noreply.github.com> Date: Fri, 6 Jun 2025 01:09:38 +0300 Subject: [PATCH 01/89] dock: Show pinned apps again --- .config/quickshell/modules/dock/Dock.qml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.config/quickshell/modules/dock/Dock.qml b/.config/quickshell/modules/dock/Dock.qml index 777aa6461..cbb291185 100644 --- a/.config/quickshell/modules/dock/Dock.qml +++ b/.config/quickshell/modules/dock/Dock.qml @@ -111,6 +111,24 @@ Scope { // Scope } } DockSeparator {} + // Pinned apps + Repeater { + model: ConfigOptions?.dock.pinnedApps ?? [] + + DockButton { + required property string modelData + onClicked: { + Hyprland.dispatch(`exec gio launch ${modelData}`) + } + contentItem: IconImage { + anchors.centerIn: parent + source: Quickshell.iconPath(AppSearch.guessIcon(modelData), "image-missing") + } + } + } + + DockSeparator { visible: (ConfigOptions?.dock.pinnedApps ?? []).length > 0 } + DockApps { id: dockApps } DockSeparator {} DockButton { From 403614d337ea39ccd3eaab79c4df793a81504a9a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 6 Jun 2025 20:39:15 +0200 Subject: [PATCH 02/89] add app name to code save notif --- .../quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml b/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml index fa4af99e0..ef0c1b5e9 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml @@ -97,7 +97,7 @@ ColumnLayout { onClicked: { const downloadPath = FileUtils.trimFileProtocol(Directories.downloads) Hyprland.dispatch(`exec echo '${StringUtils.shellSingleQuoteEscape(segmentContent)}' > '${downloadPath}/code.${segmentLang || "txt"}'`) - Hyprland.dispatch(`exec notify-send 'Code saved to file' '${downloadPath}/code.${segmentLang || "txt"}'`) + Hyprland.dispatch(`exec notify-send 'Code saved to file' '${downloadPath}/code.${segmentLang || "txt"}' -a Shell`) saveCodeButton.activated = true saveIconTimer.restart() } From 56b11e9ab7e895180f54dc1161dc4400cdcdab6e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 6 Jun 2025 20:39:29 +0200 Subject: [PATCH 03/89] comments --- .config/quickshell/modules/bar/Workspaces.qml | 4 ++-- .config/quickshell/services/Ai.qml | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.config/quickshell/modules/bar/Workspaces.qml b/.config/quickshell/modules/bar/Workspaces.qml index 4639edd22..5ed0e6af1 100644 --- a/.config/quickshell/modules/bar/Workspaces.qml +++ b/.config/quickshell/modules/bar/Workspaces.qml @@ -144,13 +144,13 @@ Item { Behavior on activeWorkspaceMargin { animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } - Behavior on idx1 { + Behavior on idx1 { // Leading anim NumberAnimation { duration: 100 easing.type: Easing.OutSine } } - Behavior on idx2 { + Behavior on idx2 { // Following anim NumberAnimation { duration: 300 easing.type: Easing.OutSine diff --git a/.config/quickshell/services/Ai.qml b/.config/quickshell/services/Ai.qml index c58137938..7b3084fca 100644 --- a/.config/quickshell/services/Ai.qml +++ b/.config/quickshell/services/Ai.qml @@ -430,8 +430,7 @@ Singleton { "parts": [{ text: root.systemPrompt }] }, "generationConfig": { - "temperature": root.temperature, - "responseMimeType": "text/plain", + // "temperature": root.temperature, }, }; return model.extraParams ? Object.assign({}, baseData, model.extraParams) : baseData; @@ -450,7 +449,7 @@ Singleton { }), ], "stream": true, - "temperature": root.temperature, + // "temperature": root.temperature, }; return model.extraParams ? Object.assign({}, baseData, model.extraParams) : baseData; } @@ -612,7 +611,7 @@ Singleton { stdout: SplitParser { onRead: data => { - // console.log("RAW DATA: ", data); + console.log("RAW DATA: ", data); if (data.length === 0) return; // Handle response line From 9111ada32b4ce747ec5609b971fecb03bda71649 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 6 Jun 2025 20:39:40 +0200 Subject: [PATCH 04/89] add m3 expressive slow spatial curve --- .config/quickshell/modules/common/Appearance.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index b9b45c288..7c1bc3104 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -176,6 +176,7 @@ Singleton { animationCurves: QtObject { readonly property list expressiveFastSpatial: [0.42, 1.67, 0.21, 0.90, 1, 1] // Default, 350ms readonly property list expressiveDefaultSpatial: [0.38, 1.21, 0.22, 1.00, 1, 1] // Default, 500ms + readonly property list expressiveSlowSpatial: [0.39, 1.29, 0.35, 0.98, 1, 1] // Default, 650ms readonly property list expressiveEffects: [0.34, 0.80, 0.34, 1.00, 1, 1] // Default, 200ms readonly property list emphasized: [0.05, 0, 2 / 15, 0.06, 1 / 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1] readonly property list emphasizedAccel: [0.3, 0, 0.8, 0.15, 1, 1] From eeb41de46ce110cec905045e9bf6cdb6a9860c27 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 6 Jun 2025 20:50:06 +0200 Subject: [PATCH 05/89] fix listview items being weird when changing both y and height --- .../modules/common/widgets/StyledListView.qml | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/.config/quickshell/modules/common/widgets/StyledListView.qml b/.config/quickshell/modules/common/widgets/StyledListView.qml index c13d8082f..835b9a43a 100644 --- a/.config/quickshell/modules/common/widgets/StyledListView.qml +++ b/.config/quickshell/modules/common/widgets/StyledListView.qml @@ -46,40 +46,40 @@ ListView { ] } - displaced: Transition { - animations: [ - Appearance?.animation.elementMove.numberAnimation.createObject(this, { - property: "y", - }), - Appearance?.animation.elementMove.numberAnimation.createObject(this, { - properties: "opacity,scale", - to: 1, - }), - ] - } + // displaced: Transition { + // animations: [ + // Appearance?.animation.elementMove.numberAnimation.createObject(this, { + // property: "y", + // }), + // Appearance?.animation.elementMove.numberAnimation.createObject(this, { + // properties: "opacity,scale", + // to: 1, + // }), + // ] + // } - move: Transition { - animations: [ - Appearance?.animation.elementMove.numberAnimation.createObject(this, { - property: "y", - }), - Appearance?.animation.elementMove.numberAnimation.createObject(this, { - properties: "opacity,scale", - to: 1, - }), - ] - } - moveDisplaced: Transition { - animations: [ - Appearance?.animation.elementMove.numberAnimation.createObject(this, { - property: "y", - }), - Appearance?.animation.elementMove.numberAnimation.createObject(this, { - properties: "opacity,scale", - to: 1, - }), - ] - } + // move: Transition { + // animations: [ + // Appearance?.animation.elementMove.numberAnimation.createObject(this, { + // property: "y", + // }), + // Appearance?.animation.elementMove.numberAnimation.createObject(this, { + // properties: "opacity,scale", + // to: 1, + // }), + // ] + // } + // moveDisplaced: Transition { + // animations: [ + // Appearance?.animation.elementMove.numberAnimation.createObject(this, { + // property: "y", + // }), + // Appearance?.animation.elementMove.numberAnimation.createObject(this, { + // properties: "opacity,scale", + // to: 1, + // }), + // ] + // } remove: Transition { animations: [ From 31e782a36f0d331f6325f17c78b7b44fb2f11414 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 6 Jun 2025 20:50:53 +0200 Subject: [PATCH 06/89] ai chat: prevent function call message from abrupt jumps --- .config/quickshell/modules/common/widgets/StyledListView.qml | 5 +++-- .config/quickshell/modules/sidebarLeft/AiChat.qml | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/modules/common/widgets/StyledListView.qml b/.config/quickshell/modules/common/widgets/StyledListView.qml index 835b9a43a..76d9782b4 100644 --- a/.config/quickshell/modules/common/widgets/StyledListView.qml +++ b/.config/quickshell/modules/common/widgets/StyledListView.qml @@ -18,6 +18,7 @@ ListView { property real removeOvershoot: 20 // Account for gaps and bouncy animations property int dragIndex: -1 property real dragDistance: 0 + property bool popin: true function resetDrag() { root.dragIndex = -1 @@ -27,7 +28,7 @@ ListView { add: Transition { animations: [ Appearance?.animation.elementMove.numberAnimation.createObject(this, { - properties: "opacity,scale", + properties: popin ? "opacity,scale" : "opacity", from: 0, to: 1, }), @@ -40,7 +41,7 @@ ListView { property: "y", }), Appearance?.animation.elementMove.numberAnimation.createObject(this, { - properties: "opacity,scale", + properties: popin ? "opacity,scale" : "opacity", to: 1, }), ] diff --git a/.config/quickshell/modules/sidebarLeft/AiChat.qml b/.config/quickshell/modules/sidebarLeft/AiChat.qml index 6eb069e94..b78ff89ce 100644 --- a/.config/quickshell/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/modules/sidebarLeft/AiChat.qml @@ -162,6 +162,7 @@ int main(int argc, char* argv[]) { id: messageListView anchors.fill: parent spacing: 10 + popin: false property int lastResponseLength: 0 @@ -175,6 +176,8 @@ int main(int argc, char* argv[]) { } } + add: null // Prevent function calls from being janky + Behavior on contentY { NumberAnimation { id: scrollAnim From a2f2fb816b9ecfa498270351cdf96559fa44b222 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 6 Jun 2025 21:25:56 +0200 Subject: [PATCH 07/89] make ripples more subtle (circle -> radial gradient) --- .../common/widgets/PrimaryTabButton.qml | 23 +++++++++++++++---- .../modules/common/widgets/RippleButton.qml | 22 ++++++++++++++---- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/.config/quickshell/modules/common/widgets/PrimaryTabButton.qml b/.config/quickshell/modules/common/widgets/PrimaryTabButton.qml index e59c8a962..b7c628712 100644 --- a/.config/quickshell/modules/common/widgets/PrimaryTabButton.qml +++ b/.config/quickshell/modules/common/widgets/PrimaryTabButton.qml @@ -110,13 +110,28 @@ TabButton { animation: Appearance?.animation.elementMoveFast.colorAnimation.createObject(this) } - Rectangle { + Item { id: ripple - - radius: Appearance?.rounding.full ?? 9999 - color: button.colRipple + width: ripple.implicitWidth + height: ripple.implicitHeight opacity: 0 + property real implicitWidth: 0 + property real implicitHeight: 0 + + Behavior on opacity { + animation: Appearance?.animation.elementMoveFast.colorAnimation.createObject(this) + } + + RadialGradient { + anchors.fill: parent + gradient: Gradient { + GradientStop { position: 0.0; color: button.colRipple } + GradientStop { position: 0.3; color: button.colRipple } + GradientStop { position: 0.5 ; color: Qt.rgba(button.colRipple.r, button.colRipple.g, button.colRipple.b, 0) } + } + } + transform: Translate { x: -ripple.width / 2 y: -ripple.height / 2 diff --git a/.config/quickshell/modules/common/widgets/RippleButton.qml b/.config/quickshell/modules/common/widgets/RippleButton.qml index 0a3a8743b..cd7762b9d 100644 --- a/.config/quickshell/modules/common/widgets/RippleButton.qml +++ b/.config/quickshell/modules/common/widgets/RippleButton.qml @@ -150,16 +150,28 @@ Button { } } - Rectangle { + Item { id: ripple - - radius: Appearance?.rounding.full ?? 9999 + width: ripple.implicitWidth + height: ripple.implicitHeight opacity: 0 - color: root.rippleColor - Behavior on color { + + property real implicitWidth: 0 + property real implicitHeight: 0 + + Behavior on opacity { animation: Appearance?.animation.elementMoveFast.colorAnimation.createObject(this) } + RadialGradient { + anchors.fill: parent + gradient: Gradient { + GradientStop { position: 0.0; color: root.rippleColor } + GradientStop { position: 0.3; color: root.rippleColor } + GradientStop { position: 0.5; color: Qt.rgba(root.rippleColor.r, root.rippleColor.g, root.rippleColor.b, 0) } + } + } + transform: Translate { x: -ripple.width / 2 y: -ripple.height / 2 From b70dbf5f10cb0bf7a122b109132928c2e6b70fb3 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 6 Jun 2025 22:56:05 +0200 Subject: [PATCH 08/89] hypridle: longer timeouts --- .config/hypr/hypridle.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.config/hypr/hypridle.conf b/.config/hypr/hypridle.conf index db2ea6082..2ec488c75 100644 --- a/.config/hypr/hypridle.conf +++ b/.config/hypr/hypridle.conf @@ -7,17 +7,17 @@ general { } listener { - timeout = 180 # 3mins + timeout = 300 # 5mins on-timeout = loginctl lock-session } listener { - timeout = 240 # 4mins + timeout = 600 # 10mins on-timeout = hyprctl dispatch dpms off on-resume = hyprctl dispatch dpms on } listener { - timeout = 540 # 9mins + timeout = 900 # 15mins on-timeout = $suspend_cmd } From 194b470cf21b59a7f265236bec95d4ea8bff8835 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 6 Jun 2025 23:29:29 +0200 Subject: [PATCH 09/89] installation: skip .local/bin --- diagnose | 1 - install.sh | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/diagnose b/diagnose index 7edbcbd1a..1964d2d66 100755 --- a/diagnose +++ b/diagnose @@ -57,7 +57,6 @@ e "Checking distro" x ii_check_distro e "Checking variables" -x declare -p XDG_BIN_HOME # ~/.local/bin x declare -p XDG_CACHE_HOME # ~/.cache x declare -p XDG_CONFIG_HOME # ~/.config x declare -p XDG_DATA_HOME # ~/.local/share diff --git a/install.sh b/install.sh index 89ee391ef..58cc6c441 100755 --- a/install.sh +++ b/install.sh @@ -249,7 +249,7 @@ esac # some foldes (eg. .local/bin) should be processed separately to avoid `--delete' for rsync, # since the files here come from different places, not only about one program. -v rsync -av ".local/bin/" "$XDG_BIN_HOME" +# v rsync -av ".local/bin/" "$XDG_BIN_HOME" # No longer needed since scripts are no longer in ~/.local/bin # Prevent hyprland from not fully loaded sleep 1 From 2b451c012beacd267d7cf60029357cb2c431b130 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 08:49:41 +0200 Subject: [PATCH 10/89] overview: anims when opening/closing windows --- .config/quickshell/modules/overview/OverviewWidget.qml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/modules/overview/OverviewWidget.qml b/.config/quickshell/modules/overview/OverviewWidget.qml index b060c8dfc..a690536fe 100644 --- a/.config/quickshell/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/modules/overview/OverviewWidget.qml @@ -144,10 +144,12 @@ Item { implicitHeight: workspaceColumnLayout.implicitHeight Repeater { // Window repeater - model: windowAddresses.filter((address) => { - var win = windowByAddress[address] - return (root.workspaceGroup * root.workspacesShown < win?.workspace?.id && win?.workspace?.id <= (root.workspaceGroup + 1) * root.workspacesShown) - }) + model: ScriptModel { + values: windowAddresses.filter((address) => { + var win = windowByAddress[address] + return (root.workspaceGroup * root.workspacesShown < win?.workspace?.id && win?.workspace?.id <= (root.workspaceGroup + 1) * root.workspacesShown) + }) + } delegate: OverviewWindow { id: window windowData: windowByAddress[modelData] From b6dcd19d04e2e4d83ecd1c2dd30161130d1c2ae7 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 11:12:10 +0200 Subject: [PATCH 11/89] bar: workspaces: use secondary container for occupied --- .config/quickshell/modules/bar/Workspaces.qml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/modules/bar/Workspaces.qml b/.config/quickshell/modules/bar/Workspaces.qml index 5ed0e6af1..cb3c6551a 100644 --- a/.config/quickshell/modules/bar/Workspaces.qml +++ b/.config/quickshell/modules/bar/Workspaces.qml @@ -2,6 +2,7 @@ import "root:/" import "root:/services/" import "root:/modules/common" import "root:/modules/common/widgets" +import "root:/modules/common/functions/color_utils.js" as ColorUtils import QtQuick import QtQuick.Controls import QtQuick.Layouts @@ -98,15 +99,17 @@ Item { implicitWidth: workspaceButtonWidth implicitHeight: workspaceButtonWidth radius: Appearance.rounding.full - property var radiusLeft: (workspaceOccupied[index-1] && !(!activeWindow?.activated && monitor.activeWorkspace?.id === index)) ? 0 : Appearance.rounding.full - property var radiusRight: (workspaceOccupied[index+1] && !(!activeWindow?.activated && monitor.activeWorkspace?.id === index+2)) ? 0 : Appearance.rounding.full + property var leftOccupied: (workspaceOccupied[index-1] && !(!activeWindow?.activated && monitor.activeWorkspace?.id === index)) + property var rightOccupied: (workspaceOccupied[index+1] && !(!activeWindow?.activated && monitor.activeWorkspace?.id === index+2)) + property var radiusLeft: leftOccupied ? 0 : Appearance.rounding.full + property var radiusRight: rightOccupied ? 0 : Appearance.rounding.full topLeftRadius: radiusLeft bottomLeftRadius: radiusLeft topRightRadius: radiusRight bottomRightRadius: radiusRight - color: Appearance.colors.colLayer2 + color: ColorUtils.transparentize(Appearance.m3colors.m3secondaryContainer, 0.4) opacity: (workspaceOccupied[index] && !(!activeWindow?.activated && monitor.activeWorkspace?.id === index+1)) ? 1 : 0 Behavior on opacity { @@ -203,7 +206,7 @@ Item { elide: Text.ElideRight color: (monitor.activeWorkspace?.id == button.workspaceValue) ? Appearance.m3colors.m3onPrimary : - (workspaceOccupied[index] ? Appearance.colors.colOnLayer1 : + (workspaceOccupied[index] ? Appearance.m3colors.m3onSecondaryContainer : Appearance.colors.colOnLayer1Inactive) Behavior on opacity { From 810ea2ce3b2fa6cfb17f0dc8fcc4ef508668ea61 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 11:14:28 +0200 Subject: [PATCH 12/89] circ prog: bigger gap angle --- .config/quickshell/modules/common/widgets/CircularProgress.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/widgets/CircularProgress.qml b/.config/quickshell/modules/common/widgets/CircularProgress.qml index 19a838c4c..d0afc6060 100644 --- a/.config/quickshell/modules/common/widgets/CircularProgress.qml +++ b/.config/quickshell/modules/common/widgets/CircularProgress.qml @@ -15,7 +15,7 @@ Item { property real value: 0 property color primaryColor: Appearance.m3colors.m3onSecondaryContainer property color secondaryColor: Appearance.m3colors.m3secondaryContainer - property real gapAngle: Math.PI / 10 + property real gapAngle: Math.PI / 9 property bool fill: false property int fillOverflow: 2 property int animationDuration: 1000 From e03800cf64cece1c3ba050b863f1d6470504a12e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 11:29:32 +0200 Subject: [PATCH 13/89] screen corners: mask layer visibility to the corners only --- .../modules/screenCorners/ScreenCorners.qml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.config/quickshell/modules/screenCorners/ScreenCorners.qml b/.config/quickshell/modules/screenCorners/ScreenCorners.qml index 32708dc60..37f0ff23b 100644 --- a/.config/quickshell/modules/screenCorners/ScreenCorners.qml +++ b/.config/quickshell/modules/screenCorners/ScreenCorners.qml @@ -5,6 +5,7 @@ import QtQuick.Controls import QtQuick.Layouts import Quickshell import Quickshell.Wayland +import Quickshell.Hyprland Scope { id: screenCorners @@ -23,6 +24,20 @@ Scope { mask: Region { item: null } + HyprlandWindow.visibleMask: Region { + Region { + item: topLeftCorner + } + Region { + item: topRightCorner + } + Region { + item: bottomLeftCorner + } + Region { + item: bottomRightCorner + } + } WlrLayershell.namespace: "quickshell:screenCorners" WlrLayershell.layer: WlrLayer.Overlay color: "transparent" @@ -35,24 +50,28 @@ Scope { } RoundCorner { + id: topLeftCorner anchors.top: parent.top anchors.left: parent.left size: Appearance.rounding.screenRounding corner: cornerEnum.topLeft } RoundCorner { + id: topRightCorner anchors.top: parent.top anchors.right: parent.right size: Appearance.rounding.screenRounding corner: cornerEnum.topRight } RoundCorner { + id: bottomLeftCorner anchors.bottom: parent.bottom anchors.left: parent.left size: Appearance.rounding.screenRounding corner: cornerEnum.bottomLeft } RoundCorner { + id: bottomRightCorner anchors.bottom: parent.bottom anchors.right: parent.right size: Appearance.rounding.screenRounding From 643b197d02c65a1895d679a8d2ca068a5a8e94af Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 14:10:31 +0200 Subject: [PATCH 14/89] notifications: fix spacing/eliding --- .../common/widgets/NotificationGroup.qml | 66 +++++++++++-------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/.config/quickshell/modules/common/widgets/NotificationGroup.qml b/.config/quickshell/modules/common/widgets/NotificationGroup.qml index 009a0b3ed..cfe93327c 100644 --- a/.config/quickshell/modules/common/widgets/NotificationGroup.qml +++ b/.config/quickshell/modules/common/widgets/NotificationGroup.qml @@ -154,42 +154,56 @@ Item { // Notification group area ColumnLayout { // Content Layout.fillWidth: true - spacing: expanded ? - ((root.multipleNotifications && - notificationGroup?.notifications[root.notificationCount - 1].image != "") ? 35 : - 5) : 0 + spacing: expanded ? (root.multipleNotifications ? + (notificationGroup?.notifications[root.notificationCount - 1].image != "") ? 35 : + 5 : 0) : 0 + // spacing: 00 Behavior on spacing { animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } - RowLayout { // App name (or summary when there's only 1 notif) and time + Item { // App name (or summary when there's only 1 notif) and time id: topRow - spacing: 0 + // spacing: 0 + Layout.fillWidth: true property real fontSize: Appearance.font.pixelSize.smaller property bool showAppName: root.multipleNotifications + implicitHeight: Math.max(topTextRow.implicitHeight, expandButton.implicitHeight) - StyledText { - id: appName - text: (topRow.showAppName ? - notificationGroup?.appName : - notificationGroup?.notifications[0]?.summary) || "" - font.pixelSize: topRow.showAppName ? - topRow.fontSize : - Appearance.font.pixelSize.small - color: topRow.showAppName ? - Appearance.colors.colSubtext : - Appearance.colors.colOnLayer2 + RowLayout { + id: topTextRow + anchors.left: parent.left + anchors.right: expandButton.left + anchors.verticalCenter: parent.verticalCenter + spacing: 5 + StyledText { + id: appName + elide: Text.ElideRight + Layout.fillWidth: true + text: (topRow.showAppName ? + notificationGroup?.appName : + notificationGroup?.notifications[0]?.summary) || "" + font.pixelSize: topRow.showAppName ? + topRow.fontSize : + Appearance.font.pixelSize.small + color: topRow.showAppName ? + Appearance.colors.colSubtext : + Appearance.colors.colOnLayer2 + } + StyledText { + id: timeText + // Layout.fillWidth: true + Layout.rightMargin: 10 + horizontalAlignment: Text.AlignLeft + text: NotificationUtils.getFriendlyNotifTimeString(notificationGroup?.time) + font.pixelSize: topRow.fontSize + color: Appearance.colors.colSubtext + } } - StyledText { - id: timeText - text: " • " + NotificationUtils.getFriendlyNotifTimeString(notificationGroup?.time) - font.pixelSize: topRow.fontSize - color: Appearance.colors.colSubtext - Layout.alignment: Qt.AlignRight - Layout.fillWidth: true - } - Item { Layout.fillWidth: true } NotificationGroupExpandButton { + id: expandButton + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter count: root.notificationCount expanded: root.expanded fontSize: topRow.fontSize From aadb38370c3984666ff7e632983271c82f080442 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 14:58:41 +0200 Subject: [PATCH 15/89] adjust shadows --- .config/hypr/hyprland/general.conf | 8 ++++---- .config/quickshell/modules/common/Appearance.qml | 4 ++-- .../quickshell/modules/sidebarLeft/SidebarLeft.qml | 2 +- .../modules/sidebarRight/SidebarRight.qml | 13 +++++++++++-- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/.config/hypr/hyprland/general.conf b/.config/hypr/hyprland/general.conf index bf3475f9f..03ad06074 100644 --- a/.config/hypr/hyprland/general.conf +++ b/.config/hypr/hyprland/general.conf @@ -64,10 +64,10 @@ decoration { shadow { enabled = true ignore_window = true - range = 70 - offset = 0 4 - render_power = 2 - color = rgba(00000020) + range = 30 + offset = 0 2 + render_power = 4 + color = rgba(00000010) } # Dim diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index 7c1bc3104..9f83ac5cf 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -136,7 +136,7 @@ Singleton { property color colTooltip: "#3C4043" // m3colors.m3inverseSurface in the specs, but the m3 website actually uses this color property color colOnTooltip: "#F8F9FA" // m3colors.m3inverseOnSurface in the specs, but the m3 website actually uses this color property color colScrim: ColorUtils.transparentize(m3colors.m3scrim, 0.5) - property color colShadow: ColorUtils.transparentize(m3colors.m3shadow, 0.85) + property color colShadow: ColorUtils.transparentize(m3colors.m3shadow, 0.7) } rounding: QtObject { @@ -288,7 +288,7 @@ Singleton { property real searchWidthCollapsed: 260 property real searchWidth: 450 property real hyprlandGapsOut: 5 - property real elevationMargin: 8 + property real elevationMargin: 10 property real fabShadowRadius: 5 property real fabHoveredShadowRadius: 7 } diff --git a/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml b/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml index 5cfd79472..ce0b22802 100644 --- a/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml +++ b/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml @@ -97,7 +97,7 @@ Scope { // Scope anchors.left: parent.left anchors.topMargin: Appearance.sizes.hyprlandGapsOut anchors.leftMargin: Appearance.sizes.hyprlandGapsOut - width: sidebarRoot.sidebarWidth - Appearance.sizes.hyprlandGapsOut * 2 + width: sidebarRoot.sidebarWidth - Appearance.sizes.hyprlandGapsOut - Appearance.sizes.elevationMargin height: parent.height - Appearance.sizes.hyprlandGapsOut * 2 color: Appearance.colors.colLayer0 radius: Appearance.rounding.screenRounding - Appearance.sizes.hyprlandGapsOut + 1 diff --git a/.config/quickshell/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/modules/sidebarRight/SidebarRight.qml index 57d836b0e..2bb92723d 100644 --- a/.config/quickshell/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/modules/sidebarRight/SidebarRight.qml @@ -52,8 +52,17 @@ Scope { Loader { id: sidebarContentLoader active: GlobalStates.sidebarRightOpen - anchors.centerIn: parent - width: sidebarWidth - Appearance.sizes.hyprlandGapsOut * 2 + anchors { + top: parent.top + bottom: parent.bottom + right: parent.right + left: parent.left + topMargin: Appearance.sizes.hyprlandGapsOut + rightMargin: Appearance.sizes.hyprlandGapsOut + bottomMargin: Appearance.sizes.hyprlandGapsOut + leftMargin: Appearance.sizes.elevationMargin + } + width: sidebarWidth - Appearance.sizes.hyprlandGapsOut - Appearance.sizes.elevationMargin height: parent.height - Appearance.sizes.hyprlandGapsOut * 2 sourceComponent: Item { From 2c548a42967aa2b72dbd50a45e22cf8fa783a1d6 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 14:58:46 +0200 Subject: [PATCH 16/89] fcitx5 blur --- .config/hypr/hyprland/general.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.config/hypr/hyprland/general.conf b/.config/hypr/hyprland/general.conf index 03ad06074..e8895efdc 100644 --- a/.config/hypr/hyprland/general.conf +++ b/.config/hypr/hyprland/general.conf @@ -59,6 +59,8 @@ decoration { contrast = 1 popups = true popups_ignorealpha = 0.6 + input_methods = true + input_methods_ignorealpha = 0.8 } shadow { From c1a4670de2712f699ee311786b1cac959e3de5ce Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 16:51:02 +0200 Subject: [PATCH 17/89] yad -> kdialog (closes #1367) --- .config/quickshell/scripts/switchwall.sh | 2 +- arch-packages/illogical-impulse-toolkit/PKGBUILD | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/scripts/switchwall.sh b/.config/quickshell/scripts/switchwall.sh index 22a87e158..838bb8b9c 100755 --- a/.config/quickshell/scripts/switchwall.sh +++ b/.config/quickshell/scripts/switchwall.sh @@ -267,7 +267,7 @@ main() { # Only prompt for wallpaper if not using --color and not using --noswitch and no imgpath set if [[ -z "$imgpath" && -z "$color_flag" && -z "$noswitch_flag" ]]; then cd "$(xdg-user-dir PICTURES)/Wallpapers" 2>/dev/null || cd "$(xdg-user-dir PICTURES)" || return 1 - imgpath="$(yad --width 1200 --height 800 --file --add-preview --large-preview --title='Choose wallpaper')" + imgpath="$(kdialog --getopenfilename . --title 'Choose wallpaper')" fi switch "$imgpath" "$mode_flag" "$type_flag" "$color_flag" "$color" diff --git a/arch-packages/illogical-impulse-toolkit/PKGBUILD b/arch-packages/illogical-impulse-toolkit/PKGBUILD index c73e804b0..673e12f8b 100644 --- a/arch-packages/illogical-impulse-toolkit/PKGBUILD +++ b/arch-packages/illogical-impulse-toolkit/PKGBUILD @@ -5,6 +5,7 @@ pkgdesc='Illogical Impulse GTK/Qt Dependencies' arch=(any) license=(None) depends=( + kdialog qt6-5compat qt6-base qt6-declarative @@ -22,6 +23,5 @@ depends=( upower wtype xdg-user-dirs-gtk - yad ydotool ) From 57327ab0fee4f255ccfb5bffb15c957584e99108 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 19:43:05 +0200 Subject: [PATCH 18/89] earbang protection --- .../modules/common/ConfigOptions.qml | 8 ++ .../OnScreenDisplayBrightness.qml | 2 +- .../onScreenDisplay/OnScreenDisplayVolume.qml | 87 +++++++++++++++---- .config/quickshell/services/Audio.qml | 37 +++++++- 4 files changed, 114 insertions(+), 20 deletions(-) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 91ba70408..529c04272 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -12,6 +12,14 @@ Singleton { property int fakeScreenRounding: 1 // 0: None | 1: Always | 2: When not fullscreen } + property QtObject audio: QtObject { // Values in % + property QtObject protection: QtObject { // Prevent sudden bangs + property bool enable: true + property real maxAllowedIncrease: 10 + property real maxAllowed: 90 // Realistically should already provide some protection when it's 99... + } + } + property QtObject apps: QtObject { property string bluetooth: "better-control --bluetooth" property string imageViewer: "loupe" diff --git a/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayBrightness.qml b/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayBrightness.qml index decb7537c..765386bc8 100644 --- a/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayBrightness.qml +++ b/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayBrightness.qml @@ -73,7 +73,7 @@ Scope { item: osdValuesWrapper } - implicitWidth: Appearance.sizes.osdWidth + implicitWidth: columnLayout.implicitWidth implicitHeight: columnLayout.implicitHeight visible: osdLoader.active diff --git a/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayVolume.qml b/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayVolume.qml index e1904354e..5d23b4405 100644 --- a/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayVolume.qml +++ b/.config/quickshell/modules/onScreenDisplay/OnScreenDisplayVolume.qml @@ -12,6 +12,7 @@ import Quickshell.Hyprland Scope { id: root property bool showOsdValues: false + property string protectionMessage: "" property var focusedScreen: Quickshell.screens.find(s => s.name === Hyprland.focusedMonitor?.name) function triggerOsd() { @@ -25,7 +26,8 @@ Scope { repeat: false running: false onTriggered: { - showOsdValues = false + root.showOsdValues = false + root.protectionMessage = "" } } @@ -36,7 +38,7 @@ Scope { } } - Connections { + Connections { // Listen to volume changes target: Audio.sink?.audio ?? null function onVolumeChanged() { if (!Audio.ready) return @@ -48,6 +50,14 @@ Scope { } } + Connections { // Listen to protection triggers + target: Audio + function onSinkProtectionTriggered(reason) { + root.protectionMessage = reason; + root.triggerOsd() + } + } + Loader { id: osdLoader active: showOsdValues @@ -75,7 +85,7 @@ Scope { item: osdValuesWrapper } - implicitWidth: Appearance.sizes.osdWidth + implicitWidth: columnLayout.implicitWidth implicitHeight: columnLayout.implicitHeight visible: osdLoader.active @@ -85,8 +95,8 @@ Scope { Item { id: osdValuesWrapper // Extra space for shadow - implicitHeight: osdValues.implicitHeight + Appearance.sizes.elevationMargin * 2 - implicitWidth: osdValues.implicitWidth + implicitHeight: contentColumnLayout.implicitHeight + Appearance.sizes.elevationMargin * 2 + implicitWidth: contentColumnLayout.implicitWidth clip: true MouseArea { @@ -95,20 +105,63 @@ Scope { onEntered: root.showOsdValues = false } - Behavior on implicitHeight { - NumberAnimation { - duration: Appearance.animation.menuDecel.duration - easing.type: Appearance.animation.menuDecel.type + ColumnLayout { + id: contentColumnLayout + anchors { + top: parent.top + left: parent.left + right: parent.right + leftMargin: Appearance.sizes.elevationMargin + rightMargin: Appearance.sizes.elevationMargin } - } + spacing: 0 - OsdValueIndicator { - id: osdValues - anchors.fill: parent - anchors.margins: Appearance.sizes.elevationMargin - value: Audio.sink?.audio.volume ?? 0 - icon: Audio.sink?.audio.muted ? "volume_off" : "volume_up" - name: qsTr("Volume") + OsdValueIndicator { + id: osdValues + Layout.fillWidth: true + value: Audio.sink?.audio.volume ?? 0 + icon: Audio.sink?.audio.muted ? "volume_off" : "volume_up" + name: qsTr("Volume") + } + + Item { + id: protectionMessageWrapper + implicitHeight: protectionMessageBackground.implicitHeight + implicitWidth: protectionMessageBackground.implicitWidth + Layout.alignment: Qt.AlignHCenter + opacity: root.protectionMessage !== "" ? 1 : 0 + + StyledRectangularShadow { + target: protectionMessageBackground + } + Rectangle { + id: protectionMessageBackground + anchors.centerIn: parent + color: Appearance.m3colors.m3error + property real padding: 10 + implicitHeight: protectionMessageRowLayout.implicitHeight + padding * 2 + implicitWidth: protectionMessageRowLayout.implicitWidth + padding * 2 + radius: Appearance.rounding.normal + + RowLayout { + id: protectionMessageRowLayout + anchors.centerIn: parent + MaterialSymbol { + id: protectionMessageIcon + text: "dangerous" + iconSize: Appearance.font.pixelSize.hugeass + color: Appearance.m3colors.m3onError + } + StyledText { + id: protectionMessageTextWidget + horizontalAlignment: Text.AlignHCenter + color: Appearance.m3colors.m3onError + wrapMode: Text.Wrap + text: root.protectionMessage + } + } + } + } } } } diff --git a/.config/quickshell/services/Audio.qml b/.config/quickshell/services/Audio.qml index 8b5f9b760..dd46f0fbb 100644 --- a/.config/quickshell/services/Audio.qml +++ b/.config/quickshell/services/Audio.qml @@ -1,3 +1,4 @@ +import "root:/modules/common" import QtQuick import Quickshell import Quickshell.Services.Pipewire @@ -11,11 +12,43 @@ Singleton { id: root property bool ready: Pipewire.defaultAudioSink?.ready ?? false - property var sink: Pipewire.defaultAudioSink - property var source: Pipewire.defaultAudioSource + property PwNode sink: Pipewire.defaultAudioSink + property PwNode source: Pipewire.defaultAudioSource + + signal sinkProtectionTriggered(string reason); PwObjectTracker { objects: [sink, source] + Component.onCompleted: { + sink.audio.volume = sink.audio.volume; // Trigger initial volume change + } + } + + Connections { // Protection against sudden volume changes + target: sink?.audio ?? null + property bool lastReady: false + property real lastVolume: 0 + function onVolumeChanged() { + if (!ConfigOptions.audio.protection.enable) return; + if (!lastReady) { + lastVolume = sink.audio.volume; + lastReady = true; + return; + } + const newVolume = sink.audio.volume; + const maxAllowedIncrease = ConfigOptions.audio.protection.maxAllowedIncrease / 100; + const maxAllowed = ConfigOptions.audio.protection.maxAllowed / 100; + + if (newVolume - lastVolume > maxAllowedIncrease) { + sink.audio.volume = lastVolume; + root.sinkProtectionTriggered("Illegal increment"); + } else if (newVolume > maxAllowed) { + sink.audio.volume = lastVolume; + root.sinkProtectionTriggered("Exceeded max allowed"); + } + lastVolume = sink.audio.volume; + } + } } From 1591b72e4a49ae98236992aeb16a1c8da2b4d9c5 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 21:00:51 +0200 Subject: [PATCH 19/89] installation: remove ags --- diagnose | 10 ---------- install.sh | 43 ++++++---------------------------------- manual-install-helper.sh | 1 - 3 files changed, 6 insertions(+), 48 deletions(-) diff --git a/diagnose b/diagnose index 1964d2d66..df1d0dee4 100755 --- a/diagnose +++ b/diagnose @@ -38,16 +38,6 @@ ii_check_venv() { which python deactivate } -ii_check_ags() { - pkill ags - pkill agsv1 - agsv1 > ii_ags.log 2>&1 & - GUI_PID=$! - sleep 10 - kill $GUI_PID - echo "AGS log saved to \"ii_ags.log\"." -} -#x ii_check_ags e "Checking git repo info" x git remote get-url origin diff --git a/install.sh b/install.sh index 58cc6c441..7b47af0d4 100755 --- a/install.sh +++ b/install.sh @@ -155,11 +155,11 @@ v mkdir -p $XDG_BIN_HOME $XDG_CACHE_HOME $XDG_CONFIG_HOME $XDG_DATA_HOME # original dotfiles and new ones in the SAME DIRECTORY # (eg. in ~/.config/hypr) won't be mixed together -# MISC (For .config/* but not AGS, not Fish, not Hyprland) +# MISC (For .config/* but not fish, not Hyprland) case $SKIP_MISCCONF in true) sleep 0;; *) - for i in $(find .config/ -mindepth 1 -maxdepth 1 ! -name 'ags' ! -name 'fish' ! -name 'hypr' -exec basename {} \;); do + for i in $(find .config/ -mindepth 1 -maxdepth 1 ! -name 'fish' ! -name 'hypr' -exec basename {} \;); do # i=".config/$i" echo "[$0]: Found target: .config/$i" if [ -d ".config/$i" ];then v rsync -av --delete ".config/$i/" "$XDG_CONFIG_HOME/$i/" @@ -176,24 +176,6 @@ case $SKIP_FISH in ;; esac -# For AGS -case $SKIP_AGS in - true) sleep 0;; - *) - v rsync -av --delete --exclude '/user_options.jsonc' .config/ags/ "$XDG_CONFIG_HOME"/ags/ - t="$XDG_CONFIG_HOME/ags/user_options.jsonc" - if [ -f $t ];then - echo -e "\e[34m[$0]: \"$t\" already exists.\e[0m" - # v cp -f .config/ags/user_options.jsonc $t.new - existed_ags_opt=y - else - echo -e "\e[33m[$0]: \"$t\" does not exist yet.\e[0m" - v cp .config/ags/user_options.jsonc $t - existed_ags_opt=n - fi - ;; -esac - # For Hyprland case $SKIP_HYPRLAND in true) sleep 0;; @@ -202,15 +184,9 @@ case $SKIP_HYPRLAND in t="$XDG_CONFIG_HOME/hypr/hyprland.conf" if [ -f $t ];then echo -e "\e[34m[$0]: \"$t\" already exists.\e[0m" - if [ -f "$XDG_STATE_HOME/ags/user/firstrun.txt" ] - then - v cp -f .config/hypr/hyprland.conf $t.new - existed_hypr_conf=y - else - v mv $t $t.old - v cp -f .config/hypr/hyprland.conf $t - existed_hypr_conf_firstrun=y - fi + v mv $t $t.old + v cp -f .config/hypr/hyprland.conf $t + existed_hypr_conf_firstrun=y else echo -e "\e[33m[$0]: \"$t\" does not exist yet.\e[0m" v cp .config/hypr/hyprland.conf $t @@ -260,10 +236,7 @@ grep -q 'source ${XDG_CONFIG_HOME:-~/.config}/zshrc.d/dots-hyprland.zsh' ~/.zshr warn_files=() warn_files_tests=() -warn_files_tests+=(/usr/local/bin/ags) -warn_files_tests+=(/usr/local/etc/pam.d/ags) warn_files_tests+=(/usr/local/lib/{GUtils-1.0.typelib,Gvc-1.0.typelib,libgutils.so,libgvc.so}) -warn_files_tests+=(/usr/local/share/com.github.Aylur.ags) warn_files_tests+=(/usr/local/share/fonts/TTF/Rubik{,-Italic}'[wght]'.ttf) warn_files_tests+=(/usr/local/share/licenses/ttf-rubik) warn_files_tests+=(/usr/local/share/fonts/TTF/Gabarito-{Black,Bold,ExtraBold,Medium,Regular,SemiBold}.ttf) @@ -289,10 +262,6 @@ printf "\e[36mPress \e[30m\e[46m Ctrl+Super+T \e[0m\e[36m to select a wallpaper\ printf "\e[36mPress \e[30m\e[46m Super+/ \e[0m\e[36m for a list of keybinds\e[0m\n" printf "\n" -case $existed_ags_opt in - y) printf "\n\e[33m[$0]: Warning: \"$XDG_CONFIG_HOME/ags/user_options.jsonc\" already existed before and we didn't overwrite it. \e[0m\n" -# printf "\e[33mPlease use \"$XDG_CONFIG_HOME/ags/user_options.jsonc.new\" as a reference for a proper format.\e[0m\n" -;;esac case $existed_hypr_conf_firstrun in y) printf "\n\e[33m[$0]: Warning: \"$XDG_CONFIG_HOME/hypr/hyprland.conf\" already existed before. As it seems it is your first run, we replaced it with a new one. \e[0m\n" printf "\e[33mAs it seems it is your first run, we replaced it with a new one. The old one has been renamed to \"$XDG_CONFIG_HOME/hypr/hyprland.conf.old\".\e[0m\n" @@ -311,7 +280,7 @@ case $existed_hyprlock_conf in ;;esac if [[ -z "${ILLOGICAL_IMPULSE_VIRTUAL_ENV}" ]]; then - printf "\n\e[31m[$0]: \!! Important \!! : Please ensure environment variable \e[0m \$ILLOGICAL_IMPULSE_VIRTUAL_ENV \e[31m is set to proper value (by default \"~/.local/state/ags/.venv\"), or AGS config will not work. We have already provided this configuration in ~/.config/hypr/hyprland/env.conf, but you need to ensure it is included in hyprland.conf, and also a restart is needed for applying it.\e[0m\n" + printf "\n\e[31m[$0]: \!! Important \!! : Please ensure environment variable \e[0m \$ILLOGICAL_IMPULSE_VIRTUAL_ENV \e[31m is set to proper value (by default \"~/.local/state/quickshell/.venv\"), or Quickshell config will not work. We have already provided this configuration in ~/.config/hypr/hyprland/env.conf, but you need to ensure it is included in hyprland.conf, and also a restart is needed for applying it.\e[0m\n" fi if [[ ! -z "${warn_files[@]}" ]]; then diff --git a/manual-install-helper.sh b/manual-install-helper.sh index 663f3009a..d594f2c16 100755 --- a/manual-install-helper.sh +++ b/manual-install-helper.sh @@ -11,7 +11,6 @@ source ./scriptdata/installers prevent_sudo_or_root if command -v pacman >/dev/null 2>&1;then printf "\e[31m[$0]: pacman found, it seems that the system is ArchLinux or Arch-based distro. Aborting...\e[0m\n";exit 1;fi -v install-agsv1 v install-Rubik v install-Gabarito v install-OneUI From 5364d0e4f7fc5fc6ae00190cd2a222107bd4dc14 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 21:45:52 +0200 Subject: [PATCH 20/89] dock: use quickshell-native way to open apps --- .config/quickshell/modules/dock/Dock.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/modules/dock/Dock.qml b/.config/quickshell/modules/dock/Dock.qml index cbb291185..7123c0810 100644 --- a/.config/quickshell/modules/dock/Dock.qml +++ b/.config/quickshell/modules/dock/Dock.qml @@ -116,9 +116,11 @@ Scope { // Scope model: ConfigOptions?.dock.pinnedApps ?? [] DockButton { + id: pinnedAppButton required property string modelData + property DesktopEntry entry: DesktopEntries.byId(modelData) onClicked: { - Hyprland.dispatch(`exec gio launch ${modelData}`) + pinnedAppButton?.entry.execute(); } contentItem: IconImage { anchors.centerIn: parent From 0d4877a77ecdf7d08a8eb3cc65b33eec075b12c9 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 21:57:57 +0200 Subject: [PATCH 21/89] dock: display num of open windows --- .../quickshell/modules/dock/DockAppButton.qml | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/modules/dock/DockAppButton.qml b/.config/quickshell/modules/dock/DockAppButton.qml index 7ff11bae1..65e8bf88d 100644 --- a/.config/quickshell/modules/dock/DockAppButton.qml +++ b/.config/quickshell/modules/dock/DockAppButton.qml @@ -17,6 +17,10 @@ DockButton { required property var appToplevel property var appListRoot property int lastFocused: -1 + property real iconSize: 35 + property real countDotWidth: 10 + property real countDotHeight: 4 + MouseArea { id: mouseArea anchors.fill: parent @@ -37,8 +41,38 @@ DockButton { lastFocused = (lastFocused + 1) % appToplevel.toplevels.length appToplevel.toplevels[lastFocused].activate() } - contentItem: IconImage { - id: iconImage - source: Quickshell.iconPath(AppSearch.guessIcon(appToplevel.appId), "image-missing") + contentItem: Item { + anchors.centerIn: parent + + IconImage { + id: iconImage + anchors { + left: parent.left + right: parent.right + verticalCenter: parent.verticalCenter + } + source: Quickshell.iconPath(AppSearch.guessIcon(appToplevel.appId), "image-missing") + implicitSize: appButton.iconSize + } + + RowLayout { + spacing: 3 + anchors { + top: iconImage.bottom + topMargin: 2 + horizontalCenter: parent.horizontalCenter + } + Repeater { + model: Math.min(appToplevel.toplevels.length, 3) + delegate: Rectangle { + required property int index + radius: Appearance.rounding.full + implicitWidth: (appToplevel.toplevels.length <= 3) ? + appButton.countDotWidth : appButton.countDotHeight // Circles when too many + implicitHeight: appButton.countDotHeight + color: Appearance.m3colors.m3primary + } + } + } } } From db1fc0f6be19db6116b5f4890ff4337d8c0df673 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 22:23:03 +0200 Subject: [PATCH 22/89] dock: fix bottom spacing --- .config/quickshell/modules/dock/Dock.qml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.config/quickshell/modules/dock/Dock.qml b/.config/quickshell/modules/dock/Dock.qml index 7123c0810..0e5cc4836 100644 --- a/.config/quickshell/modules/dock/Dock.qml +++ b/.config/quickshell/modules/dock/Dock.qml @@ -34,7 +34,9 @@ Scope { // Scope function hide() { cheatsheetLoader.active = false } - exclusiveZone: root.pinned ? implicitHeight - Appearance.sizes.hyprlandGapsOut : 0 + exclusiveZone: root.pinned ? implicitHeight + - (Appearance.sizes.hyprlandGapsOut) + - (Appearance.sizes.elevationMargin - Appearance.sizes.hyprlandGapsOut) : 0 implicitWidth: dockBackground.implicitWidth WlrLayershell.namespace: "quickshell:dock" @@ -63,11 +65,13 @@ Scope { // Scope id: dockHoverRegion anchors.fill: parent - Item { + Item { // Wrapper for the dock background id: dockBackground - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.horizontalCenter: parent.horizontalCenter + anchors { + top: parent.top + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + } implicitWidth: dockRow.implicitWidth + 5 * 2 height: parent.height - Appearance.sizes.elevationMargin - Appearance.sizes.hyprlandGapsOut @@ -75,12 +79,12 @@ Scope { // Scope StyledRectangularShadow { target: dockVisualBackground } - Rectangle { + Rectangle { // The real rectangle that is visible id: dockVisualBackground property real margin: Appearance.sizes.elevationMargin anchors.fill: parent anchors.topMargin: margin - anchors.bottomMargin: margin + anchors.bottomMargin: Appearance.sizes.hyprlandGapsOut color: Appearance.colors.colLayer0 radius: Appearance.rounding.large } From 99ab1b179b38fd88cb7780ede492aec9a16182a0 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 22:24:21 +0200 Subject: [PATCH 23/89] dock: pin kitty by default --- .config/quickshell/modules/common/ConfigOptions.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 529c04272..96832c48f 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -58,6 +58,7 @@ Singleton { property bool pinnedOnStartup: false property list pinnedApps: [ // IDs of pinned entries "org.kde.dolphin", + "kitty", ] } From a8474af78d7028610f86ce5e46501e3bd9543135 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 22:37:03 +0200 Subject: [PATCH 24/89] ai: comment debug print --- .config/quickshell/services/Ai.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/services/Ai.qml b/.config/quickshell/services/Ai.qml index 7b3084fca..dbb8869d7 100644 --- a/.config/quickshell/services/Ai.qml +++ b/.config/quickshell/services/Ai.qml @@ -611,7 +611,7 @@ Singleton { stdout: SplitParser { onRead: data => { - console.log("RAW DATA: ", data); + // console.log("RAW DATA: ", data); if (data.length === 0) return; // Handle response line From 1add44ba2fb758abf4f256b230c31c64ca82a1b0 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 22:37:32 +0200 Subject: [PATCH 25/89] dock: show on empty workspace --- .config/quickshell/modules/common/ConfigOptions.qml | 3 ++- .config/quickshell/modules/dock/Dock.qml | 5 ++++- .config/quickshell/modules/dock/DockAppButton.qml | 1 + .config/quickshell/shell.qml | 4 ++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 96832c48f..ee0522f57 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -52,10 +52,11 @@ Singleton { } property QtObject dock: QtObject { - property bool enable: false + property bool enable: true property real height: 60 property real hoverRegionHeight: 3 property bool pinnedOnStartup: false + property bool hoverToReveal: false // When false, only reveals on empty workspace property list pinnedApps: [ // IDs of pinned entries "org.kde.dolphin", "kitty", diff --git a/.config/quickshell/modules/dock/Dock.qml b/.config/quickshell/modules/dock/Dock.qml index 0e5cc4836..69e36778a 100644 --- a/.config/quickshell/modules/dock/Dock.qml +++ b/.config/quickshell/modules/dock/Dock.qml @@ -23,7 +23,10 @@ Scope { // Scope id: dockRoot screen: modelData - property bool reveal: root.pinned || dockMouseArea.containsMouse || dockApps.requestDockShow + property bool reveal: root.pinned + || ((ConfigOptions?.dock.hoverToReveal ?? true) && dockMouseArea.containsMouse) + || dockApps.requestDockShow + || (!ToplevelManager.activeToplevel?.activated) anchors { bottom: true diff --git a/.config/quickshell/modules/dock/DockAppButton.qml b/.config/quickshell/modules/dock/DockAppButton.qml index 65e8bf88d..7e79ad626 100644 --- a/.config/quickshell/modules/dock/DockAppButton.qml +++ b/.config/quickshell/modules/dock/DockAppButton.qml @@ -20,6 +20,7 @@ DockButton { property real iconSize: 35 property real countDotWidth: 10 property real countDotHeight: 4 + property bool appIsActive: appToplevel.toplevels.find(t => (t.activated == true)) !== undefined MouseArea { id: mouseArea diff --git a/.config/quickshell/shell.qml b/.config/quickshell/shell.qml index bc2cb0221..e6e5d566c 100644 --- a/.config/quickshell/shell.qml +++ b/.config/quickshell/shell.qml @@ -27,7 +27,7 @@ ShellRoot { // no unnecessary stuff will take up memory if you decide to only use, say, the overview. property bool enableBar: true property bool enableCheatsheet: true - property bool enableDock: false + property bool enableDock: true property bool enableMediaControls: true property bool enableNotificationPopup: true property bool enableOnScreenDisplayBrightness: true @@ -51,7 +51,7 @@ ShellRoot { Loader { active: enableBar; sourceComponent: Bar {} } Loader { active: enableCheatsheet; sourceComponent: Cheatsheet {} } - Loader { active: (enableDock || ConfigOptions?.dock.enable); sourceComponent: Dock {} } + Loader { active: (enableDock && ConfigOptions?.dock.enable); sourceComponent: Dock {} } Loader { active: enableMediaControls; sourceComponent: MediaControls {} } Loader { active: enableNotificationPopup; sourceComponent: NotificationPopup {} } Loader { active: enableOnScreenDisplayBrightness; sourceComponent: OnScreenDisplayBrightness {} } From bbd2bfda5d665c84f7f28284b90d3341a9b7dfe9 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 23:02:15 +0200 Subject: [PATCH 26/89] dock: adjust active color --- .config/quickshell/modules/dock/Dock.qml | 2 +- .config/quickshell/modules/dock/DockAppButton.qml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/modules/dock/Dock.qml b/.config/quickshell/modules/dock/Dock.qml index 69e36778a..b89630228 100644 --- a/.config/quickshell/modules/dock/Dock.qml +++ b/.config/quickshell/modules/dock/Dock.qml @@ -24,7 +24,7 @@ Scope { // Scope screen: modelData property bool reveal: root.pinned - || ((ConfigOptions?.dock.hoverToReveal ?? true) && dockMouseArea.containsMouse) + || (ConfigOptions?.dock.hoverToReveal && dockMouseArea.containsMouse) || dockApps.requestDockShow || (!ToplevelManager.activeToplevel?.activated) diff --git a/.config/quickshell/modules/dock/DockAppButton.qml b/.config/quickshell/modules/dock/DockAppButton.qml index 7e79ad626..9df44c853 100644 --- a/.config/quickshell/modules/dock/DockAppButton.qml +++ b/.config/quickshell/modules/dock/DockAppButton.qml @@ -2,6 +2,7 @@ import "root:/" import "root:/services" import "root:/modules/common" import "root:/modules/common/widgets" +import "root:/modules/common/functions/color_utils.js" as ColorUtils import QtQuick import QtQuick.Controls import QtQuick.Effects @@ -71,7 +72,7 @@ DockButton { implicitWidth: (appToplevel.toplevels.length <= 3) ? appButton.countDotWidth : appButton.countDotHeight // Circles when too many implicitHeight: appButton.countDotHeight - color: Appearance.m3colors.m3primary + color: appIsActive ? Appearance.m3colors.m3primary : ColorUtils.transparentize(Appearance.colors.colOnLayer0, 0.4) } } } From c9ffb84ffc53a60803eaf8f0f53158d0a2626e54 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 7 Jun 2025 23:25:13 +0200 Subject: [PATCH 27/89] bar: borderless: add separators, no longer default --- .config/quickshell/modules/bar/Bar.qml | 15 +++++++++++++-- .../quickshell/modules/common/ConfigOptions.qml | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index 891c9a2c8..ca9b1e57e 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -19,6 +19,14 @@ Scope { readonly property int osdHideMouseMoveThreshold: 20 property bool showBarBackground: ConfigOptions.bar.showBackground + component VerticalBarSeparator: Rectangle { + Layout.topMargin: barHeight / 3 + Layout.bottomMargin: barHeight / 3 + Layout.fillHeight: true + implicitWidth: 1 + color: Appearance.m3colors.m3outlineVariant + } + Variants { // For each monitor model: Quickshell.screens @@ -180,7 +188,7 @@ Scope { RowLayout { // Middle section id: middleSection anchors.centerIn: parent - spacing: 8 + spacing: ConfigOptions?.bar.borderless ? 4 : 8 RowLayout { id: leftCenterGroup @@ -201,9 +209,10 @@ Scope { } + VerticalBarSeparator {visible: ConfigOptions?.bar.borderless} + RowLayout { id: middleCenterGroup - Layout.fillWidth: true Layout.fillHeight: true Workspaces { @@ -222,6 +231,8 @@ Scope { } + VerticalBarSeparator {visible: ConfigOptions?.bar.borderless} + RowLayout { id: rightCenterGroup Layout.preferredWidth: leftCenterGroup.width diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index ee0522f57..852a4b97c 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -37,7 +37,7 @@ Singleton { property QtObject bar: QtObject { property bool bottom: false // Instead of top - property bool borderless: true + property bool borderless: false // true for no grouping of items property string topLeftIcon: "spark" // Options: distro, spark property bool showBackground: true property QtObject resources: QtObject { From 0b7f80ed0566bdcf254fb7a09da25d9735a8c431 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 8 Jun 2025 02:10:01 +0200 Subject: [PATCH 28/89] script for least busy region of image --- .config/matugen/scripts/least_busy_region.py | 253 +++++++++++++++++++ scriptdata/requirements.in | 1 + scriptdata/requirements.txt | 8 +- 3 files changed, 259 insertions(+), 3 deletions(-) create mode 100755 .config/matugen/scripts/least_busy_region.py diff --git a/.config/matugen/scripts/least_busy_region.py b/.config/matugen/scripts/least_busy_region.py new file mode 100755 index 000000000..68e08ca12 --- /dev/null +++ b/.config/matugen/scripts/least_busy_region.py @@ -0,0 +1,253 @@ +#!/usr/bin/env -S\_/bin/sh\_-c\_"source\_\$(eval\_echo\_\$ILLOGICAL_IMPULSE_VIRTUAL_ENV)/bin/activate&&exec\_python\_-E\_"\$0"\_"\$@"" +# Disclaimer: This script is vibe-coded. + +import os +os.environ["OPENCV_LOG_LEVEL"] = "SILENT" +import cv2 +import numpy as np +import argparse +import json + +def find_least_busy_region(image_path, region_width=300, region_height=200, screen_width=None, screen_height=None, verbose=False, stride=2, screen_mode="fill"): + img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) + if img is None: + raise FileNotFoundError(f"Image not found: {image_path}") + orig_h, orig_w = img.shape + scale = 1.0 + if screen_width is not None and screen_height is not None: + scale_w = screen_width / orig_w + scale_h = screen_height / orig_h + if screen_mode == "fill": + scale = max(scale_w, scale_h) + else: + scale = min(scale_w, scale_h) + new_w = int(orig_w * scale) + new_h = int(orig_h * scale) + if verbose: + print(f"Scaling image from {orig_w}x{orig_h} to {new_w}x{new_h} (scale: {scale:.3f}, mode: {screen_mode})") + img = cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_LANCZOS4) + else: + if verbose: + print(f"Using original image size: {orig_w}x{orig_h}") + arr = img.astype(np.float64) + h, w = arr.shape + # Use OpenCV's integral for fast computation + integral = cv2.integral(arr, sdepth=cv2.CV_64F)[1:,1:] + integral_sq = cv2.integral(arr**2, sdepth=cv2.CV_64F)[1:,1:] + def region_sum(ii, x1, y1, x2, y2): + total = ii[y2, x2] + if x1 > 0: + total -= ii[y2, x1-1] + if y1 > 0: + total -= ii[y1-1, x2] + if x1 > 0 and y1 > 0: + total += ii[y1-1, x1-1] + return total + min_var = None + min_coords = (0, 0) + area = region_width * region_height + for y in range(0, h - region_height + 1, stride): + for x in range(0, w - region_width + 1, stride): + x1, y1 = x, y + x2, y2 = x + region_width - 1, y + region_height - 1 + s = region_sum(integral, x1, y1, x2, y2) + s2 = region_sum(integral_sq, x1, y1, x2, y2) + mean = s / area + var = (s2 / area) - (mean ** 2) + if (min_var is None) or (var < min_var): + min_var = var + min_coords = (x, y) + return min_coords, min_var + +def find_largest_region(image_path, screen_width=None, screen_height=None, verbose=False, stride=2, screen_mode="fill", threshold=100.0, aspect_ratio=1.0): + img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) + if img is None: + raise FileNotFoundError(f"Image not found: {image_path}") + orig_h, orig_w = img.shape + scale = 1.0 + if screen_width is not None and screen_height is not None: + scale_w = screen_width / orig_w + scale_h = screen_height / orig_h + if screen_mode == "fill": + scale = max(scale_w, scale_h) + else: + scale = min(scale_w, scale_h) + new_w = int(orig_w * scale) + new_h = int(orig_h * scale) + if verbose: + print(f"Scaling image from {orig_w}x{orig_h} to {new_w}x{new_h} (scale: {scale:.3f}, mode: {screen_mode})") + img = cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_LANCZOS4) + else: + if verbose: + print(f"Using original image size: {orig_w}x{orig_h}") + arr = img.astype(np.float64) + h, w = arr.shape + # Use OpenCV's integral for fast computation + integral = cv2.integral(arr, sdepth=cv2.CV_64F)[1:,1:] + integral_sq = cv2.integral(arr**2, sdepth=cv2.CV_64F)[1:,1:] + def region_sum(ii, x1, y1, x2, y2): + total = ii[y2, x2] + if x1 > 0: + total -= ii[y2, x1-1] + if y1 > 0: + total -= ii[y1-1, x2] + if x1 > 0 and y1 > 0: + total += ii[y1-1, x1-1] + return total + min_size = 10 + max_size = min(h, int(w / aspect_ratio)) if aspect_ratio >= 1.0 else min(int(h * aspect_ratio), w) + best = None + best_size = min_size + while min_size <= max_size: + mid = (min_size + max_size) // 2 + if aspect_ratio >= 1.0: + region_h = mid + region_w = int(mid * aspect_ratio) + else: + region_w = mid + region_h = int(mid / aspect_ratio) + if region_w > w or region_h > h: + max_size = mid - 1 + continue + found = False + for y in range(0, h - region_h + 1, stride): + for x in range(0, w - region_w + 1, stride): + x1, y1 = x, y + x2, y2 = x + region_w - 1, y + region_h - 1 + s = region_sum(integral, x1, y1, x2, y2) + s2 = region_sum(integral_sq, x1, y1, x2, y2) + area = region_w * region_h + mean = s / area + var = (s2 / area) - (mean ** 2) + if var <= threshold: + found = True + best = (x, y, region_w, region_h, var) + break + if found: + break + if found: + best_size = mid + min_size = mid + 1 + else: + max_size = mid - 1 + if best: + x, y, region_w, region_h, var = best + center_x = x + region_w // 2 + center_y = y + region_h // 2 + return (center_x, center_y), (region_w, region_h), var + else: + return None, (0, 0), None + +def draw_region(image_path, coords, region_width=300, region_height=200, output_path='output.png', screen_width=None, screen_height=None, screen_mode="fill"): + img = cv2.imread(image_path) + if img is None: + raise FileNotFoundError(f"Image not found: {image_path}") + orig_h, orig_w = img.shape[:2] + if screen_width is not None and screen_height is not None: + scale_w = screen_width / orig_w + scale_h = screen_height / orig_h + if screen_mode == "fill": + scale = max(scale_w, scale_h) + else: + scale = min(scale_w, scale_h) + new_w = int(orig_w * scale) + new_h = int(orig_h * scale) + img = cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_LANCZOS4) + x, y = coords + cv2.rectangle(img, (x, y), (x+region_width-1, y+region_height-1), (0,0,255), 3) + cv2.imwrite(output_path, img) + print(f"Saved output image with rectangle at {output_path}") + +def draw_largest_region(image_path, center, size, output_path='output.png', screen_width=None, screen_height=None, screen_mode="fill"): + img = cv2.imread(image_path) + if img is None: + raise FileNotFoundError(f"Image not found: {image_path}") + orig_h, orig_w = img.shape[:2] + if screen_width is not None and screen_height is not None: + scale_w = screen_width / orig_w + scale_h = screen_height / orig_h + if screen_mode == "fill": + scale = max(scale_w, scale_h) + else: + scale = min(scale_w, scale_h) + new_w = int(orig_w * scale) + new_h = int(orig_h * scale) + img = cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_LANCZOS4) + cx, cy = center + region_w, region_h = size + x1 = cx - region_w // 2 + y1 = cy - region_h // 2 + x2 = cx + region_w // 2 - 1 + y2 = cy + region_h // 2 - 1 + cv2.rectangle(img, (x1, y1), (x2, y2), (255,0,0), 3) + cv2.imwrite(output_path, img) + print(f"Saved output image with largest region at {output_path}") + +def main(): + parser = argparse.ArgumentParser(description="Find least busy region in an image and output a JSON. Made for determining a suitable position for a wallpaper widget.") + parser.add_argument("image_path", help="Path to the input image") + parser.add_argument("--width", type=int, default=500, help="Region width") + parser.add_argument("--height", type=int, default=250, help="Region height") + parser.add_argument("-v", "--visual-output", action="store_true", help="Output image with rectangle") + parser.add_argument("--screen-width", type=int, default=1920, help="Screen width for wallpaper scaling") + parser.add_argument("--screen-height", type=int, default=1080, help="Screen height for wallpaper scaling") + parser.add_argument("--stride", type=int, default=4, help="Step size for sliding window (higher is faster, less precise)") + parser.add_argument("--screen-mode", choices=["fill", "fit"], default="fill", help="Wallpaper scaling mode: 'fill' (default) or 'fit'") + parser.add_argument("--verbose", action="store_true", help="Print verbose output") + parser.add_argument("-l", "--largest-region", action="store_true", help="Find the largest region under the variance threshold and output its center") + parser.add_argument("-t", "--variance-threshold", type=float, default=1000.0, help="Variance threshold for largest region mode") + parser.add_argument("--aspect-ratio", type=float, default=1.0, help="Aspect ratio (width/height) for largest region mode") + args = parser.parse_args() + + if args.largest_region: + center, size, var = find_largest_region( + args.image_path, + screen_width=args.screen_width, + screen_height=args.screen_height, + verbose=args.verbose, + stride=args.stride, + screen_mode=args.screen_mode, + threshold=args.variance_threshold, + aspect_ratio=args.aspect_ratio + ) + if center: + if args.visual_output: + draw_largest_region(args.image_path, center, size, screen_width=args.screen_width, screen_height=args.screen_height, screen_mode=args.screen_mode) + # Output JSON + print(json.dumps({ + "center_x": center[0], + "center_y": center[1], + "width": size[0], + "height": size[1], + "variance": var + })) + else: + print(json.dumps({"error": "No region found under the threshold."})) + return + + coords, variance = find_least_busy_region( + args.image_path, + region_width=args.width, + region_height=args.height, + screen_width=args.screen_width, + screen_height=args.screen_height, + verbose=args.verbose, + stride=args.stride, + screen_mode=args.screen_mode + ) + if args.visual_output: + draw_region(args.image_path, coords, region_width=args.width, region_height=args.height, screen_width=args.screen_width, screen_height=args.screen_height, screen_mode=args.screen_mode) + # Output JSON with center point + center_x = coords[0] + args.width // 2 + center_y = coords[1] + args.height // 2 + print(json.dumps({ + "center_x": center_x, + "center_y": center_y, + "width": args.width, + "height": args.height, + "variance": variance + })) + +if __name__ == "__main__": + main() + diff --git a/scriptdata/requirements.in b/scriptdata/requirements.in index 0b4ac323e..f312b7f15 100644 --- a/scriptdata/requirements.in +++ b/scriptdata/requirements.in @@ -8,3 +8,4 @@ materialyoucolor libsass material-color-utilities setproctitle +opencv-python diff --git a/scriptdata/requirements.txt b/scriptdata/requirements.txt index 802304132..a710f483a 100644 --- a/scriptdata/requirements.txt +++ b/scriptdata/requirements.txt @@ -11,7 +11,11 @@ material-color-utilities==0.2.1 materialyoucolor==2.0.10 # via -r scriptdata/requirements.in numpy==2.2.2 - # via material-color-utilities + # via + # material-color-utilities + # opencv-python +opencv-python==4.11.0.86 + # via -r scriptdata/requirements.in packaging==24.2 # via # build @@ -26,8 +30,6 @@ pycparser==2.22 # via cffi pyproject-hooks==1.2.0 # via build -# pywal==3.3.0 - # via -r scriptdata/requirements.in pywayland==0.4.18 # via -r scriptdata/requirements.in setproctitle==1.3.4 From f084cd7a23a9acc2c9942ec0b2374f6447fc07e9 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 8 Jun 2025 08:19:15 +0200 Subject: [PATCH 29/89] material symbols: prevent memory spikes --- .config/quickshell/modules/common/widgets/MaterialSymbol.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/widgets/MaterialSymbol.qml b/.config/quickshell/modules/common/widgets/MaterialSymbol.qml index dbbfff009..98584ce2d 100644 --- a/.config/quickshell/modules/common/widgets/MaterialSymbol.qml +++ b/.config/quickshell/modules/common/widgets/MaterialSymbol.qml @@ -6,6 +6,7 @@ Text { id: root property real iconSize: Appearance?.font.pixelSize.small ?? 16 property real fill: 0 + property real truncatedFill: Math.round(fill * 100) / 100 // Reduce memory consumption spikes from constant font remapping renderType: Text.NativeRendering font.hintingPreference: Font.PreferFullHinting verticalAlignment: Text.AlignVCenter @@ -22,7 +23,7 @@ Text { } font.variableAxes: { - "FILL": fill, + "FILL": truncatedFill, // "wght": font.weight, // "GRAD": 0, "opsz": iconSize, From 31c379cdfd4a7fb13d9f6771721b749e67f05881 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 8 Jun 2025 11:27:38 +0200 Subject: [PATCH 30/89] dont enable dock by default --- .config/quickshell/modules/common/ConfigOptions.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 852a4b97c..77b21b49a 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -52,7 +52,7 @@ Singleton { } property QtObject dock: QtObject { - property bool enable: true + property bool enable: false property real height: 60 property real hoverRegionHeight: 3 property bool pinnedOnStartup: false From e18456d18e82db2e92d086129b865cb660e2b31e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 8 Jun 2025 11:27:54 +0200 Subject: [PATCH 31/89] material symbol: use curverendering --- .../modules/common/widgets/MaterialSymbol.qml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/modules/common/widgets/MaterialSymbol.qml b/.config/quickshell/modules/common/widgets/MaterialSymbol.qml index 98584ce2d..07ec5025d 100644 --- a/.config/quickshell/modules/common/widgets/MaterialSymbol.qml +++ b/.config/quickshell/modules/common/widgets/MaterialSymbol.qml @@ -7,11 +7,13 @@ Text { property real iconSize: Appearance?.font.pixelSize.small ?? 16 property real fill: 0 property real truncatedFill: Math.round(fill * 100) / 100 // Reduce memory consumption spikes from constant font remapping - renderType: Text.NativeRendering - font.hintingPreference: Font.PreferFullHinting + renderType: Text.CurveRendering + font { + hintingPreference: Font.PreferFullHinting + family: Appearance?.font.family.iconMaterial ?? "Material Symbols Rounded" + pixelSize: iconSize + } verticalAlignment: Text.AlignVCenter - font.family: Appearance?.font.family.iconMaterial ?? "Material Symbols Rounded" - font.pixelSize: iconSize color: Appearance.m3colors.m3onBackground Behavior on fill { From be9b7f3629138067d07b491701ba64819578a836 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 8 Jun 2025 11:28:54 +0200 Subject: [PATCH 32/89] least_busy_region.py: take files with spaces properly --- .config/matugen/scripts/least_busy_region.py | 115 +++++++++++++++--- .../illogical-impulse-python/PKGBUILD | 1 + scriptdata/requirements.in | 1 - scriptdata/requirements.txt | 6 +- 4 files changed, 102 insertions(+), 21 deletions(-) diff --git a/.config/matugen/scripts/least_busy_region.py b/.config/matugen/scripts/least_busy_region.py index 68e08ca12..7ae245dd4 100755 --- a/.config/matugen/scripts/least_busy_region.py +++ b/.config/matugen/scripts/least_busy_region.py @@ -1,4 +1,4 @@ -#!/usr/bin/env -S\_/bin/sh\_-c\_"source\_\$(eval\_echo\_\$ILLOGICAL_IMPULSE_VIRTUAL_ENV)/bin/activate&&exec\_python\_-E\_"\$0"\_"\$@"" +#!/usr/bin/env python3 # Disclaimer: This script is vibe-coded. import os @@ -8,7 +8,17 @@ import numpy as np import argparse import json -def find_least_busy_region(image_path, region_width=300, region_height=200, screen_width=None, screen_height=None, verbose=False, stride=2, screen_mode="fill"): +def center_crop(img, target_w, target_h): + h, w = img.shape[:2] + if w == target_w and h == target_h: + return img + x1 = max(0, (w - target_w) // 2) + y1 = max(0, (h - target_h) // 2) + x2 = x1 + target_w + y2 = y1 + target_h + return img[y1:y2, x1:x2] + +def find_least_busy_region(image_path, region_width=300, region_height=200, screen_width=None, screen_height=None, verbose=False, stride=2, screen_mode="fill", padding=50): img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) if img is None: raise FileNotFoundError(f"Image not found: {image_path}") @@ -26,6 +36,9 @@ def find_least_busy_region(image_path, region_width=300, region_height=200, scre if verbose: print(f"Scaling image from {orig_w}x{orig_h} to {new_w}x{new_h} (scale: {scale:.3f}, mode: {screen_mode})") img = cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_LANCZOS4) + img = center_crop(img, screen_width, screen_height) + if verbose: + print(f"Cropped image to {screen_width}x{screen_height}") else: if verbose: print(f"Using original image size: {orig_w}x{orig_h}") @@ -46,8 +59,12 @@ def find_least_busy_region(image_path, region_width=300, region_height=200, scre min_var = None min_coords = (0, 0) area = region_width * region_height - for y in range(0, h - region_height + 1, stride): - for x in range(0, w - region_width + 1, stride): + x_start = padding + y_start = padding + x_end = w - region_width - padding + 1 + y_end = h - region_height - padding + 1 + for y in range(y_start, max(y_end, y_start+1), stride): + for x in range(x_start, max(x_end, x_start+1), stride): x1, y1 = x, y x2, y2 = x + region_width - 1, y + region_height - 1 s = region_sum(integral, x1, y1, x2, y2) @@ -59,7 +76,7 @@ def find_least_busy_region(image_path, region_width=300, region_height=200, scre min_coords = (x, y) return min_coords, min_var -def find_largest_region(image_path, screen_width=None, screen_height=None, verbose=False, stride=2, screen_mode="fill", threshold=100.0, aspect_ratio=1.0): +def find_largest_region(image_path, screen_width=None, screen_height=None, verbose=False, stride=2, screen_mode="fill", threshold=100.0, aspect_ratio=1.0, padding=50): img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) if img is None: raise FileNotFoundError(f"Image not found: {image_path}") @@ -77,6 +94,9 @@ def find_largest_region(image_path, screen_width=None, screen_height=None, verbo if verbose: print(f"Scaling image from {orig_w}x{orig_h} to {new_w}x{new_h} (scale: {scale:.3f}, mode: {screen_mode})") img = cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_LANCZOS4) + img = center_crop(img, screen_width, screen_height) + if verbose: + print(f"Cropped image to {screen_width}x{screen_height}") else: if verbose: print(f"Using original image size: {orig_w}x{orig_h}") @@ -110,8 +130,12 @@ def find_largest_region(image_path, screen_width=None, screen_height=None, verbo max_size = mid - 1 continue found = False - for y in range(0, h - region_h + 1, stride): - for x in range(0, w - region_w + 1, stride): + x_start = padding + y_start = padding + x_end = w - region_w - padding + 1 + y_end = h - region_h - padding + 1 + for y in range(y_start, max(y_end, y_start+1), stride): + for x in range(x_start, max(x_end, x_start+1), stride): x1, y1 = x, y x2, y2 = x + region_w - 1, y + region_h - 1 s = region_sum(integral, x1, y1, x2, y2) @@ -153,6 +177,7 @@ def draw_region(image_path, coords, region_width=300, region_height=200, output_ new_w = int(orig_w * scale) new_h = int(orig_h * scale) img = cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_LANCZOS4) + img = center_crop(img, screen_width, screen_height) x, y = coords cv2.rectangle(img, (x, y), (x+region_width-1, y+region_height-1), (0,0,255), 3) cv2.imwrite(output_path, img) @@ -173,6 +198,7 @@ def draw_largest_region(image_path, center, size, output_path='output.png', scre new_w = int(orig_w * scale) new_h = int(orig_h * scale) img = cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_LANCZOS4) + img = center_crop(img, screen_width, screen_height) cx, cy = center region_w, region_h = size x1 = cx - region_w // 2 @@ -183,11 +209,51 @@ def draw_largest_region(image_path, center, size, output_path='output.png', scre cv2.imwrite(output_path, img) print(f"Saved output image with largest region at {output_path}") +def get_dominant_color(image_path, x, y, w, h, screen_width=None, screen_height=None, screen_mode="fill"): + img = cv2.imread(image_path) + if img is None: + raise FileNotFoundError(f"Image not found: {image_path}") + orig_h, orig_w = img.shape[:2] + if screen_width is not None and screen_height is not None: + scale_w = screen_width / orig_w + scale_h = screen_height / orig_h + if screen_mode == "fill": + scale = max(scale_w, scale_h) + else: + scale = min(scale_w, scale_h) + new_w = int(orig_w * scale) + new_h = int(orig_h * scale) + img = cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_LANCZOS4) + img = center_crop(img, screen_width, screen_height) + # Ensure region is within bounds + x = max(0, x) + y = max(0, y) + w = max(1, min(w, img.shape[1] - x)) + h = max(1, min(h, img.shape[0] - y)) + region = img[y:y+h, x:x+w] + if region.size == 0 or region.shape[0] == 0 or region.shape[1] == 0: + return [0, 0, 0] + region = region.reshape((-1, 3)) + # Filter out black pixels (optional, improves accuracy for some images) + non_black = region[np.any(region > 10, axis=1)] + if non_black.shape[0] == 0: + non_black = region + region = np.float32(non_black) + if region.shape[0] < 3: + return [int(x) for x in np.mean(region, axis=0)] + # K-means to find dominant color + criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) + K = min(3, region.shape[0]) + _, labels, centers = cv2.kmeans(region, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS) + counts = np.bincount(labels.flatten()) + dominant = centers[np.argmax(counts)] + return [int(x) for x in dominant] + def main(): parser = argparse.ArgumentParser(description="Find least busy region in an image and output a JSON. Made for determining a suitable position for a wallpaper widget.") parser.add_argument("image_path", help="Path to the input image") - parser.add_argument("--width", type=int, default=500, help="Region width") - parser.add_argument("--height", type=int, default=250, help="Region height") + parser.add_argument("--width", type=int, default=300, help="Region width") + parser.add_argument("--height", type=int, default=200, help="Region height") parser.add_argument("-v", "--visual-output", action="store_true", help="Output image with rectangle") parser.add_argument("--screen-width", type=int, default=1920, help="Screen width for wallpaper scaling") parser.add_argument("--screen-height", type=int, default=1080, help="Screen height for wallpaper scaling") @@ -196,7 +262,8 @@ def main(): parser.add_argument("--verbose", action="store_true", help="Print verbose output") parser.add_argument("-l", "--largest-region", action="store_true", help="Find the largest region under the variance threshold and output its center") parser.add_argument("-t", "--variance-threshold", type=float, default=1000.0, help="Variance threshold for largest region mode") - parser.add_argument("--aspect-ratio", type=float, default=1.0, help="Aspect ratio (width/height) for largest region mode") + parser.add_argument("--aspect-ratio", type=float, default=1.78, help="Aspect ratio (width/height) for largest region mode") + parser.add_argument("--padding", type=int, default=50, help="Minimum distance from region to image edge (default: 50)") args = parser.parse_args() if args.largest_region: @@ -208,18 +275,29 @@ def main(): stride=args.stride, screen_mode=args.screen_mode, threshold=args.variance_threshold, - aspect_ratio=args.aspect_ratio + aspect_ratio=args.aspect_ratio, + padding=args.padding ) if center: if args.visual_output: draw_largest_region(args.image_path, center, size, screen_width=args.screen_width, screen_height=args.screen_height, screen_mode=args.screen_mode) - # Output JSON + # Extract dominant color + cx, cy = center + region_w, region_h = size + x1 = cx - region_w // 2 + y1 = cy - region_h // 2 + dominant_color = get_dominant_color( + args.image_path, x1, y1, region_w, region_h, + screen_width=args.screen_width, screen_height=args.screen_height, screen_mode=args.screen_mode + ) + dominant_color_hex = '#{:02x}{:02x}{:02x}'.format(*dominant_color) print(json.dumps({ "center_x": center[0], "center_y": center[1], "width": size[0], "height": size[1], - "variance": var + "variance": var, + "dominant_color": dominant_color_hex })) else: print(json.dumps({"error": "No region found under the threshold."})) @@ -233,19 +311,26 @@ def main(): screen_height=args.screen_height, verbose=args.verbose, stride=args.stride, - screen_mode=args.screen_mode + screen_mode=args.screen_mode, + padding=args.padding ) if args.visual_output: draw_region(args.image_path, coords, region_width=args.width, region_height=args.height, screen_width=args.screen_width, screen_height=args.screen_height, screen_mode=args.screen_mode) # Output JSON with center point center_x = coords[0] + args.width // 2 center_y = coords[1] + args.height // 2 + dominant_color = get_dominant_color( + args.image_path, coords[0], coords[1], args.width, args.height, + screen_width=args.screen_width, screen_height=args.screen_height, screen_mode=args.screen_mode + ) + dominant_color_hex = '#{:02x}{:02x}{:02x}'.format(*dominant_color) print(json.dumps({ "center_x": center_x, "center_y": center_y, "width": args.width, "height": args.height, - "variance": variance + "variance": variance, + "dominant_color": dominant_color_hex })) if __name__ == "__main__": diff --git a/arch-packages/illogical-impulse-python/PKGBUILD b/arch-packages/illogical-impulse-python/PKGBUILD index fc1ac1e05..d9c6caa55 100644 --- a/arch-packages/illogical-impulse-python/PKGBUILD +++ b/arch-packages/illogical-impulse-python/PKGBUILD @@ -13,4 +13,5 @@ depends=( libportal-gtk4 gobject-introspection sassc + python-opencv ) diff --git a/scriptdata/requirements.in b/scriptdata/requirements.in index f312b7f15..0b4ac323e 100644 --- a/scriptdata/requirements.in +++ b/scriptdata/requirements.in @@ -8,4 +8,3 @@ materialyoucolor libsass material-color-utilities setproctitle -opencv-python diff --git a/scriptdata/requirements.txt b/scriptdata/requirements.txt index a710f483a..c2f380c4a 100644 --- a/scriptdata/requirements.txt +++ b/scriptdata/requirements.txt @@ -11,11 +11,7 @@ material-color-utilities==0.2.1 materialyoucolor==2.0.10 # via -r scriptdata/requirements.in numpy==2.2.2 - # via - # material-color-utilities - # opencv-python -opencv-python==4.11.0.86 - # via -r scriptdata/requirements.in + # via material-color-utilities packaging==24.2 # via # build From e8c294f43436b73d975703c8e70e8223cf1f7e04 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 8 Jun 2025 11:29:16 +0200 Subject: [PATCH 33/89] remove redundant defaulted prop assignment --- .config/quickshell/services/ConfigLoader.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/.config/quickshell/services/ConfigLoader.qml b/.config/quickshell/services/ConfigLoader.qml index c1e040209..788fc728d 100644 --- a/.config/quickshell/services/ConfigLoader.qml +++ b/.config/quickshell/services/ConfigLoader.qml @@ -83,7 +83,6 @@ Singleton { Timer { id: delayedFileRead interval: ConfigOptions.hacks.arbitraryRaceConditionDelay - repeat: false running: false onTriggered: { root.applyConfig(configFileView.text()) From 8dab758d7847363454dab58b242976b189464d6e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 8 Jun 2025 11:29:33 +0200 Subject: [PATCH 34/89] dock: hover region adjustment --- .config/quickshell/modules/dock/Dock.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/modules/dock/Dock.qml b/.config/quickshell/modules/dock/Dock.qml index b89630228..bd0ac8ec7 100644 --- a/.config/quickshell/modules/dock/Dock.qml +++ b/.config/quickshell/modules/dock/Dock.qml @@ -55,7 +55,9 @@ Scope { // Scope id: dockMouseArea anchors.top: parent.top height: parent.height - anchors.topMargin: dockRoot.reveal ? 0 : dockRoot.implicitHeight - ConfigOptions.dock.hoverRegionHeight + anchors.topMargin: dockRoot.reveal ? 0 : + ConfigOptions?.dock.hoverToReveal ? (dockRoot.implicitHeight + 1) : + (dockRoot.implicitHeight - ConfigOptions.dock.hoverRegionHeight) anchors.left: parent.left anchors.right: parent.right hoverEnabled: true From 726558c0a09fe7cd34218463b5efedbb8c56b3f2 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 8 Jun 2025 11:30:12 +0200 Subject: [PATCH 35/89] background widgets --- .config/hypr/hyprland/execs.conf | 2 +- .config/hypr/hyprland/rules.conf | 2 + .config/matugen/config.toml | 2 +- .../backgroundWidgets/BackgroundWidgets.qml | 134 ++++++++++++++++++ .../modules/common/functions/color_utils.js | 26 +++- .config/quickshell/scripts/switchwall.sh | 22 ++- .config/quickshell/shell.qml | 31 ++-- 7 files changed, 199 insertions(+), 20 deletions(-) create mode 100644 .config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml diff --git a/.config/hypr/hyprland/execs.conf b/.config/hypr/hyprland/execs.conf index 32a25be4a..d4945605b 100644 --- a/.config/hypr/hyprland/execs.conf +++ b/.config/hypr/hyprland/execs.conf @@ -1,6 +1,6 @@ # Bar, wallpaper exec-once = swww-daemon --format xrgb --no-cache -exec-once = sleep 0.5; swww img "$(cat ~/.local/state/quickshell/user/generated/wallpaper.txt)" --transition-step 100 --transition-fps 120 --transition-type grow --transition-angle 30 --transition-duration 1 +exec-once = sleep 0.5; swww img "$(cat ~/.local/state/quickshell/user/generated/wallpaper/path.txt)" --transition-step 100 --transition-fps 120 --transition-type grow --transition-angle 30 --transition-duration 1 exec-once = /usr/lib/geoclue-2.0/demos/agent & gammastep exec-once = qs & diff --git a/.config/hypr/hyprland/rules.conf b/.config/hypr/hyprland/rules.conf index 19945f988..fe1f5da4c 100644 --- a/.config/hypr/hyprland/rules.conf +++ b/.config/hypr/hyprland/rules.conf @@ -119,6 +119,8 @@ layerrule = animation slide bottom, quickshell:osk layerrule = blur, quickshell:session layerrule = noanim, quickshell:session layerrule = animation fade, quickshell:notificationPopup +layerrule = blur, quickshell:backgroundWidgets +layerrule = ignorealpha 0.05, quickshell:backgroundWidgets # layerrule = blurpopups, quickshell:.* # layerrule = blur, quickshell:.* diff --git a/.config/matugen/config.toml b/.config/matugen/config.toml index ef7bf7639..66c17a37e 100644 --- a/.config/matugen/config.toml +++ b/.config/matugen/config.toml @@ -45,4 +45,4 @@ post_hook = '~/.config/matugen/templates/kde/kde-material-you-colors-wrapper.sh' [templates.wallpaper] input_path = '~/.config/matugen/templates/wallpaper.txt' -output_path = '~/.local/state/quickshell/user/generated/wallpaper.txt' +output_path = '~/.local/state/quickshell/user/generated/wallpaper/path.txt' diff --git a/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml b/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml new file mode 100644 index 000000000..dea41e08f --- /dev/null +++ b/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml @@ -0,0 +1,134 @@ +import "root:/" +import "root:/modules/common" +import "root:/modules/common/widgets" +import "root:/services" +import "root:/modules/common/functions/color_utils.js" as ColorUtils +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell +import Quickshell.Io +import Quickshell.Wayland +import Quickshell.Hyprland +import Quickshell.Services.UPower + +Scope { + id: root + property string filePath: `${Directories.state}/user/generated/wallpaper/least_busy_region.json` + property real centerX: 0 + property real centerY: 0 + property color dominantColor: Appearance.m3colors.m3primary + property bool dominantColorIsDark: dominantColor.hslLightness < 0.5 + property color colBackground: ColorUtils.transparentize(ColorUtils.mix(Appearance.m3colors.m3primary, Appearance.m3colors.m3secondaryContainer), 1) + property color colText: ColorUtils.colorWithLightness(Appearance.m3colors.m3primary, (root.dominantColorIsDark ? 0.8 : 0.12)) + + function updateWidgetPosition(fileContent) { + console.log("[BackgroundWidgets] Updating widget position with content:", fileContent) + const parsedContent = JSON.parse(fileContent) + root.centerX = parsedContent.center_x + root.centerY = parsedContent.center_y + root.dominantColor = parsedContent.dominant_color || Appearance.m3colors.m3primary + } + + Timer { + id: delayedFileRead + interval: ConfigOptions.hacks.arbitraryRaceConditionDelay + running: false + onTriggered: { + root.updateWidgetPosition(leastBusyRegionFileView.text()) + } + } + + FileView { + id: leastBusyRegionFileView + path: Qt.resolvedUrl(root.filePath) + watchChanges: true + onFileChanged: { + this.reload() + delayedFileRead.start() + } + onLoadedChanged: { + const fileContent = leastBusyRegionFileView.text() + root.updateWidgetPosition(fileContent) + } + } + + Variants { // For each monitor + model: Quickshell.screens + + Loader { + required property var modelData + active: !ToplevelManager.activeToplevel?.activated + sourceComponent: PanelWindow { // Window + id: windowRoot + screen: modelData + property var textHorizontalAlignment: root.centerX < windowRoot.width / 3 ? Text.AlignLeft : + (root.centerX > windowRoot.width * 2 / 3 ? Text.AlignRight : Text.AlignHCenter) + + WlrLayershell.layer: WlrLayer.Bottom + WlrLayershell.namespace: "quickshell:backgroundWidgets" + + anchors { + top: true + bottom:true + left: true + right: true + } + color: "transparent" + HyprlandWindow.visibleMask: Region { + item: widgetBackground + } + + Rectangle { + id: widgetBackground + property real verticalPadding: 20 + property real horizontalPadding: 30 + radius: 40 + color: root.colBackground + implicitHeight: columnLayout.implicitHeight + verticalPadding * 2 + implicitWidth: columnLayout.implicitWidth + horizontalPadding * 2 + anchors { + left: parent.left + top: parent.top + leftMargin: root.centerX - implicitWidth / 2 + topMargin: root.centerY - implicitHeight / 2 + Behavior on leftMargin { + animation: Appearance.animation.elementMove.numberAnimation.createObject(this) + } + Behavior on topMargin { + animation: Appearance.animation.elementMove.numberAnimation.createObject(this) + } + } + + ColumnLayout { + id: columnLayout + anchors.centerIn: parent + spacing: -5 + + StyledText { + Layout.fillWidth: true + horizontalAlignment: windowRoot.textHorizontalAlignment + font.pixelSize: 95 + color: root.colText + style: Text.Raised + styleColor: Appearance.colors.colShadow + text: DateTime.time + } + StyledText { + Layout.fillWidth: true + horizontalAlignment: windowRoot.textHorizontalAlignment + font.pixelSize: 25 + color: root.colText + style: Text.Raised + styleColor: Appearance.colors.colShadow + text: DateTime.date + } + } + } + + } + } + + } + +} diff --git a/.config/quickshell/modules/common/functions/color_utils.js b/.config/quickshell/modules/common/functions/color_utils.js index c0ccfda9d..eb0fc0c2f 100644 --- a/.config/quickshell/modules/common/functions/color_utils.js +++ b/.config/quickshell/modules/common/functions/color_utils.js @@ -39,6 +39,30 @@ function colorWithSaturationOf(color1, color2) { return Qt.hsva(hue, sat, val, alpha); } +/** + * Returns a color with the given lightness and the hue, saturation, and alpha of the input color (using HSL). + * + * @param {string} color - The base color (any Qt.color-compatible string). + * @param {number} lightness - The lightness value to use (0-1). + * @returns {Qt.rgba} The resulting color. + */ +function colorWithLightness(color, lightness) { + var c = Qt.color(color); + return Qt.hsla(c.hslHue, c.hslSaturation, lightness, c.a); +} + +/** + * Returns a color with the lightness of color2 and the hue, saturation, and alpha of color1 (using HSL). + * + * @param {string} color1 - The base color (any Qt.color-compatible string). + * @param {string} color2 - The color to take lightness from. + * @returns {Qt.rgba} The resulting color. + */ +function colorWithLightnessOf(color1, color2) { + var c2 = Qt.color(color2); + return colorWithLightness(color1, c2.hslLightness); +} + /** * Adapts color1 to the accent (hue and saturation) of color2 using HSL, keeping lightness and alpha from color1. * @@ -66,7 +90,7 @@ function adaptToAccent(color1, color2) { * @param {number} percentage - The mix ratio (0-1). 1 = all color1, 0 = all color2. * @returns {Qt.rgba} The resulting mixed color. */ -function mix(color1, color2, percentage) { +function mix(color1, color2, percentage = 0.5) { var c1 = Qt.color(color1); var c2 = Qt.color(color2); return Qt.rgba(percentage * c1.r + (1 - percentage) * c2.r, percentage * c1.g + (1 - percentage) * c2.g, percentage * c1.b + (1 - percentage) * c2.b, percentage * c1.a + (1 - percentage) * c2.a); diff --git a/.config/quickshell/scripts/switchwall.sh b/.config/quickshell/scripts/switchwall.sh index 838bb8b9c..adc76201d 100755 --- a/.config/quickshell/scripts/switchwall.sh +++ b/.config/quickshell/scripts/switchwall.sh @@ -7,6 +7,7 @@ CONFIG_DIR="$XDG_CONFIG_HOME/quickshell" CACHE_DIR="$XDG_CACHE_HOME/quickshell" STATE_DIR="$XDG_STATE_HOME/quickshell" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +MATUGEN_DIR="$XDG_CONFIG_HOME/matugen" terminalscheme="$XDG_CONFIG_HOME/quickshell/scripts/terminal/scheme-base.json" pre_process() { @@ -26,7 +27,19 @@ pre_process() { } post_process() { - true + local screen_width="$1" + local screen_height="$2" + local wallpaper_path="$3" + + # Determine the largest region on the wallpaper that's sufficiently un-busy to put widgets in + if [ ! -f "$MATUGEN_DIR/scripts/least_busy_region.py" ]; then + echo "Error: least_busy_region.py script not found in $MATUGEN_DIR/scripts/" + else + "$MATUGEN_DIR/scripts/least_busy_region.py" \ + --screen-width "$screen_width" --screen-height "$screen_height" \ + --width 300 --height 200 \ + "$wallpaper_path" > "$STATE_DIR"/user/generated/wallpaper/least_busy_region.json + fi } check_and_prompt_upscale() { @@ -219,7 +232,10 @@ switch() { "$SCRIPT_DIR"/applycolor.sh deactivate - post_process + # Pass screen width, height, and wallpaper path to post_process + min_width_desired="$(hyprctl monitors -j | jq '([.[].width] | max)' | xargs)" + min_height_desired="$(hyprctl monitors -j | jq '([.[].height] | max)' | xargs)" + post_process "$min_width_desired" "$min_height_desired" "$imgpath" } main() { @@ -273,4 +289,4 @@ main() { switch "$imgpath" "$mode_flag" "$type_flag" "$color_flag" "$color" } -main "$@" \ No newline at end of file +main "$@" diff --git a/.config/quickshell/shell.qml b/.config/quickshell/shell.qml index e6e5d566c..5d14061bf 100644 --- a/.config/quickshell/shell.qml +++ b/.config/quickshell/shell.qml @@ -3,6 +3,7 @@ //@ pragma Env QT_QUICK_CONTROLS_STYLE=Basic import "./modules/common/" +import "./modules/backgroundWidgets/" import "./modules/bar/" import "./modules/cheatsheet/" import "./modules/dock/" @@ -26,6 +27,7 @@ ShellRoot { // Enable/disable modules here. False = not loaded at all, so rest assured // no unnecessary stuff will take up memory if you decide to only use, say, the overview. property bool enableBar: true + property bool enableBackgroundWidgets: true property bool enableCheatsheet: true property bool enableDock: true property bool enableMediaControls: true @@ -49,19 +51,20 @@ ShellRoot { FirstRunExperience.load() } - Loader { active: enableBar; sourceComponent: Bar {} } - Loader { active: enableCheatsheet; sourceComponent: Cheatsheet {} } - Loader { active: (enableDock && ConfigOptions?.dock.enable); sourceComponent: Dock {} } - Loader { active: enableMediaControls; sourceComponent: MediaControls {} } - Loader { active: enableNotificationPopup; sourceComponent: NotificationPopup {} } - Loader { active: enableOnScreenDisplayBrightness; sourceComponent: OnScreenDisplayBrightness {} } - Loader { active: enableOnScreenDisplayVolume; sourceComponent: OnScreenDisplayVolume {} } - Loader { active: enableOnScreenKeyboard; sourceComponent: OnScreenKeyboard {} } - Loader { active: enableOverview; sourceComponent: Overview {} } - Loader { active: enableReloadPopup; sourceComponent: ReloadPopup {} } - Loader { active: enableScreenCorners; sourceComponent: ScreenCorners {} } - Loader { active: enableSession; sourceComponent: Session {} } - Loader { active: enableSidebarLeft; sourceComponent: SidebarLeft {} } - Loader { active: enableSidebarRight; sourceComponent: SidebarRight {} } + LazyLoader { active: enableBar; component: Bar {} } + LazyLoader { active: enableBackgroundWidgets; component: BackgroundWidgets {} } + LazyLoader { active: enableCheatsheet; component: Cheatsheet {} } + LazyLoader { active: (enableDock && ConfigOptions?.dock.enable); component: Dock {} } + LazyLoader { active: enableMediaControls; component: MediaControls {} } + LazyLoader { active: enableNotificationPopup; component: NotificationPopup {} } + LazyLoader { active: enableOnScreenDisplayBrightness; component: OnScreenDisplayBrightness {} } + LazyLoader { active: enableOnScreenDisplayVolume; component: OnScreenDisplayVolume {} } + LazyLoader { active: enableOnScreenKeyboard; component: OnScreenKeyboard {} } + LazyLoader { active: enableOverview; component: Overview {} } + LazyLoader { active: enableReloadPopup; component: ReloadPopup {} } + LazyLoader { active: enableScreenCorners; component: ScreenCorners {} } + LazyLoader { active: enableSession; component: Session {} } + LazyLoader { active: enableSidebarLeft; component: SidebarLeft {} } + LazyLoader { active: enableSidebarRight; component: SidebarRight {} } } From f840af4652fb4a3c58aec4874812654da6f07e40 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 8 Jun 2025 11:44:16 +0200 Subject: [PATCH 36/89] fix funny notice uhm some guys in discord said its not correct n stuff --- .config/matugen/scripts/least_busy_region.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/matugen/scripts/least_busy_region.py b/.config/matugen/scripts/least_busy_region.py index 7ae245dd4..a1f2f47b4 100755 --- a/.config/matugen/scripts/least_busy_region.py +++ b/.config/matugen/scripts/least_busy_region.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Disclaimer: This script is vibe-coded. +# Disclaimer: This script was ai-generated and went through minimal revision. import os os.environ["OPENCV_LOG_LEVEL"] = "SILENT" From cfb4f1a5e1ea43df95363b8c8caa09f759d8bc07 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 8 Jun 2025 17:05:20 +0200 Subject: [PATCH 37/89] gnome control center -> plasma systemsettings --- .config/hypr/hyprland/keybinds.conf | 2 +- .config/quickshell/modules/common/ConfigOptions.qml | 7 ++++--- .../modules/sidebarRight/quickToggles/NetworkToggle.qml | 2 +- arch-packages/illogical-impulse-kde/PKGBUILD | 1 - 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.config/hypr/hyprland/keybinds.conf b/.config/hypr/hyprland/keybinds.conf index f6e9d03b9..db554af57 100644 --- a/.config/hypr/hyprland/keybinds.conf +++ b/.config/hypr/hyprland/keybinds.conf @@ -208,7 +208,7 @@ bind = Super, W, exec, zen-browser # [hidden] bind = Super+Shift, W, exec, wps # WPS Office bind = Super, X, exec, kate # Kate (text editor) bind = Ctrl+Super, V, exec, pavucontrol-qt # Pavucontrol Qt (volume mixer) -bind = Super, I, exec, XDG_CURRENT_DESKTOP=gnome gnome-control-center # GNOME Control center (settings app) +bind = Super, I, exec, systemsettings # Plasma system settings bind = Ctrl+Shift, Escape, exec, plasma-systemmonitor --page-name Processes # Plasma system monitor # Cursed stuff diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 77b21b49a..514f21c23 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -21,10 +21,11 @@ Singleton { } property QtObject apps: QtObject { - property string bluetooth: "better-control --bluetooth" + property string bluetooth: "systemsettings kcm_bluetooth" property string imageViewer: "loupe" - property string network: "XDG_CURRENT_DESKTOP=\"gnome\" gnome-control-center wifi" - property string settings: "XDG_CURRENT_DESKTOP=\"gnome\" gnome-control-center" + property string network: "better-control --wifi" + property string networkEthernet: "systemsettings kcm_networkmanagement" + property string settings: "systemsettings kcm_bluetooth" property string taskManager: "plasma-systemmonitor --page-name Processes" property string terminal: "kitty -1" // This is only for shell actions } diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml b/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml index 8f058fd53..5271e3769 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml +++ b/.config/quickshell/modules/sidebarRight/quickToggles/NetworkToggle.qml @@ -15,7 +15,7 @@ QuickToggleButton { toggleNetwork.running = true } altAction: () => { - Hyprland.dispatch(`exec ${ConfigOptions.apps.network}`) + Hyprland.dispatch(`exec ${Network.ethernet ? ConfigOptions.apps.networkEthernet : ConfigOptions.apps.network}`) Hyprland.dispatch("global quickshell:sidebarRightClose") } Process { diff --git a/arch-packages/illogical-impulse-kde/PKGBUILD b/arch-packages/illogical-impulse-kde/PKGBUILD index 35f8d669f..d4f5e4058 100644 --- a/arch-packages/illogical-impulse-kde/PKGBUILD +++ b/arch-packages/illogical-impulse-kde/PKGBUILD @@ -7,6 +7,5 @@ license=(None) depends=( polkit-kde-agent gnome-keyring - gnome-control-center networkmanager better-control-git ) From dc8bfce62e03a884b318655d2fe4d21d95a4369d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 8 Jun 2025 18:36:40 +0200 Subject: [PATCH 38/89] ai: fix latex rendering --- .../quickshell/modules/common/Directories.qml | 2 +- .../quickshell/modules/sidebarLeft/AiChat.qml | 6 ++--- .../modules/sidebarLeft/aiChat/AiMessage.qml | 22 ++++++++++------- .../sidebarLeft/aiChat/MessageTextBlock.qml | 19 +++++++++++---- .config/quickshell/services/LatexRenderer.qml | 24 ++++++++++++------- 5 files changed, 47 insertions(+), 26 deletions(-) diff --git a/.config/quickshell/modules/common/Directories.qml b/.config/quickshell/modules/common/Directories.qml index 9e3e3000f..b256666fc 100644 --- a/.config/quickshell/modules/common/Directories.qml +++ b/.config/quickshell/modules/common/Directories.qml @@ -21,7 +21,7 @@ Singleton { property string booruPreviews: FileUtils.trimFileProtocol(`${Directories.cache}/media/boorus`) property string booruDownloads: FileUtils.trimFileProtocol(Directories.pictures + "/homework") property string booruDownloadsNsfw: FileUtils.trimFileProtocol(Directories.pictures + "/homework/🌶️") - property string latexOutput: FileUtils.trimFileProtocol(`${Directories.cache}/latex`) + property string latexOutput: FileUtils.trimFileProtocol(`${Directories.cache}/media/latex`) property string shellConfig: FileUtils.trimFileProtocol(`${Directories.config}/illogical-impulse`) property string shellConfigName: "config.json" property string shellConfigPath: `${Directories.shellConfig}/${Directories.shellConfigName}` diff --git a/.config/quickshell/modules/sidebarLeft/AiChat.qml b/.config/quickshell/modules/sidebarLeft/AiChat.qml index b78ff89ce..ecb8628be 100644 --- a/.config/quickshell/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/modules/sidebarLeft/AiChat.qml @@ -125,9 +125,9 @@ int main(int argc, char* argv[]) { ### LaTeX -- Simple inline: $\\frac{1}{2} = \\frac{2}{4}$ -- Complex inline: $$\\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}$$ -- Another complex inline: \\\\[\\int_0^\\infty \\frac{1}{x^2} dx = \\infty\\\\] +- Inline w/ dollar signs: $\\frac{1}{2} = \\frac{2}{4}$ +- Inline w/ double dollar signs: $$\\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}$$ +- Inline w/ backslash and square brackets \\[\\int_0^\\infty \\frac{1}{x^2} dx = \\infty\\] `, Ai.interfaceRole); } diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml b/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml index e115338ad..775d12082 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml @@ -28,6 +28,8 @@ Rectangle { property bool renderMarkdown: true property bool editing: false + property list messageBlocks: StringUtils.splitMarkdownBlocks(root.messageData?.content) + anchors.left: parent?.left anchors.right: parent?.right implicitHeight: columnLayout.implicitHeight + root.messagePadding * 2 @@ -246,23 +248,25 @@ Rectangle { spacing: 0 Repeater { model: ScriptModel { - values: StringUtils.splitMarkdownBlocks(root.messageData?.content) + values: root.messageBlocks.map((block, index) => index) } delegate: Loader { + required property int index + property var thisBlock: root.messageBlocks[index] Layout.fillWidth: true - // property var segment: modelData - property var segmentContent: modelData.content - property var segmentLang: modelData.lang + // property var segment: thisBlock + property var segmentContent: thisBlock.content + property var segmentLang: thisBlock.lang property var messageData: root.messageData property var editing: root.editing property var renderMarkdown: root.renderMarkdown property var enableMouseSelection: root.enableMouseSelection property bool thinking: root.messageData?.thinking ?? true property bool done: root.messageData?.done ?? false - property bool completed: modelData.completed ?? false + property bool completed: thisBlock.completed ?? false - source: modelData.type === "code" ? "MessageCodeBlock.qml" : - modelData.type === "think" ? "MessageThinkBlock.qml" : + source: thisBlock.type === "code" ? "MessageCodeBlock.qml" : + thisBlock.type === "think" ? "MessageThinkBlock.qml" : "MessageTextBlock.qml" } @@ -277,7 +281,9 @@ Rectangle { Layout.alignment: Qt.AlignLeft Repeater { - model: root.messageData?.annotationSources + model: ScriptModel { + values: root.messageData?.annotationSources || [] + } delegate: AnnotationSourceButton { id: annotationButton displayText: modelData.text diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml b/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml index 87087c6b9..bc7f93df1 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml @@ -30,6 +30,18 @@ ColumnLayout { Layout.fillWidth: true + Timer { + id: renderTimer + interval: 1000 + repeat: true + onTriggered: { + renderLatex() + for (const hash of renderedLatexHashes) { + handleRenderedLatex(hash, true); + } + } + } + function renderLatex() { // Regex for $...$, $$...$$, \[...\] // Note: This is a simple approach and may need refinement for edge cases @@ -53,16 +65,13 @@ ColumnLayout { const imagePath = LatexRenderer.renderedImagePaths[hash]; const markdownImage = `![latex](${imagePath})`; - const expression = StringUtils.escapeBackslashes(LatexRenderer.processedExpressions[hash]); + const expression = LatexRenderer.processedExpressions[hash]; renderedSegmentContent = renderedSegmentContent.replace(expression, markdownImage); } } onDoneChanged: { - renderLatex() - for (const hash of renderedLatexHashes) { - handleRenderedLatex(hash, true); - } + renderTimer.restart(); } onEditingChanged: { if (!editing) { diff --git a/.config/quickshell/services/LatexRenderer.qml b/.config/quickshell/services/LatexRenderer.qml index d3b9ade1f..e7066fa4c 100644 --- a/.config/quickshell/services/LatexRenderer.qml +++ b/.config/quickshell/services/LatexRenderer.qml @@ -25,7 +25,8 @@ Singleton { property list processedHashes: [] property var processedExpressions: ({}) property var renderedImagePaths: ({}) - property string microtexBinaryPath: Qt.resolvedUrl("/opt/MicroTeX/LaTeX") + property string microtexBinaryDir: "/opt/MicroTeX" + property string microtexBinaryName: "LaTeX" property string latexOutputPath: Directories.latexOutput signal renderFinished(string hash, string imagePath) @@ -51,23 +52,28 @@ Singleton { } // 3. If not, render it with MicroTeX and mark as processed + // console.log(`[LatexRenderer] Rendering expression: ${expression} with hash: ${hash}`) + // console.log(` to file: ${imagePath}`) + // console.log(` with command: cd ${microtexBinaryDir} && ./${microtexBinaryName} -headless -input=${StringUtils.shellSingleQuoteEscape(expression)} -output=${imagePath} -textsize=${Appearance.font.pixelSize.normal} -padding=${renderPadding} -background=${Appearance.m3colors.m3tertiary} -foreground=${Appearance.m3colors.m3onTertiary} -maxwidth=0.85`) const processQml = ` import Quickshell.Io Process { id: microtexProcess${hash} running: true - command: [ "${microtexBinaryPath}", "-headless", - "-input=${StringUtils.escapeBackslashes(expression)}", - "-output=${imagePath}", - "-textsize=${Appearance.font.pixelSize.normal}", - "-padding=${renderPadding}", - "-background=${Appearance.m3colors.m3tertiary}", - "-foreground=${Appearance.m3colors.m3onTertiary}", - "-maxwidth=0.85" ] + command: [ "bash", "-c", + "cd ${root.microtexBinaryDir} && ./${root.microtexBinaryName} -headless '-input=${StringUtils.shellSingleQuoteEscape(StringUtils.escapeBackslashes(expression))}' " + + "'-output=${imagePath}' " + + "'-textsize=${Appearance.font.pixelSize.normal}' " + + "'-padding=${renderPadding}' " + // + "'-background=${Appearance.m3colors.m3tertiary}' " + + "'-foreground=${Appearance.colors.colOnLayer1}' " + + "-maxwidth=0.85 " + ] // stdout: SplitParser { // onRead: data => { console.log("MicroTeX: " + data) } // } onExited: (exitCode, exitStatus) => { + // console.log("[LatexRenderer] MicroTeX process exited with code: " + exitCode + ", status: " + exitStatus) renderedImagePaths["${hash}"] = "${imagePath}" root.renderFinished("${hash}", "${imagePath}") microtexProcess${hash}.destroy() From d521b2aae430cd8f0c96d91d6cb2793f22e38f3c Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 8 Jun 2025 19:02:00 +0200 Subject: [PATCH 39/89] ai: latex: properly catch bracket-wrapped expressions --- .config/quickshell/modules/sidebarLeft/AiChat.qml | 11 ++++++++--- .../modules/sidebarLeft/aiChat/MessageTextBlock.qml | 10 +++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.config/quickshell/modules/sidebarLeft/AiChat.qml b/.config/quickshell/modules/sidebarLeft/AiChat.qml index ecb8628be..9ba1d3688 100644 --- a/.config/quickshell/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/modules/sidebarLeft/AiChat.qml @@ -125,9 +125,14 @@ int main(int argc, char* argv[]) { ### LaTeX -- Inline w/ dollar signs: $\\frac{1}{2} = \\frac{2}{4}$ -- Inline w/ double dollar signs: $$\\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}$$ -- Inline w/ backslash and square brackets \\[\\int_0^\\infty \\frac{1}{x^2} dx = \\infty\\] + +Inline w/ dollar signs: $\\frac{1}{2} = \\frac{2}{4}$ + +Inline w/ double dollar signs: $$\\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}$$ + +Inline w/ backslash and square brackets \\[\\int_0^\\infty \\frac{1}{x^2} dx = \\infty\\] + +Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) `, Ai.interfaceRole); } diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml b/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml index bc7f93df1..25ecb05a6 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml @@ -33,7 +33,7 @@ ColumnLayout { Timer { id: renderTimer interval: 1000 - repeat: true + repeat: false onTriggered: { renderLatex() for (const hash of renderedLatexHashes) { @@ -45,17 +45,17 @@ ColumnLayout { function renderLatex() { // Regex for $...$, $$...$$, \[...\] // Note: This is a simple approach and may need refinement for edge cases - let regex = /(\$\$([\s\S]+?)\$\$)|(\$([^\$]+?)\$)|(\\\[((?:.|\n)+?)\\\])/g; + let regex = /(\$\$([\s\S]+?)\$\$)|(\$([^\$]+?)\$)|(\\\[((?:.|\n)+?)\\\])|(\\\(([\s\S]+?)\\\))/g; let match; while ((match = regex.exec(segmentContent)) !== null) { - let expression = match[1] || match[2] || match[3]; + let expression = match[1] || match[2] || match[3] || match[4] || match[5] || match[6] || match[7] || match[8]; if (expression) { - // Qt.callLater(() => { - // }); + Qt.callLater(() => { const [renderHash, isNew] = LatexRenderer.requestRender(expression.trim()); if (!renderedLatexHashes.includes(renderHash)) { renderedLatexHashes.push(renderHash); } + }); } } } From d4f223c89469e09dc189a35038294fa388853a81 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 8 Jun 2025 21:39:03 +0200 Subject: [PATCH 40/89] starship: a refresh --- .config/starship.toml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/.config/starship.toml b/.config/starship.toml index 751f2fd2c..5ed04489e 100644 --- a/.config/starship.toml +++ b/.config/starship.toml @@ -10,25 +10,25 @@ add_newline = false # $character # """ format = """ -$cmd_duration$directory $git_branch +$cmd_duration 󰜥 $directory $git_branch $character """ # Replace the "❯" symbol in the prompt with "➜" [character] # The name of the module we are configuring is "character" -success_symbol = "[• ](bold fg:green) " -error_symbol = "[• 󰅙](bold fg:red) " +success_symbol = "[ 󰜥 ](bold fg:blue)" +error_symbol = "[ 󰜥 ](bold fg:red)" # Disable the package module, hiding it from the prompt completely [package] disabled = true [git_branch] -style = "bg: green" +style = "bg: cyan" symbol = "󰘬" -truncation_length = 4 +truncation_length = 12 truncation_symbol = "" -format = "• [](bold fg:green)[$symbol $branch(:$remote_branch)](fg:black bg:green)[ ](bold fg:green)" +format = "󰜥 [](bold fg:cyan)[$symbol $branch(:$remote_branch)](fg:black bg:cyan)[ ](bold fg:cyan)" [git_commit] commit_hash_length = 4 @@ -52,7 +52,7 @@ deleted = " 🗑 " [hostname] ssh_only = false -format = "[•$hostname](bg:cyan bold fg:black)[](bold fg:cyan )" +format = "[•$hostname](bg:cyan bold fg:black)[](bold fg:cyan)" trim_at = ".companyname.com" disabled = false @@ -82,8 +82,8 @@ home_symbol = "  " read_only = "  " style = "bg:green fg:black" truncation_length = 6 -truncation_symbol = "••/" -format = '[](bold fg:green)[$path ]($style)[](bold fg:green)' +truncation_symbol = " ••/" +format = '[](bold fg:green)[󰉋 $path]($style)[](bold fg:green)' [directory.substitutions] @@ -93,7 +93,8 @@ format = '[](bold fg:green)[$path ]($style)[](bold fg:green)' "Music" = " 󰎈 " "Pictures" = "  " "Videos" = "  " +"GitHub" = " 󰊤 " [cmd_duration] min_time = 0 -format = '[](bold fg:yellow)[ $duration](bold bg:yellow fg:black)[](bold fg:yellow) •• ' +format = '[](bold fg:yellow)[󰪢 $duration](bold bg:yellow fg:black)[](bold fg:yellow)' From 2663c46b7eb20ed3369f231256ee8fc0b8983ea3 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 8 Jun 2025 21:50:24 +0200 Subject: [PATCH 41/89] terminal: nice dir listing --- .config/fish/config.fish | 4 +++- arch-packages/illogical-impulse-fonts-themes/PKGBUILD | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.config/fish/config.fish b/.config/fish/config.fish index 7f9114d72..3ddb607e5 100755 --- a/.config/fish/config.fish +++ b/.config/fish/config.fish @@ -17,7 +17,9 @@ if test -f ~/.local/state/quickshell/user/generated/terminal/sequences.txt cat ~/.local/state/quickshell/user/generated/terminal/sequences.txt end -alias pamcan=pacman +alias pamcan pacman +alias ls 'eza --icons' + # function fish_prompt # set_color cyan; echo (pwd) diff --git a/arch-packages/illogical-impulse-fonts-themes/PKGBUILD b/arch-packages/illogical-impulse-fonts-themes/PKGBUILD index c96790c0b..ed1a95070 100644 --- a/arch-packages/illogical-impulse-fonts-themes/PKGBUILD +++ b/arch-packages/illogical-impulse-fonts-themes/PKGBUILD @@ -7,6 +7,7 @@ license=(None) depends=( adw-gtk-theme-git breeze-plus + eza fish fontconfig kde-material-you-colors From 08e46c5af88842a707849cb30b4da75536a482b7 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 09:20:51 +0200 Subject: [PATCH 42/89] make 0-size warnings stfu --- .config/quickshell/modules/bar/ActiveWindow.qml | 1 - .config/quickshell/modules/bar/Bar.qml | 2 +- .config/quickshell/modules/common/widgets/PrimaryTabButton.qml | 1 + .config/quickshell/modules/common/widgets/Revealer.qml | 1 + .config/quickshell/modules/common/widgets/RippleButton.qml | 1 + 5 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/modules/bar/ActiveWindow.qml b/.config/quickshell/modules/bar/ActiveWindow.qml index 574cdb8c6..86018129b 100644 --- a/.config/quickshell/modules/bar/ActiveWindow.qml +++ b/.config/quickshell/modules/bar/ActiveWindow.qml @@ -12,7 +12,6 @@ Item { height: parent.height width: colLayout.width - ColumnLayout { id: colLayout diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index ca9b1e57e..88a605fe1 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -176,7 +176,7 @@ Scope { } ActiveWindow { - visible: barRoot.useShortenedForm === 0 + visible: barRoot.useShortenedForm === 0 && width > 0 && height > 0 Layout.rightMargin: Appearance.rounding.screenRounding Layout.fillWidth: true bar: barRoot diff --git a/.config/quickshell/modules/common/widgets/PrimaryTabButton.qml b/.config/quickshell/modules/common/widgets/PrimaryTabButton.qml index b7c628712..a47f108b7 100644 --- a/.config/quickshell/modules/common/widgets/PrimaryTabButton.qml +++ b/.config/quickshell/modules/common/widgets/PrimaryTabButton.qml @@ -118,6 +118,7 @@ TabButton { property real implicitWidth: 0 property real implicitHeight: 0 + visible: width > 0 && height > 0 Behavior on opacity { animation: Appearance?.animation.elementMoveFast.colorAnimation.createObject(this) diff --git a/.config/quickshell/modules/common/widgets/Revealer.qml b/.config/quickshell/modules/common/widgets/Revealer.qml index 327d4aaa1..f3d438b55 100644 --- a/.config/quickshell/modules/common/widgets/Revealer.qml +++ b/.config/quickshell/modules/common/widgets/Revealer.qml @@ -13,6 +13,7 @@ Item { implicitWidth: (reveal || vertical) ? childrenRect.width : 0 implicitHeight: (reveal || !vertical) ? childrenRect.height : 0 + visible: width > 0 && height > 0 Behavior on implicitWidth { enabled: !vertical diff --git a/.config/quickshell/modules/common/widgets/RippleButton.qml b/.config/quickshell/modules/common/widgets/RippleButton.qml index cd7762b9d..9931cd02a 100644 --- a/.config/quickshell/modules/common/widgets/RippleButton.qml +++ b/.config/quickshell/modules/common/widgets/RippleButton.qml @@ -155,6 +155,7 @@ Button { width: ripple.implicitWidth height: ripple.implicitHeight opacity: 0 + visible: width > 0 && height > 0 property real implicitWidth: 0 property real implicitHeight: 0 From 8e1f28b11a68ff77b78b26c839b35795d3dcc6ac Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 09:25:22 +0200 Subject: [PATCH 43/89] less weird tooltip color for dark mode --- .config/quickshell/modules/common/Appearance.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index 9f83ac5cf..a984b9e4f 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -133,7 +133,7 @@ Singleton { property color colSecondaryContainerActive: ColorUtils.mix(m3colors.m3secondaryContainer, colLayer1Active, 0.54) property color colSurfaceContainerHighestHover: ColorUtils.mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.95) property color colSurfaceContainerHighestActive: ColorUtils.mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.85) - property color colTooltip: "#3C4043" // m3colors.m3inverseSurface in the specs, but the m3 website actually uses this color + property color colTooltip: m3colors.darkmode ? ColorUtils.mix(m3colors.m3background, "#3C4043", 0.5) : "#3C4043" // m3colors.m3inverseSurface in the specs, but the m3 website actually uses #3C4043 property color colOnTooltip: "#F8F9FA" // m3colors.m3inverseOnSurface in the specs, but the m3 website actually uses this color property color colScrim: ColorUtils.transparentize(m3colors.m3scrim, 0.5) property color colShadow: ColorUtils.transparentize(m3colors.m3shadow, 0.7) From fa2723a54defdd53f6c69a2aaee68e9b24809291 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 12:23:58 +0200 Subject: [PATCH 44/89] dock: remove user config option because it doesn't work (just use enableDock in shell.qml) --- .config/quickshell/modules/common/ConfigOptions.qml | 1 - .config/quickshell/shell.qml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 514f21c23..6f1bc112a 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -53,7 +53,6 @@ Singleton { } property QtObject dock: QtObject { - property bool enable: false property real height: 60 property real hoverRegionHeight: 3 property bool pinnedOnStartup: false diff --git a/.config/quickshell/shell.qml b/.config/quickshell/shell.qml index 5d14061bf..4acb7cccb 100644 --- a/.config/quickshell/shell.qml +++ b/.config/quickshell/shell.qml @@ -54,7 +54,7 @@ ShellRoot { LazyLoader { active: enableBar; component: Bar {} } LazyLoader { active: enableBackgroundWidgets; component: BackgroundWidgets {} } LazyLoader { active: enableCheatsheet; component: Cheatsheet {} } - LazyLoader { active: (enableDock && ConfigOptions?.dock.enable); component: Dock {} } + LazyLoader { active: enableDock; component: Dock {} } LazyLoader { active: enableMediaControls; component: MediaControls {} } LazyLoader { active: enableNotificationPopup; component: NotificationPopup {} } LazyLoader { active: enableOnScreenDisplayBrightness; component: OnScreenDisplayBrightness {} } From db8d51b931c5685b89768546d2c5e15a940e9cd2 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 12:25:41 +0200 Subject: [PATCH 45/89] overview: window previews!!! --- .../modules/common/widgets/StyledLabel.qml | 15 +++++++++++++++ .../modules/overview/OverviewWidget.qml | 18 +++++++++++++----- .../modules/overview/OverviewWindow.qml | 19 ++++++++++++++++++- 3 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 .config/quickshell/modules/common/widgets/StyledLabel.qml diff --git a/.config/quickshell/modules/common/widgets/StyledLabel.qml b/.config/quickshell/modules/common/widgets/StyledLabel.qml new file mode 100644 index 000000000..20a1cc9f0 --- /dev/null +++ b/.config/quickshell/modules/common/widgets/StyledLabel.qml @@ -0,0 +1,15 @@ +import "root:/modules/common" +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Label { + renderType: Text.NativeRendering + verticalAlignment: Text.AlignVCenter + font { + hintingPreference: Font.PreferFullHinting + family: Appearance?.font.family.main ?? "sans-serif" + pixelSize: Appearance?.font.pixelSize.small ?? 15 + } + color: Appearance?.m3colors.m3onBackground ?? "black" +} diff --git a/.config/quickshell/modules/overview/OverviewWidget.qml b/.config/quickshell/modules/overview/OverviewWidget.qml index a690536fe..f6f1f4840 100644 --- a/.config/quickshell/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/modules/overview/OverviewWidget.qml @@ -145,14 +145,22 @@ Item { Repeater { // Window repeater model: ScriptModel { - values: windowAddresses.filter((address) => { - var win = windowByAddress[address] - return (root.workspaceGroup * root.workspacesShown < win?.workspace?.id && win?.workspace?.id <= (root.workspaceGroup + 1) * root.workspacesShown) - }) + values: { + // console.log(JSON.stringify(ToplevelManager.toplevels.values.map(t => t), null, 2)) + return ToplevelManager.toplevels.values.filter((toplevel) => { + const address = `0x${toplevel.HyprlandToplevel.address}` + // console.log(`Checking window with address: ${address}`) + var win = windowByAddress[address] + return (root.workspaceGroup * root.workspacesShown < win?.workspace?.id && win?.workspace?.id <= (root.workspaceGroup + 1) * root.workspacesShown) + }) + } } delegate: OverviewWindow { + required property var modelData + property var address: `0x${modelData.HyprlandToplevel.address}` id: window - windowData: windowByAddress[modelData] + windowData: windowByAddress[address] + toplevel: modelData monitorData: root.monitorData scale: root.scale availableWorkspaceWidth: root.workspaceImplicitWidth diff --git a/.config/quickshell/modules/overview/OverviewWindow.qml b/.config/quickshell/modules/overview/OverviewWindow.qml index d4617b542..15d919f80 100644 --- a/.config/quickshell/modules/overview/OverviewWindow.qml +++ b/.config/quickshell/modules/overview/OverviewWindow.qml @@ -1,17 +1,21 @@ +import "root:/" import "root:/services/" import "root:/modules/common" import "root:/modules/common/widgets" import "root:/modules/common/functions/color_utils.js" as ColorUtils import Qt5Compat.GraphicalEffects import QtQuick +import QtQuick.Controls import QtQuick.Layouts import Quickshell import Quickshell.Widgets import Quickshell.Io +import Quickshell.Wayland import Quickshell.Hyprland Rectangle { // Window id: root + property var toplevel property var windowData property var monitorData property var scale @@ -60,6 +64,12 @@ Rectangle { // Window animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this) } + ScreencopyView { + anchors.fill: parent + captureSource: GlobalStates.overviewOpen ? root.toplevel : null + live: false + } + ColumnLayout { anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left @@ -77,12 +87,19 @@ Rectangle { // Window } } - StyledText { + StyledLabel { Layout.leftMargin: 10 Layout.rightMargin: 10 visible: !compactMode Layout.fillWidth: true Layout.fillHeight: true + + background: Rectangle { + width: parent.width + color: Appearance.colors.colLayer2 + radius: Appearance.rounding.windowRounding * root.scale + } + horizontalAlignment: Text.AlignHCenter font.pixelSize: Appearance.font.pixelSize.smaller font.italic: indicateXWayland ? true : false From a81acb3dbea5a2752be139130d674c1a1573360f Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 12:51:28 +0200 Subject: [PATCH 46/89] overview: cleaner, add back hover effect --- .../backgroundWidgets/BackgroundWidgets.qml | 2 +- .../modules/overview/OverviewWindow.qml | 69 +++++++++---------- .../modules/sidebarRight/SidebarRight.qml | 10 +++ 3 files changed, 42 insertions(+), 39 deletions(-) diff --git a/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml b/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml index dea41e08f..970dc8d17 100644 --- a/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml +++ b/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml @@ -23,7 +23,7 @@ Scope { property color colText: ColorUtils.colorWithLightness(Appearance.m3colors.m3primary, (root.dominantColorIsDark ? 0.8 : 0.12)) function updateWidgetPosition(fileContent) { - console.log("[BackgroundWidgets] Updating widget position with content:", fileContent) + // console.log("[BackgroundWidgets] Updating widget position with content:", fileContent) const parsedContent = JSON.parse(fileContent) root.centerX = parsedContent.center_x root.centerY = parsedContent.center_y diff --git a/.config/quickshell/modules/overview/OverviewWindow.qml b/.config/quickshell/modules/overview/OverviewWindow.qml index 15d919f80..1f350b7d4 100644 --- a/.config/quickshell/modules/overview/OverviewWindow.qml +++ b/.config/quickshell/modules/overview/OverviewWindow.qml @@ -45,11 +45,14 @@ Rectangle { // Window width: Math.min(windowData?.size[0] * root.scale, (restrictToWorkspace ? windowData?.size[0] : availableWorkspaceWidth - x + xOffset)) height: Math.min(windowData?.size[1] * root.scale, (restrictToWorkspace ? windowData?.size[1] : availableWorkspaceHeight - y + yOffset)) - radius: Appearance.rounding.windowRounding * root.scale - color: pressed ? Appearance.colors.colLayer2Active : hovered ? Appearance.colors.colLayer2Hover : Appearance.colors.colLayer2 - border.color : ColorUtils.transparentize(Appearance.m3colors.m3outline, 0.9) - border.pixelAligned : false - border.width : 1 + layer.enabled: true + layer.effect: OpacityMask { + maskSource: Rectangle { + width: root.width + height: root.height + radius: Appearance.rounding.windowRounding * root.scale + } + } Behavior on x { animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this) @@ -67,44 +70,34 @@ Rectangle { // Window ScreencopyView { anchors.fill: parent captureSource: GlobalStates.overviewOpen ? root.toplevel : null - live: false - } + live: true - ColumnLayout { - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.right: parent.right - spacing: Appearance.font.pixelSize.smaller * 0.5 - - IconImage { - id: windowIcon - Layout.alignment: Qt.AlignHCenter - source: root.iconPath - implicitSize: Math.min(targetWindowWidth, targetWindowHeight) * (root.compactMode ? root.iconToWindowRatioCompact : root.iconToWindowRatio) - - Behavior on implicitSize { - animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this) - } + Rectangle { + anchors.fill: parent + radius: Appearance.rounding.windowRounding * root.scale + color: pressed ? Appearance.colors.colLayer2Active : hovered ? Appearance.colors.colLayer2Hover : Appearance.colors.colLayer2 + opacity: pressed ? 0.3 : hovered ? 0.2 : 0 + border.color : ColorUtils.transparentize(Appearance.m3colors.m3outline, 0.9) + border.pixelAligned : false + border.width : 1 } - StyledLabel { - Layout.leftMargin: 10 - Layout.rightMargin: 10 - visible: !compactMode - Layout.fillWidth: true - Layout.fillHeight: true + ColumnLayout { + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.right: parent.right + spacing: Appearance.font.pixelSize.smaller * 0.5 - background: Rectangle { - width: parent.width - color: Appearance.colors.colLayer2 - radius: Appearance.rounding.windowRounding * root.scale + IconImage { + id: windowIcon + Layout.alignment: Qt.AlignHCenter + source: root.iconPath + implicitSize: Math.min(targetWindowWidth, targetWindowHeight) * (root.compactMode ? root.iconToWindowRatioCompact : root.iconToWindowRatio) + + Behavior on implicitSize { + animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this) + } } - - horizontalAlignment: Text.AlignHCenter - font.pixelSize: Appearance.font.pixelSize.smaller - font.italic: indicateXWayland ? true : false - elide: Text.ElideRight - text: windowData?.title ?? "" } } } \ No newline at end of file diff --git a/.config/quickshell/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/modules/sidebarRight/SidebarRight.qml index 2bb92723d..8fcdca4c8 100644 --- a/.config/quickshell/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/modules/sidebarRight/SidebarRight.qml @@ -127,6 +127,16 @@ Scope { Layout.fillWidth: true } + QuickToggleButton { + toggled: false + buttonIcon: "restart_alt" + onClicked: { + Quickshell.reload(true) + } + StyledToolTip { + content: qsTr("Reload") + } + } QuickToggleButton { toggled: false buttonIcon: "power_settings_new" From 936ca85babffb4332a1b35830b9c7fb45db67f7e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 13:11:39 +0200 Subject: [PATCH 47/89] overview: fix blurry icons --- .../modules/overview/OverviewWidget.qml | 4 ++-- .../modules/overview/OverviewWindow.qml | 20 ++++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.config/quickshell/modules/overview/OverviewWidget.qml b/.config/quickshell/modules/overview/OverviewWidget.qml index f6f1f4840..e1fbb3264 100644 --- a/.config/quickshell/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/modules/overview/OverviewWidget.qml @@ -180,8 +180,8 @@ Item { repeat: false running: false onTriggered: { - window.x = Math.max((windowData?.at[0] - monitorData?.reserved[0]) * root.scale, 0) + xOffset - window.y = Math.max((windowData?.at[1] - monitorData?.reserved[1]) * root.scale, 0) + yOffset + window.x = Math.round(Math.max((windowData?.at[0] - monitorData?.reserved[0]) * root.scale, 0) + xOffset) + window.y = Math.round(Math.max((windowData?.at[1] - monitorData?.reserved[1]) * root.scale, 0) + yOffset) } } diff --git a/.config/quickshell/modules/overview/OverviewWindow.qml b/.config/quickshell/modules/overview/OverviewWindow.qml index 1f350b7d4..6436120e2 100644 --- a/.config/quickshell/modules/overview/OverviewWindow.qml +++ b/.config/quickshell/modules/overview/OverviewWindow.qml @@ -13,7 +13,7 @@ import Quickshell.Io import Quickshell.Wayland import Quickshell.Hyprland -Rectangle { // Window +Item { // Window id: root property var toplevel property var windowData @@ -42,8 +42,8 @@ Rectangle { // Window x: initX y: initY - width: Math.min(windowData?.size[0] * root.scale, (restrictToWorkspace ? windowData?.size[0] : availableWorkspaceWidth - x + xOffset)) - height: Math.min(windowData?.size[1] * root.scale, (restrictToWorkspace ? windowData?.size[1] : availableWorkspaceHeight - y + yOffset)) + width: Math.round(Math.min(windowData?.size[0] * root.scale, (restrictToWorkspace ? windowData?.size[0] : availableWorkspaceWidth - x + xOffset))) + height: Math.round(Math.min(windowData?.size[1] * root.scale, (restrictToWorkspace ? windowData?.size[1] : availableWorkspaceHeight - y + yOffset))) layer.enabled: true layer.effect: OpacityMask { @@ -78,7 +78,6 @@ Rectangle { // Window color: pressed ? Appearance.colors.colLayer2Active : hovered ? Appearance.colors.colLayer2Hover : Appearance.colors.colLayer2 opacity: pressed ? 0.3 : hovered ? 0.2 : 0 border.color : ColorUtils.transparentize(Appearance.m3colors.m3outline, 0.9) - border.pixelAligned : false border.width : 1 } @@ -88,13 +87,20 @@ Rectangle { // Window anchors.right: parent.right spacing: Appearance.font.pixelSize.smaller * 0.5 - IconImage { + Image { id: windowIcon + property var iconSize: Math.min(targetWindowWidth, targetWindowHeight) * (root.compactMode ? root.iconToWindowRatioCompact : root.iconToWindowRatio) + // mipmap: true Layout.alignment: Qt.AlignHCenter source: root.iconPath - implicitSize: Math.min(targetWindowWidth, targetWindowHeight) * (root.compactMode ? root.iconToWindowRatioCompact : root.iconToWindowRatio) + width: iconSize + height: iconSize + sourceSize: Qt.size(iconSize, iconSize) - Behavior on implicitSize { + Behavior on width { + animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this) + } + Behavior on height { animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this) } } From 2a8725ec8d9266b38448cd87950dda24603e8a75 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 16:31:04 +0200 Subject: [PATCH 48/89] deps: remove xdg-user-dirs (#1369) --- arch-packages/illogical-impulse-toolkit/PKGBUILD | 1 - 1 file changed, 1 deletion(-) diff --git a/arch-packages/illogical-impulse-toolkit/PKGBUILD b/arch-packages/illogical-impulse-toolkit/PKGBUILD index 673e12f8b..6f12584a2 100644 --- a/arch-packages/illogical-impulse-toolkit/PKGBUILD +++ b/arch-packages/illogical-impulse-toolkit/PKGBUILD @@ -22,6 +22,5 @@ depends=( syntax-highlighting upower wtype - xdg-user-dirs-gtk ydotool ) From 3c82ce828b190f0aaafff0195e575a7a14b3b03f Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 17:41:33 +0200 Subject: [PATCH 49/89] config options: correct settings app --- .config/quickshell/modules/common/ConfigOptions.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 6f1bc112a..ce6e45aa8 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -25,7 +25,7 @@ Singleton { property string imageViewer: "loupe" property string network: "better-control --wifi" property string networkEthernet: "systemsettings kcm_networkmanagement" - property string settings: "systemsettings kcm_bluetooth" + property string settings: "systemsettings" property string taskManager: "plasma-systemmonitor --page-name Processes" property string terminal: "kitty -1" // This is only for shell actions } From 4b4364d2a5cf63009dba90e38af7d932356f6b73 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 17:42:04 +0200 Subject: [PATCH 50/89] right sidebar: more buttons --- .../modules/sidebarRight/SidebarRight.qml | 46 ++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/.config/quickshell/modules/sidebarRight/SidebarRight.qml b/.config/quickshell/modules/sidebarRight/SidebarRight.qml index 8fcdca4c8..a1e5a7478 100644 --- a/.config/quickshell/modules/sidebarRight/SidebarRight.qml +++ b/.config/quickshell/modules/sidebarRight/SidebarRight.qml @@ -127,24 +127,38 @@ Scope { Layout.fillWidth: true } - QuickToggleButton { - toggled: false - buttonIcon: "restart_alt" - onClicked: { - Quickshell.reload(true) + ButtonGroup { + QuickToggleButton { + toggled: false + buttonIcon: "restart_alt" + onClicked: { + Hyprland.dispatch("reload") + Quickshell.reload(true) + } + StyledToolTip { + content: qsTr("Reload Hyprland & Quickshell") + } } - StyledToolTip { - content: qsTr("Reload") + QuickToggleButton { + toggled: false + buttonIcon: "settings" + onClicked: { + Hyprland.dispatch(`exec ${ConfigOptions.apps.settings}`) + Hyprland.dispatch(`global quickshell:sidebarRightClose`) + } + StyledToolTip { + content: qsTr("Plasma Settings") + } } - } - QuickToggleButton { - toggled: false - buttonIcon: "power_settings_new" - onClicked: { - Hyprland.dispatch("global quickshell:sessionOpen") - } - StyledToolTip { - content: qsTr("Session") + QuickToggleButton { + toggled: false + buttonIcon: "power_settings_new" + onClicked: { + Hyprland.dispatch("global quickshell:sessionOpen") + } + StyledToolTip { + content: qsTr("Session") + } } } } From 5c2b12bf96af9ca0cafacf46bbc58c1cb2a5d348 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 17:43:58 +0200 Subject: [PATCH 51/89] dock: join pinned apps and open windows --- .config/quickshell/modules/dock/Dock.qml | 20 ---- .../quickshell/modules/dock/DockAppButton.qml | 112 +++++++++++------- .config/quickshell/modules/dock/DockApps.qml | 40 +++++-- 3 files changed, 99 insertions(+), 73 deletions(-) diff --git a/.config/quickshell/modules/dock/Dock.qml b/.config/quickshell/modules/dock/Dock.qml index bd0ac8ec7..25846ac5f 100644 --- a/.config/quickshell/modules/dock/Dock.qml +++ b/.config/quickshell/modules/dock/Dock.qml @@ -120,26 +120,6 @@ Scope { // Scope } } DockSeparator {} - // Pinned apps - Repeater { - model: ConfigOptions?.dock.pinnedApps ?? [] - - DockButton { - id: pinnedAppButton - required property string modelData - property DesktopEntry entry: DesktopEntries.byId(modelData) - onClicked: { - pinnedAppButton?.entry.execute(); - } - contentItem: IconImage { - anchors.centerIn: parent - source: Quickshell.iconPath(AppSearch.guessIcon(modelData), "image-missing") - } - } - } - - DockSeparator { visible: (ConfigOptions?.dock.pinnedApps ?? []).length > 0 } - DockApps { id: dockApps } DockSeparator {} DockButton { diff --git a/.config/quickshell/modules/dock/DockAppButton.qml b/.config/quickshell/modules/dock/DockAppButton.qml index 9df44c853..2304fe158 100644 --- a/.config/quickshell/modules/dock/DockAppButton.qml +++ b/.config/quickshell/modules/dock/DockAppButton.qml @@ -14,8 +14,8 @@ import Quickshell.Wayland import Quickshell.Hyprland DockButton { - id: appButton - required property var appToplevel + id: root + property var appToplevel property var appListRoot property int lastFocused: -1 property real iconSize: 35 @@ -23,56 +23,86 @@ DockButton { property real countDotHeight: 4 property bool appIsActive: appToplevel.toplevels.find(t => (t.activated == true)) !== undefined - MouseArea { - id: mouseArea - anchors.fill: parent - hoverEnabled: true - acceptedButtons: Qt.NoButton - onEntered: { - appListRoot.lastHoveredButton = appButton - appListRoot.buttonHovered = true - lastFocused = appToplevel.toplevels.length - 1 + property bool isSeparator: appToplevel.appId === "SEPARATOR" + enabled: !isSeparator + implicitWidth: isSeparator ? 1 : implicitHeight - topInset - bottomInset + + Loader { + active: isSeparator + anchors { + fill: parent + topMargin: dockVisualBackground.margin + dockRow.padding + Appearance.rounding.normal + bottomMargin: dockVisualBackground.margin + dockRow.padding + Appearance.rounding.normal } - onExited: { - if (appListRoot.lastHoveredButton === appButton) { - appListRoot.buttonHovered = false + sourceComponent: DockSeparator {} + } + + Loader { + anchors.fill: parent + active: appToplevel.toplevels.length > 0 + sourceComponent: MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + acceptedButtons: Qt.NoButton + onEntered: { + appListRoot.lastHoveredButton = root + appListRoot.buttonHovered = true + lastFocused = appToplevel.toplevels.length - 1 + } + onExited: { + if (appListRoot.lastHoveredButton === root) { + appListRoot.buttonHovered = false + } } } } + onClicked: { + if (appToplevel.toplevels.length === 0) { + DesktopEntries.byId(root.appToplevel.appId)?.execute(); + return; + } lastFocused = (lastFocused + 1) % appToplevel.toplevels.length appToplevel.toplevels[lastFocused].activate() } - contentItem: Item { - anchors.centerIn: parent - IconImage { - id: iconImage - anchors { - left: parent.left - right: parent.right - verticalCenter: parent.verticalCenter - } - source: Quickshell.iconPath(AppSearch.guessIcon(appToplevel.appId), "image-missing") - implicitSize: appButton.iconSize - } + contentItem: Loader { + active: !isSeparator + sourceComponent: Item { + anchors.centerIn: parent - RowLayout { - spacing: 3 - anchors { - top: iconImage.bottom - topMargin: 2 - horizontalCenter: parent.horizontalCenter + Loader { + id: iconImageLoader + anchors { + left: parent.left + right: parent.right + verticalCenter: parent.verticalCenter + } + active: !root.isSeparator + sourceComponent: IconImage { + source: Quickshell.iconPath(AppSearch.guessIcon(appToplevel.appId), "image-missing") + implicitSize: root.iconSize + } } - Repeater { - model: Math.min(appToplevel.toplevels.length, 3) - delegate: Rectangle { - required property int index - radius: Appearance.rounding.full - implicitWidth: (appToplevel.toplevels.length <= 3) ? - appButton.countDotWidth : appButton.countDotHeight // Circles when too many - implicitHeight: appButton.countDotHeight - color: appIsActive ? Appearance.m3colors.m3primary : ColorUtils.transparentize(Appearance.colors.colOnLayer0, 0.4) + + RowLayout { + spacing: 3 + anchors { + top: iconImageLoader.bottom + topMargin: 2 + horizontalCenter: parent.horizontalCenter + } + Repeater { + model: Math.min(appToplevel.toplevels.length, 3) + delegate: Rectangle { + required property int index + radius: Appearance.rounding.full + implicitWidth: (appToplevel.toplevels.length <= 3) ? + root.countDotWidth : root.countDotHeight // Circles when too many + implicitHeight: root.countDotHeight + color: appIsActive ? Appearance.m3colors.m3primary : ColorUtils.transparentize(Appearance.colors.colOnLayer0, 0.4) + } } } } diff --git a/.config/quickshell/modules/dock/DockApps.qml b/.config/quickshell/modules/dock/DockApps.qml index 9a8db93a9..900db0ca0 100644 --- a/.config/quickshell/modules/dock/DockApps.qml +++ b/.config/quickshell/modules/dock/DockApps.qml @@ -23,8 +23,9 @@ Item { property Item lastHoveredButton property bool buttonHovered: false property bool requestDockShow: previewPopup.show - property real popupX: parentWindow.mapFromItem(root.lastHoveredButton, root.lastHoveredButton.width / 2, root.lastHoveredButton.height / 2).x - implicitWidth / 2 - + property var parentWindow: root.QsWindow + property real popupX: parentWindow?.mapFromItem(root.lastHoveredButton, root.lastHoveredButton?.width / 2, root.lastHoveredButton?.height / 2).x - implicitWidth / 2 + ?? 0 implicitWidth: rowLayout.implicitWidth implicitHeight: rowLayout.implicitHeight @@ -38,15 +39,33 @@ Item { values: { var map = new Map(); + // Pinned apps + const pinnedApps = ConfigOptions?.dock.pinnedApps ?? []; + for (const appId of pinnedApps) { + if (!map.has(appId.toLowerCase())) map.set(appId.toLowerCase(), ({ + pinned: true, + toplevels: [] + })); + } + + // Separator + if (pinnedApps.length > 0) { + map.set("SEPARATOR", { pinned: false, toplevels: [] }); + } + + // Open windows for (const toplevel of ToplevelManager.toplevels.values) { - if (!map.has(toplevel.appId.toLowerCase())) map.set(toplevel.appId.toLowerCase(), []); - map.get(toplevel.appId.toLowerCase()).push(toplevel); + if (!map.has(toplevel.appId.toLowerCase())) map.set(toplevel.appId.toLowerCase(), ({ + pinned: false, + toplevels: [] + })); + map.get(toplevel.appId.toLowerCase()).toplevels.push(toplevel); } var values = []; for (const [key, value] of map) { - values.push({ appId: key, toplevels: value }); + values.push({ appId: key, toplevels: value.toplevels, pinned: value.pinned }); } return values; @@ -118,14 +137,9 @@ Item { anchors.bottom: parent.bottom implicitWidth: popupBackground.implicitWidth + Appearance.sizes.elevationMargin * 2 implicitHeight: root.maxWindowPreviewHeight + root.windowControlsHeight + Appearance.sizes.elevationMargin * 2 - // anchors.horizontalCenter: parent.horizontalCenter hoverEnabled: true - // x: previewPopup.width / 2 + root.popupX - // Behavior on x { - // animation: Appearance.animation.elementMove.numberAnimation.createObject(this) - // } x: { - const itemCenter = root.QsWindow.mapFromItem(root.lastHoveredButton, root.lastHoveredButton.width / 2, 0); + const itemCenter = root.QsWindow?.mapFromItem(root.lastHoveredButton, root.lastHoveredButton?.width / 2, 0); return itemCenter.x - width / 2 } StyledRectangularShadow { @@ -163,7 +177,9 @@ Item { id: previewRowLayout anchors.centerIn: parent Repeater { - model: previewPopup.appTopLevel?.toplevels ?? [] + model: ScriptModel { + values: previewPopup.appTopLevel?.toplevels ?? [] + } RippleButton { id: windowButton required property var modelData From 0beccd69e86f894403d276583ee60e76debedc78 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 17:47:57 +0200 Subject: [PATCH 52/89] overview: adjust hover/click colors --- .config/quickshell/modules/overview/OverviewWindow.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/modules/overview/OverviewWindow.qml b/.config/quickshell/modules/overview/OverviewWindow.qml index 6436120e2..17a3b4bc2 100644 --- a/.config/quickshell/modules/overview/OverviewWindow.qml +++ b/.config/quickshell/modules/overview/OverviewWindow.qml @@ -68,6 +68,7 @@ Item { // Window } ScreencopyView { + id: windowPreview anchors.fill: parent captureSource: GlobalStates.overviewOpen ? root.toplevel : null live: true @@ -76,7 +77,7 @@ Item { // Window anchors.fill: parent radius: Appearance.rounding.windowRounding * root.scale color: pressed ? Appearance.colors.colLayer2Active : hovered ? Appearance.colors.colLayer2Hover : Appearance.colors.colLayer2 - opacity: pressed ? 0.3 : hovered ? 0.2 : 0 + opacity: pressed ? 0.5 : hovered ? 0.3 : 0 border.color : ColorUtils.transparentize(Appearance.m3colors.m3outline, 0.9) border.width : 1 } From 6fffa86fc2a0d9f88342dc0f57ed097f3924649a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 18:08:10 +0200 Subject: [PATCH 53/89] dock: middle click to open new window --- .config/quickshell/modules/dock/DockAppButton.qml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/modules/dock/DockAppButton.qml b/.config/quickshell/modules/dock/DockAppButton.qml index 2304fe158..5ddb6d150 100644 --- a/.config/quickshell/modules/dock/DockAppButton.qml +++ b/.config/quickshell/modules/dock/DockAppButton.qml @@ -24,6 +24,7 @@ DockButton { property bool appIsActive: appToplevel.toplevels.find(t => (t.activated == true)) !== undefined property bool isSeparator: appToplevel.appId === "SEPARATOR" + property var desktopEntry: DesktopEntries.byId(appToplevel.appId) enabled: !isSeparator implicitWidth: isSeparator ? 1 : implicitHeight - topInset - bottomInset @@ -60,13 +61,17 @@ DockButton { onClicked: { if (appToplevel.toplevels.length === 0) { - DesktopEntries.byId(root.appToplevel.appId)?.execute(); + root.desktopEntry?.execute(); return; } lastFocused = (lastFocused + 1) % appToplevel.toplevels.length appToplevel.toplevels[lastFocused].activate() } + middleClickAction: () => { + root.desktopEntry?.execute(); + } + contentItem: Loader { active: !isSeparator sourceComponent: Item { From cfb8a851e6bfa2028c0ca4dbbd5010d4416dbd06 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 22:34:04 +0200 Subject: [PATCH 54/89] readme: screenshots --- README.md | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index a845e4899..123b8cc6b 100644 --- a/README.md +++ b/README.md @@ -81,23 +81,21 @@ It's ready if you don't need localization... so quite likely

-## Main branch (*illogical-impulse*) +## illogical-impulseQuickshell -### AI -![image](https://github.com/user-attachments/assets/9d7af13f-89ef-470d-ba78-d2288b79cf60) -_Sidebar offers online and offline chat. Text selection summary is offline only for privacy._ +| AI | Common widgets | +|:---|:---------------| +| ![image](https://github.com/user-attachments/assets/08d26785-b54d-4ad1-875b-bb08cc6757f5) | ![image](https://github.com/user-attachments/assets/4fcd63d9-0943-4b21-8737-4bed97b71961) | +| Window management | Weeb power | +| ![image](https://github.com/user-attachments/assets/86cc511b-0d33-4c78-bcc0-3037d02a17da) | ![image](https://github.com/user-attachments/assets/a34a9664-326a-4e66-a643-480d6f7fcc19) | -### Notifications, music controls, system, calendar -![image](https://github.com/end-4/dots-hyprland/assets/97237370/406b72b6-fa38-4f0d-a6c4-4d7d5d5ddcb7) -_On the sidebar: flicking the notification_ +## illogical-impulseAGS -### Intuitive window management -![image](https://github.com/user-attachments/assets/02983b9b-79ba-4c25-8717-90bef2357ae5) -_You can also drag and drop windows across workspaces_ - -### Power to weebs -![image](https://github.com/user-attachments/assets/bbb332ec-962a-4e88-a95b-486d0bd8ce76) -_Get yande.re and konachan images from sidebar_ +| AI | Common widgets | +|:---|:---------------| +| ![image](https://github.com/user-attachments/assets/9d7af13f-89ef-470d-ba78-d2288b79cf60) | ![image](https://github.com/end-4/dots-hyprland/assets/97237370/406b72b6-fa38-4f0d-a6c4-4d7d5d5ddcb7) | +| Window management | Weeb power | +| ![image](https://github.com/user-attachments/assets/02983b9b-79ba-4c25-8717-90bef2357ae5) | ![image](https://github.com/user-attachments/assets/bbb332ec-962a-4e88-a95b-486d0bd8ce76) | ## Unsupported stuff From 2c4537bd024b012833451ee875388f4d5c9b2140 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 22:36:17 +0200 Subject: [PATCH 55/89] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 123b8cc6b..9403c73f2 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ It's ready if you don't need localization... so quite likely |:---|:---------------| | ![image](https://github.com/user-attachments/assets/08d26785-b54d-4ad1-875b-bb08cc6757f5) | ![image](https://github.com/user-attachments/assets/4fcd63d9-0943-4b21-8737-4bed97b71961) | | Window management | Weeb power | -| ![image](https://github.com/user-attachments/assets/86cc511b-0d33-4c78-bcc0-3037d02a17da) | ![image](https://github.com/user-attachments/assets/a34a9664-326a-4e66-a643-480d6f7fcc19) | +| ![image](https://github.com/user-attachments/assets/86cc511b-0d33-4c78-bcc0-3037d02a17da) | ![image](https://github.com/user-attachments/assets/e402f74a-6bd8-4ebe-bcf4-3a4a4846de10) | ## illogical-impulseAGS From 56958236e2f936961f50766d8589627083cdf1e2 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 23:04:04 +0200 Subject: [PATCH 56/89] nicer link colors --- .config/quickshell/modules/common/widgets/StyledLabel.qml | 1 + .config/quickshell/modules/common/widgets/StyledText.qml | 1 + 2 files changed, 2 insertions(+) diff --git a/.config/quickshell/modules/common/widgets/StyledLabel.qml b/.config/quickshell/modules/common/widgets/StyledLabel.qml index 20a1cc9f0..f5201baea 100644 --- a/.config/quickshell/modules/common/widgets/StyledLabel.qml +++ b/.config/quickshell/modules/common/widgets/StyledLabel.qml @@ -12,4 +12,5 @@ Label { pixelSize: Appearance?.font.pixelSize.small ?? 15 } color: Appearance?.m3colors.m3onBackground ?? "black" + linkColor: Appearance?.m3colors.m3primary } diff --git a/.config/quickshell/modules/common/widgets/StyledText.qml b/.config/quickshell/modules/common/widgets/StyledText.qml index 6eef57852..7750456e0 100644 --- a/.config/quickshell/modules/common/widgets/StyledText.qml +++ b/.config/quickshell/modules/common/widgets/StyledText.qml @@ -11,4 +11,5 @@ Text { pixelSize: Appearance?.font.pixelSize.small ?? 15 } color: Appearance?.m3colors.m3onBackground ?? "black" + linkColor: Appearance?.m3colors.m3primary } From a6ecf107b3c1f61183cab9b3a65ed24b5147ba99 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 23:04:35 +0200 Subject: [PATCH 57/89] quickshell: fix some warnings --- .../modules/notificationPopup/NotificationPopup.qml | 2 +- .config/quickshell/modules/overview/Overview.qml | 4 ++-- .config/quickshell/modules/sidebarLeft/Anime.qml | 4 +++- .config/quickshell/services/Audio.qml | 3 --- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.config/quickshell/modules/notificationPopup/NotificationPopup.qml b/.config/quickshell/modules/notificationPopup/NotificationPopup.qml index 122489d88..fb046343d 100644 --- a/.config/quickshell/modules/notificationPopup/NotificationPopup.qml +++ b/.config/quickshell/modules/notificationPopup/NotificationPopup.qml @@ -15,7 +15,7 @@ Scope { PanelWindow { id: root visible: (Notifications.popupList.length > 0) - screen: Quickshell.screens.find(s => s.name === Hyprland.focusedMonitor?.name) + screen: Quickshell.screens.find(s => s.name === Hyprland.focusedMonitor?.name) ?? null WlrLayershell.namespace: "quickshell:notificationPopup" WlrLayershell.layer: WlrLayer.Overlay diff --git a/.config/quickshell/modules/overview/Overview.qml b/.config/quickshell/modules/overview/Overview.qml index 6fa85e891..d3e4e4567 100644 --- a/.config/quickshell/modules/overview/Overview.qml +++ b/.config/quickshell/modules/overview/Overview.qml @@ -92,8 +92,8 @@ Scope { visible: GlobalStates.overviewOpen anchors { horizontalCenter: parent.horizontalCenter - top: !ConfigOptions.bar.bottom ? parent.top : null - bottom: ConfigOptions.bar.bottom ? parent.bottom : null + top: !ConfigOptions.bar.bottom ? parent.top : undefined + bottom: ConfigOptions.bar.bottom ? parent.bottom : undefined } Keys.onPressed: (event) => { diff --git a/.config/quickshell/modules/sidebarLeft/Anime.qml b/.config/quickshell/modules/sidebarLeft/Anime.qml index acc1af4fe..444d3f052 100644 --- a/.config/quickshell/modules/sidebarLeft/Anime.qml +++ b/.config/quickshell/modules/sidebarLeft/Anime.qml @@ -562,8 +562,10 @@ Item { text: "•" } - Rectangle { // NSFW toggle + Item { // NSFW toggle + visible: width > 0 implicitWidth: switchesRow.implicitWidth + Layout.fillHeight: true RowLayout { id: switchesRow diff --git a/.config/quickshell/services/Audio.qml b/.config/quickshell/services/Audio.qml index dd46f0fbb..2fd5e0cac 100644 --- a/.config/quickshell/services/Audio.qml +++ b/.config/quickshell/services/Audio.qml @@ -19,9 +19,6 @@ Singleton { PwObjectTracker { objects: [sink, source] - Component.onCompleted: { - sink.audio.volume = sink.audio.volume; // Trigger initial volume change - } } Connections { // Protection against sudden volume changes From 93a14293aa3da453705c8c04d934ea44bcaf8dc3 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 23:08:51 +0200 Subject: [PATCH 58/89] overview: clearer window borders --- .config/quickshell/modules/overview/OverviewWindow.qml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/modules/overview/OverviewWindow.qml b/.config/quickshell/modules/overview/OverviewWindow.qml index 17a3b4bc2..3b376988b 100644 --- a/.config/quickshell/modules/overview/OverviewWindow.qml +++ b/.config/quickshell/modules/overview/OverviewWindow.qml @@ -76,9 +76,10 @@ Item { // Window Rectangle { anchors.fill: parent radius: Appearance.rounding.windowRounding * root.scale - color: pressed ? Appearance.colors.colLayer2Active : hovered ? Appearance.colors.colLayer2Hover : Appearance.colors.colLayer2 - opacity: pressed ? 0.5 : hovered ? 0.3 : 0 - border.color : ColorUtils.transparentize(Appearance.m3colors.m3outline, 0.9) + color: pressed ? ColorUtils.transparentize(Appearance.colors.colLayer2Active, 0.5) : + hovered ? ColorUtils.transparentize(Appearance.colors.colLayer2Hover, 0.7) : + ColorUtils.transparentize(Appearance.colors.colLayer2) + border.color : ColorUtils.transparentize(Appearance.m3colors.m3outline, 0.7) border.width : 1 } From b3a3975461e3ab4f3555a210595f3e98f173c566 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 23:29:52 +0200 Subject: [PATCH 59/89] dock: fix alignment --- .config/quickshell/modules/dock/Dock.qml | 8 +- .config/quickshell/modules/dock/DockApps.qml | 99 ++++++++++--------- .../quickshell/modules/dock/DockButton.qml | 5 +- .../quickshell/modules/dock/DockSeparator.qml | 4 +- 4 files changed, 63 insertions(+), 53 deletions(-) diff --git a/.config/quickshell/modules/dock/Dock.qml b/.config/quickshell/modules/dock/Dock.qml index 25846ac5f..a03a3f562 100644 --- a/.config/quickshell/modules/dock/Dock.qml +++ b/.config/quickshell/modules/dock/Dock.qml @@ -88,7 +88,7 @@ Scope { // Scope id: dockVisualBackground property real margin: Appearance.sizes.elevationMargin anchors.fill: parent - anchors.topMargin: margin + anchors.topMargin: Appearance.sizes.elevationMargin anchors.bottomMargin: Appearance.sizes.hyprlandGapsOut color: Appearance.colors.colLayer0 radius: Appearance.rounding.large @@ -103,6 +103,7 @@ Scope { // Scope property real padding: 5 VerticalButtonGroup { + Layout.topMargin: Appearance.sizes.hyprlandGapsOut // why does this work GroupButton { // Pin button baseWidth: 35 baseHeight: 35 @@ -120,12 +121,13 @@ Scope { // Scope } } DockSeparator {} - DockApps { id: dockApps } + DockApps { id: dockApps; } DockSeparator {} DockButton { + Layout.fillHeight: true onClicked: Hyprland.dispatch("global quickshell:overviewToggle") contentItem: MaterialSymbol { - anchors.centerIn: parent + anchors.fill: parent horizontalAlignment: Text.AlignHCenter font.pixelSize: parent.width / 2 text: "apps" diff --git a/.config/quickshell/modules/dock/DockApps.qml b/.config/quickshell/modules/dock/DockApps.qml index 900db0ca0..8b680c51a 100644 --- a/.config/quickshell/modules/dock/DockApps.qml +++ b/.config/quickshell/modules/dock/DockApps.qml @@ -23,59 +23,66 @@ Item { property Item lastHoveredButton property bool buttonHovered: false property bool requestDockShow: previewPopup.show - property var parentWindow: root.QsWindow - property real popupX: parentWindow?.mapFromItem(root.lastHoveredButton, root.lastHoveredButton?.width / 2, root.lastHoveredButton?.height / 2).x - implicitWidth / 2 - ?? 0 - implicitWidth: rowLayout.implicitWidth - implicitHeight: rowLayout.implicitHeight - RowLayout { - id: rowLayout + Layout.fillHeight: true + Layout.topMargin: Appearance.sizes.hyprlandGapsOut // why does this work + implicitWidth: listView.implicitWidth + + StyledListView { + id: listView spacing: 2 + orientation: ListView.Horizontal + anchors { + top: parent.top + bottom: parent.bottom + } + implicitWidth: contentWidth - Repeater { - model: ScriptModel { - objectProp: "appId" - values: { - var map = new Map(); + Behavior on implicitWidth { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } - // Pinned apps - const pinnedApps = ConfigOptions?.dock.pinnedApps ?? []; - for (const appId of pinnedApps) { - if (!map.has(appId.toLowerCase())) map.set(appId.toLowerCase(), ({ - pinned: true, - toplevels: [] - })); - } + model: ScriptModel { + objectProp: "appId" + values: { + var map = new Map(); - // Separator - if (pinnedApps.length > 0) { - map.set("SEPARATOR", { pinned: false, toplevels: [] }); - } - - // Open windows - for (const toplevel of ToplevelManager.toplevels.values) { - if (!map.has(toplevel.appId.toLowerCase())) map.set(toplevel.appId.toLowerCase(), ({ - pinned: false, - toplevels: [] - })); - map.get(toplevel.appId.toLowerCase()).toplevels.push(toplevel); - } - - var values = []; - - for (const [key, value] of map) { - values.push({ appId: key, toplevels: value.toplevels, pinned: value.pinned }); - } - - return values; + // Pinned apps + const pinnedApps = ConfigOptions?.dock.pinnedApps ?? []; + for (const appId of pinnedApps) { + if (!map.has(appId.toLowerCase())) map.set(appId.toLowerCase(), ({ + pinned: true, + toplevels: [] + })); } + + // Separator + if (pinnedApps.length > 0) { + map.set("SEPARATOR", { pinned: false, toplevels: [] }); + } + + // Open windows + for (const toplevel of ToplevelManager.toplevels.values) { + if (!map.has(toplevel.appId.toLowerCase())) map.set(toplevel.appId.toLowerCase(), ({ + pinned: false, + toplevels: [] + })); + map.get(toplevel.appId.toLowerCase()).toplevels.push(toplevel); + } + + var values = []; + + for (const [key, value] of map) { + values.push({ appId: key, toplevels: value.toplevels, pinned: value.pinned }); + } + + return values; } - delegate: DockAppButton { - required property var modelData - appToplevel: modelData - appListRoot: root - } + } + delegate: DockAppButton { + required property var modelData + appToplevel: modelData + appListRoot: root } } diff --git a/.config/quickshell/modules/dock/DockButton.qml b/.config/quickshell/modules/dock/DockButton.qml index 6c3010bf6..577cbcdc7 100644 --- a/.config/quickshell/modules/dock/DockButton.qml +++ b/.config/quickshell/modules/dock/DockButton.qml @@ -7,9 +7,10 @@ import QtQuick.Layouts RippleButton { Layout.fillHeight: true + Layout.topMargin: Appearance.sizes.elevationMargin - Appearance.sizes.hyprlandGapsOut implicitWidth: implicitHeight - topInset - bottomInset buttonRadius: Appearance.rounding.normal - topInset: dockVisualBackground.margin + dockRow.padding - bottomInset: dockVisualBackground.margin + dockRow.padding + topInset: Appearance.sizes.hyprlandGapsOut + dockRow.padding + bottomInset: Appearance.sizes.hyprlandGapsOut + dockRow.padding } diff --git a/.config/quickshell/modules/dock/DockSeparator.qml b/.config/quickshell/modules/dock/DockSeparator.qml index 2b27b0daf..29b77d492 100644 --- a/.config/quickshell/modules/dock/DockSeparator.qml +++ b/.config/quickshell/modules/dock/DockSeparator.qml @@ -5,8 +5,8 @@ import QtQuick.Controls import QtQuick.Layouts Rectangle { - Layout.topMargin: dockVisualBackground.margin + dockRow.padding + Appearance.rounding.normal - Layout.bottomMargin: dockVisualBackground.margin + dockRow.padding + Appearance.rounding.normal + Layout.topMargin: Appearance.sizes.elevationMargin + dockRow.padding + Appearance.rounding.normal + Layout.bottomMargin: Appearance.sizes.hyprlandGapsOut + dockRow.padding + Appearance.rounding.normal Layout.fillHeight: true implicitWidth: 1 color: Appearance.m3colors.m3outlineVariant From 49888f30f00142a93330bac74a890509d0930f12 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 9 Jun 2025 23:35:17 +0200 Subject: [PATCH 60/89] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 9403c73f2..4cc7899e4 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,10 @@ It's ready if you don't need localization... so quite likely | Window management | Weeb power | | ![image](https://github.com/user-attachments/assets/86cc511b-0d33-4c78-bcc0-3037d02a17da) | ![image](https://github.com/user-attachments/assets/e402f74a-6bd8-4ebe-bcf4-3a4a4846de10) | +By the way... +- The funny notification positions are mimicking Android 16's dragging behavior +- The clock on the wallpaper is automatically placed at the "least busy" region of the image + ## illogical-impulseAGS | AI | Common widgets | From bec43ff8ed3bbe02057a03ef6ed73cccc0355570 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 10 Jun 2025 08:53:00 +0200 Subject: [PATCH 61/89] dock: fix hover to reveal behavior (#1375) --- .config/quickshell/modules/dock/Dock.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.config/quickshell/modules/dock/Dock.qml b/.config/quickshell/modules/dock/Dock.qml index a03a3f562..d5b3912e9 100644 --- a/.config/quickshell/modules/dock/Dock.qml +++ b/.config/quickshell/modules/dock/Dock.qml @@ -56,8 +56,9 @@ Scope { // Scope anchors.top: parent.top height: parent.height anchors.topMargin: dockRoot.reveal ? 0 : - ConfigOptions?.dock.hoverToReveal ? (dockRoot.implicitHeight + 1) : - (dockRoot.implicitHeight - ConfigOptions.dock.hoverRegionHeight) + ConfigOptions?.dock.hoverToReveal ? (dockRoot.implicitHeight - ConfigOptions.dock.hoverRegionHeight) : + (dockRoot.implicitHeight + 1) + anchors.left: parent.left anchors.right: parent.right hoverEnabled: true From cf652482c5b20794255984d31988d9761e12e87d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 10 Jun 2025 08:59:31 +0200 Subject: [PATCH 62/89] better control -> plasma wifi widget --- .config/quickshell/modules/common/ConfigOptions.qml | 6 +++--- arch-packages/illogical-impulse-kde/PKGBUILD | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index ce6e45aa8..eeba677fc 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -21,10 +21,10 @@ Singleton { } property QtObject apps: QtObject { - property string bluetooth: "systemsettings kcm_bluetooth" + property string bluetooth: "kcmshell6 kcm_bluetooth" property string imageViewer: "loupe" - property string network: "better-control --wifi" - property string networkEthernet: "systemsettings kcm_networkmanagement" + property string network: "plasmawindowed org.kde.plasma.networkmanagement" + property string networkEthernet: "kcmshell6 kcm_networkmanagement" property string settings: "systemsettings" property string taskManager: "plasma-systemmonitor --page-name Processes" property string terminal: "kitty -1" // This is only for shell actions diff --git a/arch-packages/illogical-impulse-kde/PKGBUILD b/arch-packages/illogical-impulse-kde/PKGBUILD index d4f5e4058..e699db846 100644 --- a/arch-packages/illogical-impulse-kde/PKGBUILD +++ b/arch-packages/illogical-impulse-kde/PKGBUILD @@ -7,5 +7,5 @@ license=(None) depends=( polkit-kde-agent gnome-keyring - networkmanager better-control-git + networkmanager ) From f7f4affe515b81fb37f02059211a09e4b3afa59e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 10 Jun 2025 09:14:54 +0200 Subject: [PATCH 63/89] dock: unload when not needed --- .config/quickshell/modules/dock/Dock.qml | 213 ++++++++++++----------- 1 file changed, 108 insertions(+), 105 deletions(-) diff --git a/.config/quickshell/modules/dock/Dock.qml b/.config/quickshell/modules/dock/Dock.qml index d5b3912e9..524fbc11f 100644 --- a/.config/quickshell/modules/dock/Dock.qml +++ b/.config/quickshell/modules/dock/Dock.qml @@ -18,127 +18,130 @@ Scope { // Scope Variants { // For each monitor model: Quickshell.screens - PanelWindow { // Window + + Loader { + id: dockLoader required property var modelData - id: dockRoot - screen: modelData - - property bool reveal: root.pinned - || (ConfigOptions?.dock.hoverToReveal && dockMouseArea.containsMouse) - || dockApps.requestDockShow - || (!ToplevelManager.activeToplevel?.activated) + active: ConfigOptions?.dock.hoverToReveal || (!ToplevelManager.activeToplevel?.activated) - anchors { - bottom: true - left: true - right: true - } + sourceComponent: PanelWindow { // Window + id: dockRoot + screen: dockLoader.modelData + + property bool reveal: root.pinned + || (ConfigOptions?.dock.hoverToReveal && dockMouseArea.containsMouse) + || dockApps.requestDockShow + || (!ToplevelManager.activeToplevel?.activated) - function hide() { - cheatsheetLoader.active = false - } - exclusiveZone: root.pinned ? implicitHeight - - (Appearance.sizes.hyprlandGapsOut) - - (Appearance.sizes.elevationMargin - Appearance.sizes.hyprlandGapsOut) : 0 - - implicitWidth: dockBackground.implicitWidth - WlrLayershell.namespace: "quickshell:dock" - color: "transparent" - - implicitHeight: (ConfigOptions?.dock.height ?? 70) + Appearance.sizes.elevationMargin + Appearance.sizes.hyprlandGapsOut - - mask: Region { - item: dockMouseArea - } - - MouseArea { - id: dockMouseArea - anchors.top: parent.top - height: parent.height - anchors.topMargin: dockRoot.reveal ? 0 : - ConfigOptions?.dock.hoverToReveal ? (dockRoot.implicitHeight - ConfigOptions.dock.hoverRegionHeight) : - (dockRoot.implicitHeight + 1) - - anchors.left: parent.left - anchors.right: parent.right - hoverEnabled: true - - Behavior on anchors.topMargin { - animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + anchors { + bottom: true + left: true + right: true } - Item { - id: dockHoverRegion - anchors.fill: parent + exclusiveZone: root.pinned ? implicitHeight + - (Appearance.sizes.hyprlandGapsOut) + - (Appearance.sizes.elevationMargin - Appearance.sizes.hyprlandGapsOut) : 0 - Item { // Wrapper for the dock background - id: dockBackground - anchors { - top: parent.top - bottom: parent.bottom - horizontalCenter: parent.horizontalCenter - } + implicitWidth: dockBackground.implicitWidth + WlrLayershell.namespace: "quickshell:dock" + color: "transparent" - implicitWidth: dockRow.implicitWidth + 5 * 2 - height: parent.height - Appearance.sizes.elevationMargin - Appearance.sizes.hyprlandGapsOut + implicitHeight: (ConfigOptions?.dock.height ?? 70) + Appearance.sizes.elevationMargin + Appearance.sizes.hyprlandGapsOut - StyledRectangularShadow { - target: dockVisualBackground - } - Rectangle { // The real rectangle that is visible - id: dockVisualBackground - property real margin: Appearance.sizes.elevationMargin - anchors.fill: parent - anchors.topMargin: Appearance.sizes.elevationMargin - anchors.bottomMargin: Appearance.sizes.hyprlandGapsOut - color: Appearance.colors.colLayer0 - radius: Appearance.rounding.large - } + mask: Region { + item: dockMouseArea + } - RowLayout { - id: dockRow - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.horizontalCenter: parent.horizontalCenter - spacing: 3 - property real padding: 5 + MouseArea { + id: dockMouseArea + anchors.top: parent.top + height: parent.height + anchors.topMargin: dockRoot.reveal ? 0 : + ConfigOptions?.dock.hoverToReveal ? (dockRoot.implicitHeight - ConfigOptions.dock.hoverRegionHeight) : + (dockRoot.implicitHeight + 1) + + anchors.left: parent.left + anchors.right: parent.right + hoverEnabled: true - VerticalButtonGroup { - Layout.topMargin: Appearance.sizes.hyprlandGapsOut // why does this work - GroupButton { // Pin button - baseWidth: 35 - baseHeight: 35 - clickedWidth: baseWidth - clickedHeight: baseHeight + 20 - buttonRadius: Appearance.rounding.normal - toggled: root.pinned - onClicked: root.pinned = !root.pinned + Behavior on anchors.topMargin { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + + Item { + id: dockHoverRegion + anchors.fill: parent + + Item { // Wrapper for the dock background + id: dockBackground + anchors { + top: parent.top + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + } + + implicitWidth: dockRow.implicitWidth + 5 * 2 + height: parent.height - Appearance.sizes.elevationMargin - Appearance.sizes.hyprlandGapsOut + + StyledRectangularShadow { + target: dockVisualBackground + } + Rectangle { // The real rectangle that is visible + id: dockVisualBackground + property real margin: Appearance.sizes.elevationMargin + anchors.fill: parent + anchors.topMargin: Appearance.sizes.elevationMargin + anchors.bottomMargin: Appearance.sizes.hyprlandGapsOut + color: Appearance.colors.colLayer0 + radius: Appearance.rounding.large + } + + RowLayout { + id: dockRow + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + spacing: 3 + property real padding: 5 + + VerticalButtonGroup { + Layout.topMargin: Appearance.sizes.hyprlandGapsOut // why does this work + GroupButton { // Pin button + baseWidth: 35 + baseHeight: 35 + clickedWidth: baseWidth + clickedHeight: baseHeight + 20 + buttonRadius: Appearance.rounding.normal + toggled: root.pinned + onClicked: root.pinned = !root.pinned + contentItem: MaterialSymbol { + text: "keep" + horizontalAlignment: Text.AlignHCenter + iconSize: Appearance.font.pixelSize.larger + color: root.pinned ? Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer0 + } + } + } + DockSeparator {} + DockApps { id: dockApps; } + DockSeparator {} + DockButton { + Layout.fillHeight: true + onClicked: Hyprland.dispatch("global quickshell:overviewToggle") contentItem: MaterialSymbol { - text: "keep" + anchors.fill: parent horizontalAlignment: Text.AlignHCenter - iconSize: Appearance.font.pixelSize.larger - color: root.pinned ? Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer0 + font.pixelSize: parent.width / 2 + text: "apps" + color: Appearance.colors.colOnLayer0 } } } - DockSeparator {} - DockApps { id: dockApps; } - DockSeparator {} - DockButton { - Layout.fillHeight: true - onClicked: Hyprland.dispatch("global quickshell:overviewToggle") - contentItem: MaterialSymbol { - anchors.fill: parent - horizontalAlignment: Text.AlignHCenter - font.pixelSize: parent.width / 2 - text: "apps" - color: Appearance.colors.colOnLayer0 - } - } - } - } - } + } + } + } } } } From a1e052b0708a7f680bb411064b0041a04f94bcb9 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 10 Jun 2025 09:15:48 +0200 Subject: [PATCH 64/89] Update rules.conf --- .config/hypr/hyprland/rules.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.config/hypr/hyprland/rules.conf b/.config/hypr/hyprland/rules.conf index fe1f5da4c..d7ce7a061 100644 --- a/.config/hypr/hyprland/rules.conf +++ b/.config/hypr/hyprland/rules.conf @@ -19,6 +19,8 @@ windowrulev2 = center, class:^(org.pulseaudio.pavucontrol)$ windowrulev2 = float, class:^(nm-connection-editor)$ windowrulev2 = size 45%, class:^(nm-connection-editor)$ windowrulev2 = center, class:^(nm-connection-editor)$ +windowrulev2 = center, class:.*plasmawindowed.* +windowrulev2 = center, class:kcm_bluetooth # No appearance # kde-material-you-colors spawns a window when changing dark/light theme. This is to make sure it doesn't interfere at all. @@ -116,6 +118,7 @@ layerrule = animation fade, quickshell:screenCorners layerrule = animation slide right, quickshell:sidebarRight layerrule = animation slide left, quickshell:sidebarLeft layerrule = animation slide bottom, quickshell:osk +layerrule = animation slide bottom, quickshell:dock layerrule = blur, quickshell:session layerrule = noanim, quickshell:session layerrule = animation fade, quickshell:notificationPopup From de941d8b9ede4c77826d942dfb5eb7e1ed987e8e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 10 Jun 2025 11:24:52 +0200 Subject: [PATCH 65/89] hyprland: fix float rules for plasma stuff --- .config/hypr/hyprland/rules.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.config/hypr/hyprland/rules.conf b/.config/hypr/hyprland/rules.conf index d7ce7a061..42897cafe 100644 --- a/.config/hypr/hyprland/rules.conf +++ b/.config/hypr/hyprland/rules.conf @@ -19,8 +19,8 @@ windowrulev2 = center, class:^(org.pulseaudio.pavucontrol)$ windowrulev2 = float, class:^(nm-connection-editor)$ windowrulev2 = size 45%, class:^(nm-connection-editor)$ windowrulev2 = center, class:^(nm-connection-editor)$ -windowrulev2 = center, class:.*plasmawindowed.* -windowrulev2 = center, class:kcm_bluetooth +windowrulev2 = float, class:.*plasmawindowed.* +windowrulev2 = float, class:kcm_.* # No appearance # kde-material-you-colors spawns a window when changing dark/light theme. This is to make sure it doesn't interfere at all. From 4f8574ef50e4cf40104cdb607d213a54c2db152e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 10 Jun 2025 13:24:58 +0200 Subject: [PATCH 66/89] wallpaper region limit: use min size of all instead of max --- .config/quickshell/scripts/switchwall.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/scripts/switchwall.sh b/.config/quickshell/scripts/switchwall.sh index adc76201d..dffd9bd61 100755 --- a/.config/quickshell/scripts/switchwall.sh +++ b/.config/quickshell/scripts/switchwall.sh @@ -233,9 +233,9 @@ switch() { deactivate # Pass screen width, height, and wallpaper path to post_process - min_width_desired="$(hyprctl monitors -j | jq '([.[].width] | max)' | xargs)" - min_height_desired="$(hyprctl monitors -j | jq '([.[].height] | max)' | xargs)" - post_process "$min_width_desired" "$min_height_desired" "$imgpath" + max_width_desired="$(hyprctl monitors -j | jq '([.[].width] | min)' | xargs)" + max_height_desired="$(hyprctl monitors -j | jq '([.[].height] | min)' | xargs)" + post_process "$max_width_desired" "$max_height_desired" "$imgpath" } main() { From bd0438be834c4200aefe8aec2d805f289932e22e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 10 Jun 2025 13:35:45 +0200 Subject: [PATCH 67/89] bg clock: fix positioning on scaled screens --- .../modules/backgroundWidgets/BackgroundWidgets.qml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml b/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml index 970dc8d17..3fb5471df 100644 --- a/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml +++ b/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml @@ -58,12 +58,13 @@ Scope { Loader { required property var modelData + readonly property HyprlandMonitor monitor: Hyprland.monitorFor(modelData) active: !ToplevelManager.activeToplevel?.activated sourceComponent: PanelWindow { // Window id: windowRoot screen: modelData - property var textHorizontalAlignment: root.centerX < windowRoot.width / 3 ? Text.AlignLeft : - (root.centerX > windowRoot.width * 2 / 3 ? Text.AlignRight : Text.AlignHCenter) + property var textHorizontalAlignment: root.centerX / monitor.scale < windowRoot.width / 3 ? Text.AlignLeft : + (root.centerX / monitor.scale > windowRoot.width * 2 / 3 ? Text.AlignRight : Text.AlignHCenter) WlrLayershell.layer: WlrLayer.Bottom WlrLayershell.namespace: "quickshell:backgroundWidgets" @@ -90,8 +91,8 @@ Scope { anchors { left: parent.left top: parent.top - leftMargin: root.centerX - implicitWidth / 2 - topMargin: root.centerY - implicitHeight / 2 + leftMargin: (root.centerX / monitor.scale - implicitWidth / 2) + topMargin: (root.centerY / monitor.scale - implicitHeight / 2) Behavior on leftMargin { animation: Appearance.animation.elementMove.numberAnimation.createObject(this) } From bbee1e85ac2645d17b04e53e622aa2ca39edb886 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 00:33:53 +0200 Subject: [PATCH 68/89] deps: add bluedevil and plasma-nm --- arch-packages/illogical-impulse-kde/PKGBUILD | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch-packages/illogical-impulse-kde/PKGBUILD b/arch-packages/illogical-impulse-kde/PKGBUILD index e699db846..fd3a745f6 100644 --- a/arch-packages/illogical-impulse-kde/PKGBUILD +++ b/arch-packages/illogical-impulse-kde/PKGBUILD @@ -5,7 +5,9 @@ pkgdesc='Illogical Impulse KDE Dependencies' arch=(any) license=(None) depends=( - polkit-kde-agent + bluedevil gnome-keyring networkmanager + plasma-nm + polkit-kde-agent ) From 80f809b8b214dd9d9296fd765f0d93c752797440 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 00:36:09 +0200 Subject: [PATCH 69/89] config options: make fakescreenrounding default to 2 --- .config/quickshell/modules/common/ConfigOptions.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index eeba677fc..4aa54fa52 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -9,7 +9,7 @@ Singleton { } property QtObject appearance: QtObject { - property int fakeScreenRounding: 1 // 0: None | 1: Always | 2: When not fullscreen + property int fakeScreenRounding: 2 // 0: None | 1: Always | 2: When not fullscreen } property QtObject audio: QtObject { // Values in % From 74e049b7b472104f63465e5aa38c6e96d5cff2cc Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 00:36:18 +0200 Subject: [PATCH 70/89] Directories: create shell config dir --- .config/quickshell/modules/common/Directories.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/quickshell/modules/common/Directories.qml b/.config/quickshell/modules/common/Directories.qml index b256666fc..d2c570234 100644 --- a/.config/quickshell/modules/common/Directories.qml +++ b/.config/quickshell/modules/common/Directories.qml @@ -32,6 +32,7 @@ Singleton { property string wallpaperSwitchScriptPath: FileUtils.trimFileProtocol(`${Directories.config}/quickshell/scripts/switchwall.sh`) // Cleanup on init Component.onCompleted: { + Hyprland.dispatch(`exec mkdir -p '${shellConfig}'`) Hyprland.dispatch(`exec mkdir -p '${favicons}'`) Hyprland.dispatch(`exec rm -rf '${coverArt}'; mkdir -p '${coverArt}'`) Hyprland.dispatch(`exec rm -rf '${booruPreviews}'; mkdir -p '${booruPreviews}'`) From fd5553a0ad89a8bbe15e8e97015948c9c434b916 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 00:36:26 +0200 Subject: [PATCH 71/89] format --- .config/quickshell/modules/screenCorners/ScreenCorners.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/modules/screenCorners/ScreenCorners.qml b/.config/quickshell/modules/screenCorners/ScreenCorners.qml index 37f0ff23b..3988d73d8 100644 --- a/.config/quickshell/modules/screenCorners/ScreenCorners.qml +++ b/.config/quickshell/modules/screenCorners/ScreenCorners.qml @@ -15,7 +15,9 @@ Scope { model: Quickshell.screens PanelWindow { - visible: (ConfigOptions.appearance.fakeScreenRounding === 1 || (ConfigOptions.appearance.fakeScreenRounding === 2 && !activeWindow?.fullscreen)) + visible: (ConfigOptions.appearance.fakeScreenRounding === 1 + || (ConfigOptions.appearance.fakeScreenRounding === 2 + && !activeWindow?.fullscreen)) property var modelData From 0ad006eea1a59a049761be3a3068eeef21d313ba Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 00:40:07 +0200 Subject: [PATCH 72/89] config loader: write back on load to include new options in user config --- .config/quickshell/services/ConfigLoader.qml | 25 ++++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/.config/quickshell/services/ConfigLoader.qml b/.config/quickshell/services/ConfigLoader.qml index 788fc728d..61aa9b4ed 100644 --- a/.config/quickshell/services/ConfigLoader.qml +++ b/.config/quickshell/services/ConfigLoader.qml @@ -20,23 +20,30 @@ Singleton { id: root property string filePath: Directories.shellConfigPath property bool firstLoad: true + property bool preventNextLoad: false function loadConfig() { configFileView.reload() } function applyConfig(fileContent) { + console.log("[ConfigLoader] Applying config from file:", root.filePath); try { + if (fileContent.trim() === "") { + console.warn("[ConfigLoader] Config file is empty, skipping load."); + return; + } const json = JSON.parse(fileContent); ObjectUtils.applyToQtObject(ConfigOptions, json); if (root.firstLoad) { root.firstLoad = false; - } else { - Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration reloaded")}" "${root.filePath}"`) + root.preventNextLoad = true; + root.saveConfig(); // Make sure new properties are added to the user's config file } } catch (e) { console.error("[ConfigLoader] Error reading file:", e); + console.log("[ConfigLoader] File content was:", fileContent); Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration failed to load")}" "${root.filePath}"`) return; @@ -85,7 +92,16 @@ Singleton { interval: ConfigOptions.hacks.arbitraryRaceConditionDelay running: false onTriggered: { - root.applyConfig(configFileView.text()) + if (root.preventNextLoad) { + root.preventNextLoad = false; + return; + } + if (root.firstLoad) { + root.applyConfig(configFileView.text()) + } else { + root.applyConfig(configFileView.text()) + Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration reloaded")}" "${root.filePath}"`) + } } } @@ -94,13 +110,12 @@ Singleton { path: Qt.resolvedUrl(root.filePath) watchChanges: true onFileChanged: { - console.log("[ConfigLoader] File changed, reloading...") this.reload() delayedFileRead.start() } onLoadedChanged: { const fileContent = configFileView.text() - root.applyConfig(fileContent) + delayedFileRead.start() } onLoadFailed: (error) => { if(error == FileViewError.FileNotFound) { From ee0df41deca609beb10246dd2c7b05dfec2e74ab Mon Sep 17 00:00:00 2001 From: Jx <103049321+JxJxxJxJ@users.noreply.github.com> Date: Tue, 10 Jun 2025 20:39:46 -0300 Subject: [PATCH 73/89] Add systemsettings as dependency (KDE desktop config) Otherwise the gear from the right pannel does nothing --- arch-packages/illogical-impulse-kde/PKGBUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/arch-packages/illogical-impulse-kde/PKGBUILD b/arch-packages/illogical-impulse-kde/PKGBUILD index fd3a745f6..b8b91c3f9 100644 --- a/arch-packages/illogical-impulse-kde/PKGBUILD +++ b/arch-packages/illogical-impulse-kde/PKGBUILD @@ -10,4 +10,5 @@ depends=( networkmanager plasma-nm polkit-kde-agent + systemsettings ) From ac6a64efaba8023b258dbdeada1a2d047a88ae21 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 08:25:05 +0200 Subject: [PATCH 74/89] right sidebar: fix idle inhibitor exiting on close (#1381) --- .../quickToggles/IdleInhibitor.qml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/IdleInhibitor.qml b/.config/quickshell/modules/sidebarRight/quickToggles/IdleInhibitor.qml index 4ac63d220..5080d99ad 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/IdleInhibitor.qml +++ b/.config/quickshell/modules/sidebarRight/quickToggles/IdleInhibitor.qml @@ -3,16 +3,28 @@ import "root:/modules/common/widgets" import "../" import Quickshell.Io import Quickshell +import Quickshell.Hyprland QuickToggleButton { + id: root toggled: idleInhibitor.running buttonIcon: "coffee" onClicked: { - idleInhibitor.running = !idleInhibitor.running + if (toggled) { + root.toggled = false + Hyprland.dispatch("exec pkill wayland-idle") // pkill doesn't accept too long names + } else { + root.toggled = true + Hyprland.dispatch('exec ${XDG_CONFIG_HOME:-$HOME/.config}/quickshell/scripts/wayland-idle-inhibitor.py') + } } Process { - id: idleInhibitor - command: ["bash", "-c", "${XDG_CONFIG_HOME:-$HOME/.config}/quickshell/scripts/wayland-idle-inhibitor.py"] + id: fetchActiveState + running: true + command: ["bash", "-c", "pidof wayland-idle-inhibitor.py"] + onExited: (exitCode, exitStatus) => { + root.toggled = exitCode === 0 + } } StyledToolTip { content: qsTr("Keep system awake") From 039cb571675267c05bb906391c3fc3aef555fde5 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 08:39:18 +0200 Subject: [PATCH 75/89] overview: partially fix window position for offset monitors (#1388) --- .../quickshell/modules/overview/OverviewWidget.qml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/modules/overview/OverviewWidget.qml b/.config/quickshell/modules/overview/OverviewWidget.qml index e1fbb3264..1a9494938 100644 --- a/.config/quickshell/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/modules/overview/OverviewWidget.qml @@ -156,9 +156,9 @@ Item { } } delegate: OverviewWindow { + id: window required property var modelData property var address: `0x${modelData.HyprlandToplevel.address}` - id: window windowData: windowByAddress[address] toplevel: modelData monitorData: root.monitorData @@ -166,13 +166,16 @@ Item { availableWorkspaceWidth: root.workspaceImplicitWidth availableWorkspaceHeight: root.workspaceImplicitHeight + property int monitorId: windowData?.monitor + property var monitor: HyprlandData.monitors[monitorId] + property bool atInitPosition: (initX == x && initY == y) restrictToWorkspace: Drag.active || atInitPosition property int workspaceColIndex: (windowData?.workspace.id - 1) % ConfigOptions.overview.numOfCols property int workspaceRowIndex: Math.floor((windowData?.workspace.id - 1) % root.workspacesShown / ConfigOptions.overview.numOfCols) - xOffset: (root.workspaceImplicitWidth + workspaceSpacing) * workspaceColIndex - yOffset: (root.workspaceImplicitHeight + workspaceSpacing) * workspaceRowIndex + xOffset: (root.workspaceImplicitWidth + workspaceSpacing) * workspaceColIndex - (monitor?.x * root.scale) + yOffset: (root.workspaceImplicitHeight + workspaceSpacing) * workspaceRowIndex - (monitor?.y * root.scale) Timer { id: updateWindowPosition @@ -182,6 +185,7 @@ Item { onTriggered: { window.x = Math.round(Math.max((windowData?.at[0] - monitorData?.reserved[0]) * root.scale, 0) + xOffset) window.y = Math.round(Math.max((windowData?.at[1] - monitorData?.reserved[1]) * root.scale, 0) + yOffset) + console.log(`[OverviewWindow] Updated position for window ${windowData?.address} to (${window.x}, ${window.y})`) } } @@ -201,6 +205,7 @@ Item { window.pressed = true window.Drag.active = true window.Drag.source = window + console.log(`[OverviewWindow] Dragging window ${windowData?.address} from position (${window.x}, ${window.y})`) } onReleased: { const targetWorkspace = root.draggingTargetWorkspace From 8956752e85b3f88847c84b446e98563d05f71cdb Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 09:00:28 +0200 Subject: [PATCH 76/89] ripple button: default size based on contentitem --- .config/quickshell/modules/common/widgets/RippleButton.qml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.config/quickshell/modules/common/widgets/RippleButton.qml b/.config/quickshell/modules/common/widgets/RippleButton.qml index 9931cd02a..6e6e3c5fc 100644 --- a/.config/quickshell/modules/common/widgets/RippleButton.qml +++ b/.config/quickshell/modules/common/widgets/RippleButton.qml @@ -32,6 +32,9 @@ Button { property color colRipple: Appearance?.colors.colLayer1Active ?? "#D6CEE2" property color colRippleToggled: Appearance?.colors.colPrimaryActive ?? "#D6CEE2" + implicitWidth: contentItem.implicitWidth + horizontalPadding * 2 + implicitHeight: contentItem.implicitHeight + verticalPadding * 2 + property color buttonColor: root.enabled ? (root.toggled ? (root.hovered ? colBackgroundToggledHover : colBackgroundToggled) : From 244d3f6067e667d8ef81e4d4f69749dec85a773c Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 09:01:24 +0200 Subject: [PATCH 77/89] idle inhibitor button: now wrong binding --- .../modules/sidebarRight/quickToggles/IdleInhibitor.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/sidebarRight/quickToggles/IdleInhibitor.qml b/.config/quickshell/modules/sidebarRight/quickToggles/IdleInhibitor.qml index 5080d99ad..b48d3467f 100644 --- a/.config/quickshell/modules/sidebarRight/quickToggles/IdleInhibitor.qml +++ b/.config/quickshell/modules/sidebarRight/quickToggles/IdleInhibitor.qml @@ -7,7 +7,7 @@ import Quickshell.Hyprland QuickToggleButton { id: root - toggled: idleInhibitor.running + toggled: false buttonIcon: "coffee" onClicked: { if (toggled) { From 65983ade46c4a131b6534bc264969836745bf362 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 10:59:52 +0200 Subject: [PATCH 78/89] sidebar: translator: language selector --- .../modules/common/ConfigOptions.qml | 8 + .../modules/common/widgets/ButtonGroup.qml | 2 +- .../common/widgets/SelectionDialog.qml | 127 +++++++ .../modules/sidebarLeft/Translator.qml | 311 +++++++++--------- .../translator/LanguageSelectorButton.qml | 42 +++ .../sidebarLeft/translator/TextCanvas.qml | 92 ++++++ .../sidebarRight/volumeMixer/VolumeMixer.qml | 11 +- .config/quickshell/shell.qml | 2 +- 8 files changed, 439 insertions(+), 156 deletions(-) create mode 100644 .config/quickshell/modules/common/widgets/SelectionDialog.qml create mode 100644 .config/quickshell/modules/sidebarLeft/translator/LanguageSelectorButton.qml create mode 100644 .config/quickshell/modules/sidebarLeft/translator/TextCanvas.qml diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 4aa54fa52..902049729 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -63,6 +63,14 @@ Singleton { ] } + property QtObject language: QtObject { + property QtObject translator: QtObject { + property string engine: "auto" // Run `trans -list-engines` for available engines. auto should use google + property string sourceLanguage: "auto" + property string targetLanguage: "English" // Run `trans -list-all` for available languages + } + } + property QtObject networking: QtObject { property string userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" } diff --git a/.config/quickshell/modules/common/widgets/ButtonGroup.qml b/.config/quickshell/modules/common/widgets/ButtonGroup.qml index a1570c6af..5356535f4 100644 --- a/.config/quickshell/modules/common/widgets/ButtonGroup.qml +++ b/.config/quickshell/modules/common/widgets/ButtonGroup.qml @@ -11,7 +11,7 @@ import QtQuick.Layouts */ Rectangle { id: root - default property alias content: rowLayout.data + default property alias data: rowLayout.data property real spacing: 5 property real padding: 0 property int clickIndex: rowLayout.clickIndex diff --git a/.config/quickshell/modules/common/widgets/SelectionDialog.qml b/.config/quickshell/modules/common/widgets/SelectionDialog.qml new file mode 100644 index 000000000..1e1446b51 --- /dev/null +++ b/.config/quickshell/modules/common/widgets/SelectionDialog.qml @@ -0,0 +1,127 @@ +import "root:/modules/common" +import "root:/modules/common/widgets" +import "root:/services" +import Qt5Compat.GraphicalEffects +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell + +Item { + id: root + property real dialogPadding: 15 + property real dialogMargin: 30 + property string titleText: "Selection Dialog" + property alias items: choiceModel.values + property int selectedId: -1 // -1 means no selection + + signal canceled(); + signal selected(var result); + + Rectangle { // Scrim + id: scrimOverlay + anchors.fill: parent + radius: Appearance.rounding.small + color: Appearance.colors.colScrim + MouseArea { + hoverEnabled: true + anchors.fill: parent + preventStealing: true + propagateComposedEvents: false + } + } + + Rectangle { // The dialog + id: dialog + color: Appearance.m3colors.m3surfaceContainerHigh + radius: Appearance.rounding.normal + anchors.fill: parent + anchors.margins: dialogMargin + implicitHeight: dialogColumnLayout.implicitHeight + + ColumnLayout { + id: dialogColumnLayout + anchors.fill: parent + spacing: 16 + + StyledText { + id: dialogTitle + Layout.topMargin: dialogPadding + Layout.leftMargin: dialogPadding + Layout.rightMargin: dialogPadding + Layout.alignment: Qt.AlignLeft + color: Appearance.m3colors.m3onSurface + font.pixelSize: Appearance.font.pixelSize.larger + text: root.titleText + } + + Rectangle { + color: Appearance.m3colors.m3outline + implicitHeight: 1 + Layout.fillWidth: true + Layout.leftMargin: dialogPadding + Layout.rightMargin: dialogPadding + } + + ListView { + id: choiceListView + Layout.fillWidth: true + Layout.fillHeight: true + clip: true + + model: ScriptModel { + id: choiceModel + } + + delegate: StyledRadioButton { + id: radioButton + required property var modelData + required property int index + anchors { + left: parent?.left + right: parent?.right + leftMargin: root.dialogPadding + rightMargin: root.dialogPadding + } + + description: modelData.toString() + checked: index === root.selectedId + + onCheckedChanged: { + if (checked) { + root.selectedId = index; + } + } + } + } + + Rectangle { + color: Appearance.m3colors.m3outline + implicitHeight: 1 + Layout.fillWidth: true + Layout.leftMargin: dialogPadding + Layout.rightMargin: dialogPadding + } + + RowLayout { + id: dialogButtonsRowLayout + Layout.bottomMargin: dialogPadding + Layout.leftMargin: dialogPadding + Layout.rightMargin: dialogPadding + Layout.alignment: Qt.AlignRight + + DialogButton { + buttonText: qsTr("Cancel") + onClicked: root.canceled() + } + DialogButton { + buttonText: qsTr("OK") + onClicked: root.selected( + root.selectedId === -1 ? null : + root.items[root.selectedId] + ) + } + } + } + } +} diff --git a/.config/quickshell/modules/sidebarLeft/Translator.qml b/.config/quickshell/modules/sidebarLeft/Translator.qml index a853f30cf..92e0505db 100644 --- a/.config/quickshell/modules/sidebarLeft/Translator.qml +++ b/.config/quickshell/modules/sidebarLeft/Translator.qml @@ -3,6 +3,7 @@ import "root:/services" import "root:/modules/common" import "root:/modules/common/widgets" import "root:/modules/common/functions/string_utils.js" as StringUtils +import "./translator/" import QtQuick import QtQuick.Controls import QtQuick.Layouts @@ -15,11 +16,26 @@ import Quickshell.Hyprland */ Item { id: root - property var inputField: inputTextArea - property var outputField: outputTextArea - + // Widgets + property var inputField: inputCanvas.inputTextArea + // Widget variables property bool translationFor: false // Indicates if the translation is for an autocorrected text property string translatedText: "" + property list languages: [] + // Options + property string targetLanguage: ConfigOptions.language.translator.targetLanguage + property string sourceLanguage: ConfigOptions.language.translator.sourceLanguage + property string hostLanguage: targetLanguage + + property bool showLanguageSelector: false + property bool languageSelectorTarget: false // true for target language, false for source language + property string languageSelectorLanguage: "" + + function showLanguageSelectorDialog(isTargetLang: bool) { + root.showLanguageSelector = true + root.languageSelectorTarget = isTargetLang; + root.languageSelectorLanguage = isTargetLang ? root.targetLanguage : root.sourceLanguage; + } onFocusChanged: (focus) => { if (focus) { @@ -32,19 +48,23 @@ Item { interval: ConfigOptions.sidebar.translator.delay repeat: false onTriggered: () => { - if (inputTextArea.text.trim().length > 0) { + if (root.inputField.text.trim().length > 0) { + console.log("Translating with command:", translateProc.command); translateProc.running = false; translateProc.buffer = ""; // Clear the buffer translateProc.running = true; // Restart the process } else { - outputTextArea.text = ""; + root.translatedText = ""; } } } Process { id: translateProc - command: ["bash", "-c", `trans -no-theme -no-ansi '${StringUtils.shellSingleQuoteEscape(inputTextArea.text.trim())}'`] + command: ["bash", "-c", `trans -no-theme` + + ` -source '${StringUtils.shellSingleQuoteEscape(root.sourceLanguage)}'` + + ` -target '${StringUtils.shellSingleQuoteEscape(root.targetLanguage)}'` + + ` -no-ansi '${StringUtils.shellSingleQuoteEscape(root.inputField.text.trim())}'`] property string buffer: "" stdout: SplitParser { onRead: data => { @@ -54,12 +74,29 @@ Item { onExited: (exitCode, exitStatus) => { // 1. Split into sections by double newlines const sections = translateProc.buffer.trim().split(/\n\s*\n/); - // console.log("BUFFER:", translateProc.buffer); - // console.log("SECTIONS:", sections); + console.log("BUFFER:", translateProc.buffer); + console.log("SECTIONS:", sections); // 2. Extract relevant data root.translatedText = sections.length > 1 ? sections[1].trim() : ""; - root.outputField.text = root.translatedText; + } + } + + Process { + id: getLanguagesProc + command: ["trans", "-list-languages"] + property list bufferList: ["auto"] + running: true + stdout: SplitParser { + onRead: data => { + getLanguagesProc.bufferList.push(data.trim()); + } + } + onExited: (exitCode, exitStatus) => { + root.languages = getLanguagesProc.bufferList + .filter(lang => lang.trim().length > 0) // Filter out empty lines + .sort((a, b) => a.localeCompare(b)); // Sort alphabetically + getLanguagesProc.bufferList = []; // Clear the buffer } } @@ -71,159 +108,133 @@ Item { id: contentColumn anchors.fill: parent - Rectangle { // INPUT + LanguageSelectorButton { // Source language button + id: sourceLanguageButton + displayText: root.sourceLanguage + onClicked: { + root.showLanguageSelectorDialog(false); + } + } + + TextCanvas { // Content input id: inputCanvas - Layout.fillWidth: true - implicitHeight: Math.max(150, inputColumn.implicitHeight) - color: Appearance.colors.colLayer1 - radius: Appearance.rounding.normal - border.color: Appearance.m3colors.m3outlineVariant - border.width: 1 - - ColumnLayout { - id: inputColumn - anchors.fill: parent - spacing: 0 - - StyledTextArea { // Input area - id: inputTextArea - Layout.fillWidth: true - placeholderText: qsTr("Enter text to translate...") - wrapMode: TextEdit.Wrap - textFormat: TextEdit.PlainText - font.pixelSize: Appearance.font.pixelSize.small - color: Appearance.colors.colOnLayer1 - padding: 15 - background: null - onTextChanged: { - if (inputTextArea.text.trim().length > 0) { - translateTimer.restart(); - } else { - outputTextArea.text = ""; - } - } + isInput: true + placeholderText: qsTr("Enter text to translate...") + onInputTextChanged: { + translateTimer.restart(); + } + GroupButton { + id: pasteButton + baseWidth: height + buttonRadius: Appearance.rounding.small + contentItem: MaterialSymbol { + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + iconSize: Appearance.font.pixelSize.larger + text: "content_paste" + color: deleteButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext } - - Item { Layout.fillHeight: true } - - RowLayout { // Status row - Layout.fillWidth: true - Layout.margins: 10 - spacing: 10 - - Text { - Layout.leftMargin: 10 - text: qsTr("%1 characters").arg(inputTextArea.text.length) - color: Appearance.colors.colOnLayer1 - font.pixelSize: Appearance.font.pixelSize.smaller - } - Item { Layout.fillWidth: true } - ButtonGroup { - GroupButton { - id: pasteButton - baseWidth: height - buttonRadius: Appearance.rounding.small - contentItem: MaterialSymbol { - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - iconSize: Appearance.font.pixelSize.larger - text: "content_paste" - color: deleteButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext - } - onClicked: { - root.inputField.text = Quickshell.clipboardText - } - } - GroupButton { - id: deleteButton - baseWidth: height - buttonRadius: Appearance.rounding.small - enabled: inputTextArea.text.length > 0 - contentItem: MaterialSymbol { - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - iconSize: Appearance.font.pixelSize.larger - text: "close" - color: deleteButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext - } - onClicked: { - root.inputField.text = "" - } - } - } + onClicked: { + root.inputField.text = Quickshell.clipboardText + } + } + GroupButton { + id: deleteButton + baseWidth: height + buttonRadius: Appearance.rounding.small + enabled: inputCanvas.inputTextArea.text.length > 0 + contentItem: MaterialSymbol { + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + iconSize: Appearance.font.pixelSize.larger + text: "close" + color: deleteButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext + } + onClicked: { + root.inputField.text = "" } } } - Rectangle { // OUTPUT + LanguageSelectorButton { // Target language button + id: targetLanguageButton + displayText: root.targetLanguage + onClicked: { + root.showLanguageSelectorDialog(true); + } + } + + TextCanvas { // Content translation id: outputCanvas - Layout.fillWidth: true - implicitHeight: Math.max(150, outputColumn.implicitHeight) - color: Appearance.m3colors.m3surfaceContainer - radius: Appearance.rounding.normal - - ColumnLayout { // Output column - id: outputColumn - anchors.fill: parent - spacing: 0 - - StyledText { // Output area - id: outputTextArea - Layout.fillWidth: true - property bool hasTranslation: (root.translatedText.trim().length > 0) - wrapMode: TextEdit.Wrap - font.pixelSize: Appearance.font.pixelSize.small - color: hasTranslation ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext - padding: 15 - text: hasTranslation ? root.translatedText : "" + isInput: false + placeholderText: qsTr("Translation goes here...") + property bool hasTranslation: (root.translatedText.trim().length > 0) + text: hasTranslation ? root.translatedText : "" + GroupButton { + id: copyButton + baseWidth: height + buttonRadius: Appearance.rounding.small + enabled: outputCanvas.displayedText.trim().length > 0 + contentItem: MaterialSymbol { + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + iconSize: Appearance.font.pixelSize.larger + text: "content_copy" + color: copyButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext } - Item { Layout.fillHeight: true } - RowLayout { // Status row - Layout.fillWidth: true - Layout.margins: 10 - spacing: 10 - Item { Layout.fillWidth: true } - ButtonGroup { - GroupButton { - id: copyButton - baseWidth: height - buttonRadius: Appearance.rounding.small - enabled: root.outputField.text.trim().length > 0 - contentItem: MaterialSymbol { - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - iconSize: Appearance.font.pixelSize.larger - text: "content_copy" - color: deleteButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext - } - onClicked: { - Quickshell.clipboardText = root.outputField.text - } - } - GroupButton { - id: searchButton - baseWidth: height - buttonRadius: Appearance.rounding.small - enabled: root.outputField.text.trim().length > 0 - contentItem: MaterialSymbol { - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - iconSize: Appearance.font.pixelSize.larger - text: "travel_explore" - color: deleteButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext - } - onClicked: { - let url = ConfigOptions.search.engineBaseUrl + root.outputField.text; - for (let site of ConfigOptions.search.excludedSites) { - url += ` -site:${site}`; - } - Qt.openUrlExternally(url); - } - } + onClicked: { + Quickshell.clipboardText = outputCanvas.displayedText + } + } + GroupButton { + id: searchButton + baseWidth: height + buttonRadius: Appearance.rounding.small + enabled: outputCanvas.displayedText.trim().length > 0 + contentItem: MaterialSymbol { + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + iconSize: Appearance.font.pixelSize.larger + text: "travel_explore" + color: searchButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext + } + onClicked: { + let url = ConfigOptions.search.engineBaseUrl + outputCanvas.displayedText; + for (let site of ConfigOptions.search.excludedSites) { + url += ` -site:${site}`; } + Qt.openUrlExternally(url); } } } + } } + + Loader { + anchors.fill: parent + active: root.showLanguageSelector + visible: root.showLanguageSelector + z: 9999 + sourceComponent: SelectionDialog { + id: languageSelectorDialog + titleText: qsTr("Select Language") + items: root.languages + onCanceled: () => { + root.showLanguageSelector = false; + } + onSelected: (result) => { + root.showLanguageSelector = false; + if (!result || result.length === 0) return; // No selection made + + if (root.languageSelectorTarget) { + root.targetLanguage = result; + ConfigOptions.language.translator.targetLanguage = result; // Save to config + } else { + root.sourceLanguage = result; + ConfigOptions.language.translator.sourceLanguage = result; // Save to config + } + } + } + } } diff --git a/.config/quickshell/modules/sidebarLeft/translator/LanguageSelectorButton.qml b/.config/quickshell/modules/sidebarLeft/translator/LanguageSelectorButton.qml new file mode 100644 index 000000000..a78559517 --- /dev/null +++ b/.config/quickshell/modules/sidebarLeft/translator/LanguageSelectorButton.qml @@ -0,0 +1,42 @@ +import "root:/" +import "root:/services" +import "root:/modules/common" +import "root:/modules/common/widgets" +import "root:/modules/common/functions/string_utils.js" as StringUtils +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell +import Quickshell.Io +import Quickshell.Hyprland + +RippleButton { + id: root + property string displayText: "" + colBackground: Appearance.colors.colLayer2 + + contentItem: Item { + anchors.centerIn: parent + implicitWidth: languageRow.implicitWidth + implicitHeight: languageText.implicitHeight + RowLayout { + id: languageRow + anchors.centerIn: parent + spacing: 0 + StyledText { + id: languageText + Layout.alignment: Qt.AlignVCenter + Layout.leftMargin: 5 + text: root.displayText + color: Appearance.colors.colOnLayer2 + font.pixelSize: Appearance.font.pixelSize.small + } + MaterialSymbol { + Layout.alignment: Qt.AlignVCenter + iconSize: Appearance.font.pixelSize.hugeass + text: "arrow_drop_down" + color: Appearance.colors.colOnLayer2 + } + } + } +} diff --git a/.config/quickshell/modules/sidebarLeft/translator/TextCanvas.qml b/.config/quickshell/modules/sidebarLeft/translator/TextCanvas.qml new file mode 100644 index 000000000..7f32a63d9 --- /dev/null +++ b/.config/quickshell/modules/sidebarLeft/translator/TextCanvas.qml @@ -0,0 +1,92 @@ +import "root:/" +import "root:/services" +import "root:/modules/common" +import "root:/modules/common/widgets" +import "root:/modules/common/functions/string_utils.js" as StringUtils +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell +import Quickshell.Io +import Quickshell.Hyprland + +Rectangle { + id: root + property bool isInput: true // true for input, false for output + property string placeholderText + property string text: "" + property var inputTextArea: isInput ? inputLoader.item : undefined + readonly property string displayedText: isInput ? inputLoader.item.text : + root.text.length > 0 ? outputLoader.item.text : "" + default property alias actionButtons: actions.data + Layout.fillWidth: true + implicitHeight: Math.max(150, inputColumn.implicitHeight) + color: isInput ? Appearance.colors.colLayer1 : Appearance.m3colors.m3surfaceContainer + radius: Appearance.rounding.normal + border.color: isInput ? Appearance.m3colors.m3outlineVariant : "transparent" + border.width: isInput ? 1 : 0 + + signal inputTextChanged(); // Signal emitted when text changes + + ColumnLayout { + id: inputColumn + anchors.fill: parent + spacing: 0 + + Loader { + id: inputLoader + active: root.isInput + visible: root.isInput + Layout.fillWidth: true + sourceComponent: StyledTextArea { // Input area + id: inputTextArea + placeholderText: root.placeholderText + wrapMode: TextEdit.Wrap + textFormat: TextEdit.PlainText + font.pixelSize: Appearance.font.pixelSize.small + color: Appearance.colors.colOnLayer1 + padding: 15 + background: null + onTextChanged: root.inputTextChanged() + } + } + + Loader { + id: outputLoader + active: !root.isInput + visible: !root.isInput + Layout.fillWidth: true + sourceComponent: StyledText { // Output area + id: outputTextArea + padding: 15 + wrapMode: Text.Wrap + font.pixelSize: Appearance.font.pixelSize.small + color: root.text.length > 0 ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext + text: root.text.length > 0 ? root.text : root.placeholderText + } + } + + Item { Layout.fillHeight: true } + + RowLayout { // Status row + Layout.fillWidth: true + Layout.margins: 10 + spacing: 10 + + Loader { + active: root.isInput + visible: root.isInput + Layout.leftMargin: 10 + sourceComponent: Text { + text: qsTr("%1 characters").arg(inputLoader.item.text.length) + color: Appearance.colors.colOnLayer1 + font.pixelSize: Appearance.font.pixelSize.smaller + } + } + Item { Layout.fillWidth: true } + ButtonGroup { + id: actions + } + } + } +} \ No newline at end of file diff --git a/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml b/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml index a7a88a403..1799df556 100644 --- a/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml +++ b/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml @@ -5,6 +5,7 @@ import Qt5Compat.GraphicalEffects import QtQuick import QtQuick.Controls import QtQuick.Layouts +import Quickshell import Quickshell.Widgets import Quickshell.Services.Pipewire @@ -16,7 +17,7 @@ Item { property int dialogMargins: 16 property PwNode selectedDevice - function showDeviceSelectorDialog(input) { + function showDeviceSelectorDialog(input: bool) { root.selectedDevice = null root.showDeviceSelector = true root.deviceSelectorInput = input @@ -207,9 +208,11 @@ Item { spacing: 0 Repeater { - model: Pipewire.nodes.values.filter(node => { - return !node.isStream && node.isSink !== root.deviceSelectorInput && node.audio - }) + model: ScriptModel { + values: Pipewire.nodes.values.filter(node => { + return !node.isStream && node.isSink !== root.deviceSelectorInput && node.audio + }) + } // This could and should be refractored, but all data becomes null when passed wtf delegate: StyledRadioButton { diff --git a/.config/quickshell/shell.qml b/.config/quickshell/shell.qml index 4acb7cccb..35a5008ea 100644 --- a/.config/quickshell/shell.qml +++ b/.config/quickshell/shell.qml @@ -29,7 +29,7 @@ ShellRoot { property bool enableBar: true property bool enableBackgroundWidgets: true property bool enableCheatsheet: true - property bool enableDock: true + property bool enableDock: false property bool enableMediaControls: true property bool enableNotificationPopup: true property bool enableOnScreenDisplayBrightness: true From 0fb28af3c7633ac35b502bee0094e6c941e78a5c Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 11:06:22 +0200 Subject: [PATCH 79/89] sidebar: translator: change layout to reduce eye movement --- .../modules/sidebarLeft/Translator.qml | 204 +++++++++--------- 1 file changed, 105 insertions(+), 99 deletions(-) diff --git a/.config/quickshell/modules/sidebarLeft/Translator.qml b/.config/quickshell/modules/sidebarLeft/Translator.qml index 92e0505db..aacc35868 100644 --- a/.config/quickshell/modules/sidebarLeft/Translator.qml +++ b/.config/quickshell/modules/sidebarLeft/Translator.qml @@ -99,116 +99,120 @@ Item { getLanguagesProc.bufferList = []; // Clear the buffer } } - - Flickable { + + ColumnLayout { anchors.fill: parent - contentHeight: contentColumn.implicitHeight + Flickable { + Layout.fillWidth: true + Layout.fillHeight: true + contentHeight: contentColumn.implicitHeight - ColumnLayout { - id: contentColumn - anchors.fill: parent + ColumnLayout { + id: contentColumn + anchors.fill: parent - LanguageSelectorButton { // Source language button - id: sourceLanguageButton - displayText: root.sourceLanguage - onClicked: { - root.showLanguageSelectorDialog(false); - } - } - - TextCanvas { // Content input - id: inputCanvas - isInput: true - placeholderText: qsTr("Enter text to translate...") - onInputTextChanged: { - translateTimer.restart(); - } - GroupButton { - id: pasteButton - baseWidth: height - buttonRadius: Appearance.rounding.small - contentItem: MaterialSymbol { - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - iconSize: Appearance.font.pixelSize.larger - text: "content_paste" - color: deleteButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext - } + LanguageSelectorButton { // Target language button + id: targetLanguageButton + displayText: root.targetLanguage onClicked: { - root.inputField.text = Quickshell.clipboardText + root.showLanguageSelectorDialog(true); } } - GroupButton { - id: deleteButton - baseWidth: height - buttonRadius: Appearance.rounding.small - enabled: inputCanvas.inputTextArea.text.length > 0 - contentItem: MaterialSymbol { - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - iconSize: Appearance.font.pixelSize.larger - text: "close" - color: deleteButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext - } - onClicked: { - root.inputField.text = "" - } - } - } - LanguageSelectorButton { // Target language button - id: targetLanguageButton - displayText: root.targetLanguage - onClicked: { - root.showLanguageSelectorDialog(true); - } - } - - TextCanvas { // Content translation - id: outputCanvas - isInput: false - placeholderText: qsTr("Translation goes here...") - property bool hasTranslation: (root.translatedText.trim().length > 0) - text: hasTranslation ? root.translatedText : "" - GroupButton { - id: copyButton - baseWidth: height - buttonRadius: Appearance.rounding.small - enabled: outputCanvas.displayedText.trim().length > 0 - contentItem: MaterialSymbol { - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - iconSize: Appearance.font.pixelSize.larger - text: "content_copy" - color: copyButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext - } - onClicked: { - Quickshell.clipboardText = outputCanvas.displayedText - } - } - GroupButton { - id: searchButton - baseWidth: height - buttonRadius: Appearance.rounding.small - enabled: outputCanvas.displayedText.trim().length > 0 - contentItem: MaterialSymbol { - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - iconSize: Appearance.font.pixelSize.larger - text: "travel_explore" - color: searchButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext - } - onClicked: { - let url = ConfigOptions.search.engineBaseUrl + outputCanvas.displayedText; - for (let site of ConfigOptions.search.excludedSites) { - url += ` -site:${site}`; + TextCanvas { // Content translation + id: outputCanvas + isInput: false + placeholderText: qsTr("Translation goes here...") + property bool hasTranslation: (root.translatedText.trim().length > 0) + text: hasTranslation ? root.translatedText : "" + GroupButton { + id: copyButton + baseWidth: height + buttonRadius: Appearance.rounding.small + enabled: outputCanvas.displayedText.trim().length > 0 + contentItem: MaterialSymbol { + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + iconSize: Appearance.font.pixelSize.larger + text: "content_copy" + color: copyButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext + } + onClicked: { + Quickshell.clipboardText = outputCanvas.displayedText + } + } + GroupButton { + id: searchButton + baseWidth: height + buttonRadius: Appearance.rounding.small + enabled: outputCanvas.displayedText.trim().length > 0 + contentItem: MaterialSymbol { + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + iconSize: Appearance.font.pixelSize.larger + text: "travel_explore" + color: searchButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext + } + onClicked: { + let url = ConfigOptions.search.engineBaseUrl + outputCanvas.displayedText; + for (let site of ConfigOptions.search.excludedSites) { + url += ` -site:${site}`; + } + Qt.openUrlExternally(url); } - Qt.openUrlExternally(url); } } - } - } + } + } + + LanguageSelectorButton { // Source language button + id: sourceLanguageButton + displayText: root.sourceLanguage + onClicked: { + root.showLanguageSelectorDialog(false); + } + } + + TextCanvas { // Content input + id: inputCanvas + isInput: true + placeholderText: qsTr("Enter text to translate...") + onInputTextChanged: { + translateTimer.restart(); + } + GroupButton { + id: pasteButton + baseWidth: height + buttonRadius: Appearance.rounding.small + contentItem: MaterialSymbol { + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + iconSize: Appearance.font.pixelSize.larger + text: "content_paste" + color: deleteButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext + } + onClicked: { + root.inputField.text = Quickshell.clipboardText + } + } + GroupButton { + id: deleteButton + baseWidth: height + buttonRadius: Appearance.rounding.small + enabled: inputCanvas.inputTextArea.text.length > 0 + contentItem: MaterialSymbol { + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + iconSize: Appearance.font.pixelSize.larger + text: "close" + color: deleteButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext + } + onClicked: { + root.inputField.text = "" + } + } + } } Loader { @@ -234,6 +238,8 @@ Item { root.sourceLanguage = result; ConfigOptions.language.translator.sourceLanguage = result; // Save to config } + + translateTimer.restart(); // Restart translation after language change } } } From 23f0e90a7bd447c05e174ed19c8d184624bd03ce Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 11:36:56 +0200 Subject: [PATCH 80/89] sidebar: translator: save selected language, cleaner selector --- .../modules/common/ConfigOptions.qml | 2 +- .../common/widgets/SelectionDialog.qml | 8 ++++--- .../modules/sidebarLeft/Translator.qml | 18 ++++++++------- .config/quickshell/services/ConfigLoader.qml | 22 +++++++++++++++++-- 4 files changed, 36 insertions(+), 14 deletions(-) diff --git a/.config/quickshell/modules/common/ConfigOptions.qml b/.config/quickshell/modules/common/ConfigOptions.qml index 902049729..470f438df 100644 --- a/.config/quickshell/modules/common/ConfigOptions.qml +++ b/.config/quickshell/modules/common/ConfigOptions.qml @@ -66,8 +66,8 @@ Singleton { property QtObject language: QtObject { property QtObject translator: QtObject { property string engine: "auto" // Run `trans -list-engines` for available engines. auto should use google + property string targetLanguage: "auto" // Run `trans -list-all` for available languages property string sourceLanguage: "auto" - property string targetLanguage: "English" // Run `trans -list-all` for available languages } } diff --git a/.config/quickshell/modules/common/widgets/SelectionDialog.qml b/.config/quickshell/modules/common/widgets/SelectionDialog.qml index 1e1446b51..affd13bc9 100644 --- a/.config/quickshell/modules/common/widgets/SelectionDialog.qml +++ b/.config/quickshell/modules/common/widgets/SelectionDialog.qml @@ -13,7 +13,8 @@ Item { property real dialogMargin: 30 property string titleText: "Selection Dialog" property alias items: choiceModel.values - property int selectedId: -1 // -1 means no selection + property int selectedId: choiceListView.currentIndex + property var defaultChoice signal canceled(); signal selected(var result); @@ -68,6 +69,7 @@ Item { Layout.fillWidth: true Layout.fillHeight: true clip: true + currentIndex: root.defaultChoice !== undefined ? root.items.indexOf(root.defaultChoice) : -1 model: ScriptModel { id: choiceModel @@ -85,11 +87,11 @@ Item { } description: modelData.toString() - checked: index === root.selectedId + checked: index === choiceListView.currentIndex onCheckedChanged: { if (checked) { - root.selectedId = index; + choiceListView.currentIndex = index; } } } diff --git a/.config/quickshell/modules/sidebarLeft/Translator.qml b/.config/quickshell/modules/sidebarLeft/Translator.qml index aacc35868..8f93b50d7 100644 --- a/.config/quickshell/modules/sidebarLeft/Translator.qml +++ b/.config/quickshell/modules/sidebarLeft/Translator.qml @@ -29,12 +29,10 @@ Item { property bool showLanguageSelector: false property bool languageSelectorTarget: false // true for target language, false for source language - property string languageSelectorLanguage: "" function showLanguageSelectorDialog(isTargetLang: bool) { - root.showLanguageSelector = true root.languageSelectorTarget = isTargetLang; - root.languageSelectorLanguage = isTargetLang ? root.targetLanguage : root.sourceLanguage; + root.showLanguageSelector = true } onFocusChanged: (focus) => { @@ -93,9 +91,12 @@ Item { } } onExited: (exitCode, exitStatus) => { - root.languages = getLanguagesProc.bufferList - .filter(lang => lang.trim().length > 0) // Filter out empty lines - .sort((a, b) => a.localeCompare(b)); // Sort alphabetically + // Ensure "auto" is always the first language + let langs = getLanguagesProc.bufferList + .filter(lang => lang.trim().length > 0 && lang !== "auto") + .sort((a, b) => a.localeCompare(b)); + langs.unshift("auto"); + root.languages = langs; getLanguagesProc.bufferList = []; // Clear the buffer } } @@ -224,6 +225,7 @@ Item { id: languageSelectorDialog titleText: qsTr("Select Language") items: root.languages + defaultChoice: root.languageSelectorTarget ? root.targetLanguage : root.sourceLanguage onCanceled: () => { root.showLanguageSelector = false; } @@ -233,10 +235,10 @@ Item { if (root.languageSelectorTarget) { root.targetLanguage = result; - ConfigOptions.language.translator.targetLanguage = result; // Save to config + ConfigLoader.setConfigValueAndSave("language.translator.targetLanguage", result); // Save to config } else { root.sourceLanguage = result; - ConfigOptions.language.translator.sourceLanguage = result; // Save to config + ConfigLoader.setConfigValueAndSave("language.translator.sourceLanguage", result); // Save to config } translateTimer.restart(); // Restart translation after language change diff --git a/.config/quickshell/services/ConfigLoader.qml b/.config/quickshell/services/ConfigLoader.qml index 61aa9b4ed..688bb47bb 100644 --- a/.config/quickshell/services/ConfigLoader.qml +++ b/.config/quickshell/services/ConfigLoader.qml @@ -14,13 +14,18 @@ import Qt.labs.platform /** * Loads and manages the shell configuration file. * The config file is by default at XDG_CONFIG_HOME/illogical-impulse/config.json. - * Automatically reloaded when the file changes, but does not provide a way to save changes. + * Automatically reloaded when the file changes. */ Singleton { id: root property string filePath: Directories.shellConfigPath property bool firstLoad: true property bool preventNextLoad: false + property var preventNextNotification: false + + onPreventNextNotificationChanged: { + console.log("HMM: preventNextNotification:", root.preventNextNotification); + } function loadConfig() { configFileView.reload() @@ -87,11 +92,19 @@ Singleton { Hyprland.dispatch(`exec echo '${StringUtils.shellSingleQuoteEscape(JSON.stringify(plainConfig, null, 2))}' > '${root.filePath}'`) } + function setConfigValueAndSave(nestedKey, value, preventNextNotification = true) { + setLiveConfigValue(nestedKey, value); + root.preventNextNotification = preventNextNotification; + console.log("SETTING: preventNextNotification:", root.preventNextNotification); + saveConfig(); + } + Timer { id: delayedFileRead interval: ConfigOptions.hacks.arbitraryRaceConditionDelay running: false onTriggered: { + console.log("GONNA APPLY KONFIG preventNextNotification:", root.preventNextNotification); if (root.preventNextLoad) { root.preventNextLoad = false; return; @@ -99,8 +112,13 @@ Singleton { if (root.firstLoad) { root.applyConfig(configFileView.text()) } else { + console.log("APPLYING: preventNextNotification:", root.preventNextNotification); root.applyConfig(configFileView.text()) - Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration reloaded")}" "${root.filePath}"`) + if (!root.preventNextNotification) { + Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration reloaded")}" "${root.filePath}"`) + } else { + // root.preventNextNotification = false; + } } } } From 447312959937ccb87dae37cca58cb6a0b9469b00 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 11:52:24 +0200 Subject: [PATCH 81/89] fix session screen button size --- .config/quickshell/modules/common/widgets/RippleButton.qml | 3 --- .../modules/sidebarLeft/translator/LanguageSelectorButton.qml | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.config/quickshell/modules/common/widgets/RippleButton.qml b/.config/quickshell/modules/common/widgets/RippleButton.qml index 6e6e3c5fc..9931cd02a 100644 --- a/.config/quickshell/modules/common/widgets/RippleButton.qml +++ b/.config/quickshell/modules/common/widgets/RippleButton.qml @@ -32,9 +32,6 @@ Button { property color colRipple: Appearance?.colors.colLayer1Active ?? "#D6CEE2" property color colRippleToggled: Appearance?.colors.colPrimaryActive ?? "#D6CEE2" - implicitWidth: contentItem.implicitWidth + horizontalPadding * 2 - implicitHeight: contentItem.implicitHeight + verticalPadding * 2 - property color buttonColor: root.enabled ? (root.toggled ? (root.hovered ? colBackgroundToggledHover : colBackgroundToggled) : diff --git a/.config/quickshell/modules/sidebarLeft/translator/LanguageSelectorButton.qml b/.config/quickshell/modules/sidebarLeft/translator/LanguageSelectorButton.qml index a78559517..37df25f83 100644 --- a/.config/quickshell/modules/sidebarLeft/translator/LanguageSelectorButton.qml +++ b/.config/quickshell/modules/sidebarLeft/translator/LanguageSelectorButton.qml @@ -15,6 +15,9 @@ RippleButton { property string displayText: "" colBackground: Appearance.colors.colLayer2 + implicitWidth: contentItem.implicitWidth + horizontalPadding * 2 + implicitHeight: contentItem.implicitHeight + verticalPadding * 2 + contentItem: Item { anchors.centerIn: parent implicitWidth: languageRow.implicitWidth From a3818322a675d57a0940b1bc3b64cdc07c8cec63 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 22:30:43 +0200 Subject: [PATCH 82/89] media controls: visualizer --- .../modules/mediaControls/MediaControls.qml | 23 ++++- .../modules/mediaControls/PlayerControl.qml | 83 +++++++++++++++++-- .../scripts/cava/raw_output_config.txt | 14 ++++ .../illogical-impulse-audio/PKGBUILD | 1 + 4 files changed, 114 insertions(+), 7 deletions(-) create mode 100644 .config/quickshell/scripts/cava/raw_output_config.txt diff --git a/.config/quickshell/modules/mediaControls/MediaControls.qml b/.config/quickshell/modules/mediaControls/MediaControls.qml index 81b1d62d9..0a85bde0a 100644 --- a/.config/quickshell/modules/mediaControls/MediaControls.qml +++ b/.config/quickshell/modules/mediaControls/MediaControls.qml @@ -26,6 +26,7 @@ Scope { property real contentPadding: 13 property real popupRounding: Appearance.rounding.screenRounding - Appearance.sizes.elevationMargin + 1 property real artRounding: Appearance.rounding.verysmall + property list visualizerPoints: [] property bool hasPlasmaIntegration: false function isRealPlayer(player) { @@ -68,13 +69,32 @@ Scope { return filtered; } + Process { + id: cavaProc + running: mediaControlsLoader.active + onRunningChanged: { + if (!cavaProc.running) { + root.visualizerPoints = []; + } + } + command: ["cava", "-p", `${FileUtils.trimFileProtocol(Directories.config)}/quickshell/scripts/cava/raw_output_config.txt`] + stdout: SplitParser { + onRead: data => { + // Parse `;`-separated values into the visualizerPoints array + let allPoints = data.split(";").map(p => parseFloat(p.trim())).filter(p => !isNaN(p)); + let points = allPoints.slice(Math.floor(allPoints.length / 2), allPoints.length); + root.visualizerPoints = points; + } + } + } + Loader { id: mediaControlsLoader active: false sourceComponent: PanelWindow { id: mediaControlsRoot - visible: mediaControlsLoader.active + visible: true exclusiveZone: 0 implicitWidth: ( @@ -112,6 +132,7 @@ Scope { delegate: PlayerControl { required property MprisPlayer modelData player: modelData + visualizerPoints: root.visualizerPoints } } } diff --git a/.config/quickshell/modules/mediaControls/PlayerControl.qml b/.config/quickshell/modules/mediaControls/PlayerControl.qml index 16be41b83..842b681fd 100644 --- a/.config/quickshell/modules/mediaControls/PlayerControl.qml +++ b/.config/quickshell/modules/mediaControls/PlayerControl.qml @@ -25,6 +25,8 @@ Item { // Player instance property string artFilePath: `${artDownloadLocation}/${artFileName}` property color artDominantColor: colorQuantizer?.colors[0] || Appearance.m3colors.m3secondaryContainer property bool downloaded: false + property list visualizerPoints: [] + property real maxVisualizerValue: 1000 // Max value in the data points implicitWidth: widgetWidth implicitHeight: widgetHeight @@ -150,6 +152,69 @@ Item { // Player instance } } + Canvas { // Visualizer + id: visualizerCanvas + anchors.fill: parent + onPaint: { + var ctx = getContext("2d"); + ctx.clearRect(0, 0, width, height); + + var points = playerController.visualizerPoints; + var maxVal = playerController.maxVisualizerValue || 1; + var h = height; + var w = width; + var n = points.length; + if (n < 2) return; + + // Smoothing: simple moving average (optional) + var smoothPoints = []; + var smoothWindow = 3; // adjust for more/less smoothing + for (var i = 0; i < n; ++i) { + var sum = 0, count = 0; + for (var j = -smoothWindow; j <= smoothWindow; ++j) { + var idx = Math.max(0, Math.min(n - 1, i + j)); + sum += points[idx]; + count++; + } + smoothPoints.push(sum / count); + } + + ctx.beginPath(); + ctx.moveTo(0, h); + for (var i = 0; i < n; ++i) { + var x = i * w / (n - 1); + var y = h - (smoothPoints[i] / maxVal) * h; + ctx.lineTo(x, y); + } + ctx.lineTo(w, h); + ctx.closePath(); + + ctx.fillStyle = Qt.rgba( + blendedColors.colPrimary.r, + blendedColors.colPrimary.g, + blendedColors.colPrimary.b, + 0.25 + ); + ctx.fill(); + } + Connections { + target: playerController + function onVisualizerPointsChanged() { + visualizerCanvas.requestPaint() + } + } + + layer.enabled: true + layer.effect: MultiEffect { // Blur a tiny bit to obscure away the points + source: visualizerCanvas + saturation: 0.2 + blurEnabled: true + blurMax: 6 + blur: 1 + } + } + + RowLayout { anchors.fill: parent anchors.margins: root.contentPadding @@ -160,7 +225,7 @@ Item { // Player instance Layout.fillHeight: true implicitWidth: height radius: root.artRounding - color: blendedColors.colLayer1 + color: ColorUtils.transparentize(blendedColors.colLayer1, 0.5) layer.enabled: true layer.effect: OpacityMask { @@ -235,12 +300,18 @@ Item { // Player instance iconName: "skip_previous" onClicked: playerController.player?.previous() } - StyledProgressBar { - id: slider + Item { + id: progressBarContainer Layout.fillWidth: true - highlightColor: blendedColors.colPrimary - trackColor: blendedColors.colSecondaryContainer - value: playerController.player?.position / playerController.player?.length + implicitHeight: progressBar.implicitHeight + + StyledProgressBar { + id: progressBar + anchors.fill: parent + highlightColor: blendedColors.colPrimary + trackColor: blendedColors.colSecondaryContainer + value: playerController.player?.position / playerController.player?.length + } } TrackChangeButton { iconName: "skip_next" diff --git a/.config/quickshell/scripts/cava/raw_output_config.txt b/.config/quickshell/scripts/cava/raw_output_config.txt new file mode 100644 index 000000000..a223a31cb --- /dev/null +++ b/.config/quickshell/scripts/cava/raw_output_config.txt @@ -0,0 +1,14 @@ +[general] +mode = waves +framerate = 60 +autosens = 1 +bars = 60 + +[output] +method = raw +raw_target = /dev/stdout +data_format = ascii + +[smoothing] +noise_reduction = 20 + diff --git a/arch-packages/illogical-impulse-audio/PKGBUILD b/arch-packages/illogical-impulse-audio/PKGBUILD index 81054e0b7..6cab7de53 100644 --- a/arch-packages/illogical-impulse-audio/PKGBUILD +++ b/arch-packages/illogical-impulse-audio/PKGBUILD @@ -5,6 +5,7 @@ pkgdesc='Illogical Impulse Audio Dependencies' arch=(any) license=(None) depends=( + cava pavucontrol-qt wireplumber libdbusmenu-gtk3 From c2c7078957a93dc4e6919cb93917d0568edd4584 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 22:30:55 +0200 Subject: [PATCH 83/89] translator: remove debug print --- .../quickshell/modules/sidebarLeft/Translator.qml | 6 +++--- .config/quickshell/services/ConfigLoader.qml | 14 ++------------ 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/.config/quickshell/modules/sidebarLeft/Translator.qml b/.config/quickshell/modules/sidebarLeft/Translator.qml index 8f93b50d7..999fe3e44 100644 --- a/.config/quickshell/modules/sidebarLeft/Translator.qml +++ b/.config/quickshell/modules/sidebarLeft/Translator.qml @@ -47,7 +47,7 @@ Item { repeat: false onTriggered: () => { if (root.inputField.text.trim().length > 0) { - console.log("Translating with command:", translateProc.command); + // console.log("Translating with command:", translateProc.command); translateProc.running = false; translateProc.buffer = ""; // Clear the buffer translateProc.running = true; // Restart the process @@ -72,8 +72,8 @@ Item { onExited: (exitCode, exitStatus) => { // 1. Split into sections by double newlines const sections = translateProc.buffer.trim().split(/\n\s*\n/); - console.log("BUFFER:", translateProc.buffer); - console.log("SECTIONS:", sections); + // console.log("BUFFER:", translateProc.buffer); + // console.log("SECTIONS:", sections); // 2. Extract relevant data root.translatedText = sections.length > 1 ? sections[1].trim() : ""; diff --git a/.config/quickshell/services/ConfigLoader.qml b/.config/quickshell/services/ConfigLoader.qml index 688bb47bb..347e8f400 100644 --- a/.config/quickshell/services/ConfigLoader.qml +++ b/.config/quickshell/services/ConfigLoader.qml @@ -23,16 +23,11 @@ Singleton { property bool preventNextLoad: false property var preventNextNotification: false - onPreventNextNotificationChanged: { - console.log("HMM: preventNextNotification:", root.preventNextNotification); - } - function loadConfig() { configFileView.reload() } function applyConfig(fileContent) { - console.log("[ConfigLoader] Applying config from file:", root.filePath); try { if (fileContent.trim() === "") { console.warn("[ConfigLoader] Config file is empty, skipping load."); @@ -82,8 +77,6 @@ Singleton { } } - console.log(parents.join(".")); - console.log(`[ConfigLoader] Setting live config value: ${nestedKey} = ${convertedValue}`); obj[keys[keys.length - 1]] = convertedValue; } @@ -95,7 +88,6 @@ Singleton { function setConfigValueAndSave(nestedKey, value, preventNextNotification = true) { setLiveConfigValue(nestedKey, value); root.preventNextNotification = preventNextNotification; - console.log("SETTING: preventNextNotification:", root.preventNextNotification); saveConfig(); } @@ -104,7 +96,6 @@ Singleton { interval: ConfigOptions.hacks.arbitraryRaceConditionDelay running: false onTriggered: { - console.log("GONNA APPLY KONFIG preventNextNotification:", root.preventNextNotification); if (root.preventNextLoad) { root.preventNextLoad = false; return; @@ -112,12 +103,11 @@ Singleton { if (root.firstLoad) { root.applyConfig(configFileView.text()) } else { - console.log("APPLYING: preventNextNotification:", root.preventNextNotification); root.applyConfig(configFileView.text()) if (!root.preventNextNotification) { - Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration reloaded")}" "${root.filePath}"`) + // Hyprland.dispatch(`exec notify-send "${qsTr("Shell configuration reloaded")}" "${root.filePath}"`) } else { - // root.preventNextNotification = false; + root.preventNextNotification = false; } } } From 5a867ea0616a2ba254844458c8f443528454be88 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 22:59:16 +0200 Subject: [PATCH 84/89] media controls: improve dupe entry filtering, correct cava config --- .../modules/mediaControls/MediaControls.qml | 5 ++--- .../modules/mediaControls/PlayerControl.qml | 11 ++++++----- .config/quickshell/scripts/cava/raw_output_config.txt | 5 ++++- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/.config/quickshell/modules/mediaControls/MediaControls.qml b/.config/quickshell/modules/mediaControls/MediaControls.qml index 0a85bde0a..4350658f6 100644 --- a/.config/quickshell/modules/mediaControls/MediaControls.qml +++ b/.config/quickshell/modules/mediaControls/MediaControls.qml @@ -54,7 +54,7 @@ Scope { for (let j = i + 1; j < players.length; ++j) { let p2 = players[j]; if (p1.trackTitle && p2.trackTitle && - (p1.trackTitle.startsWith(p2.trackTitle) || p2.trackTitle.startsWith(p1.trackTitle))) { + (p1.trackTitle.includes(p2.trackTitle) || p2.trackTitle.includes(p1.trackTitle))) { group.push(j); } } @@ -81,8 +81,7 @@ Scope { stdout: SplitParser { onRead: data => { // Parse `;`-separated values into the visualizerPoints array - let allPoints = data.split(";").map(p => parseFloat(p.trim())).filter(p => !isNaN(p)); - let points = allPoints.slice(Math.floor(allPoints.length / 2), allPoints.length); + let points = data.split(";").map(p => parseFloat(p.trim())).filter(p => !isNaN(p)); root.visualizerPoints = points; } } diff --git a/.config/quickshell/modules/mediaControls/PlayerControl.qml b/.config/quickshell/modules/mediaControls/PlayerControl.qml index 842b681fd..fb4799e17 100644 --- a/.config/quickshell/modules/mediaControls/PlayerControl.qml +++ b/.config/quickshell/modules/mediaControls/PlayerControl.qml @@ -27,6 +27,7 @@ Item { // Player instance property bool downloaded: false property list visualizerPoints: [] property real maxVisualizerValue: 1000 // Max value in the data points + property int visualizerSmoothing: 2 // Number of points to average for smoothing implicitWidth: widgetWidth implicitHeight: widgetHeight @@ -168,7 +169,7 @@ Item { // Player instance // Smoothing: simple moving average (optional) var smoothPoints = []; - var smoothWindow = 3; // adjust for more/less smoothing + var smoothWindow = playerController.visualizerSmoothing; // adjust for more/less smoothing for (var i = 0; i < n; ++i) { var sum = 0, count = 0; for (var j = -smoothWindow; j <= smoothWindow; ++j) { @@ -178,6 +179,7 @@ Item { // Player instance } smoothPoints.push(sum / count); } + if (!playerController.player?.isPlaying) smoothedPoints.fill(0); // If not playing, show no points ctx.beginPath(); ctx.moveTo(0, h); @@ -193,7 +195,7 @@ Item { // Player instance blendedColors.colPrimary.r, blendedColors.colPrimary.g, blendedColors.colPrimary.b, - 0.25 + 0.15 ); ctx.fill(); } @@ -205,15 +207,14 @@ Item { // Player instance } layer.enabled: true - layer.effect: MultiEffect { // Blur a tiny bit to obscure away the points + layer.effect: MultiEffect { // Blur a bit to obscure away the points source: visualizerCanvas saturation: 0.2 blurEnabled: true - blurMax: 6 + blurMax: 7 blur: 1 } } - RowLayout { anchors.fill: parent diff --git a/.config/quickshell/scripts/cava/raw_output_config.txt b/.config/quickshell/scripts/cava/raw_output_config.txt index a223a31cb..7760e4ea2 100644 --- a/.config/quickshell/scripts/cava/raw_output_config.txt +++ b/.config/quickshell/scripts/cava/raw_output_config.txt @@ -2,13 +2,16 @@ mode = waves framerate = 60 autosens = 1 -bars = 60 +bars = 50 [output] method = raw raw_target = /dev/stdout data_format = ascii +channels = mono +mono_option = average [smoothing] noise_reduction = 20 + From 24374efdce1850d8695d4eeb893577f949d0d71c Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 23:16:11 +0200 Subject: [PATCH 85/89] bar: change music icon --- .config/quickshell/modules/bar/Media.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/quickshell/modules/bar/Media.qml b/.config/quickshell/modules/bar/Media.qml index f4b8606b9..c59b6379d 100644 --- a/.config/quickshell/modules/bar/Media.qml +++ b/.config/quickshell/modules/bar/Media.qml @@ -68,7 +68,7 @@ Item { MaterialSymbol { anchors.centerIn: parent fill: 1 - text: activePlayer?.isPlaying ? "pause" : "play_arrow" + text: activePlayer?.isPlaying ? "pause" : "music_note" iconSize: Appearance.font.pixelSize.normal color: Appearance.m3colors.m3onSecondaryContainer } From 1721c2bbb27f94c38090408a2806302a74b7d335 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 11 Jun 2025 23:16:38 +0200 Subject: [PATCH 86/89] material symbols: disable filll anim for now performance/memory concerns --- .../modules/common/widgets/MaterialSymbol.qml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.config/quickshell/modules/common/widgets/MaterialSymbol.qml b/.config/quickshell/modules/common/widgets/MaterialSymbol.qml index 07ec5025d..450a856db 100644 --- a/.config/quickshell/modules/common/widgets/MaterialSymbol.qml +++ b/.config/quickshell/modules/common/widgets/MaterialSymbol.qml @@ -16,13 +16,13 @@ Text { verticalAlignment: Text.AlignVCenter color: Appearance.m3colors.m3onBackground - Behavior on fill { - NumberAnimation { - duration: Appearance?.animation.elementMoveFast.duration ?? 200 - easing.type: Appearance?.animation.elementMoveFast.type ?? Easing.BezierSpline - easing.bezierCurve: Appearance?.animation.elementMoveFast.bezierCurve ?? [0.34, 0.80, 0.34, 1.00, 1, 1] - } - } + // Behavior on fill { + // NumberAnimation { + // duration: Appearance?.animation.elementMoveFast.duration ?? 200 + // easing.type: Appearance?.animation.elementMoveFast.type ?? Easing.BezierSpline + // easing.bezierCurve: Appearance?.animation.elementMoveFast.bezierCurve ?? [0.34, 0.80, 0.34, 1.00, 1, 1] + // } + // } font.variableAxes: { "FILL": truncatedFill, From b7b183d2ca47a972e71f93487494a694d3bac3a2 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 12 Jun 2025 00:12:24 +0200 Subject: [PATCH 87/89] quickshell: use more .colors (rather than .m3colors) --- .../backgroundWidgets/BackgroundWidgets.qml | 8 ++++---- .config/quickshell/modules/bar/Bar.qml | 6 +++--- .../quickshell/modules/bar/BatteryIndicator.qml | 2 +- .config/quickshell/modules/bar/Media.qml | 2 +- .config/quickshell/modules/bar/Resource.qml | 2 +- .config/quickshell/modules/bar/Workspaces.qml | 2 +- .../quickshell/modules/common/Appearance.qml | 17 ++++++++++++----- .../modules/common/widgets/CircularProgress.qml | 2 +- .../modules/common/widgets/KeyboardKey.qml | 2 +- .../modules/common/widgets/NavRailButton.qml | 2 +- .../common/widgets/NotificationActionButton.qml | 2 +- .../common/widgets/NotificationAppIcon.qml | 2 +- .../common/widgets/NotificationGroup.qml | 2 +- .../modules/common/widgets/NotificationItem.qml | 6 +++--- .../modules/common/widgets/SelectionDialog.qml | 2 +- .../modules/common/widgets/StyledSlider.qml | 2 +- .../modules/common/widgets/StyledSwitch.qml | 2 +- .../modules/common/widgets/StyledTextArea.qml | 2 +- .../quickshell/modules/dock/DockAppButton.qml | 2 +- .config/quickshell/modules/dock/DockApps.qml | 6 +++--- .../quickshell/modules/dock/DockSeparator.qml | 2 +- .../onScreenKeyboard/OnScreenKeyboard.qml | 2 +- .../modules/overview/OverviewWidget.qml | 2 +- .../quickshell/modules/overview/SearchItem.qml | 2 +- .../modules/overview/SearchWidget.qml | 4 ++-- .../modules/session/SessionActionButton.qml | 2 +- .../quickshell/modules/sidebarLeft/AiChat.qml | 2 +- .../quickshell/modules/sidebarLeft/Anime.qml | 2 +- .../modules/sidebarLeft/aiChat/AiMessage.qml | 2 +- .../aiChat/AnnotationSourceButton.qml | 2 +- .../sidebarLeft/aiChat/MessageCodeBlock.qml | 4 ++-- .../sidebarLeft/aiChat/MessageTextBlock.qml | 2 +- .../sidebarLeft/aiChat/MessageThinkBlock.qml | 2 +- .../modules/sidebarLeft/anime/BooruImage.qml | 2 +- .../modules/sidebarLeft/anime/BooruResponse.qml | 4 ++-- .../sidebarLeft/translator/TextCanvas.qml | 4 ++-- .../sidebarRight/calendar/CalendarDayButton.qml | 2 +- .../modules/sidebarRight/todo/TodoWidget.qml | 6 +++--- .../sidebarRight/volumeMixer/VolumeMixer.qml | 2 +- 39 files changed, 65 insertions(+), 58 deletions(-) diff --git a/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml b/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml index 3fb5471df..b6add8968 100644 --- a/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml +++ b/.config/quickshell/modules/backgroundWidgets/BackgroundWidgets.qml @@ -17,17 +17,17 @@ Scope { property string filePath: `${Directories.state}/user/generated/wallpaper/least_busy_region.json` property real centerX: 0 property real centerY: 0 - property color dominantColor: Appearance.m3colors.m3primary + property color dominantColor: Appearance.colors.colPrimary property bool dominantColorIsDark: dominantColor.hslLightness < 0.5 - property color colBackground: ColorUtils.transparentize(ColorUtils.mix(Appearance.m3colors.m3primary, Appearance.m3colors.m3secondaryContainer), 1) - property color colText: ColorUtils.colorWithLightness(Appearance.m3colors.m3primary, (root.dominantColorIsDark ? 0.8 : 0.12)) + property color colBackground: ColorUtils.transparentize(ColorUtils.mix(Appearance.colors.colPrimary, Appearance.colors.colSecondaryContainer), 1) + property color colText: ColorUtils.colorWithLightness(Appearance.colors.colPrimary, (root.dominantColorIsDark ? 0.8 : 0.12)) function updateWidgetPosition(fileContent) { // console.log("[BackgroundWidgets] Updating widget position with content:", fileContent) const parsedContent = JSON.parse(fileContent) root.centerX = parsedContent.center_x root.centerY = parsedContent.center_y - root.dominantColor = parsedContent.dominant_color || Appearance.m3colors.m3primary + root.dominantColor = parsedContent.dominant_color || Appearance.colors.colPrimary } Timer { diff --git a/.config/quickshell/modules/bar/Bar.qml b/.config/quickshell/modules/bar/Bar.qml index 88a605fe1..e9efa4b1c 100644 --- a/.config/quickshell/modules/bar/Bar.qml +++ b/.config/quickshell/modules/bar/Bar.qml @@ -24,7 +24,7 @@ Scope { Layout.bottomMargin: barHeight / 3 Layout.fillHeight: true implicitWidth: 1 - color: Appearance.m3colors.m3outlineVariant + color: Appearance.colors.colOutlineVariant } Variants { // For each monitor @@ -149,7 +149,7 @@ Scope { colBackground: barLeftSideMouseArea.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1) colBackgroundHover: Appearance.colors.colLayer1Hover colRipple: Appearance.colors.colLayer1Active - colBackgroundToggled: Appearance.m3colors.m3secondaryContainer + colBackgroundToggled: Appearance.colors.colSecondaryContainer colBackgroundToggledHover: Appearance.colors.colSecondaryContainerHover colRippleToggled: Appearance.colors.colSecondaryContainerActive toggled: GlobalStates.sidebarLeftOpen @@ -346,7 +346,7 @@ Scope { colBackground: barRightSideMouseArea.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1) colBackgroundHover: Appearance.colors.colLayer1Hover colRipple: Appearance.colors.colLayer1Active - colBackgroundToggled: Appearance.m3colors.m3secondaryContainer + colBackgroundToggled: Appearance.colors.colSecondaryContainer colBackgroundToggledHover: Appearance.colors.colSecondaryContainerHover colRippleToggled: Appearance.colors.colSecondaryContainerActive toggled: GlobalStates.sidebarRightOpen diff --git a/.config/quickshell/modules/bar/BatteryIndicator.qml b/.config/quickshell/modules/bar/BatteryIndicator.qml index 74cdf0169..271cd8c28 100644 --- a/.config/quickshell/modules/bar/BatteryIndicator.qml +++ b/.config/quickshell/modules/bar/BatteryIndicator.qml @@ -48,7 +48,7 @@ Rectangle { lineWidth: 2 value: percentage size: 26 - secondaryColor: (isLow && !isCharging) ? batteryLowBackground : Appearance.m3colors.m3secondaryContainer + secondaryColor: (isLow && !isCharging) ? batteryLowBackground : Appearance.colors.colSecondaryContainer primaryColor: (isLow && !isCharging) ? batteryLowOnBackground : Appearance.m3colors.m3onSecondaryContainer fill: (isLow && !isCharging) diff --git a/.config/quickshell/modules/bar/Media.qml b/.config/quickshell/modules/bar/Media.qml index c59b6379d..d105ea203 100644 --- a/.config/quickshell/modules/bar/Media.qml +++ b/.config/quickshell/modules/bar/Media.qml @@ -62,7 +62,7 @@ Item { lineWidth: 2 value: activePlayer?.position / activePlayer?.length size: 26 - secondaryColor: Appearance.m3colors.m3secondaryContainer + secondaryColor: Appearance.colors.colSecondaryContainer primaryColor: Appearance.m3colors.m3onSecondaryContainer MaterialSymbol { diff --git a/.config/quickshell/modules/bar/Resource.qml b/.config/quickshell/modules/bar/Resource.qml index 18fdcba42..2b2dd0b60 100644 --- a/.config/quickshell/modules/bar/Resource.qml +++ b/.config/quickshell/modules/bar/Resource.qml @@ -23,7 +23,7 @@ Item { lineWidth: 2 value: percentage size: 26 - secondaryColor: Appearance.m3colors.m3secondaryContainer + secondaryColor: Appearance.colors.colSecondaryContainer primaryColor: Appearance.m3colors.m3onSecondaryContainer MaterialSymbol { diff --git a/.config/quickshell/modules/bar/Workspaces.qml b/.config/quickshell/modules/bar/Workspaces.qml index cb3c6551a..b95526375 100644 --- a/.config/quickshell/modules/bar/Workspaces.qml +++ b/.config/quickshell/modules/bar/Workspaces.qml @@ -109,7 +109,7 @@ Item { topRightRadius: radiusRight bottomRightRadius: radiusRight - color: ColorUtils.transparentize(Appearance.m3colors.m3secondaryContainer, 0.4) + color: ColorUtils.transparentize(Appearance.colors.colSecondaryContainer, 0.4) opacity: (workspaceOccupied[index] && !(!activeWindow?.activated && monitor.activeWorkspace?.id === index+1)) ? 1 : 0 Behavior on opacity { diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index a984b9e4f..97a8502ff 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -15,11 +15,11 @@ Singleton { property QtObject sizes property string syntaxHighlightingTheme - // [!] Enabling transparency can affect readability when using light theme. + // Extremely conservative transparency values for consistency and readability property real transparency: 0 property real contentTransparency: 0 - // property real transparency: 0.15 - // property real contentTransparency: 0.5 + // property real transparency: m3colors.darkmode ? 0.05 : 0 + // property real contentTransparency: m3colors.darkmode ? 0.18 : 0 m3colors: QtObject { property bool darkmode: false @@ -106,10 +106,10 @@ Singleton { property color colOnLayer0: m3colors.m3onBackground property color colLayer0Hover: ColorUtils.transparentize(ColorUtils.mix(colLayer0, colOnLayer0, 0.9, root.contentTransparency)) property color colLayer0Active: ColorUtils.transparentize(ColorUtils.mix(colLayer0, colOnLayer0, 0.8, root.contentTransparency)) - property color colLayer1: ColorUtils.transparentize(ColorUtils.mix(m3colors.m3surfaceContainerLow, m3colors.m3background, 0.7), root.contentTransparency); + property color colLayer1: ColorUtils.transparentize(ColorUtils.mix(m3colors.m3surfaceContainerLow, m3colors.m3background, 0.8), root.contentTransparency); property color colOnLayer1: m3colors.m3onSurfaceVariant; property color colOnLayer1Inactive: ColorUtils.mix(colOnLayer1, colLayer1, 0.45); - property color colLayer2: ColorUtils.transparentize(ColorUtils.mix(m3colors.m3surfaceContainer, m3colors.m3surfaceContainerHigh, 0.55), root.contentTransparency) + property color colLayer2: ColorUtils.transparentize(ColorUtils.mix(m3colors.m3surfaceContainer, m3colors.m3surfaceContainerHigh, 0.7), root.contentTransparency) property color colOnLayer2: m3colors.m3onSurface; property color colOnLayer2Disabled: ColorUtils.mix(colOnLayer2, m3colors.m3background, 0.4); property color colLayer3: ColorUtils.transparentize(ColorUtils.mix(m3colors.m3surfaceContainerHigh, m3colors.m3onSurface, 0.96), root.contentTransparency) @@ -127,16 +127,23 @@ Singleton { property color colPrimaryContainer: m3colors.m3primaryContainer property color colPrimaryContainerHover: ColorUtils.mix(colors.colPrimaryContainer, colLayer1Hover, 0.7) property color colPrimaryContainerActive: ColorUtils.mix(colors.colPrimaryContainer, colLayer1Active, 0.6) + property color colSecondary: m3colors.m3secondary property color colSecondaryHover: ColorUtils.mix(m3colors.m3secondary, colLayer1Hover, 0.85) property color colSecondaryActive: ColorUtils.mix(m3colors.m3secondary, colLayer1Active, 0.4) + property color colSecondaryContainer: ColorUtils.transparentize(m3colors.m3secondaryContainer, root.contentTransparency) property color colSecondaryContainerHover: ColorUtils.mix(m3colors.m3secondaryContainer, colLayer1Hover, 0.6) property color colSecondaryContainerActive: ColorUtils.mix(m3colors.m3secondaryContainer, colLayer1Active, 0.54) + property color colSurfaceContainerLow: ColorUtils.transparentize(m3colors.m3surfaceContainerLow, root.contentTransparency) + property color colSurfaceContainer: ColorUtils.transparentize(m3colors.m3surfaceContainer, root.contentTransparency) + property color colSurfaceContainerHigh: ColorUtils.transparentize(m3colors.m3surfaceContainerHigh, root.contentTransparency) + property color colSurfaceContainerHighest: ColorUtils.transparentize(m3colors.m3surfaceContainerHighest, root.contentTransparency) property color colSurfaceContainerHighestHover: ColorUtils.mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.95) property color colSurfaceContainerHighestActive: ColorUtils.mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.85) property color colTooltip: m3colors.darkmode ? ColorUtils.mix(m3colors.m3background, "#3C4043", 0.5) : "#3C4043" // m3colors.m3inverseSurface in the specs, but the m3 website actually uses #3C4043 property color colOnTooltip: "#F8F9FA" // m3colors.m3inverseOnSurface in the specs, but the m3 website actually uses this color property color colScrim: ColorUtils.transparentize(m3colors.m3scrim, 0.5) property color colShadow: ColorUtils.transparentize(m3colors.m3shadow, 0.7) + property color colOutlineVariant: m3colors.m3outlineVariant } rounding: QtObject { diff --git a/.config/quickshell/modules/common/widgets/CircularProgress.qml b/.config/quickshell/modules/common/widgets/CircularProgress.qml index d0afc6060..c3731e64e 100644 --- a/.config/quickshell/modules/common/widgets/CircularProgress.qml +++ b/.config/quickshell/modules/common/widgets/CircularProgress.qml @@ -14,7 +14,7 @@ Item { property int lineWidth: 2 property real value: 0 property color primaryColor: Appearance.m3colors.m3onSecondaryContainer - property color secondaryColor: Appearance.m3colors.m3secondaryContainer + property color secondaryColor: Appearance.colors.colSecondaryContainer property real gapAngle: Math.PI / 9 property bool fill: false property int fillOverflow: 2 diff --git a/.config/quickshell/modules/common/widgets/KeyboardKey.qml b/.config/quickshell/modules/common/widgets/KeyboardKey.qml index d6ba5ba08..0cc80429e 100644 --- a/.config/quickshell/modules/common/widgets/KeyboardKey.qml +++ b/.config/quickshell/modules/common/widgets/KeyboardKey.qml @@ -15,7 +15,7 @@ Rectangle { property real extraBottomBorderWidth: 2 property color borderColor: Appearance.colors.colOnLayer0 property real borderRadius: 5 - property color keyColor: Appearance.m3colors.m3surfaceContainerLow + property color keyColor: Appearance.colors.colSurfaceContainerLow implicitWidth: keyFace.implicitWidth + borderWidth * 2 implicitHeight: keyFace.implicitHeight + borderWidth * 2 + extraBottomBorderWidth radius: borderRadius diff --git a/.config/quickshell/modules/common/widgets/NavRailButton.qml b/.config/quickshell/modules/common/widgets/NavRailButton.qml index 1f55ad282..0a241553f 100644 --- a/.config/quickshell/modules/common/widgets/NavRailButton.qml +++ b/.config/quickshell/modules/common/widgets/NavRailButton.qml @@ -30,7 +30,7 @@ Button { Layout.alignment: Qt.AlignHCenter radius: Appearance.rounding.full color: toggled ? - (button.down ? Appearance.colors.colSecondaryContainerActive : button.hovered ? Appearance.colors.colSecondaryContainerHover : Appearance.m3colors.m3secondaryContainer) : + (button.down ? Appearance.colors.colSecondaryContainerActive : button.hovered ? Appearance.colors.colSecondaryContainerHover : Appearance.colors.colSecondaryContainer) : (button.down ? Appearance.colors.colLayer1Active : button.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1)) Behavior on color { diff --git a/.config/quickshell/modules/common/widgets/NotificationActionButton.qml b/.config/quickshell/modules/common/widgets/NotificationActionButton.qml index 370814f91..e85735a71 100644 --- a/.config/quickshell/modules/common/widgets/NotificationActionButton.qml +++ b/.config/quickshell/modules/common/widgets/NotificationActionButton.qml @@ -15,7 +15,7 @@ RippleButton { leftPadding: 15 rightPadding: 15 buttonRadius: Appearance.rounding.small - colBackground: (urgency == NotificationUrgency.Critical) ? Appearance.m3colors.m3secondaryContainer : Appearance.m3colors.m3surfaceContainerHighest + colBackground: (urgency == NotificationUrgency.Critical) ? Appearance.colors.colSecondaryContainer : Appearance.colors.colSurfaceContainerHighest colBackgroundHover: (urgency == NotificationUrgency.Critical) ? Appearance.colors.colSecondaryContainerHover : Appearance.colors.colSurfaceContainerHighestHover colRipple: (urgency == NotificationUrgency.Critical) ? Appearance.colors.colSecondaryContainerActive : Appearance.colors.colSurfaceContainerHighestActive diff --git a/.config/quickshell/modules/common/widgets/NotificationAppIcon.qml b/.config/quickshell/modules/common/widgets/NotificationAppIcon.qml index 371093b25..81505aff6 100644 --- a/.config/quickshell/modules/common/widgets/NotificationAppIcon.qml +++ b/.config/quickshell/modules/common/widgets/NotificationAppIcon.qml @@ -26,7 +26,7 @@ Rectangle { // App icon implicitWidth: size implicitHeight: size radius: Appearance.rounding.full - color: Appearance.m3colors.m3secondaryContainer + color: Appearance.colors.colSecondaryContainer Loader { id: materialSymbolLoader active: root.appIcon == "" diff --git a/.config/quickshell/modules/common/widgets/NotificationGroup.qml b/.config/quickshell/modules/common/widgets/NotificationGroup.qml index cfe93327c..e79f400ae 100644 --- a/.config/quickshell/modules/common/widgets/NotificationGroup.qml +++ b/.config/quickshell/modules/common/widgets/NotificationGroup.qml @@ -113,7 +113,7 @@ Item { // Notification group area id: background anchors.left: parent.left width: parent.width - color: Appearance.m3colors.m3surfaceContainer + color: Appearance.colors.colSurfaceContainer radius: Appearance.rounding.normal anchors.leftMargin: root.xOffset diff --git a/.config/quickshell/modules/common/widgets/NotificationItem.qml b/.config/quickshell/modules/common/widgets/NotificationItem.qml index 26286290c..9a2a7c31d 100644 --- a/.config/quickshell/modules/common/widgets/NotificationItem.qml +++ b/.config/quickshell/modules/common/widgets/NotificationItem.qml @@ -129,9 +129,9 @@ Item { // Notification item area color: (expanded && !onlyNotification) ? (notificationObject.urgency == NotificationUrgency.Critical) ? - ColorUtils.mix(Appearance.m3colors.m3secondaryContainer, Appearance.colors.colLayer2, 0.35) : - (Appearance.m3colors.m3surfaceContainerHigh) : - ColorUtils.transparentize(Appearance.m3colors.m3surfaceContainerHighest) + ColorUtils.mix(Appearance.colors.colSecondaryContainer, Appearance.colors.colLayer2, 0.35) : + (Appearance.colors.colSurfaceContainerHigh) : + ColorUtils.transparentize(Appearance.colors.colSurfaceContainerHighest) implicitHeight: expanded ? (contentColumn.implicitHeight + padding * 2) : summaryRow.implicitHeight Behavior on implicitHeight { diff --git a/.config/quickshell/modules/common/widgets/SelectionDialog.qml b/.config/quickshell/modules/common/widgets/SelectionDialog.qml index affd13bc9..9cf0940ed 100644 --- a/.config/quickshell/modules/common/widgets/SelectionDialog.qml +++ b/.config/quickshell/modules/common/widgets/SelectionDialog.qml @@ -34,7 +34,7 @@ Item { Rectangle { // The dialog id: dialog - color: Appearance.m3colors.m3surfaceContainerHigh + color: Appearance.colors.colSurfaceContainerHigh radius: Appearance.rounding.normal anchors.fill: parent anchors.margins: dialogMargin diff --git a/.config/quickshell/modules/common/widgets/StyledSlider.qml b/.config/quickshell/modules/common/widgets/StyledSlider.qml index 70491b8bb..ca0980030 100644 --- a/.config/quickshell/modules/common/widgets/StyledSlider.qml +++ b/.config/quickshell/modules/common/widgets/StyledSlider.qml @@ -19,7 +19,7 @@ Slider { property real handleLimit: root.backgroundDotMargins property real trackHeight: 30 * scale property color highlightColor: Appearance.colors.colPrimary - property color trackColor: Appearance.m3colors.m3secondaryContainer + property color trackColor: Appearance.colors.colSecondaryContainer property color handleColor: Appearance.m3colors.m3onSecondaryContainer property real trackRadius: Appearance.rounding.verysmall * scale property real unsharpenRadius: Appearance.rounding.unsharpen diff --git a/.config/quickshell/modules/common/widgets/StyledSwitch.qml b/.config/quickshell/modules/common/widgets/StyledSwitch.qml index bbc2ae513..217a2f7e4 100644 --- a/.config/quickshell/modules/common/widgets/StyledSwitch.qml +++ b/.config/quickshell/modules/common/widgets/StyledSwitch.qml @@ -13,7 +13,7 @@ Switch { implicitHeight: 32 * root.scale implicitWidth: 52 * root.scale property color activeColor: Appearance?.colors.colPrimary ?? "#685496" - property color inactiveColor: Appearance?.m3colors.m3surfaceContainerHighest ?? "#45464F" + property color inactiveColor: Appearance?.colors.colSurfaceContainerHighest ?? "#45464F" PointingHandInteraction {} diff --git a/.config/quickshell/modules/common/widgets/StyledTextArea.qml b/.config/quickshell/modules/common/widgets/StyledTextArea.qml index 1ea9a349a..67d417576 100644 --- a/.config/quickshell/modules/common/widgets/StyledTextArea.qml +++ b/.config/quickshell/modules/common/widgets/StyledTextArea.qml @@ -5,7 +5,7 @@ import QtQuick.Controls TextArea { renderType: Text.NativeRendering selectedTextColor: Appearance.m3colors.m3onSecondaryContainer - selectionColor: Appearance.m3colors.m3secondaryContainer + selectionColor: Appearance.colors.colSecondaryContainer placeholderTextColor: Appearance.m3colors.m3outline font { family: Appearance?.font.family.main ?? "sans-serif" diff --git a/.config/quickshell/modules/dock/DockAppButton.qml b/.config/quickshell/modules/dock/DockAppButton.qml index 5ddb6d150..f4623e625 100644 --- a/.config/quickshell/modules/dock/DockAppButton.qml +++ b/.config/quickshell/modules/dock/DockAppButton.qml @@ -106,7 +106,7 @@ DockButton { implicitWidth: (appToplevel.toplevels.length <= 3) ? root.countDotWidth : root.countDotHeight // Circles when too many implicitHeight: root.countDotHeight - color: appIsActive ? Appearance.m3colors.m3primary : ColorUtils.transparentize(Appearance.colors.colOnLayer0, 0.4) + color: appIsActive ? Appearance.colors.colPrimary : ColorUtils.transparentize(Appearance.colors.colOnLayer0, 0.4) } } } diff --git a/.config/quickshell/modules/dock/DockApps.qml b/.config/quickshell/modules/dock/DockApps.qml index 8b680c51a..ffda024c7 100644 --- a/.config/quickshell/modules/dock/DockApps.qml +++ b/.config/quickshell/modules/dock/DockApps.qml @@ -166,7 +166,7 @@ Item { animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } clip: true - color: Appearance.m3colors.m3surfaceContainer + color: Appearance.colors.colSurfaceContainer radius: Appearance.rounding.normal anchors.bottom: parent.bottom anchors.bottomMargin: Appearance.sizes.elevationMargin @@ -205,7 +205,7 @@ Item { contentWidth: parent.width - anchors.margins * 2 WrapperRectangle { Layout.fillWidth: true - color: ColorUtils.transparentize(Appearance.m3colors.m3surfaceContainer) + color: ColorUtils.transparentize(Appearance.colors.colSurfaceContainer) radius: Appearance.rounding.small margin: 5 StyledText { @@ -218,7 +218,7 @@ Item { } GroupButton { id: closeButton - colBackground: ColorUtils.transparentize(Appearance.m3colors.m3surfaceContainer) + colBackground: ColorUtils.transparentize(Appearance.colors.colSurfaceContainer) baseWidth: windowControlsHeight baseHeight: windowControlsHeight buttonRadius: Appearance.rounding.full diff --git a/.config/quickshell/modules/dock/DockSeparator.qml b/.config/quickshell/modules/dock/DockSeparator.qml index 29b77d492..abb45d1da 100644 --- a/.config/quickshell/modules/dock/DockSeparator.qml +++ b/.config/quickshell/modules/dock/DockSeparator.qml @@ -9,5 +9,5 @@ Rectangle { Layout.bottomMargin: Appearance.sizes.hyprlandGapsOut + dockRow.padding + Appearance.rounding.normal Layout.fillHeight: true implicitWidth: 1 - color: Appearance.m3colors.m3outlineVariant + color: Appearance.colors.colOutlineVariant } diff --git a/.config/quickshell/modules/onScreenKeyboard/OnScreenKeyboard.qml b/.config/quickshell/modules/onScreenKeyboard/OnScreenKeyboard.qml index 39862c55f..e78f45b2e 100644 --- a/.config/quickshell/modules/onScreenKeyboard/OnScreenKeyboard.qml +++ b/.config/quickshell/modules/onScreenKeyboard/OnScreenKeyboard.qml @@ -111,7 +111,7 @@ Scope { // Scope Layout.bottomMargin: 20 Layout.fillHeight: true implicitWidth: 1 - color: Appearance.m3colors.m3outlineVariant + color: Appearance.colors.colOutlineVariant } OskContent { id: oskContent diff --git a/.config/quickshell/modules/overview/OverviewWidget.qml b/.config/quickshell/modules/overview/OverviewWidget.qml index 1a9494938..9ab39fd02 100644 --- a/.config/quickshell/modules/overview/OverviewWidget.qml +++ b/.config/quickshell/modules/overview/OverviewWidget.qml @@ -25,7 +25,7 @@ Item { property var windowAddresses: HyprlandData.addresses property var monitorData: HyprlandData.monitors.find(m => m.id === root.monitor.id) property real scale: ConfigOptions.overview.scale - property color activeBorderColor: Appearance.m3colors.m3secondary + property color activeBorderColor: Appearance.colors.colSecondary property real workspaceImplicitWidth: (monitorData?.transform % 2 === 1) ? ((monitor.height - monitorData?.reserved[0] - monitorData?.reserved[2]) * root.scale / monitor.scale) : diff --git a/.config/quickshell/modules/overview/SearchItem.qml b/.config/quickshell/modules/overview/SearchItem.qml index 00d5da743..d23cb4c09 100644 --- a/.config/quickshell/modules/overview/SearchItem.qml +++ b/.config/quickshell/modules/overview/SearchItem.qml @@ -80,7 +80,7 @@ RippleButton { buttonRadius: Appearance.rounding.normal colBackground: (root.down || root.keyboardDown) ? Appearance.colors.colLayer1Active : ((root.hovered || root.focus) ? Appearance.colors.colLayer1Hover : - ColorUtils.transparentize(Appearance.m3colors.m3surfaceContainerHigh, 1)) + ColorUtils.transparentize(Appearance.colors.colSurfaceContainerHigh, 1)) colBackgroundHover: Appearance.colors.colLayer1Hover colRipple: Appearance.colors.colLayer1Active diff --git a/.config/quickshell/modules/overview/SearchWidget.qml b/.config/quickshell/modules/overview/SearchWidget.qml index ea8dcb3b9..9e6866240 100644 --- a/.config/quickshell/modules/overview/SearchWidget.qml +++ b/.config/quickshell/modules/overview/SearchWidget.qml @@ -219,7 +219,7 @@ Item { // Wrapper } color: activeFocus ? Appearance.m3colors.m3onSurface : Appearance.m3colors.m3onSurfaceVariant selectedTextColor: Appearance.m3colors.m3onSecondaryContainer - selectionColor: Appearance.m3colors.m3secondaryContainer + selectionColor: Appearance.colors.colSecondaryContainer placeholderText: qsTr("Search, calculate or run") placeholderTextColor: Appearance.m3colors.m3outline implicitWidth: root.searchingText == "" ? Appearance.sizes.searchWidthCollapsed : Appearance.sizes.searchWidth @@ -260,7 +260,7 @@ Item { // Wrapper visible: root.showResults Layout.fillWidth: true height: 1 - color: Appearance.m3colors.m3outlineVariant + color: Appearance.colors.colOutlineVariant } ListView { // App results diff --git a/.config/quickshell/modules/session/SessionActionButton.qml b/.config/quickshell/modules/session/SessionActionButton.qml index 207305769..becda60c1 100644 --- a/.config/quickshell/modules/session/SessionActionButton.qml +++ b/.config/quickshell/modules/session/SessionActionButton.qml @@ -18,7 +18,7 @@ RippleButton { buttonRadius: (button.focus || button.down) ? size / 2 : Appearance.rounding.verylarge colBackground: button.keyboardDown ? Appearance.colors.colSecondaryContainerActive : button.focus ? Appearance.colors.colPrimary : - Appearance.m3colors.m3secondaryContainer + Appearance.colors.colSecondaryContainer colBackgroundHover: Appearance.colors.colPrimary colRipple: Appearance.colors.colPrimaryActive property color colText: (button.down || button.keyboardDown || button.focus || button.hovered) ? diff --git a/.config/quickshell/modules/sidebarLeft/AiChat.qml b/.config/quickshell/modules/sidebarLeft/AiChat.qml index 9ba1d3688..1ce752c7b 100644 --- a/.config/quickshell/modules/sidebarLeft/AiChat.qml +++ b/.config/quickshell/modules/sidebarLeft/AiChat.qml @@ -345,7 +345,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\) implicitHeight: Math.max(inputFieldRowLayout.implicitHeight + inputFieldRowLayout.anchors.topMargin + commandButtonsRow.implicitHeight + commandButtonsRow.anchors.bottomMargin + columnSpacing, 45) clip: true - border.color: Appearance.m3colors.m3outlineVariant + border.color: Appearance.colors.colOutlineVariant border.width: 1 Behavior on implicitHeight { diff --git a/.config/quickshell/modules/sidebarLeft/Anime.qml b/.config/quickshell/modules/sidebarLeft/Anime.qml index 444d3f052..1300d5482 100644 --- a/.config/quickshell/modules/sidebarLeft/Anime.qml +++ b/.config/quickshell/modules/sidebarLeft/Anime.qml @@ -359,7 +359,7 @@ Item { implicitHeight: Math.max(inputFieldRowLayout.implicitHeight + inputFieldRowLayout.anchors.topMargin + commandButtonsRow.implicitHeight + commandButtonsRow.anchors.bottomMargin + columnSpacing, 45) clip: true - border.color: Appearance.m3colors.m3outlineVariant + border.color: Appearance.colors.colOutlineVariant border.width: 1 Behavior on implicitHeight { diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml b/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml index 775d12082..8d7952110 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/AiMessage.qml @@ -91,7 +91,7 @@ Rectangle { Rectangle { // Name id: nameWrapper - color: Appearance.m3colors.m3secondaryContainer + color: Appearance.colors.colSecondaryContainer // color: "transparent" radius: Appearance.rounding.small implicitHeight: Math.max(nameRowLayout.implicitHeight + 5 * 2, 30) diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/AnnotationSourceButton.qml b/.config/quickshell/modules/sidebarLeft/aiChat/AnnotationSourceButton.qml index f344308ca..a253a291e 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/AnnotationSourceButton.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/AnnotationSourceButton.qml @@ -21,7 +21,7 @@ RippleButton { leftPadding: (implicitHeight - faviconSize) / 2 rightPadding: 10 buttonRadius: Appearance.rounding.full - colBackground: Appearance.m3colors.m3surfaceContainerHighest + colBackground: Appearance.colors.colSurfaceContainerHighest colBackgroundHover: Appearance.colors.colSurfaceContainerHighestHover colRipple: Appearance.colors.colSurfaceContainerHighestActive diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml b/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml index ef0c1b5e9..ea7bb0ee3 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/MessageCodeBlock.qml @@ -40,7 +40,7 @@ ColumnLayout { topRightRadius: codeBlockBackgroundRounding bottomLeftRadius: Appearance.rounding.unsharpen bottomRightRadius: Appearance.rounding.unsharpen - color: Appearance.m3colors.m3surfaceContainerHighest + color: Appearance.colors.colSurfaceContainerHighest implicitHeight: codeBlockTitleBarRowLayout.implicitHeight + codeBlockHeaderPadding * 2 RowLayout { // Language and buttons @@ -209,7 +209,7 @@ ColumnLayout { font.hintingPreference: Font.PreferNoHinting // Prevent weird bold text font.pixelSize: Appearance.font.pixelSize.small selectedTextColor: Appearance.m3colors.m3onSecondaryContainer - selectionColor: Appearance.m3colors.m3secondaryContainer + selectionColor: Appearance.colors.colSecondaryContainer // wrapMode: TextEdit.Wrap color: messageData.thinking ? Appearance.colors.colSubtext : Appearance.colors.colOnLayer1 diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml b/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml index 25ecb05a6..faa6c5590 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/MessageTextBlock.qml @@ -120,7 +120,7 @@ ColumnLayout { font.hintingPreference: Font.PreferNoHinting // Prevent weird bold text font.pixelSize: Appearance.font.pixelSize.small selectedTextColor: Appearance.m3colors.m3onSecondaryContainer - selectionColor: Appearance.m3colors.m3secondaryContainer + selectionColor: Appearance.colors.colSecondaryContainer wrapMode: TextEdit.Wrap color: messageData.thinking ? Appearance.colors.colSubtext : Appearance.colors.colOnLayer1 textFormat: renderMarkdown ? TextEdit.MarkdownText : TextEdit.PlainText diff --git a/.config/quickshell/modules/sidebarLeft/aiChat/MessageThinkBlock.qml b/.config/quickshell/modules/sidebarLeft/aiChat/MessageThinkBlock.qml index 27dae3bd3..1ae941b78 100644 --- a/.config/quickshell/modules/sidebarLeft/aiChat/MessageThinkBlock.qml +++ b/.config/quickshell/modules/sidebarLeft/aiChat/MessageThinkBlock.qml @@ -64,7 +64,7 @@ Item { Rectangle { // Header background id: header - color: Appearance.m3colors.m3surfaceContainerHighest + color: Appearance.colors.colSurfaceContainerHighest Layout.fillWidth: true implicitHeight: thinkBlockTitleBarRowLayout.implicitHeight + thinkBlockHeaderPaddingVertical * 2 diff --git a/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml b/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml index c8c89f72a..4e115bc76 100644 --- a/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml +++ b/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml @@ -133,7 +133,7 @@ Button { opacity: root.showActions ? 1 : 0 visible: opacity > 0 radius: Appearance.rounding.small - color: Appearance.m3colors.m3surfaceContainer + color: Appearance.colors.colSurfaceContainer implicitHeight: contextMenuColumnLayout.implicitHeight + radius * 2 implicitWidth: contextMenuColumnLayout.implicitWidth diff --git a/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml b/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml index c19c8bb98..7a207582f 100644 --- a/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml +++ b/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml @@ -67,7 +67,7 @@ Rectangle { RowLayout { // Header Rectangle { // Provider name id: providerNameWrapper - color: Appearance.m3colors.m3secondaryContainer + color: Appearance.colors.colSecondaryContainer radius: Appearance.rounding.small implicitWidth: providerName.implicitWidth + 10 * 2 implicitHeight: Math.max(providerName.implicitHeight + 5 * 2, 30) @@ -269,7 +269,7 @@ Rectangle { } buttonRadius: Appearance.rounding.small - colBackground: Appearance.m3colors.m3surfaceContainerHighest + colBackground: Appearance.colors.colSurfaceContainerHighest colBackgroundHover: Appearance.colors.colSurfaceContainerHighestHover colRipple: Appearance.colors.colSurfaceContainerHighestActive diff --git a/.config/quickshell/modules/sidebarLeft/translator/TextCanvas.qml b/.config/quickshell/modules/sidebarLeft/translator/TextCanvas.qml index 7f32a63d9..dad25020f 100644 --- a/.config/quickshell/modules/sidebarLeft/translator/TextCanvas.qml +++ b/.config/quickshell/modules/sidebarLeft/translator/TextCanvas.qml @@ -21,9 +21,9 @@ Rectangle { default property alias actionButtons: actions.data Layout.fillWidth: true implicitHeight: Math.max(150, inputColumn.implicitHeight) - color: isInput ? Appearance.colors.colLayer1 : Appearance.m3colors.m3surfaceContainer + color: isInput ? Appearance.colors.colLayer1 : Appearance.colors.colSurfaceContainer radius: Appearance.rounding.normal - border.color: isInput ? Appearance.m3colors.m3outlineVariant : "transparent" + border.color: isInput ? Appearance.colors.colOutlineVariant : "transparent" border.width: isInput ? 1 : 0 signal inputTextChanged(); // Signal emitted when text changes diff --git a/.config/quickshell/modules/sidebarRight/calendar/CalendarDayButton.qml b/.config/quickshell/modules/sidebarRight/calendar/CalendarDayButton.qml index 88de9202c..7d1af447d 100644 --- a/.config/quickshell/modules/sidebarRight/calendar/CalendarDayButton.qml +++ b/.config/quickshell/modules/sidebarRight/calendar/CalendarDayButton.qml @@ -26,7 +26,7 @@ RippleButton { font.weight: bold ? Font.DemiBold : Font.Normal color: (isToday == 1) ? Appearance.m3colors.m3onPrimary : (isToday == 0) ? Appearance.colors.colOnLayer1 : - Appearance.m3colors.m3outlineVariant + Appearance.colors.colOutlineVariant Behavior on color { animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this) diff --git a/.config/quickshell/modules/sidebarRight/todo/TodoWidget.qml b/.config/quickshell/modules/sidebarRight/todo/TodoWidget.qml index 527ed6978..9f5f4fd08 100644 --- a/.config/quickshell/modules/sidebarRight/todo/TodoWidget.qml +++ b/.config/quickshell/modules/sidebarRight/todo/TodoWidget.qml @@ -114,7 +114,7 @@ Item { id: tabBarBottomBorder Layout.fillWidth: true height: 1 - color: Appearance.m3colors.m3outlineVariant + color: Appearance.colors.colOutlineVariant } SwipeView { @@ -228,7 +228,7 @@ Item { anchors.margins: root.dialogMargins implicitHeight: dialogColumnLayout.implicitHeight - color: Appearance.m3colors.m3surfaceContainerHigh + color: Appearance.colors.colSurfaceContainerHigh radius: Appearance.rounding.normal function addTask() { @@ -264,7 +264,7 @@ Item { color: activeFocus ? Appearance.m3colors.m3onSurface : Appearance.m3colors.m3onSurfaceVariant renderType: Text.NativeRendering selectedTextColor: Appearance.m3colors.m3onSecondaryContainer - selectionColor: Appearance.m3colors.m3secondaryContainer + selectionColor: Appearance.colors.colSecondaryContainer placeholderText: qsTr("Task description") placeholderTextColor: Appearance.m3colors.m3outline focus: root.showAddDialog diff --git a/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml b/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml index 1799df556..2e1570f30 100644 --- a/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml +++ b/.config/quickshell/modules/sidebarRight/volumeMixer/VolumeMixer.qml @@ -161,7 +161,7 @@ Item { Rectangle { // The dialog id: dialog - color: Appearance.m3colors.m3surfaceContainerHigh + color: Appearance.colors.colSurfaceContainerHigh radius: Appearance.rounding.normal anchors.left: parent.left anchors.right: parent.right From 89ff743c5dd916e13aa20eac13c0522bc4e7055e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 12 Jun 2025 07:43:52 +0200 Subject: [PATCH 88/89] Appearance: more m3colors in colors --- .config/quickshell/modules/bar/Workspaces.qml | 2 +- .config/quickshell/modules/common/Appearance.qml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.config/quickshell/modules/bar/Workspaces.qml b/.config/quickshell/modules/bar/Workspaces.qml index b95526375..cb3c6551a 100644 --- a/.config/quickshell/modules/bar/Workspaces.qml +++ b/.config/quickshell/modules/bar/Workspaces.qml @@ -109,7 +109,7 @@ Item { topRightRadius: radiusRight bottomRightRadius: radiusRight - color: ColorUtils.transparentize(Appearance.colors.colSecondaryContainer, 0.4) + color: ColorUtils.transparentize(Appearance.m3colors.m3secondaryContainer, 0.4) opacity: (workspaceOccupied[index] && !(!activeWindow?.activated && monitor.activeWorkspace?.id === index+1)) ? 1 : 0 Behavior on opacity { diff --git a/.config/quickshell/modules/common/Appearance.qml b/.config/quickshell/modules/common/Appearance.qml index 97a8502ff..49e9576bd 100644 --- a/.config/quickshell/modules/common/Appearance.qml +++ b/.config/quickshell/modules/common/Appearance.qml @@ -122,6 +122,7 @@ Singleton { property color colLayer3Hover: ColorUtils.transparentize(ColorUtils.mix(colLayer3, colOnLayer3, 0.90), root.contentTransparency) property color colLayer3Active: ColorUtils.transparentize(ColorUtils.mix(colLayer3, colOnLayer3, 0.80), root.contentTransparency); property color colPrimary: m3colors.m3primary + property color colOnPrimary: m3colors.m3onPrimary property color colPrimaryHover: ColorUtils.mix(colors.colPrimary, colLayer1Hover, 0.87) property color colPrimaryActive: ColorUtils.mix(colors.colPrimary, colLayer1Active, 0.7) property color colPrimaryContainer: m3colors.m3primaryContainer @@ -133,6 +134,7 @@ Singleton { property color colSecondaryContainer: ColorUtils.transparentize(m3colors.m3secondaryContainer, root.contentTransparency) property color colSecondaryContainerHover: ColorUtils.mix(m3colors.m3secondaryContainer, colLayer1Hover, 0.6) property color colSecondaryContainerActive: ColorUtils.mix(m3colors.m3secondaryContainer, colLayer1Active, 0.54) + property color colOnSecondaryContainer: m3colors.m3onSecondaryContainer property color colSurfaceContainerLow: ColorUtils.transparentize(m3colors.m3surfaceContainerLow, root.contentTransparency) property color colSurfaceContainer: ColorUtils.transparentize(m3colors.m3surfaceContainer, root.contentTransparency) property color colSurfaceContainerHigh: ColorUtils.transparentize(m3colors.m3surfaceContainerHigh, root.contentTransparency) From 13bad429bc5d5f9938164f62c4c2d0b9e2300f9c Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 12 Jun 2025 07:44:03 +0200 Subject: [PATCH 89/89] refractor visualizer to its own file --- .../modules/common/widgets/WaveVisualizer.qml | 78 +++++++++++++++++++ .../modules/mediaControls/PlayerControl.qml | 65 ++-------------- 2 files changed, 84 insertions(+), 59 deletions(-) create mode 100644 .config/quickshell/modules/common/widgets/WaveVisualizer.qml diff --git a/.config/quickshell/modules/common/widgets/WaveVisualizer.qml b/.config/quickshell/modules/common/widgets/WaveVisualizer.qml new file mode 100644 index 000000000..eb579d7e1 --- /dev/null +++ b/.config/quickshell/modules/common/widgets/WaveVisualizer.qml @@ -0,0 +1,78 @@ +import "root:/modules/common" +import "root:/modules/common/widgets" +import "root:/services" +import "root:/modules/common/functions/color_utils.js" as ColorUtils +import QtQuick +import QtQuick.Effects +import QtQuick.Layouts +import QtQuick.Controls +import Quickshell +import Quickshell.Io + +Canvas { // Visualizer + id: root + property list points + property list smoothPoints + property real maxVisualizerValue: 1000 + property int smoothing: 2 + property bool live: true + property color color: Appearance.m3colors.m3primary + + onPointsChanged: () => { + root.requestPaint() + } + + anchors.fill: parent + onPaint: { + var ctx = getContext("2d"); + ctx.clearRect(0, 0, width, height); + + var points = root.points; + var maxVal = root.maxVisualizerValue || 1; + var h = height; + var w = width; + var n = points.length; + if (n < 2) return; + + // Smoothing: simple moving average (optional) + var smoothWindow = root.smoothing; // adjust for more/less smoothing + root.smoothPoints = []; + for (var i = 0; i < n; ++i) { + var sum = 0, count = 0; + for (var j = -smoothWindow; j <= smoothWindow; ++j) { + var idx = Math.max(0, Math.min(n - 1, i + j)); + sum += points[idx]; + count++; + } + root.smoothPoints.push(sum / count); + } + if (!root.live) smoothedPoints.fill(0); // If not playing, show no points + + ctx.beginPath(); + ctx.moveTo(0, h); + for (var i = 0; i < n; ++i) { + var x = i * w / (n - 1); + var y = h - (root.smoothPoints[i] / maxVal) * h; + ctx.lineTo(x, y); + } + ctx.lineTo(w, h); + ctx.closePath(); + + ctx.fillStyle = Qt.rgba( + root.color.r, + root.color.g, + root.color.b, + 0.15 + ); + ctx.fill(); + } + + layer.enabled: true + layer.effect: MultiEffect { // Blur a bit to obscure away the points + source: root + saturation: 0.2 + blurEnabled: true + blurMax: 7 + blur: 1 + } +} \ No newline at end of file diff --git a/.config/quickshell/modules/mediaControls/PlayerControl.qml b/.config/quickshell/modules/mediaControls/PlayerControl.qml index fb4799e17..2100cc90c 100644 --- a/.config/quickshell/modules/mediaControls/PlayerControl.qml +++ b/.config/quickshell/modules/mediaControls/PlayerControl.qml @@ -153,67 +153,14 @@ Item { // Player instance } } - Canvas { // Visualizer + WaveVisualizer { id: visualizerCanvas anchors.fill: parent - onPaint: { - var ctx = getContext("2d"); - ctx.clearRect(0, 0, width, height); - - var points = playerController.visualizerPoints; - var maxVal = playerController.maxVisualizerValue || 1; - var h = height; - var w = width; - var n = points.length; - if (n < 2) return; - - // Smoothing: simple moving average (optional) - var smoothPoints = []; - var smoothWindow = playerController.visualizerSmoothing; // adjust for more/less smoothing - for (var i = 0; i < n; ++i) { - var sum = 0, count = 0; - for (var j = -smoothWindow; j <= smoothWindow; ++j) { - var idx = Math.max(0, Math.min(n - 1, i + j)); - sum += points[idx]; - count++; - } - smoothPoints.push(sum / count); - } - if (!playerController.player?.isPlaying) smoothedPoints.fill(0); // If not playing, show no points - - ctx.beginPath(); - ctx.moveTo(0, h); - for (var i = 0; i < n; ++i) { - var x = i * w / (n - 1); - var y = h - (smoothPoints[i] / maxVal) * h; - ctx.lineTo(x, y); - } - ctx.lineTo(w, h); - ctx.closePath(); - - ctx.fillStyle = Qt.rgba( - blendedColors.colPrimary.r, - blendedColors.colPrimary.g, - blendedColors.colPrimary.b, - 0.15 - ); - ctx.fill(); - } - Connections { - target: playerController - function onVisualizerPointsChanged() { - visualizerCanvas.requestPaint() - } - } - - layer.enabled: true - layer.effect: MultiEffect { // Blur a bit to obscure away the points - source: visualizerCanvas - saturation: 0.2 - blurEnabled: true - blurMax: 7 - blur: 1 - } + live: playerController.player?.isPlaying + points: playerController.visualizerPoints + maxVisualizerValue: playerController.maxVisualizerValue + smoothing: playerController.visualizerSmoothing + color: blendedColors.colPrimary } RowLayout {