From 549a43ac7f2ae8d60f6d1ce3896856295e94a650 Mon Sep 17 00:00:00 2001 From: marepallisanthosh999333 <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sat, 8 Nov 2025 20:29:14 +0530 Subject: [PATCH 01/85] feat: add sticky overlay functionality --- .../ii/modules/common/Directories.qml | 6 +- .../ii/modules/common/Persistent.qml | 8 + .../quickshell/ii/modules/overlay/Overlay.qml | 5 +- .../ii/modules/overlay/OverlayContext.qml | 5 +- .../overlay/OverlayWidgetDelegateChooser.qml | 6 + .../modules/overlay/stickypad/Stickypad.qml | 23 ++ .../overlay/stickypad/StickypadContent.qml | 363 ++++++++++++++++++ .../ii/modules/overlay/stickypad/qmldir | 4 + 8 files changed, 417 insertions(+), 3 deletions(-) create mode 100644 dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml create mode 100644 dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml create mode 100644 dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir diff --git a/dots/.config/quickshell/ii/modules/common/Directories.qml b/dots/.config/quickshell/ii/modules/common/Directories.qml index 59f3dab53..7f1694f45 100644 --- a/dots/.config/quickshell/ii/modules/common/Directories.qml +++ b/dots/.config/quickshell/ii/modules/common/Directories.qml @@ -31,7 +31,11 @@ Singleton { property string shellConfig: FileUtils.trimFileProtocol(`${Directories.config}/illogical-impulse`) property string shellConfigName: "config.json" property string shellConfigPath: `${Directories.shellConfig}/${Directories.shellConfigName}` - property string todoPath: FileUtils.trimFileProtocol(`${Directories.state}/user/todo.json`) + property string todoPath: FileUtils.trimFileProtocol(`${Directories.state}/user/todo.json`) + // CUSTOM: Stickypad integration - START + property string stickypadPath: FileUtils.trimFileProtocol(`${Directories.state}/user/stickypad.txt`) + // CUSTOM: Stickypad integration - END + property string conflictCachePath: FileUtils.trimFileProtocol(`${Directories.cache}/conflict-killer`) property string notificationsPath: FileUtils.trimFileProtocol(`${Directories.cache}/notifications/notifications.json`) property string generatedMaterialThemePath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/colors.json`) property string generatedWallpaperCategoryPath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/wallpaper/category.txt`) diff --git a/dots/.config/quickshell/ii/modules/common/Persistent.qml b/dots/.config/quickshell/ii/modules/common/Persistent.qml index 5848b1683..ee5d327cc 100644 --- a/dots/.config/quickshell/ii/modules/common/Persistent.qml +++ b/dots/.config/quickshell/ii/modules/common/Persistent.qml @@ -113,6 +113,14 @@ Singleton { property real x: 1576 property real y: 630 } + // CUSTOM: Stickypad integration - START + property JsonObject stickypad: JsonObject { + property bool pinned: true + property bool clickthrough: false + property real x: 100 + property real y: 100 + } + // CUSTOM: Stickypad integration - END } property JsonObject timer: JsonObject { diff --git a/dots/.config/quickshell/ii/modules/overlay/Overlay.qml b/dots/.config/quickshell/ii/modules/overlay/Overlay.qml index 71ba510c6..12e3d6b44 100644 --- a/dots/.config/quickshell/ii/modules/overlay/Overlay.qml +++ b/dots/.config/quickshell/ii/modules/overlay/Overlay.qml @@ -25,7 +25,10 @@ Scope { exclusionMode: ExclusionMode.Ignore WlrLayershell.namespace: "quickshell:overlay" WlrLayershell.layer: WlrLayer.Overlay - WlrLayershell.keyboardFocus: GlobalStates.overlayOpen ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None + // CUSTOM: Stickypad keyboard focus fix - START + // Use OnDemand for pinned widgets to allow focus switching with mouse clicks + WlrLayershell.keyboardFocus: GlobalStates.overlayOpen ? WlrKeyboardFocus.Exclusive : (OverlayContext.clickableWidgets.length > 0 ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None) + // CUSTOM: Stickypad keyboard focus fix - END visible: true color: "transparent" diff --git a/dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml b/dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml index b228deda6..4eed3e5b5 100644 --- a/dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml +++ b/dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml @@ -10,7 +10,10 @@ Singleton { { identifier: "volumeMixer", materialSymbol: "volume_up" }, { identifier: "crosshair", materialSymbol: "point_scan" }, { identifier: "fpsLimiter", materialSymbol: "animation" }, - { identifier: "resources", materialSymbol: "browse_activity" } + { identifier: "resources", materialSymbol: "browse_activity" }, + // CUSTOM: Stickypad integration - START + { identifier: "stickypad", materialSymbol: "note_stack" } + // CUSTOM: Stickypad integration - END ] readonly property bool hasPinnedWidgets: root.pinnedWidgetIdentifiers.length > 0 diff --git a/dots/.config/quickshell/ii/modules/overlay/OverlayWidgetDelegateChooser.qml b/dots/.config/quickshell/ii/modules/overlay/OverlayWidgetDelegateChooser.qml index fc75d1455..823b5d488 100644 --- a/dots/.config/quickshell/ii/modules/overlay/OverlayWidgetDelegateChooser.qml +++ b/dots/.config/quickshell/ii/modules/overlay/OverlayWidgetDelegateChooser.qml @@ -11,6 +11,9 @@ import qs.modules.overlay.volumeMixer import qs.modules.overlay.fpsLimiter import qs.modules.overlay.recorder import qs.modules.overlay.resources +// CUSTOM: Stickypad integration - START +import qs.modules.overlay.stickypad +// CUSTOM: Stickypad integration - END DelegateChooser { id: root @@ -21,4 +24,7 @@ DelegateChooser { DelegateChoice { roleValue: "fpsLimiter"; FpsLimiter {} } DelegateChoice { roleValue: "recorder"; Recorder {} } DelegateChoice { roleValue: "resources"; Resources {} } + // CUSTOM: Stickypad integration - START + DelegateChoice { roleValue: "stickypad"; Stickypad {} } + // CUSTOM: Stickypad integration - END } diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml new file mode 100644 index 000000000..149b65ac0 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml @@ -0,0 +1,23 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import qs.modules.common +import qs.modules.overlay + +StyledOverlayWidget { + id: root + title: "Stickypad" + minWidth: 440 + showCenterButton: true + + // Override opacity to always stay fully opaque, even in clickthrough mode + opacity: 1.0 + + contentItem: StickypadContent { + implicitWidth: 440 + implicitHeight: 380 + // CUSTOM: Pass clickthrough state to content - START + isClickthrough: root.clickthrough + // CUSTOM: Pass clickthrough state to content - END + } +} diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml new file mode 100644 index 000000000..db57ab40a --- /dev/null +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml @@ -0,0 +1,363 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell +import Quickshell.Io +import qs.modules.common +import qs.modules.common.widgets + +Rectangle { + id: root + + readonly property real panelPadding: 20 + property string stickypadContents: "" + property bool pendingReload: false + property var copylistEntries: [] + property string lastParsedCopylistText: "" + property var parsedCopylistLines: [] + // CUSTOM: Track clickthrough state to disable text editing - START + property bool isClickthrough: false + // CUSTOM: Track clickthrough state to disable text editing - END + + color: Appearance.colors.colLayer0 + radius: Appearance.rounding.windowRounding - 6 + + Component.onCompleted: { + stickypadFile.reload() + updateCopylistEntries() + } + + function saveStickypad() { + if (!stickypadInput) + return + stickypadContents = stickypadInput.text + stickypadFile.setText(stickypadContents) + } + + function focusStickypadAtEnd() { + if (!stickypadInput) + return + stickypadInput.forceActiveFocus() + const endPos = stickypadInput.text.length + applySelection(endPos, endPos) + } + + function applySelection(cursorPos, anchorPos) { + if (!stickypadInput) + return + const textLength = stickypadInput.text.length + const cursor = Math.max(0, Math.min(cursorPos, textLength)) + const anchor = Math.max(0, Math.min(anchorPos, textLength)) + stickypadInput.select(anchor, cursor) + if (cursor === anchor) + stickypadInput.deselect() + } + + function scheduleCopylistUpdate(immediate = false) { + if (!stickypadInput) + return + if (immediate) { + copylistDebounce.stop() + updateCopylistEntries() + } else { + copylistDebounce.restart() + } + } + + function updateCopylistEntries() { + if (!stickypadInput) + return + const textValue = stickypadInput.text + if (!textValue || textValue.length === 0) { + lastParsedCopylistText = "" + parsedCopylistLines = [] + copylistEntries = [] + return + } + + if (textValue !== lastParsedCopylistText) { + const lineRegex = /(.*?)(\r?\n|$)/g + let match = null + const parsed = [] + while ((match = lineRegex.exec(textValue)) !== null) { + const lineText = match[1] + const newlineText = match[2] + const lineStart = match.index + const lineEnd = lineStart + lineText.length + const bulletMatch = lineText.match(/^\s*-\s+(.*\S)\s*$/) + if (bulletMatch) { + parsed.push({ + content: bulletMatch[1].trim(), + start: lineStart, + end: lineEnd + }) + } + if (newlineText === "") + break + } + lastParsedCopylistText = textValue + parsedCopylistLines = parsed + if (parsed.length === 0) { + copylistEntries = [] + return + } + } + + updateCopylistPositions() + } + + function updateCopylistPositions() { + if (!stickypadInput || parsedCopylistLines.length === 0) + return + + const rawSelectionStart = stickypadInput.selectionStart + const rawSelectionEnd = stickypadInput.selectionEnd + const selectionStart = rawSelectionStart === -1 ? stickypadInput.cursorPosition : rawSelectionStart + const selectionEnd = rawSelectionEnd === -1 ? stickypadInput.cursorPosition : rawSelectionEnd + const rangeStart = Math.min(selectionStart, selectionEnd) + const rangeEnd = Math.max(selectionStart, selectionEnd) + + const entries = parsedCopylistLines.map(line => { + const caretIntersects = rangeEnd > line.start && rangeStart <= line.end + if (caretIntersects) + return null + const startRect = stickypadInput.positionToRectangle(line.start) + let endRect = stickypadInput.positionToRectangle(line.end) + if (!isFinite(startRect.y)) + return null + if (!isFinite(endRect.y)) + endRect = startRect + const lineBottom = endRect.y + endRect.height + const rectHeight = Math.max(lineBottom - startRect.y, stickypadInput.font.pixelSize + 8) + return { + content: line.content, + y: startRect.y, + height: rectHeight + } + }).filter(entry => entry !== null) + + copylistEntries = entries + } + + ColumnLayout { + id: stickypadLayout + anchors { + fill: parent + margins: panelPadding + } + spacing: 14 + + ScrollView { + id: editorScrollView + Layout.fillWidth: true + Layout.fillHeight: true + Layout.minimumHeight: 200 + clip: true + ScrollBar.vertical.policy: ScrollBar.AsNeeded + onWidthChanged: root.scheduleCopylistUpdate(true) + + StyledTextArea { + id: stickypadInput + wrapMode: TextEdit.Wrap + placeholderText: Translation.tr("Write...") + selectByMouse: true + persistentSelection: true + textFormat: TextEdit.PlainText + background: null + rightPadding: 44 + // CUSTOM: Adapt text color to theme (light/dark mode) - START + color: Appearance.colors.colOnLayer0 + // CUSTOM: Adapt text color to theme (light/dark mode) - END + // CUSTOM: Disable text area when clickthrough enabled - START + // Allow editing when overlay is open OR when clickthrough is disabled + enabled: GlobalStates.overlayOpen || !root.isClickthrough + activeFocusOnTab: GlobalStates.overlayOpen || !root.isClickthrough + + // Release focus when clickthrough is enabled and overlay closes + Connections { + target: root + function onIsClickthroughChanged() { + if (root.isClickthrough && !GlobalStates.overlayOpen && stickypadInput.activeFocus) { + stickypadInput.focus = false + } + } + } + + Connections { + target: GlobalStates + function onOverlayOpenChanged() { + if (!GlobalStates.overlayOpen && root.isClickthrough && stickypadInput.activeFocus) { + stickypadInput.focus = false + } + } + } + // CUSTOM: Disable text area when clickthrough enabled - END + + Keys.onPressed: (event) => { + if (event.key === Qt.Key_Escape && event.modifiers === Qt.NoModifier) { + Persistent.states.overlay.open = Persistent.states.overlay.open.filter(type => type !== "stickypad") + event.accepted = true + return + } + } + onTextChanged: { + if (stickypadInput.activeFocus) { + saveDebounce.restart() + } + root.scheduleCopylistUpdate(true) + } + onCursorPositionChanged: root.scheduleCopylistUpdate() + onSelectionStartChanged: root.scheduleCopylistUpdate() + onSelectionEndChanged: root.scheduleCopylistUpdate() + onHeightChanged: root.scheduleCopylistUpdate(true) + onContentHeightChanged: root.scheduleCopylistUpdate(true) + } + + Item { + anchors.fill: stickypadInput + visible: copylistEntries.length > 0 + clip: true + + Repeater { + model: copylistEntries + delegate: Item { + readonly property real lineHeight: Math.max(modelData.height, Appearance.font.pixelSize.normal + 6) + readonly property real iconSizeLocal: Appearance.font.pixelSize.normal + readonly property real hitPadding: 6 + + width: iconSizeLocal + hitPadding * 2 + height: lineHeight + y: modelData.y + x: Math.max(stickypadInput.width - width - 8, 0) + z: 5 + + Rectangle { + id: feedbackFlash + anchors.centerIn: iconItem + width: iconSizeLocal + hitPadding + height: width + radius: width / 2 + color: Appearance.colors.colLayer2 + opacity: 0 + z: -1 + } + + MaterialSymbol { + id: iconItem + anchors.centerIn: parent + text: "content_copy" + iconSize: iconSizeLocal + color: Appearance.colors.colOnLayer1 + opacity: mouseArea.containsMouse ? 1 : 0.85 + scale: 1 + Behavior on scale { + NumberAnimation { + duration: 120 + easing.type: Easing.OutQuad + } + } + Behavior on opacity { + NumberAnimation { + duration: 120 + } + } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + anchors.margins: hitPadding + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onPressed: iconItem.scale = 0.85 + onReleased: iconItem.scale = 1 + onCanceled: iconItem.scale = 1 + onClicked: { + feedbackFlash.opacity = 0.6 + feedbackFade.restart() + Quickshell.clipboardText = modelData.content + } + } + + NumberAnimation { + id: feedbackFade + target: feedbackFlash + property: "opacity" + to: 0 + duration: 200 + easing.type: Easing.OutQuad + } + } + } + } + } + + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 28 + Layout.minimumHeight: 28 + color: "transparent" + + StyledText { + id: statusLabel + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + rightMargin: 8 + } + text: saveDebounce.running ? "Saving..." : "Saved" + color: saveDebounce.running ? Appearance.colors.colAccent : Appearance.colors.colSubtext + font.pixelSize: Appearance.font.pixelSize.small + font.weight: Font.Medium + } + } + } + + Timer { + id: saveDebounce + interval: 500 + repeat: false + onTriggered: saveStickypad() + } + + Timer { + id: copylistDebounce + interval: 100 + repeat: false + onTriggered: updateCopylistPositions() + } + + FileView { + id: stickypadFile + path: Qt.resolvedUrl(Directories.stickypadPath) + onLoaded: { + stickypadContents = stickypadFile.text() + if (stickypadInput && stickypadInput.text !== stickypadContents) { + const previousCursor = stickypadInput.cursorPosition + const previousAnchor = stickypadInput.selectionStart + stickypadInput.text = stickypadContents + applySelection(previousCursor, previousAnchor) + } + if (pendingReload) { + pendingReload = false + Qt.callLater(focusStickypadAtEnd) + } + Qt.callLater(root.updateCopylistEntries) + } + onLoadFailed: (error) => { + if (error === FileViewError.FileNotFound) { + stickypadContents = "" + stickypadFile.setText(stickypadContents) + if (stickypadInput) + stickypadInput.text = stickypadContents + if (pendingReload) { + pendingReload = false + Qt.callLater(focusStickypadAtEnd) + } + Qt.callLater(root.updateCopylistEntries) + } else { + console.log("[Stickypad] Error loading file: " + error) + } + } + } +} diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir b/dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir new file mode 100644 index 000000000..13d756392 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir @@ -0,0 +1,4 @@ +module qs.modules.overlay.stickypad + +Stickypad 1.0 Stickypad.qml +StickypadContent 1.0 StickypadContent.qml From c035427e6ad2c02a418b4fad64cef99135c7bda5 Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 10:49:52 +0530 Subject: [PATCH 02/85] removed unnecessary comments --- dots/.config/quickshell/ii/modules/common/Directories.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/Directories.qml b/dots/.config/quickshell/ii/modules/common/Directories.qml index 7f1694f45..fa25fedba 100644 --- a/dots/.config/quickshell/ii/modules/common/Directories.qml +++ b/dots/.config/quickshell/ii/modules/common/Directories.qml @@ -32,9 +32,7 @@ Singleton { property string shellConfigName: "config.json" property string shellConfigPath: `${Directories.shellConfig}/${Directories.shellConfigName}` property string todoPath: FileUtils.trimFileProtocol(`${Directories.state}/user/todo.json`) - // CUSTOM: Stickypad integration - START property string stickypadPath: FileUtils.trimFileProtocol(`${Directories.state}/user/stickypad.txt`) - // CUSTOM: Stickypad integration - END property string conflictCachePath: FileUtils.trimFileProtocol(`${Directories.cache}/conflict-killer`) property string notificationsPath: FileUtils.trimFileProtocol(`${Directories.cache}/notifications/notifications.json`) property string generatedMaterialThemePath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/colors.json`) From cd452c256e3e02baef1a1a2fb2b3a59be402f120 Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 10:59:51 +0530 Subject: [PATCH 03/85] Delete dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir --- dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir b/dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir deleted file mode 100644 index 13d756392..000000000 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/qmldir +++ /dev/null @@ -1,4 +0,0 @@ -module qs.modules.overlay.stickypad - -Stickypad 1.0 Stickypad.qml -StickypadContent 1.0 StickypadContent.qml From 5820106e31dee7c273d8e57e9b83213e0d998066 Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:11:17 +0530 Subject: [PATCH 04/85] removed overriding opacity, as one can change in their config, current default is 0.7 --- .../quickshell/ii/modules/overlay/stickypad/Stickypad.qml | 3 --- 1 file changed, 3 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml index 149b65ac0..cc42e754a 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml @@ -10,9 +10,6 @@ StyledOverlayWidget { minWidth: 440 showCenterButton: true - // Override opacity to always stay fully opaque, even in clickthrough mode - opacity: 1.0 - contentItem: StickypadContent { implicitWidth: 440 implicitHeight: 380 From 631d4960018682fd7e30ed7515c8848fb74ad1d3 Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:20:19 +0530 Subject: [PATCH 05/85] removed unnecessary keyboard focus and ESC handler, as they are handled by overlay --- .../overlay/stickypad/StickypadContent.qml | 35 +++---------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml index db57ab40a..d84dff509 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml @@ -165,41 +165,14 @@ Rectangle { textFormat: TextEdit.PlainText background: null rightPadding: 44 - // CUSTOM: Adapt text color to theme (light/dark mode) - START + // Adapt text color to theme (light/dark mode) - START color: Appearance.colors.colOnLayer0 - // CUSTOM: Adapt text color to theme (light/dark mode) - END - // CUSTOM: Disable text area when clickthrough enabled - START - // Allow editing when overlay is open OR when clickthrough is disabled + // Adapt text color to theme (light/dark mode) - END + // Disable text area when clickthrough enabled - START enabled: GlobalStates.overlayOpen || !root.isClickthrough activeFocusOnTab: GlobalStates.overlayOpen || !root.isClickthrough + // Disable text area when clickthrough enabled - END - // Release focus when clickthrough is enabled and overlay closes - Connections { - target: root - function onIsClickthroughChanged() { - if (root.isClickthrough && !GlobalStates.overlayOpen && stickypadInput.activeFocus) { - stickypadInput.focus = false - } - } - } - - Connections { - target: GlobalStates - function onOverlayOpenChanged() { - if (!GlobalStates.overlayOpen && root.isClickthrough && stickypadInput.activeFocus) { - stickypadInput.focus = false - } - } - } - // CUSTOM: Disable text area when clickthrough enabled - END - - Keys.onPressed: (event) => { - if (event.key === Qt.Key_Escape && event.modifiers === Qt.NoModifier) { - Persistent.states.overlay.open = Persistent.states.overlay.open.filter(type => type !== "stickypad") - event.accepted = true - return - } - } onTextChanged: { if (stickypadInput.activeFocus) { saveDebounce.restart() From 77e626456876f47059184c6b4231c0b386949575 Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:34:00 +0530 Subject: [PATCH 06/85] removed unnecessary comments --- dots/.config/quickshell/ii/modules/common/Persistent.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/Persistent.qml b/dots/.config/quickshell/ii/modules/common/Persistent.qml index ee5d327cc..7585e6c62 100644 --- a/dots/.config/quickshell/ii/modules/common/Persistent.qml +++ b/dots/.config/quickshell/ii/modules/common/Persistent.qml @@ -113,14 +113,12 @@ Singleton { property real x: 1576 property real y: 630 } - // CUSTOM: Stickypad integration - START property JsonObject stickypad: JsonObject { property bool pinned: true property bool clickthrough: false property real x: 100 property real y: 100 } - // CUSTOM: Stickypad integration - END } property JsonObject timer: JsonObject { From 9c1c97a7ecdaa23619a10d7368a2da24bb204214 Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:35:14 +0530 Subject: [PATCH 07/85] removed unnecessary comments --- dots/.config/quickshell/ii/modules/overlay/Overlay.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/overlay/Overlay.qml b/dots/.config/quickshell/ii/modules/overlay/Overlay.qml index 12e3d6b44..65901ea13 100644 --- a/dots/.config/quickshell/ii/modules/overlay/Overlay.qml +++ b/dots/.config/quickshell/ii/modules/overlay/Overlay.qml @@ -25,10 +25,8 @@ Scope { exclusionMode: ExclusionMode.Ignore WlrLayershell.namespace: "quickshell:overlay" WlrLayershell.layer: WlrLayer.Overlay - // CUSTOM: Stickypad keyboard focus fix - START // Use OnDemand for pinned widgets to allow focus switching with mouse clicks WlrLayershell.keyboardFocus: GlobalStates.overlayOpen ? WlrKeyboardFocus.Exclusive : (OverlayContext.clickableWidgets.length > 0 ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None) - // CUSTOM: Stickypad keyboard focus fix - END visible: true color: "transparent" From 8a5852f61a0e83a9afc890e06d73afd78a4bf9ca Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:36:04 +0530 Subject: [PATCH 08/85] removed unnecessary comments --- dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml b/dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml index 4eed3e5b5..7570d7312 100644 --- a/dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml +++ b/dots/.config/quickshell/ii/modules/overlay/OverlayContext.qml @@ -11,9 +11,7 @@ Singleton { { identifier: "crosshair", materialSymbol: "point_scan" }, { identifier: "fpsLimiter", materialSymbol: "animation" }, { identifier: "resources", materialSymbol: "browse_activity" }, - // CUSTOM: Stickypad integration - START { identifier: "stickypad", materialSymbol: "note_stack" } - // CUSTOM: Stickypad integration - END ] readonly property bool hasPinnedWidgets: root.pinnedWidgetIdentifiers.length > 0 From 935a8ee4112a1d7d015cadc679e3cddff0be787d Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:37:32 +0530 Subject: [PATCH 09/85] removed unnecessary comments --- .../ii/modules/overlay/OverlayWidgetDelegateChooser.qml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/overlay/OverlayWidgetDelegateChooser.qml b/dots/.config/quickshell/ii/modules/overlay/OverlayWidgetDelegateChooser.qml index 823b5d488..42a2d7e4b 100644 --- a/dots/.config/quickshell/ii/modules/overlay/OverlayWidgetDelegateChooser.qml +++ b/dots/.config/quickshell/ii/modules/overlay/OverlayWidgetDelegateChooser.qml @@ -11,9 +11,7 @@ import qs.modules.overlay.volumeMixer import qs.modules.overlay.fpsLimiter import qs.modules.overlay.recorder import qs.modules.overlay.resources -// CUSTOM: Stickypad integration - START import qs.modules.overlay.stickypad -// CUSTOM: Stickypad integration - END DelegateChooser { id: root @@ -24,7 +22,5 @@ DelegateChooser { DelegateChoice { roleValue: "fpsLimiter"; FpsLimiter {} } DelegateChoice { roleValue: "recorder"; Recorder {} } DelegateChoice { roleValue: "resources"; Resources {} } - // CUSTOM: Stickypad integration - START DelegateChoice { roleValue: "stickypad"; Stickypad {} } - // CUSTOM: Stickypad integration - END } From ee94828d9711bd6fd6a5b304fdc35614562b8f9b Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:39:23 +0530 Subject: [PATCH 10/85] removed unnecessary comments --- .../ii/modules/overlay/stickypad/StickypadContent.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml index d84dff509..881116a66 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml @@ -15,9 +15,7 @@ Rectangle { property var copylistEntries: [] property string lastParsedCopylistText: "" property var parsedCopylistLines: [] - // CUSTOM: Track clickthrough state to disable text editing - START property bool isClickthrough: false - // CUSTOM: Track clickthrough state to disable text editing - END color: Appearance.colors.colLayer0 radius: Appearance.rounding.windowRounding - 6 From 819735169bcfa59dc77f85e442ce01e56fd4593b Mon Sep 17 00:00:00 2001 From: Marepalli Santhosh <173584372+marepallisanthosh999333@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:40:53 +0530 Subject: [PATCH 11/85] removed unnecessary comments --- .../quickshell/ii/modules/overlay/stickypad/Stickypad.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml index cc42e754a..cd1ccbfc8 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml @@ -13,8 +13,6 @@ StyledOverlayWidget { contentItem: StickypadContent { implicitWidth: 440 implicitHeight: 380 - // CUSTOM: Pass clickthrough state to content - START isClickthrough: root.clickthrough - // CUSTOM: Pass clickthrough state to content - END } } From 3502e46d19b62c193df5d0dcae161b6dca7dba52 Mon Sep 17 00:00:00 2001 From: imitoy Date: Sun, 9 Nov 2025 16:03:19 +0800 Subject: [PATCH 12/85] Brightness fix: Use percentage brightness to handle multiple devices correctly --- .../quickshell/ii/services/Brightness.qml | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/dots/.config/quickshell/ii/services/Brightness.qml b/dots/.config/quickshell/ii/services/Brightness.qml index f3cec016c..d2bc31ec6 100644 --- a/dots/.config/quickshell/ii/services/Brightness.qml +++ b/dots/.config/quickshell/ii/services/Brightness.qml @@ -110,7 +110,7 @@ Singleton { function initialize() { monitor.ready = false; - initProc.command = isDdc ? ["ddcutil", "-b", busNum, "getvcp", "10", "--brief"] : ["sh", "-c", `echo "a b c $(brightnessctl g) $(brightnessctl m)"`]; + initProc.command = isDdc ? ["ddcutil", "-b", busNum, "getvcp", "10", "--brief"] : ["sh", "-c", `echo "a b c $(brightnessctl g --device intel_backlight) $(brightnessctl m --device intel_backlight)"`]; initProc.running = true; } @@ -135,14 +135,24 @@ Singleton { } function syncBrightness() { - const brightnessValue = Math.max(monitor.multipliedBrightness, 0) - const rawValueRounded = Math.max(Math.floor(brightnessValue * monitor.rawMaxBrightness), 1); - setProc.command = isDdc ? ["ddcutil", "-b", busNum, "setvcp", "10", rawValueRounded] : ["brightnessctl", "--class", "backlight", "s", rawValueRounded, "--quiet"]; - setProc.startDetached(); + const brightnessValue = Math.max(monitor.multipliedBrightness, 0); + if(isDdc){ + const rawValueRounded = Math.max(Math.floor(brightnessValue * monitor.rawMaxBrightness), 1); + setProc.command = ["ddcutil", "-b", busNum, "setvcp", "10", rawValueRounded]; + setProc.startDetached(); + }else{ + const valuePercentNumber = Math.floor(brightnessValue * 100); + let valuePercent = ""+valuePercentNumber+"%"; + if(valuePercentNumber == 0) + //Set it to raw 1 + valuePercent = 1; + setProc.command = ["brightnessctl", "--class", "backlight", "s", valuePercent, "--quiet"]; + setProc.startDetached(); + } } function setBrightness(value: real): void { - value = Math.max(0, Math.min(1, value)); + value = Math.max(0, Math.min(value, 1)); monitor.brightness = value; } From 11fa846ae18c4338ee7d3f74a465b65588a06a59 Mon Sep 17 00:00:00 2001 From: imitoy Date: Sun, 9 Nov 2025 16:10:24 +0800 Subject: [PATCH 13/85] Brightness fix: Use percentage brightness to handle multiple devices correctly --- dots/.config/quickshell/ii/services/Brightness.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/services/Brightness.qml b/dots/.config/quickshell/ii/services/Brightness.qml index d2bc31ec6..c5206c601 100644 --- a/dots/.config/quickshell/ii/services/Brightness.qml +++ b/dots/.config/quickshell/ii/services/Brightness.qml @@ -110,7 +110,7 @@ Singleton { function initialize() { monitor.ready = false; - initProc.command = isDdc ? ["ddcutil", "-b", busNum, "getvcp", "10", "--brief"] : ["sh", "-c", `echo "a b c $(brightnessctl g --device intel_backlight) $(brightnessctl m --device intel_backlight)"`]; + initProc.command = isDdc ? ["ddcutil", "-b", busNum, "getvcp", "10", "--brief"] : ["sh", "-c", `echo "a b c $(brightnessctl g) $(brightnessctl m)"`]; initProc.running = true; } From 60eed56ea73e4877e50c04f6e54c24eff383bd90 Mon Sep 17 00:00:00 2001 From: imitoy Date: Sun, 9 Nov 2025 16:12:11 +0800 Subject: [PATCH 14/85] Brightness fix: Use percentage brightness to handle multiple devices correctly --- dots/.config/quickshell/ii/services/Brightness.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/services/Brightness.qml b/dots/.config/quickshell/ii/services/Brightness.qml index c5206c601..c443a4a7d 100644 --- a/dots/.config/quickshell/ii/services/Brightness.qml +++ b/dots/.config/quickshell/ii/services/Brightness.qml @@ -152,7 +152,7 @@ Singleton { } function setBrightness(value: real): void { - value = Math.max(0, Math.min(value, 1)); + value = Math.max(0, Math.min(1, value)); monitor.brightness = value; } From a065829eee98201ed6a74bd392f6f7ed7de5df54 Mon Sep 17 00:00:00 2001 From: nrand Date: Mon, 10 Nov 2025 20:58:35 +0200 Subject: [PATCH 15/85] clock: separate style for lock screen (#2374) --- .../quickshell/ii/modules/common/Config.qml | 3 +- .../background/widgets/clock/ClockWidget.qml | 2 +- .../ii/modules/settings/BackgroundConfig.qml | 45 +++++++++++++++---- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml index 1b13540ef..2987faed2 100644 --- a/dots/.config/quickshell/ii/modules/common/Config.qml +++ b/dots/.config/quickshell/ii/modules/common/Config.qml @@ -157,7 +157,8 @@ Singleton { property string placementStrategy: "leastBusy" // "free", "leastBusy", "mostBusy" property real x: 100 property real y: 100 - property string style: "cookie" // Options: "cookie", "digital" + property string style: "cookie" // Options: "cookie", "digital" + property string styleLocked: "digital" // Options: "cookie", "digital" property JsonObject cookie: JsonObject { property bool aiStyling: false property int sides: 14 diff --git a/dots/.config/quickshell/ii/modules/ii/background/widgets/clock/ClockWidget.qml b/dots/.config/quickshell/ii/modules/ii/background/widgets/clock/ClockWidget.qml index cf8c739e0..ba3197621 100644 --- a/dots/.config/quickshell/ii/modules/ii/background/widgets/clock/ClockWidget.qml +++ b/dots/.config/quickshell/ii/modules/ii/background/widgets/clock/ClockWidget.qml @@ -16,7 +16,7 @@ AbstractBackgroundWidget { implicitHeight: contentColumn.implicitHeight implicitWidth: contentColumn.implicitWidth - readonly property string clockStyle: Config.options.background.widgets.clock.style + readonly property string clockStyle: GlobalStates.screenLocked ? Config.options.background.widgets.clock.styleLocked : Config.options.background.widgets.clock.style readonly property bool forceCenter: (GlobalStates.screenLocked && Config.options.lock.centerClock) readonly property bool shouldShow: (!Config.options.background.widgets.clock.showOnlyWhenLocked || GlobalStates.screenLocked) property bool wallpaperSafetyTriggered: false diff --git a/dots/.config/quickshell/ii/modules/settings/BackgroundConfig.qml b/dots/.config/quickshell/ii/modules/settings/BackgroundConfig.qml index ec9dc320d..c12a04c54 100644 --- a/dots/.config/quickshell/ii/modules/settings/BackgroundConfig.qml +++ b/dots/.config/quickshell/ii/modules/settings/BackgroundConfig.qml @@ -55,6 +55,10 @@ ContentPage { ContentSection { icon: "clock_loader_40" title: Translation.tr("Widget: Clock") + id: settingsClock + + readonly property bool digitalPresent: (!Config.options.background.widgets.clock.showOnlyWhenLocked && Config.options.background.widgets.clock.style === "digital") || Config.options.background.widgets.clock.styleLocked === "digital" + readonly property bool cookiePresent: (!Config.options.background.widgets.clock.showOnlyWhenLocked && Config.options.background.widgets.clock.style === "cookie") || Config.options.background.widgets.clock.styleLocked === "cookie" ConfigRow { Layout.fillWidth: true @@ -107,6 +111,7 @@ ContentPage { } ContentSubsection { + visible: !Config.options.background.widgets.clock.showOnlyWhenLocked title: Translation.tr("Clock style") ConfigSelectionArray { currentValue: Config.options.background.widgets.clock.style @@ -129,7 +134,29 @@ ContentPage { } ContentSubsection { - visible: Config.options.background.widgets.clock.style === "digital" + title: Translation.tr("Clock style (locked)") + ConfigSelectionArray { + currentValue: Config.options.background.widgets.clock.styleLocked + onSelected: newValue => { + Config.options.background.widgets.clock.styleLocked = newValue; + } + options: [ + { + displayName: Translation.tr("Digital"), + icon: "timer_10", + value: "digital" + }, + { + displayName: Translation.tr("Cookie"), + icon: "cookie", + value: "cookie" + } + ] + } + } + + ContentSubsection { + visible: settingsClock.digitalPresent title: Translation.tr("Digital clock settings") ConfigSwitch { @@ -143,7 +170,7 @@ ContentPage { } ContentSubsection { - visible: Config.options.background.widgets.clock.style === "cookie" + visible: settingsClock.cookiePresent title: Translation.tr("Cookie clock settings") ConfigSwitch { @@ -197,7 +224,7 @@ ContentPage { ConfigRow { ConfigSwitch { - enabled: Config.options.background.widgets.clock.style === "cookie" && Config.options.background.widgets.clock.cookie.dialNumberStyle === "dots" || Config.options.background.widgets.clock.cookie.dialNumberStyle === "full" + enabled: Config.options.background.widgets.clock.cookie.dialNumberStyle === "dots" || Config.options.background.widgets.clock.cookie.dialNumberStyle === "full" buttonIcon: "brightness_7" text: Translation.tr("Hour marks") checked: Config.options.background.widgets.clock.cookie.hourMarks @@ -213,7 +240,7 @@ ContentPage { } ConfigSwitch { - enabled: Config.options.background.widgets.clock.style === "cookie" && Config.options.background.widgets.clock.cookie.dialNumberStyle !== "numbers" + enabled: Config.options.background.widgets.clock.cookie.dialNumberStyle !== "numbers" buttonIcon: "timer_10" text: Translation.tr("Digits in the middle") checked: Config.options.background.widgets.clock.cookie.timeIndicators @@ -231,7 +258,7 @@ ContentPage { } ContentSubsection { - visible: Config.options.background.widgets.clock.style === "cookie" + visible: settingsClock.cookiePresent title: Translation.tr("Dial style") ConfigSelectionArray { currentValue: Config.options.background.widgets.clock.cookie.dialNumberStyle @@ -270,7 +297,7 @@ ContentPage { } ContentSubsection { - visible: Config.options.background.widgets.clock.style === "cookie" + visible: settingsClock.cookiePresent title: Translation.tr("Hour hand") ConfigSelectionArray { currentValue: Config.options.background.widgets.clock.cookie.hourHandStyle @@ -303,7 +330,7 @@ ContentPage { } ContentSubsection { - visible: Config.options.background.widgets.clock.style === "cookie" + visible: settingsClock.cookiePresent title: Translation.tr("Minute hand") ConfigSelectionArray { @@ -342,7 +369,7 @@ ContentPage { } ContentSubsection { - visible: Config.options.background.widgets.clock.style === "cookie" + visible: settingsClock.cookiePresent title: Translation.tr("Second hand") ConfigSelectionArray { @@ -376,7 +403,7 @@ ContentPage { } ContentSubsection { - visible: Config.options.background.widgets.clock.style === "cookie" + visible: settingsClock.cookiePresent title: Translation.tr("Date style") ConfigSelectionArray { From 499b0628eaf836ecf72fbf3acfd681739a7cdfb1 Mon Sep 17 00:00:00 2001 From: fuggy <45698918+nonetrix@users.noreply.github.com> Date: Thu, 13 Nov 2025 18:37:09 -0600 Subject: [PATCH 16/85] Add Valve icon --- dots/.config/quickshell/ii/modules/settings/InterfaceConfig.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/settings/InterfaceConfig.qml b/dots/.config/quickshell/ii/modules/settings/InterfaceConfig.qml index 738578585..1614ec47f 100644 --- a/dots/.config/quickshell/ii/modules/settings/InterfaceConfig.qml +++ b/dots/.config/quickshell/ii/modules/settings/InterfaceConfig.qml @@ -22,7 +22,7 @@ ContentPage { // Use a nerdfont to see the icons options: ([ "󰖳", "", "󰨡", "", "󰌽", "󰣇", "", "", "", - "", "", "󱄛", "", "", "⌘", "󰀲", "󰟍", "" + "", "", "󱄛", "", "", "", "⌘", "󰀲", "󰟍", "" ]).map(icon => { return { displayName: icon, value: icon From c369db75ebd78c40432acddb30b81b6e387a6d8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8F=9C=E5=8F=B6=E7=89=87=28ItsSunshineXD=29?= <61444298+CNMrSunshine@users.noreply.github.com> Date: Fri, 14 Nov 2025 13:22:09 +0800 Subject: [PATCH 17/85] Refactor message block model to use root.messageBlocks --- .../ii/sidebarLeft/aiChat/AiMessage.qml | 26 +++++-------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/AiMessage.qml b/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/AiMessage.qml index 74d5c5f6a..46a87eacb 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/AiMessage.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/AiMessage.qml @@ -285,48 +285,34 @@ Rectangle { } } } - Repeater { - model: ScriptModel { - values: Array.from({ length: root.messageBlocks.length }, (msg, i) => { - return ({ - type: root.messageBlocks[i].type - }) - }); - } - + model: root.messageBlocks delegate: DelegateChooser { id: messageDelegate role: "type" DelegateChoice { roleValue: "code"; MessageCodeBlock { - required property int index - property var thisBlock: root.messageBlocks[index] editing: root.editing renderMarkdown: root.renderMarkdown enableMouseSelection: root.enableMouseSelection - segmentContent: thisBlock.content - segmentLang: thisBlock.lang + segmentContent: modelData.content + segmentLang: modelData.lang messageData: root.messageData } } DelegateChoice { roleValue: "think"; MessageThinkBlock { - required property int index - property var thisBlock: root.messageBlocks[index] editing: root.editing renderMarkdown: root.renderMarkdown enableMouseSelection: root.enableMouseSelection - segmentContent: thisBlock.content + segmentContent: modelData.content messageData: root.messageData done: root.messageData?.done ?? false - completed: thisBlock.completed ?? false + completed: modelData.completed ?? false } } DelegateChoice { roleValue: "text"; MessageTextBlock { - required property int index - property var thisBlock: root.messageBlocks[index] editing: root.editing renderMarkdown: root.renderMarkdown enableMouseSelection: root.enableMouseSelection - segmentContent: thisBlock.content + segmentContent: modelData.content messageData: root.messageData done: root.messageData?.done ?? false forceDisableChunkSplitting: root.messageData?.content.includes("```") ?? true From 2e5be9023744af7fe8120665b0ac2cb267dad4e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8F=9C=E5=8F=B6=E7=89=87=28ItsSunshineXD=29?= <61444298+CNMrSunshine@users.noreply.github.com> Date: Fri, 14 Nov 2025 13:22:25 +0800 Subject: [PATCH 18/85] Fix segmentContent property assignment in MessageThinkBlock --- .../ii/modules/ii/sidebarLeft/aiChat/MessageThinkBlock.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/MessageThinkBlock.qml b/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/MessageThinkBlock.qml index 1463c6e60..ee00ffdff 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/MessageThinkBlock.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/MessageThinkBlock.qml @@ -156,7 +156,6 @@ Item { property bool editing: root.editing property bool renderMarkdown: root.renderMarkdown property bool enableMouseSelection: root.enableMouseSelection - property string segmentContent: root.segmentContent property var messageData: root.messageData property bool done: root.done @@ -165,8 +164,9 @@ Item { anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom + segmentContent: root.segmentContent } } } } -} \ No newline at end of file +} From bf225d6de2715748534c34053434838fd85ed5db Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 09:38:10 +0100 Subject: [PATCH 19/85] Change model to ScriptModel for messageBlocks --- .../quickshell/ii/modules/ii/sidebarLeft/aiChat/AiMessage.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/AiMessage.qml b/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/AiMessage.qml index 46a87eacb..487665851 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/AiMessage.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarLeft/aiChat/AiMessage.qml @@ -286,7 +286,9 @@ Rectangle { } } Repeater { - model: root.messageBlocks + model: ScriptModel { + values: root.messageBlocks + } delegate: DelegateChooser { id: messageDelegate role: "type" From 61a9d406f21c06fbd09cebb94c1f0a3a0368bbf5 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 09:52:22 +0100 Subject: [PATCH 20/85] fix not launching --- .../quickshell/ii/modules/overlay/stickypad/Stickypad.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml index cd1ccbfc8..74b68fdf4 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml @@ -7,7 +7,6 @@ import qs.modules.overlay StyledOverlayWidget { id: root title: "Stickypad" - minWidth: 440 showCenterButton: true contentItem: StickypadContent { From 42147b2117b785c94f2ae0cfd9445a7edb078b5d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 09:56:57 +0100 Subject: [PATCH 21/85] stickypad: fix imports --- .../ii/modules/overlay/stickypad/StickypadContent.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml index 881116a66..d8473ea33 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml @@ -3,6 +3,8 @@ import QtQuick.Controls import QtQuick.Layouts import Quickshell import Quickshell.Io +import qs +import qs.services import qs.modules.common import qs.modules.common.widgets From 98ef819feeee075494fdbbef6a1e1591794f94a0 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 09:57:11 +0100 Subject: [PATCH 22/85] stickypad: unfuck window size --- dots/.config/quickshell/ii/modules/common/Persistent.qml | 2 ++ .../quickshell/ii/modules/overlay/stickypad/Stickypad.qml | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/Persistent.qml b/dots/.config/quickshell/ii/modules/common/Persistent.qml index fbb52071c..afa554d26 100644 --- a/dots/.config/quickshell/ii/modules/common/Persistent.qml +++ b/dots/.config/quickshell/ii/modules/common/Persistent.qml @@ -128,6 +128,8 @@ Singleton { property bool clickthrough: false property real x: 100 property real y: 100 + property real width: 350 + property real height: 600 } } diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml index 74b68fdf4..1db5f6693 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml +++ b/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml @@ -10,8 +10,7 @@ StyledOverlayWidget { showCenterButton: true contentItem: StickypadContent { - implicitWidth: 440 - implicitHeight: 380 + anchors.fill: parent isClickthrough: root.clickthrough } } From f46835c9a1ad0cec52f5ac50059fe1d02274868a Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 10:07:07 +0100 Subject: [PATCH 23/85] stickypad: moves files to correct place --- .../ii/modules/{ => ii}/overlay/stickypad/Stickypad.qml | 2 +- .../{ => ii}/overlay/stickypad/StickypadContent.qml | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) rename dots/.config/quickshell/ii/modules/{ => ii}/overlay/stickypad/Stickypad.qml (90%) rename dots/.config/quickshell/ii/modules/{ => ii}/overlay/stickypad/StickypadContent.qml (98%) diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml similarity index 90% rename from dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml rename to dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml index 1db5f6693..b702f9b94 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/Stickypad.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml @@ -2,7 +2,7 @@ import QtQuick import QtQuick.Layouts import Quickshell import qs.modules.common -import qs.modules.overlay +import qs.modules.ii.overlay StyledOverlayWidget { id: root diff --git a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml similarity index 98% rename from dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml rename to dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index d8473ea33..adc7724d0 100644 --- a/dots/.config/quickshell/ii/modules/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -7,8 +7,9 @@ import qs import qs.services import qs.modules.common import qs.modules.common.widgets +import qs.modules.ii.overlay -Rectangle { +OverlayBackground { id: root readonly property real panelPadding: 20 @@ -19,9 +20,6 @@ Rectangle { property var parsedCopylistLines: [] property bool isClickthrough: false - color: Appearance.colors.colLayer0 - radius: Appearance.rounding.windowRounding - 6 - Component.onCompleted: { stickypadFile.reload() updateCopylistEntries() @@ -279,7 +277,7 @@ Rectangle { rightMargin: 8 } text: saveDebounce.running ? "Saving..." : "Saved" - color: saveDebounce.running ? Appearance.colors.colAccent : Appearance.colors.colSubtext + color: Appearance.colors.colSubtext font.pixelSize: Appearance.font.pixelSize.small font.weight: Font.Medium } From c8c4642c6140ae1e510632df62aa08261d2e8f67 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 10:28:09 +0100 Subject: [PATCH 24/85] call stickypad notes --- .../quickshell/ii/modules/common/Persistent.qml | 14 +++++++------- .../ii/modules/ii/overlay/OverlayContext.qml | 2 +- .../ii/overlay/OverlayWidgetDelegateChooser.qml | 2 +- .../ii/modules/ii/overlay/stickypad/Stickypad.qml | 5 +++-- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/Persistent.qml b/dots/.config/quickshell/ii/modules/common/Persistent.qml index 5774912a2..478cadd10 100644 --- a/dots/.config/quickshell/ii/modules/common/Persistent.qml +++ b/dots/.config/quickshell/ii/modules/common/Persistent.qml @@ -131,13 +131,13 @@ Singleton { property real height: 600 property int tabIndex: 0 } - property JsonObject stickypad: JsonObject { - property bool pinned: true - property bool clickthrough: false - property real x: 100 - property real y: 100 - property real width: 350 - property real height: 600 + property JsonObject notes: JsonObject { + property bool pinned: false + property bool clickthrough: true + property real x: 1400 + property real y: 42 + property real width: 460 + property real height: 330 } } diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayContext.qml b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayContext.qml index 7cdc938bf..bb68cefc3 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayContext.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayContext.qml @@ -11,7 +11,7 @@ Singleton { { identifier: "floatingImage", materialSymbol: "imagesmode" }, { identifier: "recorder", materialSymbol: "screen_record" }, { identifier: "resources", materialSymbol: "browse_activity" }, - { identifier: "stickypad", materialSymbol: "note_stack" }, + { identifier: "notes", materialSymbol: "note_stack" }, { identifier: "volumeMixer", materialSymbol: "volume_up" }, ] diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml index 97fc3b9ab..b7b26b9cf 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml @@ -23,6 +23,6 @@ DelegateChooser { DelegateChoice { roleValue: "fpsLimiter"; FpsLimiter {} } DelegateChoice { roleValue: "recorder"; Recorder {} } DelegateChoice { roleValue: "resources"; Resources {} } - DelegateChoice { roleValue: "stickypad"; Stickypad {} } + DelegateChoice { roleValue: "notes"; Stickypad {} } DelegateChoice { roleValue: "volumeMixer"; VolumeMixer {} } } diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml index b702f9b94..e6a60bd78 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml @@ -1,16 +1,17 @@ import QtQuick import QtQuick.Layouts import Quickshell +import qs.services import qs.modules.common import qs.modules.ii.overlay StyledOverlayWidget { id: root - title: "Stickypad" + title: Translation.tr("Notes") showCenterButton: true contentItem: StickypadContent { - anchors.fill: parent + radius: root.contentRadius isClickthrough: root.clickthrough } } From a5b941360c8826254dc3e0d39950ed86ee067916 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 10:44:08 +0100 Subject: [PATCH 25/85] stickypad: make placeholder show tip with bulletpoints --- .../ii/overlay/stickypad/StickypadContent.qml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index adc7724d0..a5eac4363 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -55,10 +55,10 @@ OverlayBackground { if (!stickypadInput) return if (immediate) { - copylistDebounce.stop() + copyListDebounce.stop() updateCopylistEntries() } else { - copylistDebounce.restart() + copyListDebounce.restart() } } @@ -156,8 +156,12 @@ OverlayBackground { StyledTextArea { id: stickypadInput + anchors { + left: parent.left + right: parent.right + } wrapMode: TextEdit.Wrap - placeholderText: Translation.tr("Write...") + placeholderText: Translation.tr("Write something here...\nUse '-' to create copyable bullet points, like this:\n\nSheep fricker\n- 4x Slab\n- 1x Boat\n- 4x Redstone Dust\n- 1x Sticky Piston\n- 1x End Rod\n- 4x Redstone Repeater\n- 1x Redstone Torch\n- 1x Sheep") selectByMouse: true persistentSelection: true textFormat: TextEdit.PlainText @@ -292,7 +296,7 @@ OverlayBackground { } Timer { - id: copylistDebounce + id: copyListDebounce interval: 100 repeat: false onTriggered: updateCopylistPositions() From f8ffe5e63f73c2c0e9ea8036974406e3777cc936 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 10:57:26 +0100 Subject: [PATCH 26/85] format, move text color to styled text area --- .../modules/common/widgets/StyledTextArea.qml | 1 + .../ii/overlay/stickypad/StickypadContent.qml | 249 ++++++++---------- 2 files changed, 118 insertions(+), 132 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml b/dots/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml index b1f4579d2..13702e1f9 100644 --- a/dots/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml +++ b/dots/.config/quickshell/ii/modules/common/widgets/StyledTextArea.qml @@ -10,6 +10,7 @@ TextArea { selectedTextColor: Appearance.m3colors.m3onSecondaryContainer selectionColor: Appearance.colors.colSecondaryContainer placeholderTextColor: Appearance.m3colors.m3outline + color: Appearance.colors.colOnLayer0 font { family: Appearance.font.family.main pixelSize: Appearance?.font.pixelSize.small ?? 15 diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index a5eac4363..fe5852c35 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -11,149 +11,146 @@ import qs.modules.ii.overlay OverlayBackground { id: root - - readonly property real panelPadding: 20 + property string stickypadContents: "" property bool pendingReload: false property var copylistEntries: [] property string lastParsedCopylistText: "" property var parsedCopylistLines: [] property bool isClickthrough: false - + Component.onCompleted: { - stickypadFile.reload() - updateCopylistEntries() + stickypadFile.reload(); + updateCopylistEntries(); } - + function saveStickypad() { if (!stickypadInput) - return - stickypadContents = stickypadInput.text - stickypadFile.setText(stickypadContents) + return; + stickypadContents = stickypadInput.text; + stickypadFile.setText(stickypadContents); } - + function focusStickypadAtEnd() { if (!stickypadInput) - return - stickypadInput.forceActiveFocus() - const endPos = stickypadInput.text.length - applySelection(endPos, endPos) + return; + stickypadInput.forceActiveFocus(); + const endPos = stickypadInput.text.length; + applySelection(endPos, endPos); } - + function applySelection(cursorPos, anchorPos) { if (!stickypadInput) - return - const textLength = stickypadInput.text.length - const cursor = Math.max(0, Math.min(cursorPos, textLength)) - const anchor = Math.max(0, Math.min(anchorPos, textLength)) - stickypadInput.select(anchor, cursor) + return; + const textLength = stickypadInput.text.length; + const cursor = Math.max(0, Math.min(cursorPos, textLength)); + const anchor = Math.max(0, Math.min(anchorPos, textLength)); + stickypadInput.select(anchor, cursor); if (cursor === anchor) - stickypadInput.deselect() + stickypadInput.deselect(); } - + function scheduleCopylistUpdate(immediate = false) { if (!stickypadInput) - return + return; if (immediate) { - copyListDebounce.stop() - updateCopylistEntries() + copyListDebounce.stop(); + updateCopylistEntries(); } else { - copyListDebounce.restart() + copyListDebounce.restart(); } } - + function updateCopylistEntries() { if (!stickypadInput) - return - const textValue = stickypadInput.text + return; + const textValue = stickypadInput.text; if (!textValue || textValue.length === 0) { - lastParsedCopylistText = "" - parsedCopylistLines = [] - copylistEntries = [] - return + lastParsedCopylistText = ""; + parsedCopylistLines = []; + copylistEntries = []; + return; } - + if (textValue !== lastParsedCopylistText) { - const lineRegex = /(.*?)(\r?\n|$)/g - let match = null - const parsed = [] + const lineRegex = /(.*?)(\r?\n|$)/g; + let match = null; + const parsed = []; while ((match = lineRegex.exec(textValue)) !== null) { - const lineText = match[1] - const newlineText = match[2] - const lineStart = match.index - const lineEnd = lineStart + lineText.length - const bulletMatch = lineText.match(/^\s*-\s+(.*\S)\s*$/) + const lineText = match[1]; + const newlineText = match[2]; + const lineStart = match.index; + const lineEnd = lineStart + lineText.length; + const bulletMatch = lineText.match(/^\s*-\s+(.*\S)\s*$/); if (bulletMatch) { parsed.push({ content: bulletMatch[1].trim(), start: lineStart, end: lineEnd - }) + }); } if (newlineText === "") - break + break; } - lastParsedCopylistText = textValue - parsedCopylistLines = parsed + lastParsedCopylistText = textValue; + parsedCopylistLines = parsed; if (parsed.length === 0) { - copylistEntries = [] - return + copylistEntries = []; + return; } } - - updateCopylistPositions() + + updateCopylistPositions(); } - + function updateCopylistPositions() { if (!stickypadInput || parsedCopylistLines.length === 0) - return - - const rawSelectionStart = stickypadInput.selectionStart - const rawSelectionEnd = stickypadInput.selectionEnd - const selectionStart = rawSelectionStart === -1 ? stickypadInput.cursorPosition : rawSelectionStart - const selectionEnd = rawSelectionEnd === -1 ? stickypadInput.cursorPosition : rawSelectionEnd - const rangeStart = Math.min(selectionStart, selectionEnd) - const rangeEnd = Math.max(selectionStart, selectionEnd) - + return; + const rawSelectionStart = stickypadInput.selectionStart; + const rawSelectionEnd = stickypadInput.selectionEnd; + const selectionStart = rawSelectionStart === -1 ? stickypadInput.cursorPosition : rawSelectionStart; + const selectionEnd = rawSelectionEnd === -1 ? stickypadInput.cursorPosition : rawSelectionEnd; + const rangeStart = Math.min(selectionStart, selectionEnd); + const rangeEnd = Math.max(selectionStart, selectionEnd); + const entries = parsedCopylistLines.map(line => { - const caretIntersects = rangeEnd > line.start && rangeStart <= line.end + const caretIntersects = rangeEnd > line.start && rangeStart <= line.end; if (caretIntersects) - return null - const startRect = stickypadInput.positionToRectangle(line.start) - let endRect = stickypadInput.positionToRectangle(line.end) + return null; + const startRect = stickypadInput.positionToRectangle(line.start); + let endRect = stickypadInput.positionToRectangle(line.end); if (!isFinite(startRect.y)) - return null + return null; if (!isFinite(endRect.y)) - endRect = startRect - const lineBottom = endRect.y + endRect.height - const rectHeight = Math.max(lineBottom - startRect.y, stickypadInput.font.pixelSize + 8) + endRect = startRect; + const lineBottom = endRect.y + endRect.height; + const rectHeight = Math.max(lineBottom - startRect.y, stickypadInput.font.pixelSize + 8); return { content: line.content, y: startRect.y, height: rectHeight - } - }).filter(entry => entry !== null) - - copylistEntries = entries + }; + }).filter(entry => entry !== null); + + copylistEntries = entries; } - + ColumnLayout { id: stickypadLayout anchors { fill: parent - margins: panelPadding + margins: 16 } - spacing: 14 - + spacing: 10 + ScrollView { id: editorScrollView Layout.fillWidth: true Layout.fillHeight: true - Layout.minimumHeight: 200 clip: true ScrollBar.vertical.policy: ScrollBar.AsNeeded onWidthChanged: root.scheduleCopylistUpdate(true) - + StyledTextArea { id: stickypadInput anchors { @@ -167,19 +164,16 @@ OverlayBackground { textFormat: TextEdit.PlainText background: null rightPadding: 44 - // Adapt text color to theme (light/dark mode) - START - color: Appearance.colors.colOnLayer0 - // Adapt text color to theme (light/dark mode) - END // Disable text area when clickthrough enabled - START enabled: GlobalStates.overlayOpen || !root.isClickthrough activeFocusOnTab: GlobalStates.overlayOpen || !root.isClickthrough // Disable text area when clickthrough enabled - END - + onTextChanged: { if (stickypadInput.activeFocus) { - saveDebounce.restart() + saveDebounce.restart(); } - root.scheduleCopylistUpdate(true) + root.scheduleCopylistUpdate(true); } onCursorPositionChanged: root.scheduleCopylistUpdate() onSelectionStartChanged: root.scheduleCopylistUpdate() @@ -187,25 +181,25 @@ OverlayBackground { onHeightChanged: root.scheduleCopylistUpdate(true) onContentHeightChanged: root.scheduleCopylistUpdate(true) } - + Item { anchors.fill: stickypadInput visible: copylistEntries.length > 0 clip: true - + Repeater { model: copylistEntries delegate: Item { readonly property real lineHeight: Math.max(modelData.height, Appearance.font.pixelSize.normal + 6) readonly property real iconSizeLocal: Appearance.font.pixelSize.normal readonly property real hitPadding: 6 - + width: iconSizeLocal + hitPadding * 2 height: lineHeight y: modelData.y x: Math.max(stickypadInput.width - width - 8, 0) z: 5 - + Rectangle { id: feedbackFlash anchors.centerIn: iconItem @@ -214,9 +208,9 @@ OverlayBackground { radius: width / 2 color: Appearance.colors.colLayer2 opacity: 0 - z: -1 + z: 999 } - + MaterialSymbol { id: iconItem anchors.centerIn: parent @@ -237,7 +231,7 @@ OverlayBackground { } } } - + MouseArea { id: mouseArea anchors.fill: parent @@ -248,12 +242,12 @@ OverlayBackground { onReleased: iconItem.scale = 1 onCanceled: iconItem.scale = 1 onClicked: { - feedbackFlash.opacity = 0.6 - feedbackFade.restart() - Quickshell.clipboardText = modelData.content + feedbackFlash.opacity = 0.6; + feedbackFade.restart(); + Quickshell.clipboardText = modelData.content; } } - + NumberAnimation { id: feedbackFade target: feedbackFlash @@ -266,72 +260,63 @@ OverlayBackground { } } } - - Rectangle { + + StyledText { + id: statusLabel Layout.fillWidth: true - Layout.preferredHeight: 28 - Layout.minimumHeight: 28 - color: "transparent" - - StyledText { - id: statusLabel - anchors { - right: parent.right - verticalCenter: parent.verticalCenter - rightMargin: 8 - } - text: saveDebounce.running ? "Saving..." : "Saved" - color: Appearance.colors.colSubtext - font.pixelSize: Appearance.font.pixelSize.small - font.weight: Font.Medium - } + // Layout.preferredHeight: 28 + horizontalAlignment: Text.AlignRight + text: saveDebounce.running ? Translation.tr("Saving...") : Translation.tr("Saved") + color: Appearance.colors.colSubtext + font.pixelSize: Appearance.font.pixelSize.small + font.weight: Font.Medium } } - + Timer { id: saveDebounce interval: 500 repeat: false onTriggered: saveStickypad() } - + Timer { id: copyListDebounce interval: 100 repeat: false onTriggered: updateCopylistPositions() } - + FileView { id: stickypadFile path: Qt.resolvedUrl(Directories.stickypadPath) onLoaded: { - stickypadContents = stickypadFile.text() + stickypadContents = stickypadFile.text(); if (stickypadInput && stickypadInput.text !== stickypadContents) { - const previousCursor = stickypadInput.cursorPosition - const previousAnchor = stickypadInput.selectionStart - stickypadInput.text = stickypadContents - applySelection(previousCursor, previousAnchor) + const previousCursor = stickypadInput.cursorPosition; + const previousAnchor = stickypadInput.selectionStart; + stickypadInput.text = stickypadContents; + applySelection(previousCursor, previousAnchor); } if (pendingReload) { - pendingReload = false - Qt.callLater(focusStickypadAtEnd) + pendingReload = false; + Qt.callLater(focusStickypadAtEnd); } - Qt.callLater(root.updateCopylistEntries) + Qt.callLater(root.updateCopylistEntries); } - onLoadFailed: (error) => { + onLoadFailed: error => { if (error === FileViewError.FileNotFound) { - stickypadContents = "" - stickypadFile.setText(stickypadContents) + stickypadContents = ""; + stickypadFile.setText(stickypadContents); if (stickypadInput) - stickypadInput.text = stickypadContents + stickypadInput.text = stickypadContents; if (pendingReload) { - pendingReload = false - Qt.callLater(focusStickypadAtEnd) + pendingReload = false; + Qt.callLater(focusStickypadAtEnd); } - Qt.callLater(root.updateCopylistEntries) + Qt.callLater(root.updateCopylistEntries); } else { - console.log("[Stickypad] Error loading file: " + error) + console.log("[Stickypad] Error loading file: " + error); } } } From a3cb292fe9b87e77c1a70a9cd95c649d74d4fd17 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 11:05:50 +0100 Subject: [PATCH 27/85] reduce manual updates by aliasing stickypadContents to input area's text --- .../ii/overlay/stickypad/StickypadContent.qml | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index fe5852c35..99c3b5173 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -12,7 +12,7 @@ import qs.modules.ii.overlay OverlayBackground { id: root - property string stickypadContents: "" + property alias stickypadContents: stickypadInput.text property bool pendingReload: false property var copylistEntries: [] property string lastParsedCopylistText: "" @@ -27,22 +27,21 @@ OverlayBackground { function saveStickypad() { if (!stickypadInput) return; - stickypadContents = stickypadInput.text; - stickypadFile.setText(stickypadContents); + stickypadFile.setText(root.stickypadContents); } function focusStickypadAtEnd() { if (!stickypadInput) return; stickypadInput.forceActiveFocus(); - const endPos = stickypadInput.text.length; + const endPos = root.stickypadContents.length; applySelection(endPos, endPos); } function applySelection(cursorPos, anchorPos) { if (!stickypadInput) return; - const textLength = stickypadInput.text.length; + const textLength = root.stickypadContents.length; const cursor = Math.max(0, Math.min(cursorPos, textLength)); const anchor = Math.max(0, Math.min(anchorPos, textLength)); stickypadInput.select(anchor, cursor); @@ -64,7 +63,7 @@ OverlayBackground { function updateCopylistEntries() { if (!stickypadInput) return; - const textValue = stickypadInput.text; + const textValue = root.stickypadContents; if (!textValue || textValue.length === 0) { lastParsedCopylistText = ""; parsedCopylistLines = []; @@ -175,9 +174,7 @@ OverlayBackground { } root.scheduleCopylistUpdate(true); } - onCursorPositionChanged: root.scheduleCopylistUpdate() - onSelectionStartChanged: root.scheduleCopylistUpdate() - onSelectionEndChanged: root.scheduleCopylistUpdate() + onHeightChanged: root.scheduleCopylistUpdate(true) onContentHeightChanged: root.scheduleCopylistUpdate(true) } @@ -291,28 +288,26 @@ OverlayBackground { id: stickypadFile path: Qt.resolvedUrl(Directories.stickypadPath) onLoaded: { - stickypadContents = stickypadFile.text(); - if (stickypadInput && stickypadInput.text !== stickypadContents) { + root.stickypadContents = stickypadFile.text(); + if (root.stickypadContents !== root.stickypadContents) { const previousCursor = stickypadInput.cursorPosition; const previousAnchor = stickypadInput.selectionStart; - stickypadInput.text = stickypadContents; + root.stickypadContents = root.stickypadContents; applySelection(previousCursor, previousAnchor); } if (pendingReload) { pendingReload = false; - Qt.callLater(focusStickypadAtEnd); + Qt.callLater(root.focusStickypadAtEnd); } Qt.callLater(root.updateCopylistEntries); } onLoadFailed: error => { if (error === FileViewError.FileNotFound) { - stickypadContents = ""; - stickypadFile.setText(stickypadContents); - if (stickypadInput) - stickypadInput.text = stickypadContents; + root.stickypadContents = ""; + stickypadFile.setText(root.stickypadContents); if (pendingReload) { pendingReload = false; - Qt.callLater(focusStickypadAtEnd); + Qt.callLater(root.focusStickypadAtEnd); } Qt.callLater(root.updateCopylistEntries); } else { From eb8f1379f2ff50e707728629a391fd730c8caf13 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 11:09:26 +0100 Subject: [PATCH 28/85] fix null warning --- .../ii/modules/ii/overlay/stickypad/StickypadContent.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index 99c3b5173..aa4507e0a 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -53,7 +53,7 @@ OverlayBackground { if (!stickypadInput) return; if (immediate) { - copyListDebounce.stop(); + copyListDebounce?.stop(); updateCopylistEntries(); } else { copyListDebounce.restart(); From 8404817e51dc04449d40a21c5eb4622bc13775be Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 11:13:49 +0100 Subject: [PATCH 29/85] capitalize L in copyList --- .../ii/overlay/stickypad/StickypadContent.qml | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index aa4507e0a..3f4818cb5 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -14,14 +14,14 @@ OverlayBackground { property alias stickypadContents: stickypadInput.text property bool pendingReload: false - property var copylistEntries: [] + property var copyListEntries: [] property string lastParsedCopylistText: "" property var parsedCopylistLines: [] property bool isClickthrough: false Component.onCompleted: { stickypadFile.reload(); - updateCopylistEntries(); + updateCopyListEntries(); } function saveStickypad() { @@ -54,20 +54,20 @@ OverlayBackground { return; if (immediate) { copyListDebounce?.stop(); - updateCopylistEntries(); + updateCopyListEntries(); } else { copyListDebounce.restart(); } } - function updateCopylistEntries() { + function updateCopyListEntries() { if (!stickypadInput) return; const textValue = root.stickypadContents; if (!textValue || textValue.length === 0) { lastParsedCopylistText = ""; parsedCopylistLines = []; - copylistEntries = []; + root.copyListEntries = []; return; } @@ -94,7 +94,7 @@ OverlayBackground { lastParsedCopylistText = textValue; parsedCopylistLines = parsed; if (parsed.length === 0) { - copylistEntries = []; + root.copyListEntries = []; return; } } @@ -131,7 +131,7 @@ OverlayBackground { }; }).filter(entry => entry !== null); - copylistEntries = entries; + root.copyListEntries = entries; } ColumnLayout { @@ -181,11 +181,13 @@ OverlayBackground { Item { anchors.fill: stickypadInput - visible: copylistEntries.length > 0 + visible: root.copyListEntries.length > 0 clip: true Repeater { - model: copylistEntries + model: ScriptModel { + values: root.copyListEntries + } delegate: Item { readonly property real lineHeight: Math.max(modelData.height, Appearance.font.pixelSize.normal + 6) readonly property real iconSizeLocal: Appearance.font.pixelSize.normal @@ -261,12 +263,9 @@ OverlayBackground { StyledText { id: statusLabel Layout.fillWidth: true - // Layout.preferredHeight: 28 horizontalAlignment: Text.AlignRight - text: saveDebounce.running ? Translation.tr("Saving...") : Translation.tr("Saved") + text: saveDebounce.running ? Translation.tr("Saving...") : Translation.tr("Saved ") color: Appearance.colors.colSubtext - font.pixelSize: Appearance.font.pixelSize.small - font.weight: Font.Medium } } @@ -299,7 +298,7 @@ OverlayBackground { pendingReload = false; Qt.callLater(root.focusStickypadAtEnd); } - Qt.callLater(root.updateCopylistEntries); + Qt.callLater(root.updateCopyListEntries); } onLoadFailed: error => { if (error === FileViewError.FileNotFound) { @@ -309,7 +308,7 @@ OverlayBackground { pendingReload = false; Qt.callLater(root.focusStickypadAtEnd); } - Qt.callLater(root.updateCopylistEntries); + Qt.callLater(root.updateCopyListEntries); } else { console.log("[Stickypad] Error loading file: " + error); } From 5bec6594863a8509b18297889d7565c0bd80b465 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 11:18:31 +0100 Subject: [PATCH 30/85] stickypad: remove redundant stuff, make clickable text area larger --- .../ii/overlay/stickypad/StickypadContent.qml | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index 3f4818cb5..1dad37cd1 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -136,11 +136,8 @@ OverlayBackground { ColumnLayout { id: stickypadLayout - anchors { - fill: parent - margins: 16 - } - spacing: 10 + anchors.fill: parent + spacing: 0 ScrollView { id: editorScrollView @@ -162,11 +159,8 @@ OverlayBackground { persistentSelection: true textFormat: TextEdit.PlainText background: null - rightPadding: 44 - // Disable text area when clickthrough enabled - START - enabled: GlobalStates.overlayOpen || !root.isClickthrough - activeFocusOnTab: GlobalStates.overlayOpen || !root.isClickthrough - // Disable text area when clickthrough enabled - END + padding: 16 + rightPadding: 44 + padding onTextChanged: { if (stickypadInput.activeFocus) { @@ -263,6 +257,7 @@ OverlayBackground { StyledText { id: statusLabel Layout.fillWidth: true + Layout.margins: 16 horizontalAlignment: Text.AlignRight text: saveDebounce.running ? Translation.tr("Saving...") : Translation.tr("Saved ") color: Appearance.colors.colSubtext From c16cff52b87753b91aa237124fd2e9ad5c59132b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 11:44:25 +0100 Subject: [PATCH 31/85] simplify copy button --- .../ii/overlay/stickypad/StickypadContent.qml | 76 +++++-------------- 1 file changed, 20 insertions(+), 56 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index 1dad37cd1..4055929ae 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -171,6 +171,9 @@ OverlayBackground { onHeightChanged: root.scheduleCopylistUpdate(true) onContentHeightChanged: root.scheduleCopylistUpdate(true) + onCursorPositionChanged: root.scheduleCopylistUpdate() + onSelectionStartChanged: root.scheduleCopylistUpdate() + onSelectionEndChanged: root.scheduleCopylistUpdate() } Item { @@ -182,72 +185,33 @@ OverlayBackground { model: ScriptModel { values: root.copyListEntries } - delegate: Item { - readonly property real lineHeight: Math.max(modelData.height, Appearance.font.pixelSize.normal + 6) + delegate: RippleButton { + id: copyButton + required property var modelData + readonly property real lineHeight: Math.min(Math.max(modelData.height, Appearance.font.pixelSize.normal + 6), 40) readonly property real iconSizeLocal: Appearance.font.pixelSize.normal readonly property real hitPadding: 6 - width: iconSizeLocal + hitPadding * 2 - height: lineHeight + implicitHeight: lineHeight + implicitWidth: lineHeight + buttonRadius: height / 2 y: modelData.y - x: Math.max(stickypadInput.width - width - 8, 0) + x: Math.max(stickypadInput.width - width - 16, 0) z: 5 - Rectangle { - id: feedbackFlash - anchors.centerIn: iconItem - width: iconSizeLocal + hitPadding - height: width - radius: width / 2 - color: Appearance.colors.colLayer2 - opacity: 0 - z: 999 + onClicked: { + Quickshell.clipboardText = copyButton.modelData.content; } - MaterialSymbol { - id: iconItem + contentItem: Item { anchors.centerIn: parent - text: "content_copy" - iconSize: iconSizeLocal - color: Appearance.colors.colOnLayer1 - opacity: mouseArea.containsMouse ? 1 : 0.85 - scale: 1 - Behavior on scale { - NumberAnimation { - duration: 120 - easing.type: Easing.OutQuad - } + MaterialSymbol { + id: iconItem + anchors.centerIn: parent + text: "content_copy" + iconSize: copyButton.iconSizeLocal + color: Appearance.colors.colOnLayer1 } - Behavior on opacity { - NumberAnimation { - duration: 120 - } - } - } - - MouseArea { - id: mouseArea - anchors.fill: parent - anchors.margins: hitPadding - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onPressed: iconItem.scale = 0.85 - onReleased: iconItem.scale = 1 - onCanceled: iconItem.scale = 1 - onClicked: { - feedbackFlash.opacity = 0.6; - feedbackFade.restart(); - Quickshell.clipboardText = modelData.content; - } - } - - NumberAnimation { - id: feedbackFade - target: feedbackFlash - property: "opacity" - to: 0 - duration: 200 - easing.type: Easing.OutQuad } } } From 4ea48d60f8f15a1db278f7113296c5ba83204ffa Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 11:46:21 +0100 Subject: [PATCH 32/85] stickypad: feedback for copy --- .../ii/overlay/stickypad/StickypadContent.qml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index 4055929ae..22c467bf8 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -191,6 +191,7 @@ OverlayBackground { readonly property real lineHeight: Math.min(Math.max(modelData.height, Appearance.font.pixelSize.normal + 6), 40) readonly property real iconSizeLocal: Appearance.font.pixelSize.normal readonly property real hitPadding: 6 + property bool justCopied: false implicitHeight: lineHeight implicitWidth: lineHeight @@ -199,8 +200,18 @@ OverlayBackground { x: Math.max(stickypadInput.width - width - 16, 0) z: 5 + Timer { + id: resetState + interval: 700 + onTriggered: { + copyButton.justCopied = false; + } + } + onClicked: { Quickshell.clipboardText = copyButton.modelData.content; + justCopied = true; + resetState.start(); } contentItem: Item { @@ -208,7 +219,7 @@ OverlayBackground { MaterialSymbol { id: iconItem anchors.centerIn: parent - text: "content_copy" + text: copyButton.justCopied ? "check" : "content_copy" iconSize: copyButton.iconSizeLocal color: Appearance.colors.colOnLayer1 } From 02afa37da157579842f61ed7c6b5314c12e3c3f3 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 13:34:12 +0100 Subject: [PATCH 33/85] stickypad: adjust spacing --- .../ii/modules/ii/overlay/stickypad/StickypadContent.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index 22c467bf8..364df7bc0 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -113,6 +113,7 @@ OverlayBackground { const rangeEnd = Math.max(selectionStart, selectionEnd); const entries = parsedCopylistLines.map(line => { + // Don't show copy button if line is (partially) selected const caretIntersects = rangeEnd > line.start && rangeStart <= line.end; if (caretIntersects) return null; @@ -137,7 +138,7 @@ OverlayBackground { ColumnLayout { id: stickypadLayout anchors.fill: parent - spacing: 0 + spacing: -16 ScrollView { id: editorScrollView @@ -147,7 +148,7 @@ OverlayBackground { ScrollBar.vertical.policy: ScrollBar.AsNeeded onWidthChanged: root.scheduleCopylistUpdate(true) - StyledTextArea { + StyledTextArea { // This has to be a direct child of ScrollView for proper scrolling id: stickypadInput anchors { left: parent.left From 2ccdf3b751edfeb87cc6f2bf0333f26ae98e9ae2 Mon Sep 17 00:00:00 2001 From: Firmino Veras Date: Fri, 14 Nov 2025 09:55:06 -0300 Subject: [PATCH 34/85] add option to open tooltips by pressing the mouse button --- .../quickshell/ii/modules/common/Config.qml | 3 +++ .../ii/modules/ii/bar/BatteryIndicator.qml | 2 +- .../ii/modules/ii/bar/ClockWidget.qml | 3 +-- .../quickshell/ii/modules/ii/bar/Resources.qml | 2 +- .../ii/modules/ii/bar/weather/WeatherBar.qml | 18 +++++++++++------- .../ii/verticalBar/BatteryIndicator.qml | 2 +- .../ii/modules/ii/verticalBar/Resources.qml | 2 +- .../ii/verticalBar/VerticalClockWidget.qml | 2 +- .../modules/ii/verticalBar/VerticalMedia.qml | 2 +- .../ii/modules/settings/BarConfig.qml | 13 +++++++++++++ 10 files changed, 34 insertions(+), 15 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml index a724c043d..993d48398 100644 --- a/dots/.config/quickshell/ii/modules/common/Config.qml +++ b/dots/.config/quickshell/ii/modules/common/Config.qml @@ -264,6 +264,9 @@ Singleton { property bool showUnreadCount: false } } + property JsonObject tooltips: JsonObject { + property bool clickToShow: false + } } property JsonObject battery: JsonObject { diff --git a/dots/.config/quickshell/ii/modules/ii/bar/BatteryIndicator.qml b/dots/.config/quickshell/ii/modules/ii/bar/BatteryIndicator.qml index 3cabf9f36..36799fefd 100644 --- a/dots/.config/quickshell/ii/modules/ii/bar/BatteryIndicator.qml +++ b/dots/.config/quickshell/ii/modules/ii/bar/BatteryIndicator.qml @@ -16,7 +16,7 @@ MouseArea { implicitWidth: batteryProgress.implicitWidth implicitHeight: Appearance.sizes.barHeight - hoverEnabled: true + hoverEnabled: !Config.options.bar.tooltips.clickToShow ClippedProgressBar { id: batteryProgress diff --git a/dots/.config/quickshell/ii/modules/ii/bar/ClockWidget.qml b/dots/.config/quickshell/ii/modules/ii/bar/ClockWidget.qml index 958695a86..1d4b9f865 100644 --- a/dots/.config/quickshell/ii/modules/ii/bar/ClockWidget.qml +++ b/dots/.config/quickshell/ii/modules/ii/bar/ClockWidget.qml @@ -40,8 +40,7 @@ Item { MouseArea { id: mouseArea anchors.fill: parent - hoverEnabled: true - acceptedButtons: Qt.NoButton + hoverEnabled: !Config.options.bar.tooltips.clickToShow ClockWidgetPopup { hoverTarget: mouseArea diff --git a/dots/.config/quickshell/ii/modules/ii/bar/Resources.qml b/dots/.config/quickshell/ii/modules/ii/bar/Resources.qml index 6c25ab507..2d9e936ac 100644 --- a/dots/.config/quickshell/ii/modules/ii/bar/Resources.qml +++ b/dots/.config/quickshell/ii/modules/ii/bar/Resources.qml @@ -9,7 +9,7 @@ MouseArea { property bool alwaysShowAllResources: false implicitWidth: rowLayout.implicitWidth + rowLayout.anchors.leftMargin + rowLayout.anchors.rightMargin implicitHeight: Appearance.sizes.barHeight - hoverEnabled: true + hoverEnabled: !Config.options.bar.tooltips.clickToShow RowLayout { id: rowLayout diff --git a/dots/.config/quickshell/ii/modules/ii/bar/weather/WeatherBar.qml b/dots/.config/quickshell/ii/modules/ii/bar/weather/WeatherBar.qml index 1fcde7176..e82f41dab 100644 --- a/dots/.config/quickshell/ii/modules/ii/bar/weather/WeatherBar.qml +++ b/dots/.config/quickshell/ii/modules/ii/bar/weather/WeatherBar.qml @@ -13,15 +13,19 @@ MouseArea { implicitWidth: rowLayout.implicitWidth + 10 * 2 implicitHeight: Appearance.sizes.barHeight - hoverEnabled: true + acceptedButtons: Qt.LeftButton | Qt.RightButton + hoverEnabled: !Config.options.bar.tooltips.clickToShow onPressed: { - Weather.getData(); - Quickshell.execDetached(["notify-send", - Translation.tr("Weather"), - Translation.tr("Refreshing (manually triggered)") - , "-a", "Shell" - ]) + if (mouse.button === Qt.RightButton) { + Weather.getData(); + Quickshell.execDetached(["notify-send", + Translation.tr("Weather"), + Translation.tr("Refreshing (manually triggered)") + , "-a", "Shell" + ]) + mouse.accepted = false + } } RowLayout { diff --git a/dots/.config/quickshell/ii/modules/ii/verticalBar/BatteryIndicator.qml b/dots/.config/quickshell/ii/modules/ii/verticalBar/BatteryIndicator.qml index d2b729244..3f20cbd2c 100644 --- a/dots/.config/quickshell/ii/modules/ii/verticalBar/BatteryIndicator.qml +++ b/dots/.config/quickshell/ii/modules/ii/verticalBar/BatteryIndicator.qml @@ -15,7 +15,7 @@ MouseArea { readonly property bool isLow: percentage <= Config.options.battery.low / 100 implicitHeight: batteryProgress.implicitHeight - hoverEnabled: true + hoverEnabled: !Config.options.bar.tooltips.clickToShow ClippedProgressBar { id: batteryProgress diff --git a/dots/.config/quickshell/ii/modules/ii/verticalBar/Resources.qml b/dots/.config/quickshell/ii/modules/ii/verticalBar/Resources.qml index 353874723..1c3815721 100644 --- a/dots/.config/quickshell/ii/modules/ii/verticalBar/Resources.qml +++ b/dots/.config/quickshell/ii/modules/ii/verticalBar/Resources.qml @@ -9,7 +9,7 @@ MouseArea { property bool alwaysShowAllResources: false implicitHeight: columnLayout.implicitHeight implicitWidth: columnLayout.implicitWidth - hoverEnabled: true + hoverEnabled: !Config.options.bar.tooltips.clickToShow ColumnLayout { id: columnLayout diff --git a/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalClockWidget.qml b/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalClockWidget.qml index 15a49c5a5..3fdacc337 100644 --- a/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalClockWidget.qml +++ b/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalClockWidget.qml @@ -33,7 +33,7 @@ Item { MouseArea { id: mouseArea anchors.fill: parent - hoverEnabled: true + hoverEnabled: !Config.options.bar.tooltips.clickToShow acceptedButtons: Qt.NoButton Bar.ClockWidgetPopup { diff --git a/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalMedia.qml b/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalMedia.qml index 8d38caa76..4db432b26 100644 --- a/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalMedia.qml +++ b/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalMedia.qml @@ -28,7 +28,7 @@ MouseArea { } acceptedButtons: Qt.MiddleButton | Qt.BackButton | Qt.ForwardButton | Qt.RightButton | Qt.LeftButton - hoverEnabled: true + hoverEnabled: !Config.options.bar.tooltips.clickToShow onPressed: (event) => { if (event.button === Qt.MiddleButton) { activePlayer.togglePlaying(); diff --git a/dots/.config/quickshell/ii/modules/settings/BarConfig.qml b/dots/.config/quickshell/ii/modules/settings/BarConfig.qml index a53d30644..182124693 100644 --- a/dots/.config/quickshell/ii/modules/settings/BarConfig.qml +++ b/dots/.config/quickshell/ii/modules/settings/BarConfig.qml @@ -334,4 +334,17 @@ ContentPage { } } } + + ContentSection { + icon: "tooltip" + title: Translation.tr("Tooltips") + ConfigSwitch { + buttonIcon: "web_traffic" + text: Translation.tr("Click to show") + checked: Config.options.bar.tooltips.clickToShow + onCheckedChanged: { + Config.options.bar.tooltips.clickToShow = checked; + } + } + } } From 42f29d47b4993959284ec598bace7566eb983afc Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 14:26:02 +0100 Subject: [PATCH 35/85] stickypad: adjust copy button size --- .../ii/modules/ii/overlay/stickypad/StickypadContent.qml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml index 364df7bc0..f0e8185d4 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml @@ -18,6 +18,7 @@ OverlayBackground { property string lastParsedCopylistText: "" property var parsedCopylistLines: [] property bool isClickthrough: false + property real maxCopyButtonSize: 20 Component.onCompleted: { stickypadFile.reload(); @@ -161,7 +162,7 @@ OverlayBackground { textFormat: TextEdit.PlainText background: null padding: 16 - rightPadding: 44 + padding + rightPadding: root.maxCopyButtonSize + padding onTextChanged: { if (stickypadInput.activeFocus) { @@ -189,7 +190,7 @@ OverlayBackground { delegate: RippleButton { id: copyButton required property var modelData - readonly property real lineHeight: Math.min(Math.max(modelData.height, Appearance.font.pixelSize.normal + 6), 40) + readonly property real lineHeight: Math.min(Math.max(modelData.height, Appearance.font.pixelSize.normal + 6), root.maxCopyButtonSize) readonly property real iconSizeLocal: Appearance.font.pixelSize.normal readonly property real hitPadding: 6 property bool justCopied: false @@ -198,7 +199,8 @@ OverlayBackground { implicitWidth: lineHeight buttonRadius: height / 2 y: modelData.y - x: Math.max(stickypadInput.width - width - 16, 0) + anchors.right: parent.right + anchors.rightMargin: 16 z: 5 Timer { From c19dd725b85bc8357d3617cbf3b61edeb82fa82c Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 14:32:58 +0100 Subject: [PATCH 36/85] really rename all "stickypad" to "notes" --- .../ii/modules/common/Directories.qml | 2 +- .../overlay/OverlayWidgetDelegateChooser.qml | 4 +- .../Stickypad.qml => notes/Notes.qml} | 2 +- .../NotesContent.qml} | 82 +++++++++---------- 4 files changed, 45 insertions(+), 45 deletions(-) rename dots/.config/quickshell/ii/modules/ii/overlay/{stickypad/Stickypad.qml => notes/Notes.qml} (89%) rename dots/.config/quickshell/ii/modules/ii/overlay/{stickypad/StickypadContent.qml => notes/NotesContent.qml} (79%) diff --git a/dots/.config/quickshell/ii/modules/common/Directories.qml b/dots/.config/quickshell/ii/modules/common/Directories.qml index 04b205baf..56f647684 100644 --- a/dots/.config/quickshell/ii/modules/common/Directories.qml +++ b/dots/.config/quickshell/ii/modules/common/Directories.qml @@ -33,7 +33,7 @@ Singleton { property string shellConfigName: "config.json" property string shellConfigPath: `${Directories.shellConfig}/${Directories.shellConfigName}` property string todoPath: FileUtils.trimFileProtocol(`${Directories.state}/user/todo.json`) - property string stickypadPath: FileUtils.trimFileProtocol(`${Directories.state}/user/stickypad.txt`) + property string notesPath: FileUtils.trimFileProtocol(`${Directories.state}/user/notes.txt`) property string conflictCachePath: FileUtils.trimFileProtocol(`${Directories.cache}/conflict-killer`) property string notificationsPath: FileUtils.trimFileProtocol(`${Directories.cache}/notifications/notifications.json`) property string generatedMaterialThemePath: FileUtils.trimFileProtocol(`${Directories.state}/user/generated/colors.json`) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml index b7b26b9cf..e004be7dd 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayWidgetDelegateChooser.qml @@ -12,7 +12,7 @@ import qs.modules.ii.overlay.floatingImage import qs.modules.ii.overlay.fpsLimiter import qs.modules.ii.overlay.recorder import qs.modules.ii.overlay.resources -import qs.modules.ii.overlay.stickypad +import qs.modules.ii.overlay.notes DelegateChooser { id: root @@ -23,6 +23,6 @@ DelegateChooser { DelegateChoice { roleValue: "fpsLimiter"; FpsLimiter {} } DelegateChoice { roleValue: "recorder"; Recorder {} } DelegateChoice { roleValue: "resources"; Resources {} } - DelegateChoice { roleValue: "notes"; Stickypad {} } + DelegateChoice { roleValue: "notes"; Notes {} } DelegateChoice { roleValue: "volumeMixer"; VolumeMixer {} } } diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml b/dots/.config/quickshell/ii/modules/ii/overlay/notes/Notes.qml similarity index 89% rename from dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml rename to dots/.config/quickshell/ii/modules/ii/overlay/notes/Notes.qml index e6a60bd78..64aa11d05 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/Stickypad.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/notes/Notes.qml @@ -10,7 +10,7 @@ StyledOverlayWidget { title: Translation.tr("Notes") showCenterButton: true - contentItem: StickypadContent { + contentItem: NotesContent { radius: root.contentRadius isClickthrough: root.clickthrough } diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/notes/NotesContent.qml similarity index 79% rename from dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml rename to dots/.config/quickshell/ii/modules/ii/overlay/notes/NotesContent.qml index f0e8185d4..dfcc4e052 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/stickypad/StickypadContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/notes/NotesContent.qml @@ -12,7 +12,7 @@ import qs.modules.ii.overlay OverlayBackground { id: root - property alias stickypadContents: stickypadInput.text + property alias content: textInput.text property bool pendingReload: false property var copyListEntries: [] property string lastParsedCopylistText: "" @@ -21,37 +21,37 @@ OverlayBackground { property real maxCopyButtonSize: 20 Component.onCompleted: { - stickypadFile.reload(); + noteFile.reload(); updateCopyListEntries(); } - function saveStickypad() { - if (!stickypadInput) + function saveContent() { + if (!textInput) return; - stickypadFile.setText(root.stickypadContents); + noteFile.setText(root.content); } - function focusStickypadAtEnd() { - if (!stickypadInput) + function focusAtEnd() { + if (!textInput) return; - stickypadInput.forceActiveFocus(); - const endPos = root.stickypadContents.length; + textInput.forceActiveFocus(); + const endPos = root.content.length; applySelection(endPos, endPos); } function applySelection(cursorPos, anchorPos) { - if (!stickypadInput) + if (!textInput) return; - const textLength = root.stickypadContents.length; + const textLength = root.content.length; const cursor = Math.max(0, Math.min(cursorPos, textLength)); const anchor = Math.max(0, Math.min(anchorPos, textLength)); - stickypadInput.select(anchor, cursor); + textInput.select(anchor, cursor); if (cursor === anchor) - stickypadInput.deselect(); + textInput.deselect(); } function scheduleCopylistUpdate(immediate = false) { - if (!stickypadInput) + if (!textInput) return; if (immediate) { copyListDebounce?.stop(); @@ -62,9 +62,9 @@ OverlayBackground { } function updateCopyListEntries() { - if (!stickypadInput) + if (!textInput) return; - const textValue = root.stickypadContents; + const textValue = root.content; if (!textValue || textValue.length === 0) { lastParsedCopylistText = ""; parsedCopylistLines = []; @@ -104,12 +104,12 @@ OverlayBackground { } function updateCopylistPositions() { - if (!stickypadInput || parsedCopylistLines.length === 0) + if (!textInput || parsedCopylistLines.length === 0) return; - const rawSelectionStart = stickypadInput.selectionStart; - const rawSelectionEnd = stickypadInput.selectionEnd; - const selectionStart = rawSelectionStart === -1 ? stickypadInput.cursorPosition : rawSelectionStart; - const selectionEnd = rawSelectionEnd === -1 ? stickypadInput.cursorPosition : rawSelectionEnd; + const rawSelectionStart = textInput.selectionStart; + const rawSelectionEnd = textInput.selectionEnd; + const selectionStart = rawSelectionStart === -1 ? textInput.cursorPosition : rawSelectionStart; + const selectionEnd = rawSelectionEnd === -1 ? textInput.cursorPosition : rawSelectionEnd; const rangeStart = Math.min(selectionStart, selectionEnd); const rangeEnd = Math.max(selectionStart, selectionEnd); @@ -118,14 +118,14 @@ OverlayBackground { const caretIntersects = rangeEnd > line.start && rangeStart <= line.end; if (caretIntersects) return null; - const startRect = stickypadInput.positionToRectangle(line.start); - let endRect = stickypadInput.positionToRectangle(line.end); + const startRect = textInput.positionToRectangle(line.start); + let endRect = textInput.positionToRectangle(line.end); if (!isFinite(startRect.y)) return null; if (!isFinite(endRect.y)) endRect = startRect; const lineBottom = endRect.y + endRect.height; - const rectHeight = Math.max(lineBottom - startRect.y, stickypadInput.font.pixelSize + 8); + const rectHeight = Math.max(lineBottom - startRect.y, textInput.font.pixelSize + 8); return { content: line.content, y: startRect.y, @@ -137,7 +137,7 @@ OverlayBackground { } ColumnLayout { - id: stickypadLayout + id: contentItem anchors.fill: parent spacing: -16 @@ -150,7 +150,7 @@ OverlayBackground { onWidthChanged: root.scheduleCopylistUpdate(true) StyledTextArea { // This has to be a direct child of ScrollView for proper scrolling - id: stickypadInput + id: textInput anchors { left: parent.left right: parent.right @@ -165,7 +165,7 @@ OverlayBackground { rightPadding: root.maxCopyButtonSize + padding onTextChanged: { - if (stickypadInput.activeFocus) { + if (textInput.activeFocus) { saveDebounce.restart(); } root.scheduleCopylistUpdate(true); @@ -179,7 +179,7 @@ OverlayBackground { } Item { - anchors.fill: stickypadInput + anchors.fill: textInput visible: root.copyListEntries.length > 0 clip: true @@ -246,7 +246,7 @@ OverlayBackground { id: saveDebounce interval: 500 repeat: false - onTriggered: saveStickypad() + onTriggered: saveContent() } Timer { @@ -257,33 +257,33 @@ OverlayBackground { } FileView { - id: stickypadFile - path: Qt.resolvedUrl(Directories.stickypadPath) + id: noteFile + path: Qt.resolvedUrl(Directories.notesPath) onLoaded: { - root.stickypadContents = stickypadFile.text(); - if (root.stickypadContents !== root.stickypadContents) { - const previousCursor = stickypadInput.cursorPosition; - const previousAnchor = stickypadInput.selectionStart; - root.stickypadContents = root.stickypadContents; + root.content = noteFile.text(); + if (root.content !== root.content) { + const previousCursor = textInput.cursorPosition; + const previousAnchor = textInput.selectionStart; + root.content = root.content; applySelection(previousCursor, previousAnchor); } if (pendingReload) { pendingReload = false; - Qt.callLater(root.focusStickypadAtEnd); + Qt.callLater(root.focusAtEnd); } Qt.callLater(root.updateCopyListEntries); } onLoadFailed: error => { if (error === FileViewError.FileNotFound) { - root.stickypadContents = ""; - stickypadFile.setText(root.stickypadContents); + root.content = ""; + noteFile.setText(root.content); if (pendingReload) { pendingReload = false; - Qt.callLater(root.focusStickypadAtEnd); + Qt.callLater(root.focusAtEnd); } Qt.callLater(root.updateCopyListEntries); } else { - console.log("[Stickypad] Error loading file: " + error); + console.log("[Overlay Notes] Error loading file: " + error); } } } From 11064d04f024ce9cd7fb2d41396d64ed421d2b51 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 15:37:02 +0100 Subject: [PATCH 37/85] use a proper icon for tooltips click to show option --- dots/.config/quickshell/ii/modules/settings/BarConfig.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/settings/BarConfig.qml b/dots/.config/quickshell/ii/modules/settings/BarConfig.qml index 182124693..06e694bc8 100644 --- a/dots/.config/quickshell/ii/modules/settings/BarConfig.qml +++ b/dots/.config/quickshell/ii/modules/settings/BarConfig.qml @@ -339,7 +339,7 @@ ContentPage { icon: "tooltip" title: Translation.tr("Tooltips") ConfigSwitch { - buttonIcon: "web_traffic" + buttonIcon: "ads_click" text: Translation.tr("Click to show") checked: Config.options.bar.tooltips.clickToShow onCheckedChanged: { From 541c701d5a19879d2146458524ba55e35b12dedd Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 15:41:37 +0100 Subject: [PATCH 38/85] fix click to show for vertical bar clock --- .../quickshell/ii/modules/ii/verticalBar/VerticalClockWidget.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalClockWidget.qml b/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalClockWidget.qml index 3fdacc337..3f9ca818a 100644 --- a/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalClockWidget.qml +++ b/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalClockWidget.qml @@ -34,7 +34,6 @@ Item { id: mouseArea anchors.fill: parent hoverEnabled: !Config.options.bar.tooltips.clickToShow - acceptedButtons: Qt.NoButton Bar.ClockWidgetPopup { hoverTarget: mouseArea From bd284a5ef457dc31b55789dc653ac00482c3144e Mon Sep 17 00:00:00 2001 From: nrand Date: Fri, 14 Nov 2025 17:49:02 +0200 Subject: [PATCH 39/85] clock: code cleanups + cookie by default --- .../quickshell/ii/modules/common/Config.qml | 2 +- .../ii/modules/settings/BackgroundConfig.qml | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml index 2987faed2..a71f6e9e7 100644 --- a/dots/.config/quickshell/ii/modules/common/Config.qml +++ b/dots/.config/quickshell/ii/modules/common/Config.qml @@ -158,7 +158,7 @@ Singleton { property real x: 100 property real y: 100 property string style: "cookie" // Options: "cookie", "digital" - property string styleLocked: "digital" // Options: "cookie", "digital" + property string styleLocked: "cookie" // Options: "cookie", "digital" property JsonObject cookie: JsonObject { property bool aiStyling: false property int sides: 14 diff --git a/dots/.config/quickshell/ii/modules/settings/BackgroundConfig.qml b/dots/.config/quickshell/ii/modules/settings/BackgroundConfig.qml index c12a04c54..66630cc24 100644 --- a/dots/.config/quickshell/ii/modules/settings/BackgroundConfig.qml +++ b/dots/.config/quickshell/ii/modules/settings/BackgroundConfig.qml @@ -57,8 +57,18 @@ ContentPage { title: Translation.tr("Widget: Clock") id: settingsClock - readonly property bool digitalPresent: (!Config.options.background.widgets.clock.showOnlyWhenLocked && Config.options.background.widgets.clock.style === "digital") || Config.options.background.widgets.clock.styleLocked === "digital" - readonly property bool cookiePresent: (!Config.options.background.widgets.clock.showOnlyWhenLocked && Config.options.background.widgets.clock.style === "cookie") || Config.options.background.widgets.clock.styleLocked === "cookie" + function stylePresent(styleName) { + if (!Config.options.background.widgets.clock.showOnlyWhenLocked && Config.options.background.widgets.clock.style === styleName) { + return true; + } + if (Config.options.background.widgets.clock.styleLocked === styleName) { + return true; + } + return false; + } + + readonly property bool digitalPresent: stylePresent("digital") + readonly property bool cookiePresent: stylePresent("cookie") ConfigRow { Layout.fillWidth: true From cc519e9f601b2eddd49b9b093d7db838306d4e3b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 22:46:11 +0100 Subject: [PATCH 40/85] background: make switching between clock stylies less janky --- .../.config/quickshell/ii/modules/common/widgets/FadeLoader.qml | 2 ++ .../ii/modules/ii/background/widgets/clock/ClockWidget.qml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/dots/.config/quickshell/ii/modules/common/widgets/FadeLoader.qml b/dots/.config/quickshell/ii/modules/common/widgets/FadeLoader.qml index aaa2753f8..f5064939b 100644 --- a/dots/.config/quickshell/ii/modules/common/widgets/FadeLoader.qml +++ b/dots/.config/quickshell/ii/modules/common/widgets/FadeLoader.qml @@ -6,11 +6,13 @@ import qs.modules.common.widgets Loader { id: root property bool shown: true + property alias fade: opacityBehavior.enabled opacity: shown ? 1 : 0 visible: opacity > 0 active: opacity > 0 Behavior on opacity { + id: opacityBehavior animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } } diff --git a/dots/.config/quickshell/ii/modules/ii/background/widgets/clock/ClockWidget.qml b/dots/.config/quickshell/ii/modules/ii/background/widgets/clock/ClockWidget.qml index 2c58b19f7..97e1e468a 100644 --- a/dots/.config/quickshell/ii/modules/ii/background/widgets/clock/ClockWidget.qml +++ b/dots/.config/quickshell/ii/modules/ii/background/widgets/clock/ClockWidget.qml @@ -44,6 +44,7 @@ AbstractBackgroundWidget { id: cookieClockLoader anchors.horizontalCenter: parent.horizontalCenter shown: root.clockStyle === "cookie" && (root.shouldShow) + fade: false sourceComponent: Column { spacing: 10 CookieClock { @@ -61,6 +62,7 @@ AbstractBackgroundWidget { id: digitalClockLoader anchors.horizontalCenter: parent.horizontalCenter shown: root.clockStyle === "digital" && (root.shouldShow) + fade: false sourceComponent: ColumnLayout { id: clockColumn spacing: 6 From 3c25d18f88937e22048451720c344d6dee33b998 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 23:00:56 +0100 Subject: [PATCH 41/85] sidebar: grey out bluetooth button if unavailable --- .../quickToggles/androidStyle/AndroidBluetoothToggle.qml | 1 + .../quickToggles/androidStyle/AndroidQuickToggleButton.qml | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidBluetoothToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidBluetoothToggle.qml index ae76d5751..4b35cf51a 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidBluetoothToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidBluetoothToggle.qml @@ -12,6 +12,7 @@ AndroidQuickToggleButton { name: Translation.tr("Bluetooth") statusText: BluetoothStatus.firstActiveDevice?.name ?? Translation.tr("No device") + available: BluetoothStatus.available toggled: BluetoothStatus.enabled buttonIcon: BluetoothStatus.connected ? "bluetooth_connected" : BluetoothStatus.enabled ? "bluetooth" : "bluetooth_disabled" mainAction: () => { diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidQuickToggleButton.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidQuickToggleButton.qml index 96401a6c0..31ad2f262 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidQuickToggleButton.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidQuickToggleButton.qml @@ -15,6 +15,7 @@ GroupButton { required property string name required property var mainAction property string statusText: toggled ? Translation.tr("Active") : Translation.tr("Inactive") + property bool available: true required property real baseCellWidth required property real baseCellHeight @@ -42,6 +43,7 @@ GroupButton { signal openMenu() + enabled: available || editMode padding: 6 horizontalPadding: padding verticalPadding: padding @@ -52,8 +54,8 @@ GroupButton { colBackgroundToggledActive: (altAction && expandedSize) ? Appearance.colors.colLayer2Active : Appearance.colors.colPrimaryActive buttonRadius: toggled ? Appearance.rounding.large : height / 2 buttonRadiusPressed: Appearance.rounding.normal - property color colText: (toggled && !(altAction && expandedSize)) ? Appearance.colors.colOnPrimary : Appearance.colors.colOnLayer2 - property color colIcon: expandedSize ? (root.toggled ? Appearance.colors.colOnPrimary : Appearance.colors.colOnLayer3) : colText + property color colText: (toggled && !(altAction && expandedSize) && enabled) ? Appearance.colors.colOnPrimary : ColorUtils.transparentize(Appearance.colors.colOnLayer2, enabled ? 0 : 0.7) + property color colIcon: expandedSize ? ((root.toggled) ? Appearance.colors.colOnPrimary : Appearance.colors.colOnLayer3) : colText onClicked: { if (root.expandedSize && root.altAction) root.altAction(); From 47cd7be87e6dee1cc351a877bcaf80505850ff5e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 14 Nov 2025 23:13:33 +0100 Subject: [PATCH 42/85] grey out easyeffects button if not available --- .../quickToggles/androidStyle/AndroidBluetoothToggle.qml | 1 - .../quickToggles/androidStyle/AndroidEasyEffectsToggle.qml | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidBluetoothToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidBluetoothToggle.qml index 4b35cf51a..d592de63b 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidBluetoothToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidBluetoothToggle.qml @@ -28,4 +28,3 @@ AndroidQuickToggleButton { ) } } - diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidEasyEffectsToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidEasyEffectsToggle.qml index bfd14335c..0ce6b7ab4 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidEasyEffectsToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidEasyEffectsToggle.qml @@ -9,6 +9,7 @@ AndroidQuickToggleButton { name: Translation.tr("EasyEffects") + available: EasyEffects.available toggled: EasyEffects.active buttonIcon: "graphic_eq" From b6dfbf6c973d16da602bb0d5d95b87d2aad4a971 Mon Sep 17 00:00:00 2001 From: clsty Date: Sat, 15 Nov 2025 08:26:50 +0800 Subject: [PATCH 43/85] Add --ignore-outdate; improve outdate message --- sdata/lib/dist-determine.sh | 4 ++- sdata/subcmd-install/1.deps-router.sh | 39 ++++++++++++++++++--------- sdata/subcmd-install/options.sh | 4 ++- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/sdata/lib/dist-determine.sh b/sdata/lib/dist-determine.sh index 46f9afdd8..78f548ac1 100644 --- a/sdata/lib/dist-determine.sh +++ b/sdata/lib/dist-determine.sh @@ -25,7 +25,9 @@ function print_os_group_id_unofficial(){ printf "The support for your distro is provided by the community.\n" printf "It is not officially supported by github:end-4/dots-hyprland .\n" printf "${STY_BOLD}" - printf "If you find out any problems about it, PR is welcomed if you are able to address it. Or, create a discussion about it, but please do not submit issue, because the developers do not use this distro, therefore they cannot help.${STY_RST}\n" + printf "If you find out any problems about it, PR is welcomed if you are able to address it.\n" + printf "Or, create a discussion about it, but please do not submit issue, \n" + printf "because the developers do not use this distro, therefore they cannot help.${STY_RST}\n" printf "${STY_PURPLE}" printf "Proceed only at your own risk.\n" printf "============\n\n" diff --git a/sdata/subcmd-install/1.deps-router.sh b/sdata/subcmd-install/1.deps-router.sh index 1287e4c6f..c21b6b959 100644 --- a/sdata/subcmd-install/1.deps-router.sh +++ b/sdata/subcmd-install/1.deps-router.sh @@ -64,26 +64,39 @@ elif [[ "$OS_GROUP_ID" =~ ^(arch|gentoo|fedora)$ ]]; then if [[ "${tmp_update_status}" =~ ^(OUTDATED|EMPTY_TARGET|EMPTY_SOURCE|FORCE_OUTDATED|WIP)$ ]]; then printf "${STY_RED}${STY_BOLD}===URGENT===${STY_RST}\n" printf "${STY_RED}" - printf "The community provided ./sdata/dist-${TARGET_ID}/ is outdated (status: ${tmp_update_status}),\n" + printf "Status code: ${tmp_update_status}\n" + printf "The community provided ./sdata/dist-${TARGET_ID}/ seems to be outdated,\n" printf "which means it probably does not reflect all latest changes of ./sdata/dist-arch/ .\n" + printf "In such case it may work unexpectedly.${STY_RST}\n" printf "\n" - printf "According to the actual changes, it may still works, but it can also work unexpectedly.\n" - printf "It's highly recommended to check the following links before continue:${STY_RST}\n" + printf "${STY_RED}It's highly recommended to check the following links before continue:${STY_RST}\n" printf "${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/discussions/2140${STY_RST}\n" printf "${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/commits/main/sdata/dist-arch${STY_RST}\n" printf "${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/commits/main/sdata/dist-${TARGET_ID}${STY_RST}\n" printf "\n" - printf "${STY_PURPLE}${STY_INVERT}PR on ./sdata/dist-${TARGET_ID}/ to properly reflect the latest changes of ./sdata/dist-arch is welcomed.${STY_RST}\n" + printf "${STY_PURPLE}PR on ./sdata/dist-${TARGET_ID}/ to properly reflect the latest changes of ./sdata/dist-arch is welcomed.${STY_RST}\n" + printf "${STY_PURPLE}${STY_BOLD}Again, do not create any issue,${STY_RST}\n" + printf "${STY_PURPLE}But you can create a discussion under \"Extra Distros\" category: ${STY_RST}\n" + printf "${STY_PURPLE}${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/discussions/new?category=extra-distros${STY_RST}\n" printf "\n" - if [ "$ask" = "false" ]; then - echo "Urgent problem encountered, aborting...";exit 1 - else - printf "${STY_RED}Still proceed?${STY_RST}\n" - read -p "[y/N]: " p - case "$p" in - [yY])sleep 0;; - *)echo "Aborting...";exit 1;; - esac + if [[ "${tmp_update_status}" = "OUTDATED" ]]; then + printf "${STY_RED}NOTE: The conclusion above is determined automatically by comparing latest Git commit time,\n" + printf "which is not always correct because some changes on \"dist-arch\" is not needed for \"dist-${TARGET_ID}\",\n" + printf "in such case you should just ignore it and continue.\n" + printf "${STY_RST}\n" + fi + printf "\n" + if ! [[ "$IGNORE_OUTDATE_CHECK" = "true" ]]; then + if [ "$ask" = "false" ]; then + printf "${STY_RED}Urgent problem encountered, aborting...${STY_RST}\n";exit 1 + else + printf "${STY_RED}Still proceed?${STY_RST}\n" + read -p "[y/N]: " p + case "$p" in + [yY])sleep 0;; + *)echo "Aborting...";exit 1;; + esac + fi fi fi fi diff --git a/sdata/subcmd-install/options.sh b/sdata/subcmd-install/options.sh index 992010cfb..727a3c13b 100644 --- a/sdata/subcmd-install/options.sh +++ b/sdata/subcmd-install/options.sh @@ -14,6 +14,7 @@ Options for install: --skip-alldeps Skip the whole process installing dependency --skip-allsetups Skip the whole process setting up permissions/services etc --skip-allfiles Skip the whole process copying configuration files + --ignore-outdate Ignore outdate checking for community supported \"dist-*\". -s, --skip-sysupdate Skip system package upgrade e.g. \"sudo pacman -Syu\" --skip-plasmaintg Skip installing plasma-browser-integration --skip-backup Skip backup conflicting files @@ -45,7 +46,7 @@ cleancache(){ # `man getopt` to see more para=$(getopt \ -o hfFk:cs \ - -l help,force,firstrun,fontset:,clean,skip-allgreeting,skip-alldeps,skip-allsetups,skip-allfiles,skip-sysupdate,skip-plasmaintg,skip-backup,skip-quickshell,skip-fish,skip-hyprland,skip-fontconfig,skip-miscconf,core,exp-files,via-nix \ + -l help,force,firstrun,fontset:,clean,skip-allgreeting,skip-alldeps,skip-allsetups,skip-allfiles,ignore-outdate,skip-sysupdate,skip-plasmaintg,skip-backup,skip-quickshell,skip-fish,skip-hyprland,skip-fontconfig,skip-miscconf,core,exp-files,via-nix \ -n "$0" -- "$@") [ $? != 0 ] && echo "$0: Error when getopt, please recheck parameters." && exit 1 ##################################################################################### @@ -76,6 +77,7 @@ while true ; do --skip-allsetups) SKIP_ALLSETUPS=true;shift;; --skip-allfiles) SKIP_ALLFILES=true;shift;; -s|--skip-sysupdate) SKIP_SYSUPDATE=true;shift;; + --ignore-outdate) IGNORE_OUTDATE_CHECK=true;shift;; --skip-plasmaintg) SKIP_PLASMAINTG=true;shift;; --skip-backup) SKIP_BACKUP=true;shift;; --skip-hyprland) SKIP_HYPRLAND=true;shift;; From 6dd0387833dc3d168521329a0b74692426e0741e Mon Sep 17 00:00:00 2001 From: clsty Date: Sat, 15 Nov 2025 08:35:59 +0800 Subject: [PATCH 44/85] Improve message --- sdata/subcmd-install/1.deps-router.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdata/subcmd-install/1.deps-router.sh b/sdata/subcmd-install/1.deps-router.sh index c21b6b959..2d2c78aff 100644 --- a/sdata/subcmd-install/1.deps-router.sh +++ b/sdata/subcmd-install/1.deps-router.sh @@ -81,7 +81,7 @@ elif [[ "$OS_GROUP_ID" =~ ^(arch|gentoo|fedora)$ ]]; then printf "\n" if [[ "${tmp_update_status}" = "OUTDATED" ]]; then printf "${STY_RED}NOTE: The conclusion above is determined automatically by comparing latest Git commit time,\n" - printf "which is not always correct because some changes on \"dist-arch\" is not needed for \"dist-${TARGET_ID}\",\n" + printf "however sometimes the changes on \"dist-arch\" are actually not needed for \"dist-${TARGET_ID}\",\n" printf "in such case you should just ignore it and continue.\n" printf "${STY_RST}\n" fi From 443f86d347c304d2b842ee71fb787d34a51ae06a Mon Sep 17 00:00:00 2001 From: clsty Date: Sat, 15 Nov 2025 09:23:41 +0800 Subject: [PATCH 45/85] Improve message --- sdata/subcmd-install/1.deps-router.sh | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/sdata/subcmd-install/1.deps-router.sh b/sdata/subcmd-install/1.deps-router.sh index 2d2c78aff..dd6712518 100644 --- a/sdata/subcmd-install/1.deps-router.sh +++ b/sdata/subcmd-install/1.deps-router.sh @@ -69,14 +69,17 @@ elif [[ "$OS_GROUP_ID" =~ ^(arch|gentoo|fedora)$ ]]; then printf "which means it probably does not reflect all latest changes of ./sdata/dist-arch/ .\n" printf "In such case it may work unexpectedly.${STY_RST}\n" printf "\n" - printf "${STY_RED}It's highly recommended to check the following links before continue:${STY_RST}\n" - printf "${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/discussions/2140${STY_RST}\n" - printf "${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/commits/main/sdata/dist-arch${STY_RST}\n" - printf "${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/commits/main/sdata/dist-${TARGET_ID}${STY_RST}\n" + printf "${STY_RED}It's highly recommended to check the following links before continue.${STY_RST}\n" + printf "${STY_RED}1. Normally just check discussion#2140 to see if there's any valid update notice.${STY_RST}\n" + printf " ${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/discussions/2140${STY_RST}\n" + printf " ${STY_RED}Note that the timeliness relies on manual maintenance.${STY_RST}\n" + printf "${STY_RED}2. For details please compare the two lists of commit history:${STY_RST}\n" + printf " ${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/commits/main/sdata/dist-arch${STY_RST}\n" + printf " ${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/commits/main/sdata/dist-${TARGET_ID}${STY_RST}\n" printf "\n" printf "${STY_PURPLE}PR on ./sdata/dist-${TARGET_ID}/ to properly reflect the latest changes of ./sdata/dist-arch is welcomed.${STY_RST}\n" printf "${STY_PURPLE}${STY_BOLD}Again, do not create any issue,${STY_RST}\n" - printf "${STY_PURPLE}But you can create a discussion under \"Extra Distros\" category: ${STY_RST}\n" + printf "${STY_PURPLE}but you can create a discussion under \"Extra Distros\" category: ${STY_RST}\n" printf "${STY_PURPLE}${STY_UNDERLINE}https://github.com/end-4/dots-hyprland/discussions/new?category=extra-distros${STY_RST}\n" printf "\n" if [[ "${tmp_update_status}" = "OUTDATED" ]]; then From bd1c9bfb2ab2917bd315884d2bdbf8299c37b25d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 15 Nov 2025 08:07:29 +0100 Subject: [PATCH 46/85] add artix in distro recognition (#2487) --- dots/.config/quickshell/ii/services/SystemInfo.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/dots/.config/quickshell/ii/services/SystemInfo.qml b/dots/.config/quickshell/ii/services/SystemInfo.qml index 1d5c0bf6e..2b519a229 100644 --- a/dots/.config/quickshell/ii/services/SystemInfo.qml +++ b/dots/.config/quickshell/ii/services/SystemInfo.qml @@ -58,6 +58,7 @@ Singleton { // Update the distroIcon property based on distroId switch (distroId) { + case "artix": case "arch": distroIcon = "arch-symbolic"; break; case "endeavouros": distroIcon = "endeavouros-symbolic"; break; case "cachyos": distroIcon = "cachyos-symbolic"; break; From 6f7b501430a61fb4e5a8357db7e03b26d241c962 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 15 Nov 2025 08:16:30 +0100 Subject: [PATCH 47/85] fix weird notes text area sizing --- .../ii/modules/ii/overlay/notes/NotesContent.qml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/notes/NotesContent.qml b/dots/.config/quickshell/ii/modules/ii/overlay/notes/NotesContent.qml index dfcc4e052..e52c226b1 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/notes/NotesContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/notes/NotesContent.qml @@ -136,6 +136,9 @@ OverlayBackground { root.copyListEntries = entries; } + implicitWidth: 300 + implicitHeight: 200 + ColumnLayout { id: contentItem anchors.fill: parent @@ -161,8 +164,7 @@ OverlayBackground { persistentSelection: true textFormat: TextEdit.PlainText background: null - padding: 16 - rightPadding: root.maxCopyButtonSize + padding + padding: 24 onTextChanged: { if (textInput.activeFocus) { @@ -179,7 +181,7 @@ OverlayBackground { } Item { - anchors.fill: textInput + anchors.fill: parent visible: root.copyListEntries.length > 0 clip: true @@ -200,7 +202,7 @@ OverlayBackground { buttonRadius: height / 2 y: modelData.y anchors.right: parent.right - anchors.rightMargin: 16 + anchors.rightMargin: 10 z: 5 Timer { From d0de047db088e363c63e35541bc205d67dd28759 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 15 Nov 2025 08:27:31 +0100 Subject: [PATCH 48/85] wbar: (partial) right click menu for start button --- .../ii/modules/waffle/bar/AppButton.qml | 4 +- .../ii/modules/waffle/bar/BarButton.qml | 4 +- .../ii/modules/waffle/bar/BarMenu.qml | 111 ++++++++++++++++++ .../ii/modules/waffle/bar/StartButton.qml | 9 ++ .../ii/modules/waffle/bar/SystemButton.qml | 2 +- .../ii/modules/waffle/bar/WidgetsButton.qml | 12 ++ .../waffle/bar/tasks/TaskAppButton.qml | 2 +- .../modules/waffle/bar/tasks/TaskPreview.qml | 2 +- .../ii/modules/waffle/bar/tasks/Tasks.qml | 10 ++ 9 files changed, 148 insertions(+), 8 deletions(-) create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/BarMenu.qml diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml index a35e12a2e..dbb430b6d 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml @@ -45,9 +45,7 @@ BarButton { anchors.fill: parent anchors.rightMargin: 5 active: root.multiple - sourceComponent: BackgroundAcrylicRectangle { - - } + sourceComponent: BackgroundAcrylicRectangle {} } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml index ce1a4cdc7..65ef521c4 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml @@ -8,8 +8,8 @@ import qs.modules.waffle.looks Button { id: root - signal altAction() - signal middleClickAction() + property var altAction: () => {} + property var middleClickAction: () => {} property color colBackground property color colBackgroundBorder diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarMenu.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarMenu.qml new file mode 100644 index 000000000..2dbda095d --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarMenu.qml @@ -0,0 +1,111 @@ +import QtQuick +import QtQuick.Controls +import Quickshell +import Quickshell.Hyprland +import qs.modules.common +import qs.modules.common.functions +import qs.modules.waffle.looks + +Loader { + id: root + + property Item anchorItem: parent + property real visualMargin: 12 + readonly property bool barAtBottom: Config.options.waffles.bar.bottom + property real ambientShadowWidth: 1 + + active: false + visible: active + sourceComponent: PopupWindow { + id: popupWindow + visible: true + Component.onCompleted: { + openAnim.start(); + } + + anchor { + adjustment: PopupAdjustment.Slide + item: root.anchorItem + gravity: root.barAtBottom ? Edges.Top : Edges.Bottom + edges: root.barAtBottom ? Edges.Top : Edges.Bottom + } + + HyprlandFocusGrab { + id: focusGrab + active: true + windows: [popupWindow] + onCleared: { + closeAnim.start(); + } + } + + implicitWidth: realContent.implicitWidth + (ambientShadow.border.width * 2) + (root.visualMargin * 2) + implicitHeight: realContent.implicitHeight + (ambientShadow.border.width * 2) + (root.visualMargin * 2) + + property real sourceEdgeMargin: -implicitHeight + PropertyAnimation { + id: openAnim + target: popupWindow + property: "sourceEdgeMargin" + to: (root.ambientShadowWidth + root.visualMargin) + duration: 200 + easing.type: Easing.BezierSpline + easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn + } + SequentialAnimation { + id: closeAnim + PropertyAnimation { + target: popupWindow + property: "sourceEdgeMargin" + to: -implicitHeight + duration: 150 + easing.type: Easing.BezierSpline + easing.bezierCurve: Looks.transition.easing.bezierCurve.easeOut + } + ScriptAction { + script: { + root.active = false; + } + } + } + + color: "transparent" + Rectangle { + id: ambientShadow + z: 0 + anchors { + fill: realContent + margins: -border.width + } + border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.shadowTransparency) + border.width: root.ambientShadowWidth + color: "transparent" + radius: realContent.radius + border.width + } + + Rectangle { + id: realContent + z: 1 + anchors { + left: parent.left + right: parent.right + top: root.barAtBottom ? undefined : parent.top + bottom: root.barAtBottom ? parent.bottom : undefined + margins: root.ambientShadowWidth + root.visualMargin + // Opening anim + bottomMargin: root.barAtBottom ? popupWindow.sourceEdgeMargin : (root.ambientShadowWidth + root.visualMargin) + topMargin: root.barAtBottom ? (root.ambientShadowWidth + root.visualMargin) : popupWindow.sourceEdgeMargin + } + color: Looks.colors.bg1 + radius: Looks.radius.large + + // test + implicitWidth: 300 + implicitHeight: 400 + + Menu { + id: menu + } + } + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml index 4595802ee..a7911d181 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml @@ -1,4 +1,5 @@ import QtQuick +import QtQuick.Controls import QtQuick.Layouts import org.kde.kirigami as Kirigami import qs @@ -21,4 +22,12 @@ AppButton { text: Translation.tr("Start") extraVisibleCondition: root.shouldShowTooltip } + + altAction: () => { + contextMenu.active = !contextMenu.active; + } + + BarMenu { + id: contextMenu + } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml index 1de9654d5..2a74ca171 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml @@ -90,6 +90,6 @@ BarButton { } BarToolTip { extraVisibleCondition: root.shouldShowTooltip && batteryHoverArea.containsMouse - text: Translation.tr("Battery: %1").arg(`${Math.round(Battery.percentage * 100) || 0}%`) + text: Translation.tr("Battery: %1%2").arg(`${Math.round(Battery.percentage * 100) || 0}%`).arg(Battery.isPluggedIn ? (" " + Translation.tr("(Plugged in)")) : "") } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml index 1c6c11859..51a3175bc 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml @@ -18,6 +18,11 @@ AppButton { onClicked: { GlobalStates.sidebarLeftOpen = !GlobalStates.sidebarLeftOpen } + onDownChanged: { + scaleAnim.duration = root.down ? 150 : 200 + scaleAnim.easing.bezierCurve = root.down ? Looks.transition.easing.bezierCurve.easeIn : Looks.transition.easing.bezierCurve.easeOut + iconWidget.scale = root.down ? 5/6 : 1 // If/When we do dragging, the scale is 1.25 + } contentItem: Item { anchors { @@ -41,6 +46,13 @@ AppButton { id: iconWidget anchors.verticalCenter: parent.verticalCenter iconName: root.iconName + + Behavior on scale { + NumberAnimation { + id: scaleAnim + easing.type: Easing.BezierSpline + } + } } Column { diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml index 53b68b82c..ce7349a97 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml @@ -37,7 +37,7 @@ AppButton { } } - onMiddleClickAction: { + middleClickAction: () => { if (root.desktopEntry) { desktopEntry.execute() } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml index 6d8aeba1a..777dfb3e7 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml @@ -16,7 +16,7 @@ PopupWindow { property Item anchorItem //////////////////// Functions //////////////////// - function close() { + function close() { // Closing doesn't animate, not sure if they're just lazy or it's intentional marginBehavior.enabled = false; root.visible = false; } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml index 895b1353f..260c1c37f 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml @@ -17,6 +17,10 @@ MouseArea { previewPopup.show(appEntry, button); } + function showContextMenu(appEntry, button) { + // TODO + } + // Apps row RowLayout { id: row @@ -36,6 +40,10 @@ MouseArea { onHoverPreviewRequested: { root.showPreviewPopup(appEntry, this) } + + altAction: () => { + root.showContextMenu(appEntry, this) + } } } } @@ -46,4 +54,6 @@ MouseArea { tasksHovered: root.containsMouse anchor.window: root.QsWindow.window } + + } From f3ad9f27f61713507e97e57589121f8313133f21 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 15 Nov 2025 08:29:48 +0100 Subject: [PATCH 49/85] format (kinda) --- dots/.config/quickshell/ii/services/Brightness.qml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/dots/.config/quickshell/ii/services/Brightness.qml b/dots/.config/quickshell/ii/services/Brightness.qml index c443a4a7d..465d8729c 100644 --- a/dots/.config/quickshell/ii/services/Brightness.qml +++ b/dots/.config/quickshell/ii/services/Brightness.qml @@ -136,16 +136,14 @@ Singleton { function syncBrightness() { const brightnessValue = Math.max(monitor.multipliedBrightness, 0); - if(isDdc){ + if (isDdc) { const rawValueRounded = Math.max(Math.floor(brightnessValue * monitor.rawMaxBrightness), 1); setProc.command = ["ddcutil", "-b", busNum, "setvcp", "10", rawValueRounded]; setProc.startDetached(); - }else{ + } else { const valuePercentNumber = Math.floor(brightnessValue * 100); - let valuePercent = ""+valuePercentNumber+"%"; - if(valuePercentNumber == 0) - //Set it to raw 1 - valuePercent = 1; + let valuePercent = `${valuePercentNumber}%`; + if (valuePercentNumber == 0) valuePercent = "1"; // Prevent fully black setProc.command = ["brightnessctl", "--class", "backlight", "s", valuePercent, "--quiet"]; setProc.startDetached(); } From 6d221f558b3bde687963077bf7841744655f829b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 15 Nov 2025 08:51:42 +0100 Subject: [PATCH 50/85] contributing.md: add code style guide --- .github/CONTRIBUTING.md | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index d1affa686..d95366fb4 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -2,22 +2,33 @@ - Please, please, please, make multiple PRs if you have many features/fixes, and don't shove your personal changes along with the PR, including changed defaults - We can accept features that we do not personally want, but in that case we will ask you to make it configurable/optionally loaded. -- If you want to start working on something big to contribute, it might be a good idea to ask first to not waste your effort (but if you've already done it for yourself, it doesn't hurt to submit). +- If you want to start working on something _big_ to contribute, it might be a good idea to ask first to not waste your effort (but if you've already done it for yourself, it doesn't hurt to submit). -# Code details +# Translations -## Contributing to i18n +See `dots/.config/quickshell/ii/translations/tools` -For contributing in translation (i18n) for Quickshell, see also `dots/.config/quickshell/ii/translations/tools`. +# Code ## Dynamic loading -- If something's not always necessary, especially when guarded by a config option to enable/disable, put it in a `Loader`. One tip with `Loader`s is sometimes you will need to declare positioning properties (like `anchors`) in the `Loader`, not the `sourceComponent`. +- If something's not always necessary, especially when guarded by a config option to enable/disable, put it in a `Loader` + - Note that you will need to declare positioning properties (like `anchors`) in the `Loader`, not the `sourceComponent` + - When something that's to be dynamically loaded doesn't affect its parent layout, you can have a fading animation by using FadeLoader and set the `shown` prop instead of `active` and `visible` ## Practical concerns - Make sure what you add does not require significant resources for a minor purpose or harm usability just for the sake of looking nice. The dotfiles must remain practical for daily driving. -- If there is something really fancy and impractical anyway, add a config option for it and make sure it's disabled by default. +- If there is something really fancy and impractical anyway, add a config option for it and make sure it's disabled by default (example: constantly rotating background clock) + +## Style + +- Spaces + - Space properties and children data into meaningful groups. (but of course, don't use 2+ blanks in a row) + - Put spaces between text and operators: `if (condition) { ... } else { ... }` instead of `if(condition){ ... }else{ ... }` +- As you can see, it's pretty easy to use lots of nesting. There's no hard limit, end-4 himself nests a lot too, but avoid/mitigate that: + - Prefer early return: Use something like `if (!condition) return; doStuff();` instead of `if (condition) { doStuff() }` + - If you feel it's a bother to refractor something into a new file, remember there's `component` to declare reusable components in the same file. # Setting up From 4393c05e46cde31d05554bb115e22350a34e2555 Mon Sep 17 00:00:00 2001 From: "Celestial.y" Date: Sat, 15 Nov 2025 17:06:05 +0800 Subject: [PATCH 51/85] Update diagnose --- diagnose | 1 + 1 file changed, 1 insertion(+) diff --git a/diagnose b/diagnose index db4a239e0..3001a62a2 100755 --- a/diagnose +++ b/diagnose @@ -70,6 +70,7 @@ x git submodule status --recursive e "Checking distro" x _check_distro_id +x cat os-release #x _check_distro e "Checking variables" From 24df9ce2e4e4c6f497d59be364cbf26c6e87d354 Mon Sep 17 00:00:00 2001 From: "Celestial.y" Date: Sat, 15 Nov 2025 17:38:33 +0800 Subject: [PATCH 52/85] Improve .gitignore --- .gitignore | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index b59d26bf8..9e298d049 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,17 @@ /diagnose.result /cache + # Ignore Python cache files __pycache__/ *.py[cod] -dots/.config/quickshell/ii/.qmlls.ini -.update-lock + +/dots/.config/quickshell/ii/.qmlls.ini + +# exp-update +/.update-lock + +# custom os-release /os-release -#emacs backup + +# Emacs auto backup file *~ From d990d684726e83e3591db4ee2ea7c9db1bed0e53 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 15 Nov 2025 17:22:32 +0100 Subject: [PATCH 53/85] not use anchors in children items in notif list view --- .../ii/modules/common/widgets/NotificationListView.qml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/widgets/NotificationListView.qml b/dots/.config/quickshell/ii/modules/common/widgets/NotificationListView.qml index 1b68059d0..ec76349bb 100644 --- a/dots/.config/quickshell/ii/modules/common/widgets/NotificationListView.qml +++ b/dots/.config/quickshell/ii/modules/common/widgets/NotificationListView.qml @@ -18,10 +18,9 @@ StyledListView { // Scrollable window required property int index required property var modelData popup: root.popup - anchors.left: parent?.left - anchors.right: parent?.right + width: ListView.view.width // https://doc.qt.io/qt-6/qml-qtquick-listview.html notificationGroup: popup ? Notifications.popupGroupsByAppName[modelData] : Notifications.groupsByAppName[modelData] } -} \ No newline at end of file +} From 5d6d9234ac0913dc5db3659283b8bccab071dbbb Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 15 Nov 2025 17:22:46 +0100 Subject: [PATCH 54/85] refractor taskbar pinning --- .../quickshell/ii/modules/ii/dock/DockAppButton.qml | 6 +----- dots/.config/quickshell/ii/services/TaskbarApps.qml | 8 ++++++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/ii/dock/DockAppButton.qml b/dots/.config/quickshell/ii/modules/ii/dock/DockAppButton.qml index 41ed8cd07..8d2d270ae 100644 --- a/dots/.config/quickshell/ii/modules/ii/dock/DockAppButton.qml +++ b/dots/.config/quickshell/ii/modules/ii/dock/DockAppButton.qml @@ -67,11 +67,7 @@ DockButton { } altAction: () => { - if (Config.options.dock.pinnedApps.indexOf(appToplevel.appId) !== -1) { - Config.options.dock.pinnedApps = Config.options.dock.pinnedApps.filter(id => id !== appToplevel.appId) - } else { - Config.options.dock.pinnedApps = Config.options.dock.pinnedApps.concat([appToplevel.appId]) - } + TaskbarApps.togglePin(appToplevel.appId); } contentItem: Loader { diff --git a/dots/.config/quickshell/ii/services/TaskbarApps.qml b/dots/.config/quickshell/ii/services/TaskbarApps.qml index 0b5818b71..052abcaec 100644 --- a/dots/.config/quickshell/ii/services/TaskbarApps.qml +++ b/dots/.config/quickshell/ii/services/TaskbarApps.qml @@ -8,6 +8,14 @@ import Quickshell.Wayland Singleton { id: root + function togglePin(appId) { + if (Config.options.dock.pinnedApps.indexOf(appId) !== -1) { + Config.options.dock.pinnedApps = Config.options.dock.pinnedApps.filter(id => id !== appId) + } else { + Config.options.dock.pinnedApps = Config.options.dock.pinnedApps.concat([appId]) + } + } + property list apps: { var map = new Map(); From bbe0329df4d462449db666bdfa10ee15be3ad8e8 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 15 Nov 2025 17:29:48 +0100 Subject: [PATCH 55/85] add radius to barbutton --- dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml index 65ef521c4..c98d57baf 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml @@ -37,6 +37,7 @@ Button { } } + colBackgroundBorder: ColorUtils.transparentize(Looks.colors.bg1Border, root.checked ? Looks.contentTransparency : 1) colBackground: { if (root.down) { return Looks.colors.bg1Active @@ -46,7 +47,6 @@ Button { return ColorUtils.transparentize(Looks.colors.bg1) } } - colBackgroundBorder: ColorUtils.transparentize(Looks.colors.bg1Border, root.checked ? Looks.contentTransparency : 1) MouseArea { anchors.fill: parent @@ -67,6 +67,7 @@ Button { background: AcrylicRectangle { shiny: ((root.hovered && !root.down) || root.checked) color: root.colBackground + radius: Looks.radius.medium border.width: 1 border.color: root.colBackgroundBorder From 839718cc2ba748c5f1adc6bc783935080cfafff7 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 15 Nov 2025 17:30:17 +0100 Subject: [PATCH 56/85] FluentIcon: add monochrome prop --- dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml b/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml index 81b6ebf08..5a7f15902 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml @@ -6,6 +6,7 @@ import qs.modules.waffle.looks Kirigami.Icon { id: root required property string icon + property alias monochrome: root.isMask // Should be 16, but it appears the icons have some padding, // Unlike the Windows-only Segoe UI icons, the open source FluentUI ones are hella small property int implicitSize: 20 From 6ee7212bdce32131d523f53c3c84d12a348c6a4f Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 15 Nov 2025 17:30:51 +0100 Subject: [PATCH 57/85] wbar: add right click menus --- .../ii/assets/icons/fluent/pin-off.svg | 1 + .../quickshell/ii/assets/icons/fluent/pin.svg | 1 + .../quickshell/ii/modules/common/Config.qml | 4 + .../modules/common/functions/StringUtils.qml | 10 ++ .../ii/modules/waffle/bar/BarMenu.qml | 115 ++++------------ .../ii/modules/waffle/bar/BarPopup.qml | 123 ++++++++++++++++++ .../ii/modules/waffle/bar/StartButton.qml | 37 +++++- .../waffle/bar/tasks/TaskAppButton.qml | 41 ++++++ .../ii/modules/waffle/bar/tasks/Tasks.qml | 10 +- .../ii/modules/waffle/looks/Looks.qml | 2 +- .../ii/modules/waffle/looks/WButton.qml | 94 +++++++++++++ 11 files changed, 334 insertions(+), 104 deletions(-) create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/pin-off.svg create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/pin.svg create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/looks/WButton.qml diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/pin-off.svg b/dots/.config/quickshell/ii/assets/icons/fluent/pin-off.svg new file mode 100644 index 000000000..046a27cea --- /dev/null +++ b/dots/.config/quickshell/ii/assets/icons/fluent/pin-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/pin.svg b/dots/.config/quickshell/ii/assets/icons/fluent/pin.svg new file mode 100644 index 000000000..b31790338 --- /dev/null +++ b/dots/.config/quickshell/ii/assets/icons/fluent/pin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml index eb995df55..d5169e701 100644 --- a/dots/.config/quickshell/ii/modules/common/Config.qml +++ b/dots/.config/quickshell/ii/modules/common/Config.qml @@ -563,6 +563,10 @@ Singleton { } property JsonObject waffles: JsonObject { + // Animations on Windoes are kinda janky. Set the following to + // false will make (some) stuff also be like that for accuracy. + // Example: the right-click menu of the Start button + property bool smootherAnimations: true property JsonObject bar: JsonObject { property bool bottom: true property bool leftAlignApps: false diff --git a/dots/.config/quickshell/ii/modules/common/functions/StringUtils.qml b/dots/.config/quickshell/ii/modules/common/functions/StringUtils.qml index 88ab95b2d..0839b5386 100644 --- a/dots/.config/quickshell/ii/modules/common/functions/StringUtils.qml +++ b/dots/.config/quickshell/ii/modules/common/functions/StringUtils.qml @@ -285,4 +285,14 @@ Singleton { } return str; } + + function toTitleCase(str) { + // Replace "-" and "_" with space, then capitalize each word + return str.replace(/[-_]/g, " ").replace( + /\w\S*/g, + function(txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); + } + ); + } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarMenu.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarMenu.qml index 2dbda095d..14a9bc0ec 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/BarMenu.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarMenu.qml @@ -1,111 +1,40 @@ import QtQuick import QtQuick.Controls +import QtQuick.Layouts import Quickshell import Quickshell.Hyprland import qs.modules.common import qs.modules.common.functions import qs.modules.waffle.looks -Loader { +BarPopup { id: root + default property var menuData + property var model: [ + {iconName: "start-here", text: "Start", action: () => {print("hello")}} + ] + padding: 2 - property Item anchorItem: parent - property real visualMargin: 12 - readonly property bool barAtBottom: Config.options.waffles.bar.bottom - property real ambientShadowWidth: 1 + contentItem: ColumnLayout { + anchors.centerIn: parent + spacing: 0 - active: false - visible: active - sourceComponent: PopupWindow { - id: popupWindow - visible: true - Component.onCompleted: { - openAnim.start(); - } + Repeater { + model: root.model + delegate: WButton { + id: btn + Layout.fillWidth: true - anchor { - adjustment: PopupAdjustment.Slide - item: root.anchorItem - gravity: root.barAtBottom ? Edges.Top : Edges.Bottom - edges: root.barAtBottom ? Edges.Top : Edges.Bottom - } + required property var modelData + icon.name: modelData.iconName ? modelData.iconName : "" + monochromeIcon: modelData.monochromeIcon ?? true + text: modelData.text ? modelData.text : "" - HyprlandFocusGrab { - id: focusGrab - active: true - windows: [popupWindow] - onCleared: { - closeAnim.start(); - } - } - - implicitWidth: realContent.implicitWidth + (ambientShadow.border.width * 2) + (root.visualMargin * 2) - implicitHeight: realContent.implicitHeight + (ambientShadow.border.width * 2) + (root.visualMargin * 2) - - property real sourceEdgeMargin: -implicitHeight - PropertyAnimation { - id: openAnim - target: popupWindow - property: "sourceEdgeMargin" - to: (root.ambientShadowWidth + root.visualMargin) - duration: 200 - easing.type: Easing.BezierSpline - easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn - } - SequentialAnimation { - id: closeAnim - PropertyAnimation { - target: popupWindow - property: "sourceEdgeMargin" - to: -implicitHeight - duration: 150 - easing.type: Easing.BezierSpline - easing.bezierCurve: Looks.transition.easing.bezierCurve.easeOut - } - ScriptAction { - script: { - root.active = false; + onClicked: { + if (modelData.action) modelData.action(); + root.close(); } } } - - color: "transparent" - Rectangle { - id: ambientShadow - z: 0 - anchors { - fill: realContent - margins: -border.width - } - border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.shadowTransparency) - border.width: root.ambientShadowWidth - color: "transparent" - radius: realContent.radius + border.width - } - - Rectangle { - id: realContent - z: 1 - anchors { - left: parent.left - right: parent.right - top: root.barAtBottom ? undefined : parent.top - bottom: root.barAtBottom ? parent.bottom : undefined - margins: root.ambientShadowWidth + root.visualMargin - // Opening anim - bottomMargin: root.barAtBottom ? popupWindow.sourceEdgeMargin : (root.ambientShadowWidth + root.visualMargin) - topMargin: root.barAtBottom ? (root.ambientShadowWidth + root.visualMargin) : popupWindow.sourceEdgeMargin - } - color: Looks.colors.bg1 - radius: Looks.radius.large - - // test - implicitWidth: 300 - implicitHeight: 400 - - Menu { - id: menu - } - } } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml new file mode 100644 index 000000000..30f695367 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml @@ -0,0 +1,123 @@ +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Controls +import Quickshell +import Quickshell.Hyprland +import qs.modules.common +import qs.modules.common.functions +import qs.modules.waffle.looks + +Loader { + id: root + + required property var contentItem + property real padding: Looks.radius.large - Looks.radius.medium + property bool noSmoothClosing: !Config.options.waffles.smootherAnimations + + property Item anchorItem: parent + property real visualMargin: 12 + readonly property bool barAtBottom: Config.options.waffles.bar.bottom + property real ambientShadowWidth: 1 + + function close() { + item.close(); + } + + active: false + visible: active + sourceComponent: PopupWindow { + id: popupWindow + visible: true + Component.onCompleted: { + openAnim.start(); + } + + anchor { + adjustment: PopupAdjustment.ResizeY | PopupAdjustment.SlideX + item: root.anchorItem + gravity: root.barAtBottom ? Edges.Top : Edges.Bottom + edges: root.barAtBottom ? Edges.Top : Edges.Bottom + } + + HyprlandFocusGrab { + id: focusGrab + active: true + windows: [popupWindow] + onCleared: { + root.close() + } + } + + function close() { + if (root.noSmoothClosing) root.active = false; + else closeAnim.start(); + } + + implicitWidth: realContent.implicitWidth + (ambientShadow.border.width * 2) + (root.visualMargin * 2) + implicitHeight: realContent.implicitHeight + (ambientShadow.border.width * 2) + (root.visualMargin * 2) + + property real sourceEdgeMargin: -implicitHeight + PropertyAnimation { + id: openAnim + target: popupWindow + property: "sourceEdgeMargin" + to: (root.ambientShadowWidth + root.visualMargin) + duration: 200 + easing.type: Easing.BezierSpline + easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn + } + SequentialAnimation { + id: closeAnim + PropertyAnimation { + target: popupWindow + property: "sourceEdgeMargin" + to: -implicitHeight + duration: 150 + easing.type: Easing.BezierSpline + easing.bezierCurve: Looks.transition.easing.bezierCurve.easeOut + } + ScriptAction { + script: { + root.active = false; + } + } + } + + color: "transparent" + Rectangle { + id: ambientShadow + z: 0 + anchors { + fill: realContent + margins: -border.width + } + border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.shadowTransparency) + border.width: root.ambientShadowWidth + color: "transparent" + radius: realContent.radius + border.width + } + + Rectangle { + id: realContent + z: 1 + anchors { + left: parent.left + right: parent.right + top: root.barAtBottom ? undefined : parent.top + bottom: root.barAtBottom ? parent.bottom : undefined + margins: root.ambientShadowWidth + root.visualMargin + // Opening anim + bottomMargin: root.barAtBottom ? popupWindow.sourceEdgeMargin : (root.ambientShadowWidth + root.visualMargin) + topMargin: root.barAtBottom ? (root.ambientShadowWidth + root.visualMargin) : popupWindow.sourceEdgeMargin + } + color: Looks.colors.bg1 + radius: Looks.radius.large + + // test + implicitWidth: root.contentItem.implicitWidth + (root.padding * 2) + implicitHeight: root.contentItem.implicitHeight + (root.padding * 2) + + children: [root.contentItem] + } + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml index a7911d181..1f2ed8342 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml @@ -1,7 +1,7 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts -import org.kde.kirigami as Kirigami +import Quickshell import qs import qs.services import qs.modules.common @@ -24,10 +24,43 @@ AppButton { } altAction: () => { - contextMenu.active = !contextMenu.active; + contextMenu.active = true; } BarMenu { id: contextMenu + + model: [ + { + text: Translation.tr("Terminal"), + action: () => { + Quickshell.execDetached(["bash", "-c", Config.options.apps.terminal]); + } + }, + { + text: Translation.tr("Task Manager"), + action: () => { + Quickshell.execDetached(["bash", "-c", Config.options.apps.taskManager]); + } + }, + { + text: Translation.tr("Settings"), + action: () => { + Quickshell.execDetached(["qs", "-p", Quickshell.shellPath("settings.qml")]); + } + }, + { + text: Translation.tr("File Explorer"), + action: () => { + Qt.openUrlExternally(Directories.home); + } + }, + { + text: Translation.tr("Search"), + action: () => { + Quickshell.execDetached(["qs", "-p", Quickshell.shellPath(""), "ipc", "call", "overview", "toggle"]); + } + }, + ] } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml index ce7349a97..58f5a9959 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml @@ -2,6 +2,7 @@ import QtQuick import QtQuick.Layouts import qs.services import qs.modules.common +import qs.modules.common.functions import qs.modules.waffle.looks import qs.modules.waffle.bar import Quickshell @@ -16,6 +17,7 @@ AppButton { property bool hasWindows: appEntry.toplevels.length > 0 signal hoverPreviewRequested() + signal hoverPreviewDismissed() multiple: appEntry.toplevels.length > 1 checked: active @@ -43,6 +45,12 @@ AppButton { } } + altAction: () => { + root.hoverPreviewDismissed() + root.hoverTimer.stop() + contextMenu.active = true; + } + // Active indicator Rectangle { id: activeIndicator @@ -74,4 +82,37 @@ AppButton { extraVisibleCondition: root.shouldShowTooltip && !root.hasWindows text: desktopEntry ? desktopEntry.name : appEntry.appId } + + BarMenu { + id: contextMenu + + model: [ + { + iconName: root.iconName, + text: root.desktopEntry ? root.desktopEntry.name : StringUtils.toTitleCase(appEntry.appId), + monochromeIcon: false, + action: () => { + if (root.desktopEntry) { + root.desktopEntry.execute() + } + } + }, + { + iconName: root.appEntry.pinned ? "pin-off" : "pin", + text: root.appEntry.pinned ? qsTr("Unpin from taskbar") : qsTr("Pin to taskbar"), + action: () => { + TaskbarApps.togglePin(root.appEntry.appId); + } + }, + ...(root.appEntry.toplevels.length > 0 ? [{ + iconName: "dismiss", + text: root.multiple ? qsTr("Close all windows") : qsTr("Close window"), + action: () => { + for (let toplevel of root.appEntry.toplevels) { + toplevel.close(); + } + } + }] : []), + ] + } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml index 260c1c37f..ad42a93fa 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml @@ -17,10 +17,6 @@ MouseArea { previewPopup.show(appEntry, button); } - function showContextMenu(appEntry, button) { - // TODO - } - // Apps row RowLayout { id: row @@ -40,9 +36,8 @@ MouseArea { onHoverPreviewRequested: { root.showPreviewPopup(appEntry, this) } - - altAction: () => { - root.showContextMenu(appEntry, this) + onHoverPreviewDismissed: { + previewPopup.close() } } } @@ -55,5 +50,4 @@ MouseArea { anchor.window: root.QsWindow.window } - } diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml index 09176830f..8ece22ea5 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml @@ -61,7 +61,7 @@ Singleton { } property QtObject pixelSize: QtObject { property real normal: 11 - property real large: 15 + property real large: 14 } } diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WButton.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WButton.qml new file mode 100644 index 000000000..5583fd48f --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WButton.qml @@ -0,0 +1,94 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import qs.modules.common +import qs.modules.common.functions +import qs.modules.waffle.looks + +// Generic button with background +Button { + id: root + + property color colBackgroundHover: Looks.colors.bg2Hover + property color colBackgroundActive: Looks.colors.bg2Active + property color colBackground: ColorUtils.transparentize(Looks.colors.bg1) + + property alias monochromeIcon: buttonIcon.monochrome + + property var altAction: () => {} + property var middleClickAction: () => {} + + property real inset: 2 + topInset: inset + bottomInset: inset + leftInset: inset + rightInset: inset + horizontalPadding: 10 + verticalPadding: 6 + implicitHeight: contentItem.implicitHeight + verticalPadding * 2 + implicitWidth: contentItem.implicitWidth + horizontalPadding * 2 + + background: Rectangle { + radius: Looks.radius.medium + color: { + if (root.down) { + return root.colBackgroundActive; + } else if ((root.hovered && !root.down) || root.checked) { + return root.colBackgroundHover; + } else { + return root.colBackground; + } + } + Behavior on color { + animation: Looks.transition.color.createObject(this) + } + } + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.RightButton | Qt.MiddleButton + onClicked: (event) => { + if (event.button === Qt.LeftButton) root.clicked(); + if (event.button === Qt.RightButton) root.altAction(); + if (event.button === Qt.MiddleButton) root.middleClickAction(); + } + } + + contentItem: Item { + anchors { + fill: parent + margins: root.inset + } + implicitWidth: contentLayout.implicitWidth + implicitHeight: contentLayout.implicitHeight + RowLayout { + id: contentLayout + anchors { + fill: parent + leftMargin: root.horizontalPadding + rightMargin: root.horizontalPadding + } + spacing: 12 + FluentIcon { + id: buttonIcon + monochrome: true + implicitSize: 16 + Layout.leftMargin: 6 + Layout.fillWidth: false + Layout.alignment: Qt.AlignVCenter + visible: root.icon.name !== "" + icon: root.icon.name + } + WText { + Layout.rightMargin: 12 + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft + text: root.text + horizontalAlignment: Text.AlignLeft + font { + pixelSize: Looks.font.pixelSize.large + } + } + } + } +} From fdc38d69f701393206a09730a0c7afd45d6699a4 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 15 Nov 2025 21:30:28 +0100 Subject: [PATCH 58/85] wbar: add updates indicator --- .../ii/assets/icons/fluent/arrow-sync.svg | 39 +++++++++++++ .../quickshell/ii/modules/common/Config.qml | 6 ++ .../ii/modules/waffle/bar/BarMenu.qml | 41 +++++++++---- .../ii/modules/waffle/bar/BarPopup.qml | 2 +- .../ii/modules/waffle/bar/UpdatesButton.qml | 41 +++++++++++++ .../modules/waffle/bar/WaffleBarContent.qml | 1 + .../waffle/bar/tasks/TaskAppButton.qml | 7 +++ .../modules/waffle/bar/tasks/TaskPreview.qml | 2 +- .../ii/modules/waffle/looks/Looks.qml | 2 + .../ii/modules/waffle/looks/WButton.qml | 3 +- .../ii/modules/waffle/looks/WPopupToolTip.qml | 12 ++-- .../quickshell/ii/services/Updates.qml | 57 +++++++++++++++++++ dots/.config/quickshell/ii/shell.qml | 1 + 13 files changed, 194 insertions(+), 20 deletions(-) create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/arrow-sync.svg create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/UpdatesButton.qml create mode 100644 dots/.config/quickshell/ii/services/Updates.qml diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/arrow-sync.svg b/dots/.config/quickshell/ii/assets/icons/fluent/arrow-sync.svg new file mode 100644 index 000000000..73df6838e --- /dev/null +++ b/dots/.config/quickshell/ii/assets/icons/fluent/arrow-sync.svg @@ -0,0 +1,39 @@ + + + + + + diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml index d5169e701..c9330d78e 100644 --- a/dots/.config/quickshell/ii/modules/common/Config.qml +++ b/dots/.config/quickshell/ii/modules/common/Config.qml @@ -536,6 +536,12 @@ Singleton { } property bool secondPrecision: false } + + property JsonObject updates: JsonObject { + property int checkInterval: 120 // minutes + property int adviseUpdateThreshold: 75 // packages + property int stronglyAdviseUpdateThreshold: 200 // packages + } property JsonObject wallpaperSelector: JsonObject { property bool useSystemFileDialog: false diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarMenu.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarMenu.qml index 14a9bc0ec..871abc23f 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/BarMenu.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarMenu.qml @@ -11,8 +11,10 @@ BarPopup { id: root default property var menuData property var model: [ - {iconName: "start-here", text: "Start", action: () => {print("hello")}} + { iconName: "start-here", text: "Start", action: () => {print("hello")} }, + { type : "separator" }, ] + readonly property bool hasIcons: model.some(item => item.iconName !== undefined && item.iconName !== "") padding: 2 contentItem: ColumnLayout { @@ -21,18 +23,35 @@ BarPopup { Repeater { model: root.model - delegate: WButton { - id: btn - Layout.fillWidth: true + delegate: DelegateChooser { + role: "type" + DelegateChoice { + roleValue: "separator" + Rectangle { + Layout.topMargin: 2 + Layout.bottomMargin: 2 + Layout.fillWidth: true + implicitHeight: 1 + color: Looks.colors.bg0Border + } + } + DelegateChoice { + roleValue: undefined + WButton { + id: btn + Layout.fillWidth: true - required property var modelData - icon.name: modelData.iconName ? modelData.iconName : "" - monochromeIcon: modelData.monochromeIcon ?? true - text: modelData.text ? modelData.text : "" + required property var modelData + forceShowIcon: root.hasIcons + icon.name: modelData.iconName ? modelData.iconName : "" + monochromeIcon: modelData.monochromeIcon ?? true + text: modelData.text ? modelData.text : "" - onClicked: { - if (modelData.action) modelData.action(); - root.close(); + onClicked: { + if (modelData.action) modelData.action(); + root.close(); + } + } } } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml index 30f695367..512b3b2bd 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml @@ -91,7 +91,7 @@ Loader { fill: realContent margins: -border.width } - border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.shadowTransparency) + border.color: ColorUtils.transparentize(Looks.colors.ambientShadow, Looks.shadowTransparency) border.width: root.ambientShadowWidth color: "transparent" radius: realContent.radius + border.width diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/UpdatesButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/UpdatesButton.qml new file mode 100644 index 000000000..ac6118e8b --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/bar/UpdatesButton.qml @@ -0,0 +1,41 @@ +import QtQuick +import qs +import qs.services +import qs.modules.common +import qs.modules.waffle.looks + +BarButton { + id: root + + visible: Updates.available && Updates.updateAdvised + + padding: 4 + contentItem: Item { + anchors.centerIn: parent + implicitWidth: iconContent.implicitWidth + implicitHeight: iconContent.implicitHeight + + FluentIcon { + id: iconContent + anchors.centerIn: parent + icon: "arrow-sync" + + Rectangle { + anchors { + right: parent.right + bottom: parent.bottom + margins: 1 + } + implicitWidth: 8 + implicitHeight: implicitWidth + radius: height / 2 + color: Updates.updateStronglyAdvised ? Looks.colors.warning : Looks.colors.accent + } + } + } + + BarToolTip { + extraVisibleCondition: root.shouldShowTooltip + text: Translation.tr("Get the latest features and security improvements with\nthe newest feature update.\n\n%1 packages").arg(Updates.count) + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml index aa064118a..2ac4dc944 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml @@ -68,6 +68,7 @@ Rectangle { shown: Config.options.waffles.bar.leftAlignApps sourceComponent: WidgetsButton {} } + UpdatesButton {} SystemButton {} TimeButton {} } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml index 58f5a9959..a5915e83e 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml @@ -87,6 +87,13 @@ AppButton { id: contextMenu model: [ + ...((root.desktopEntry?.actions.length > 0) ? root.desktopEntry.actions.map(action =>({ + iconName: action.icon, + text: action.name, + action: () => { + action.execute() + } + })).concat({ type: "separator" }) : []), { iconName: root.iconName, text: root.desktopEntry ? root.desktopEntry.name : StringUtils.toTitleCase(appEntry.appId), diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml index 777dfb3e7..0228ee755 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml @@ -70,7 +70,7 @@ PopupWindow { fill: contentItem margins: -border.width } - border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.shadowTransparency) + border.color: ColorUtils.transparentize(Looks.colors.ambientShadow, Looks.shadowTransparency) border.width: 1 color: "transparent" radius: Looks.radius.large + border.width diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml index 8ece22ea5..d2f67fea7 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml @@ -20,6 +20,7 @@ Singleton { property real shadowTransparency: 0.6 colors: QtObject { id: colors + property color ambientShadow: ColorUtils.transparentize("#000000", 0.4) property color bg0: root.dark ? "#1C1C1C" : "#EEEEEE" property color bg0Border: root.dark ? "#404040" : "#BEBEBE" property color bg1: root.dark ? "#2C2C2C" : "#F7F7F7" @@ -34,6 +35,7 @@ Singleton { property color fg1: root.dark ? "#D1D1D1" : "#626262" property color danger: "#C42B1C" property color dangerActive: "#B62D1F" + property color warning: "#FF9900" // property color accent: root.dark ? "#A5C6D8" : "#5377A3" property color accent: Appearance.m3colors.m3primary property color accentUnfocused: root.dark ? "#989898" : "#848484" diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WButton.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WButton.qml index 5583fd48f..3b48a79e3 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/WButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WButton.qml @@ -14,6 +14,7 @@ Button { property color colBackground: ColorUtils.transparentize(Looks.colors.bg1) property alias monochromeIcon: buttonIcon.monochrome + property bool forceShowIcon: false property var altAction: () => {} property var middleClickAction: () => {} @@ -71,12 +72,12 @@ Button { spacing: 12 FluentIcon { id: buttonIcon + visible: root.icon.name !== "" || root.forceShowIcon monochrome: true implicitSize: 16 Layout.leftMargin: 6 Layout.fillWidth: false Layout.alignment: Qt.AlignVCenter - visible: root.icon.name !== "" icon: root.icon.name } WText { diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml index b35258204..6b89d4f24 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml @@ -10,14 +10,14 @@ import qs.modules.waffle.looks PopupToolTip { id: root - property real padding: 2 - verticalPadding: padding - horizontalPadding: padding + property real visualMargin: 11 + verticalPadding: visualMargin + horizontalPadding: visualMargin contentItem: Item { anchors.centerIn: parent - implicitWidth: realContent.implicitWidth + root.verticalPadding * 2 - implicitHeight: realContent.implicitHeight + root.horizontalPadding * 2 + implicitWidth: realContent.implicitWidth + 2 * 2 + implicitHeight: realContent.implicitHeight + 2 * 2 Rectangle { id: ambientShadow @@ -26,7 +26,7 @@ PopupToolTip { fill: realContent margins: -border.width } - border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.shadowTransparency) + border.color: ColorUtils.transparentize(Looks.colors.ambientShadow, Looks.shadowTransparency) border.width: 1 color: "transparent" radius: realContent.radius + border.width diff --git a/dots/.config/quickshell/ii/services/Updates.qml b/dots/.config/quickshell/ii/services/Updates.qml new file mode 100644 index 000000000..58b8be892 --- /dev/null +++ b/dots/.config/quickshell/ii/services/Updates.qml @@ -0,0 +1,57 @@ +pragma Singleton + +import qs.modules.common +import qs.modules.common.functions +import QtQuick +import Quickshell +import Quickshell.Io + +/* + * System updates service. Currently only supports Arch. + */ +Singleton { + id: root + + property bool available: false + property int count: 0 + + readonly property bool updateAdvised: available && count > Config.options.updates.adviseUpdateThreshold + readonly property bool updateStronglyAdvised: available && count > Config.options.updates.stronglyAdviseUpdateThreshold + + function load() {} + function refresh() { + if (!available) return; + print("[Updates] Checking for system updates") + checkUpdatesProc.running = true; + } + + Timer { + interval: Config.options.updates.checkInterval * 60 * 1000 + repeat: true + running: Config.ready + onTriggered: { + print("[Updates] Periodic update check due") + root.refresh(); + } + } + + Process { + id: checkAvailabilityProc + running: true + command: ["which", "checkupdates"] + onExited: (exitCode, exitStatus) => { + root.available = (exitCode === 0); + root.refresh(); + } + } + + Process { + id: checkUpdatesProc + command: ["bash", "-c", "checkupdates | wc -l"] + stdout: StdioCollector { + onStreamFinished: { + root.count = parseInt(text.trim()); + } + } + } +} diff --git a/dots/.config/quickshell/ii/shell.qml b/dots/.config/quickshell/ii/shell.qml index ea100fdda..746c1003d 100644 --- a/dots/.config/quickshell/ii/shell.qml +++ b/dots/.config/quickshell/ii/shell.qml @@ -49,6 +49,7 @@ ShellRoot { ConflictKiller.load() Cliphist.refresh() Wallpapers.load() + Updates.load() } // Load enabled stuff From 7ff3a212ab626573e8812691aaf9ef3d67f19cf9 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 15 Nov 2025 22:01:04 +0100 Subject: [PATCH 59/85] readme: update overview pic --- .github/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/README.md b/.github/README.md index de4c9c790..a8134a426 100644 --- a/.github/README.md +++ b/.github/README.md @@ -81,7 +81,7 @@ Widget system: Quickshell | Support: Yes |:---|:---------------| | image | image | | Window management | Weeb power | -| image | image | +| image | image | ### Other styles: Available at the end of the readme. From 4e07aa52bab875013cc315963f1842f4585d31b8 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 15 Nov 2025 22:03:34 +0100 Subject: [PATCH 60/85] wbar: make update button update when clicked --- dots/.config/quickshell/ii/modules/common/Config.qml | 1 + .../quickshell/ii/modules/waffle/bar/UpdatesButton.qml | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml index c9330d78e..c71b77cc9 100644 --- a/dots/.config/quickshell/ii/modules/common/Config.qml +++ b/dots/.config/quickshell/ii/modules/common/Config.qml @@ -147,6 +147,7 @@ Singleton { property string networkEthernet: "kcmshell6 kcm_networkmanagement" property string taskManager: "plasma-systemmonitor --page-name Processes" property string terminal: "kitty -1" // This is only for shell actions + property string update: "kitty -1 --hold=yes fish -i -c 'sudo pacman -Syu'" property string volumeMixer: `~/.config/hypr/hyprland/scripts/launch_first_available.sh "pavucontrol-qt" "pavucontrol"` } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/UpdatesButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/UpdatesButton.qml index ac6118e8b..232f025c3 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/UpdatesButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/UpdatesButton.qml @@ -1,4 +1,5 @@ import QtQuick +import Quickshell import qs import qs.services import qs.modules.common @@ -8,8 +9,12 @@ BarButton { id: root visible: Updates.available && Updates.updateAdvised - padding: 4 + + onClicked: { + Quickshell.execDetached(["bash", "-c", Config.options.apps.update]); + } + contentItem: Item { anchors.centerIn: parent implicitWidth: iconContent.implicitWidth From 68a9c8729f3fb8ec9cbdb5819e9c9db28e6d2a0d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 15 Nov 2025 22:05:22 +0100 Subject: [PATCH 61/85] make super and super+tab use different quickshell globalshortcuts --- dots/.config/hypr/hyprland/keybinds.conf | 4 ++-- .../quickshell/ii/modules/ii/overview/Overview.qml | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/dots/.config/hypr/hyprland/keybinds.conf b/dots/.config/hypr/hyprland/keybinds.conf index fdda9a714..020fe582d 100644 --- a/dots/.config/hypr/hyprland/keybinds.conf +++ b/dots/.config/hypr/hyprland/keybinds.conf @@ -24,8 +24,8 @@ bindit = ,Super_L, global, quickshell:workspaceNumber # [hidden] bindit = ,Super_R, global, quickshell:workspaceNumber # [hidden] bindd = Super, V, Clipboard history >> clipboard, global, quickshell:overviewClipboardToggle # Clipboard history >> clipboard bindd = Super, Period, Emoji >> clipboard, global, quickshell:overviewEmojiToggle # Emoji >> clipboard -bindd = Super, Tab, Toggle overview, global, quickshell:overviewToggle # [hidden] Toggle overview/launcher (alt) -bindd = Super, A, Toggle left sidebar, global, quickshell:sidebarLeftToggle # Toggle left sidebar +bind = Super, Tab, global, quickshell:overviewWorkspacesToggle # [hidden] Toggle overview/launcher (alt) +bind = Super, A, global, quickshell:sidebarLeftToggle # Toggle left sidebar bind = Super+Alt, A, global, quickshell:sidebarLeftToggleDetach # [hidden] bind = Super, B, global, quickshell:sidebarLeftToggle # [hidden] bind = Super, O, global, quickshell:sidebarLeftToggle # [hidden] diff --git a/dots/.config/quickshell/ii/modules/ii/overview/Overview.qml b/dots/.config/quickshell/ii/modules/ii/overview/Overview.qml index 6385b2485..248b46b56 100644 --- a/dots/.config/quickshell/ii/modules/ii/overview/Overview.qml +++ b/dots/.config/quickshell/ii/modules/ii/overview/Overview.qml @@ -167,6 +167,9 @@ Scope { function toggle() { GlobalStates.overviewOpen = !GlobalStates.overviewOpen; } + function workspacesToggle() { + GlobalStates.overviewOpen = !GlobalStates.overviewOpen; + } function close() { GlobalStates.overviewOpen = false; } @@ -189,6 +192,14 @@ Scope { GlobalStates.overviewOpen = !GlobalStates.overviewOpen; } } + GlobalShortcut { + name: "overviewWorkspacesToggle" + description: "Toggles overview on press" + + onPressed: { + GlobalStates.overviewOpen = !GlobalStates.overviewOpen; + } + } GlobalShortcut { name: "overviewClose" description: "Closes overview" From 4abfcd016201a4c393e0df348788324ed3d9eb47 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 16 Nov 2025 00:02:57 +0100 Subject: [PATCH 62/85] wbar: animated start icon, search, and task view icons --- .../icons/fluent/start-here-pressed.svg | 24 ++++ .../ii/assets/icons/fluent/start-here.svg | 24 ++++ .../fluent/system-search-checked-dark.svg | 105 ++++++++++++++ .../fluent/system-search-checked-light.svg | 81 +++++++++++ .../icons/fluent/system-search-dark.svg | 30 +++- .../icons/fluent/task-view-pressed-dark.svg | 132 ++++++++++++++++++ .../icons/fluent/task-view-pressed-light.svg | 108 ++++++++++++++ .../ii/modules/waffle/bar/AppIcon.qml | 2 + .../ii/modules/waffle/bar/SearchButton.qml | 3 +- .../ii/modules/waffle/bar/StartButton.qml | 2 +- .../ii/modules/waffle/bar/TaskViewButton.qml | 2 +- 11 files changed, 506 insertions(+), 7 deletions(-) create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/start-here-pressed.svg create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/start-here.svg create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/system-search-checked-dark.svg create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/system-search-checked-light.svg create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/task-view-pressed-dark.svg create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/task-view-pressed-light.svg diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/start-here-pressed.svg b/dots/.config/quickshell/ii/assets/icons/fluent/start-here-pressed.svg new file mode 100644 index 000000000..e6b950eca --- /dev/null +++ b/dots/.config/quickshell/ii/assets/icons/fluent/start-here-pressed.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/start-here.svg b/dots/.config/quickshell/ii/assets/icons/fluent/start-here.svg new file mode 100644 index 000000000..708d5a71b --- /dev/null +++ b/dots/.config/quickshell/ii/assets/icons/fluent/start-here.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/system-search-checked-dark.svg b/dots/.config/quickshell/ii/assets/icons/fluent/system-search-checked-dark.svg new file mode 100644 index 000000000..af58d933f --- /dev/null +++ b/dots/.config/quickshell/ii/assets/icons/fluent/system-search-checked-dark.svg @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/system-search-checked-light.svg b/dots/.config/quickshell/ii/assets/icons/fluent/system-search-checked-light.svg new file mode 100644 index 000000000..8d0e69fce --- /dev/null +++ b/dots/.config/quickshell/ii/assets/icons/fluent/system-search-checked-light.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/system-search-dark.svg b/dots/.config/quickshell/ii/assets/icons/fluent/system-search-dark.svg index 2d972a7b4..8eb990cc4 100644 --- a/dots/.config/quickshell/ii/assets/icons/fluent/system-search-dark.svg +++ b/dots/.config/quickshell/ii/assets/icons/fluent/system-search-dark.svg @@ -7,10 +7,11 @@ version="1.1" viewBox="0 0 16.933 16.933" id="svg2" - sodipodi:docname="system-search.svg" + sodipodi:docname="system-search-dark.svg" inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> + + + + + + style="fill:url(#linearGradient4);fill-opacity:1;stroke:url(#linearGradient919)" /> diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/task-view-pressed-dark.svg b/dots/.config/quickshell/ii/assets/icons/fluent/task-view-pressed-dark.svg new file mode 100644 index 000000000..a7e14009c --- /dev/null +++ b/dots/.config/quickshell/ii/assets/icons/fluent/task-view-pressed-dark.svg @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/task-view-pressed-light.svg b/dots/.config/quickshell/ii/assets/icons/fluent/task-view-pressed-light.svg new file mode 100644 index 000000000..b1785dbd0 --- /dev/null +++ b/dots/.config/quickshell/ii/assets/icons/fluent/task-view-pressed-light.svg @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml b/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml index f70a80603..48ff26104 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml @@ -13,6 +13,8 @@ Kirigami.Icon { property real implicitSize: 26 implicitWidth: implicitSize implicitHeight: implicitSize + + animated: true roundToIconSize: false fallback: root.iconName source: tryCustomIcon ? `${Looks.iconsPath}/${root.iconName}${!root.separateLightDark ? "" : Looks.dark ? "-dark" : "-light"}.svg` : fallback diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml index a86faaece..3e8dd6282 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml @@ -9,9 +9,10 @@ import qs.modules.waffle.looks AppButton { id: root - iconName: "system-search" + iconName: checked ? "system-search-checked" : "system-search" separateLightDark: true + checked: GlobalStates.overviewOpen onClicked: { GlobalStates.overviewOpen = !GlobalStates.overviewOpen; // For now... } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml index 1f2ed8342..f4a15cc00 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml @@ -11,7 +11,7 @@ AppButton { id: root leftInset: Config.options.waffles.bar.leftAlignApps ? 12 : 0 - iconName: "start-here" + iconName: down ? "start-here-pressed" : "start-here" onClicked: { GlobalStates.overviewOpen = !GlobalStates.overviewOpen; // For now... diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml index cc35c8b41..ac564b7dc 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml @@ -9,7 +9,7 @@ import qs.modules.waffle.looks AppButton { id: root - iconName: "task-view" + iconName: (down && !checked) ? "task-view-pressed" : "task-view" separateLightDark: true checked: GlobalStates.overviewOpen From 885a9eb0b38023b56e5d32284a8de8067508801e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 16 Nov 2025 00:10:55 +0100 Subject: [PATCH 63/85] wbar: make task view btn anim less weird --- dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml | 4 +++- .../quickshell/ii/modules/waffle/bar/TaskViewButton.qml | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml index dbb430b6d..e29c13a44 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml @@ -17,10 +17,12 @@ BarButton { rightInset: 2 implicitWidth: height - topInset - bottomInset + leftInset + rightInset + property real pressedScale: 5/6 + onDownChanged: { scaleAnim.duration = root.down ? 150 : 200 scaleAnim.easing.bezierCurve = root.down ? Looks.transition.easing.bezierCurve.easeIn : Looks.transition.easing.bezierCurve.easeOut - contentItem.scale = root.down ? 5/6 : 1 // If/When we do dragging, the scale is 1.25 + contentItem.scale = root.down ? root.pressedScale : 1 // If/When we do dragging, the scale is 1.25 } background: Item { diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml index ac564b7dc..760c00608 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml @@ -10,6 +10,7 @@ AppButton { id: root iconName: (down && !checked) ? "task-view-pressed" : "task-view" + pressedScale: checked ? 5/6 : 1 separateLightDark: true checked: GlobalStates.overviewOpen From d15960d930758132c869067773eae71e89575e9d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 16 Nov 2025 00:15:26 +0100 Subject: [PATCH 64/85] wbar: make volume tooltip show muted state --- .../quickshell/ii/modules/waffle/bar/SystemButton.qml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml index 2a74ca171..53caca6ed 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml @@ -85,11 +85,13 @@ BarButton { BarToolTip { extraVisibleCondition: root.shouldShowTooltip && volumeHoverArea.containsMouse text: Translation.tr("Speakers (%1): %2") // - .arg(Audio.sink?.nickname || Audio.sink?.description || Translation.tr("Unknown")) // - .arg(`${Math.round(Audio.sink?.audio.volume * 100) || 0}%`) // + .arg(Audio.sink?.nickname || Audio.sink?.description || Translation.tr("Unknown")) // + .arg(Audio.sink?.audio.muted ? Translation.tr("Muted") : `${Math.round(Audio.sink?.audio.volume * 100) || 0}%`) // } BarToolTip { extraVisibleCondition: root.shouldShowTooltip && batteryHoverArea.containsMouse - text: Translation.tr("Battery: %1%2").arg(`${Math.round(Battery.percentage * 100) || 0}%`).arg(Battery.isPluggedIn ? (" " + Translation.tr("(Plugged in)")) : "") + text: Translation.tr("Battery: %1%2") // + .arg(`${Math.round(Battery.percentage * 100) || 0}%`) // + .arg(Battery.isPluggedIn ? (" " + Translation.tr("(Plugged in)")) : "") } } From 3dfd043645dd05c534eac36f93ba69950b22bb00 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 16 Nov 2025 00:25:14 +0100 Subject: [PATCH 65/85] deps: add kirigami --- sdata/dist-arch/illogical-impulse-quickshell-git/PKGBUILD | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdata/dist-arch/illogical-impulse-quickshell-git/PKGBUILD b/sdata/dist-arch/illogical-impulse-quickshell-git/PKGBUILD index 806f2272e..690b73123 100644 --- a/sdata/dist-arch/illogical-impulse-quickshell-git/PKGBUILD +++ b/sdata/dist-arch/illogical-impulse-quickshell-git/PKGBUILD @@ -9,7 +9,7 @@ conflicts=("quickshell-git") _pkgname=quickshell pkgname="$_prefix-$_pkgname-git" pkgver=0.1.0.r1 -pkgrel=5 +pkgrel=6 pkgdesc="$_pkgname-git pinned commit and extra deps for $_prefix" arch=(x86_64 aarch64) url='https://git.outfoxxed.me/quickshell/quickshell' @@ -39,6 +39,7 @@ depends=( qt6-translations qt6-virtualkeyboard qt6-wayland + kirigami kdialog syntax-highlighting ) From 5c746f34b70eb652438501d53d5e676b03797f0d Mon Sep 17 00:00:00 2001 From: clsty Date: Sun, 16 Nov 2025 08:00:36 +0800 Subject: [PATCH 66/85] Add kdePackages.kirigami in deps-info and dist-nix --- sdata/deps-info.md | 1 + sdata/dist-nix/home-manager/quickshell.nix | 1 + 2 files changed, 2 insertions(+) diff --git a/sdata/deps-info.md b/sdata/deps-info.md index 475639b6e..a7e0f9f14 100644 --- a/sdata/deps-info.md +++ b/sdata/deps-info.md @@ -211,6 +211,7 @@ Extra dependencies. - `qt6-translations` - `qt6-virtualkeyboard` - `qt6-wayland` +- `kirigami` - `kdialog` - `syntax-highlighting` diff --git a/sdata/dist-nix/home-manager/quickshell.nix b/sdata/dist-nix/home-manager/quickshell.nix index 823797082..0fb7b57fe 100644 --- a/sdata/dist-nix/home-manager/quickshell.nix +++ b/sdata/dist-nix/home-manager/quickshell.nix @@ -40,6 +40,7 @@ in pkgs.stdenv.mkDerivation { qt6.qttranslations #qt6-translations qt6.qtvirtualkeyboard #qt6-virtualkeyboard qt6.qtwayland #qt6-wayland + kdePackages.kirigami #kirigami kdePackages.kdialog #kdialog kdePackages.syntax-highlighting #syntax-highlighting ]; From 2a34831f87c87bd08f3eec0228dba1c52cef1310 Mon Sep 17 00:00:00 2001 From: Elysia <1391048988@qq.com> Date: Sun, 16 Nov 2025 14:40:19 +0800 Subject: [PATCH 67/85] Delete redundant spec files --- .../SPECS/Bibata-Modern-Classic.spec | 36 ------------- .../SPECS/JetBrainsMonoNerdFont-Regular.spec | 42 ---------------- sdata/dist-fedora/SPECS/MicroTeX.spec | 50 ------------------- sdata/dist-fedora/SPECS/breeze-plus.spec | 38 -------------- sdata/dist-fedora/SPECS/otf-SpaceGrotesk.spec | 44 ---------------- sdata/dist-fedora/SPECS/ttf-gabarito.spec | 46 ----------------- .../SPECS/ttf-material-symbols-variable.spec | 42 ---------------- sdata/dist-fedora/SPECS/ttf-roboto-flex.spec | 42 ---------------- .../dist-fedora/SPECS/ttf-rubik-variable.spec | 46 ----------------- 9 files changed, 386 deletions(-) delete mode 100644 sdata/dist-fedora/SPECS/Bibata-Modern-Classic.spec delete mode 100644 sdata/dist-fedora/SPECS/JetBrainsMonoNerdFont-Regular.spec delete mode 100644 sdata/dist-fedora/SPECS/MicroTeX.spec delete mode 100644 sdata/dist-fedora/SPECS/breeze-plus.spec delete mode 100644 sdata/dist-fedora/SPECS/otf-SpaceGrotesk.spec delete mode 100644 sdata/dist-fedora/SPECS/ttf-gabarito.spec delete mode 100644 sdata/dist-fedora/SPECS/ttf-material-symbols-variable.spec delete mode 100644 sdata/dist-fedora/SPECS/ttf-roboto-flex.spec delete mode 100644 sdata/dist-fedora/SPECS/ttf-rubik-variable.spec diff --git a/sdata/dist-fedora/SPECS/Bibata-Modern-Classic.spec b/sdata/dist-fedora/SPECS/Bibata-Modern-Classic.spec deleted file mode 100644 index 1522ae851..000000000 --- a/sdata/dist-fedora/SPECS/Bibata-Modern-Classic.spec +++ /dev/null @@ -1,36 +0,0 @@ -Name: Bibata-Modern-Classic -Version: 2.0.7 -Release: %autorelease -Summary: Open source, compact, and material designed cursor set. - -License: GPL-3.0 -URL: https://github.com/ful1e5/Bibata_Cursor -Source0: %{name}.tar.xz - -BuildArch: noarch - -%description -Open source, compact, and material designed cursor set. - -%prep -wget --content-disposition -q -N -P %{_sourcedir} %{url}/releases/download/v%{version}/Bibata-Modern-Classic.tar.xz -wget -q -O %{_buildrootdir}/LICENSE %{url}/raw/refs/heads/main/LICENSE -%setup -q -n %{name} - -%build -: - -%install -install -d -m 0755 %{buildroot}%{_iconsdir}/Bibata-Modern-Classic -cp -r * %{buildroot}%{_iconsdir}/Bibata-Modern-Classic - -install -d -m 0755 %{buildroot}%{_licensedir}/%{name} -install -m 0644 %{_buildrootdir}/LICENSE %{buildroot}%{_licensedir}/%{name}/ - -%files -%{_iconsdir}/Bibata-Modern-Classic -%license %{_licensedir}/%{name}/LICENSE - -%changelog -%autochangelog - diff --git a/sdata/dist-fedora/SPECS/JetBrainsMonoNerdFont-Regular.spec b/sdata/dist-fedora/SPECS/JetBrainsMonoNerdFont-Regular.spec deleted file mode 100644 index 01f1e0e08..000000000 --- a/sdata/dist-fedora/SPECS/JetBrainsMonoNerdFont-Regular.spec +++ /dev/null @@ -1,42 +0,0 @@ -Name: JetBrainsMonoNerdFont-Regular -Version: 1.2 -Release: %autorelease -Summary: JetBrainsMonoNerdFonts (TrueType Outlines) (Regulear) - -License: MIT -URL: https://github.com/Zhaopudark/JetBrainsMonoNerdFonts -Source0: %{name} - -BuildRequires: fonts-rpm-macros -BuildArch: noarch - -%description -An auto-updated compiling version of JetBrains Mono that has been patched with Nerd Fonts. - -%prep -wget --content-disposition -q -N -P %{_sourcedir} %{url}/releases/download/v%{version}/JetBrainsMonoNerdFont-Regular-v%{version}.ttf -wget -q -P %{_sourcedir} %{url}/raw/refs/heads/main/LICENSE - -%build -: - -%install -install -d -m 0755 %{buildroot}%{_fontdir} -install -m 0644 %{_sourcedir}/JetBrainsMonoNerdFont*ttf %{buildroot}%{_fontdir} - -install -d -m 0755 %{buildroot}%{_licensedir}/%{name} -install -m 0644 %{_sourcedir}/LICENSE %{buildroot}%{_licensedir}/%{name}/ - -%post -/usr/bin/fc-cache -fv >/dev/null 2>&1 || : - -%postun -/usr/bin/fc-cache -fv >/dev/null 2>&1 || : - -%files -%{_fontdir}/JetBrainsMonoNerdFont*ttf -%license %{_licensedir}/%{name}/LICENSE - -%changelog -%autochangelog - diff --git a/sdata/dist-fedora/SPECS/MicroTeX.spec b/sdata/dist-fedora/SPECS/MicroTeX.spec deleted file mode 100644 index ec8ae436f..000000000 --- a/sdata/dist-fedora/SPECS/MicroTeX.spec +++ /dev/null @@ -1,50 +0,0 @@ -%global commit0 0e3707f6dafebb121d98b53c64364d16fefe481d -%global shortcommit0 %(c=%{commit0}; echo ${c:0:7}) -%global bumpver 100 - -Name: MicroTeX -Version: 0.0.1%{?bumpver:^%{bumpver}.git%{shortcommit0}} -Release: %autorelease -Summary: A dynamic, cross-platform, and embeddable LaTeX rendering library - -License: MIT -URL: https://github.com/NanoMichael/MicroTeX -Source0: %{name}-%{shortcommit0}.tar.gz - -BuildRequires: gcc-c++ cmake -BuildRequires: pkgconfig(tinyxml2) -BuildRequires: gtkmm3.0-devel gtksourceviewmm3-devel cairomm-devel - -%description -MicroTeX is a library for rendering LaTeX mathematical formulas, supporting multiple backends -such as GTK+, Qt, and Skia. It provides both library components and demo applications for -testing LaTeX rendering. - -%prep -curl -fsSL --retry 3 \ - https://codeload.github.com/NanoMichael/MicroTeX/tar.gz/%{shortcommit0} \ - -o %{_sourcedir}/%{name}-%{shortcommit0}.tar.gz -%setup -q -n %{name}-%{shortcommit0} - -%build -mkdir -p build -cd build -cmake .. -make -j$(nproc) - -%install -mkdir -p %{buildroot}/opt/MicroTeX -cp build/LaTeX %{buildroot}/opt/MicroTeX/ -cp -r build/res %{buildroot}/opt/MicroTeX/ - -install -Dpm 0644 LICENSE %{buildroot}%{_licensedir}/%{name}/LICENSE -install -Dpm 0644 res/greek/LICENSE %{buildroot}%{_licensedir}/%{name}/LICENSE-greek -install -Dpm 0644 res/cyrillic/LICENSE %{buildroot}%{_licensedir}/%{name}/LICENSE-cyrillic - -%files -/opt/MicroTeX/ -%license %{_licensedir}/%{name}/ - -%changelog -%autochangelog - diff --git a/sdata/dist-fedora/SPECS/breeze-plus.spec b/sdata/dist-fedora/SPECS/breeze-plus.spec deleted file mode 100644 index d37ff8e41..000000000 --- a/sdata/dist-fedora/SPECS/breeze-plus.spec +++ /dev/null @@ -1,38 +0,0 @@ -Name: breeze-plus -Version: 6.19.0 -Release: %autorelease -Summary: Breeze theme with additional icons - -License: LGPL-2.1 -URL: https://github.com/mjkim0727/breeze-plus -Source0: %{name}-%{version}.tar.gz - -BuildArch: noarch - -%description -Breeze icon theme with additional icons for applications not covered by the -official Breeze theme. Includes icons for Wine, third-party apps, and more. - -%prep -wget --content-disposition -q -N -P %{_sourcedir} %{url}/archive/refs/tags/%{version}.tar.gz -%setup -q - -%build -: - -%install -install -d -m 0755 %{buildroot}%{_iconsdir}/breeze-plus -cp -r src/breeze-plus %{buildroot}%{_iconsdir}/ -cp -r src/breeze-plus-dark %{buildroot}%{_iconsdir}/ - -install -d -m 0755 %{buildroot}%{_licensedir}/%{name} -install -m 0644 LICENSE %{buildroot}%{_licensedir}/%{name}/ - -%files -%{_iconsdir}/breeze-plus/ -%{_iconsdir}/breeze-plus-dark/ -%license %{_licensedir}/%{name}/LICENSE - -%changelog -%autochangelog - diff --git a/sdata/dist-fedora/SPECS/otf-SpaceGrotesk.spec b/sdata/dist-fedora/SPECS/otf-SpaceGrotesk.spec deleted file mode 100644 index e42e4bc8e..000000000 --- a/sdata/dist-fedora/SPECS/otf-SpaceGrotesk.spec +++ /dev/null @@ -1,44 +0,0 @@ -Name: otf-SpaceGrotesk -Version: 2.0.0 -Release: %autorelease -Summary: Space Grotesk: a proportional variant of the original fixed-width Space Mono family - -License: OFL-1.1 -URL: https://github.com/floriankarsten/space-grotesk -Source0: %{name}-%{version} - -BuildRequires: fonts-rpm-macros -BuildArch: noarch - -%description -Space Grotesk is a proportional sans-serif typeface variant based on Colophon Foundry's fixed-width Space Mono family (2016). -Originally designed by Florian Karsten in 2018, -Space Grotesk retains the monospace's idiosyncratic details while optimizing for improved readability at non-display sizes. - -%prep -wget --content-disposition -q -N -P %{_sourcedir} %{url}/releases/download/%{version}/SpaceGrotesk-%{version}.zip -unzip %{_sourcedir}/SpaceGrotesk-%{version}.zip - -%build -: - -%install -install -d -m 0755 %{buildroot}%{_fontdir} -install -m 0644 %{_buildrootdir}/SpaceGrotesk-%{version}/otf/SpaceGrotesk*otf %{buildroot}%{_fontdir} - -install -d -m 0755 %{buildroot}%{_licensedir}/%{name} -install -m 0644 %{_buildrootdir}/SpaceGrotesk-%{version}/OFL.txt %{buildroot}%{_licensedir}/%{name}/ - -%post -/usr/bin/fc-cache -fv >/dev/null 2>&1 || : - -%postun -/usr/bin/fc-cache -fv >/dev/null 2>&1 || : - -%files -%{_fontdir}/SpaceGrotesk*otf -%license %{_licensedir}/%{name}/OFL.txt - -%changelog -%autochangelog - diff --git a/sdata/dist-fedora/SPECS/ttf-gabarito.spec b/sdata/dist-fedora/SPECS/ttf-gabarito.spec deleted file mode 100644 index a46341bf9..000000000 --- a/sdata/dist-fedora/SPECS/ttf-gabarito.spec +++ /dev/null @@ -1,46 +0,0 @@ -%global commit0 1f3fb39d6449eefa880543f109f33ede0cd4064f -%global shortcommit0 %(c=%{commit0}; echo ${c:0:7}) -%global bumpver 100 - -Name: ttf-gabarito -Version: 1.000%{?bumpver:^%{bumpver}.git%{shortcommit0}} -Release: %autorelease -Summary: Gabarito Font - -License: OFL-1.1 -URL: https://github.com/naipefoundry/gabarito -Source0: gabarito-%{shortcommit0}.tar.gz - -BuildRequires: fonts-rpm-macros -BuildArch: noarch - -%description -Gabarito is a light-hearted geometric sans typeface with 6 weights ranging from Regular to Black originally designed for an online learning platform in Brazil. - -%prep -wget --content-disposition -q -N -P %{_sourcedir} https://codeload.github.com/naipefoundry/gabarito/tar.gz/%{shortcommit0} -%setup -q -n gabarito-%{shortcommit0} - -%build -: - -%install -install -d -m 0755 %{buildroot}%{_fontdir} -install -m 0644 fonts/ttf/Gabarito*.ttf %{buildroot}%{_fontdir} - -install -d -m 0755 %{buildroot}%{_licensedir}/%{name} -install -m 0644 OFL.txt %{buildroot}%{_licensedir}/%{name}/ - -%post -/usr/bin/fc-cache -fv >/dev/null 2>&1 || : - -%postun -/usr/bin/fc-cache -fv >/dev/null 2>&1 || : - -%files -%{_fontdir}/Gabarito*ttf -%license %{_licensedir}/%{name}/OFL.txt - -%changelog -%autochangelog - diff --git a/sdata/dist-fedora/SPECS/ttf-material-symbols-variable.spec b/sdata/dist-fedora/SPECS/ttf-material-symbols-variable.spec deleted file mode 100644 index 989540ec3..000000000 --- a/sdata/dist-fedora/SPECS/ttf-material-symbols-variable.spec +++ /dev/null @@ -1,42 +0,0 @@ -Name: ttf-material-symbols-variable -Version: 4.0.0 -Release: %autorelease -Summary: Material Design icons by Google (Material Symbols) - -License: Apache-2.0 -URL: https://github.com/google/material-design-icons -Source0: %{name}-%{version} - -BuildRequires: fonts-rpm-macros -BuildArch: noarch - -%description -Google Material Symbols Rounded - -%prep -wget --content-disposition -q -N -P %{_sourcedir} %{url}/raw/refs/heads/master/variablefont/MaterialSymbolsRounded%5BFILL,GRAD,opsz,wght%5D.ttf -wget -q -N -P %{_sourcedir} %{url}/raw/refs/heads/master/LICENSE - -%build -: - -%install -install -d -m 0755 %{buildroot}%{_fontdir}/variable-fonts -install -m 0644 %{_sourcedir}/MaterialSymbolsRounded*ttf %{buildroot}%{_fontdir}/variable-fonts/ - -install -d -m 0755 %{buildroot}%{_licensedir}/%{name} -install -m 0644 %{_sourcedir}/LICENSE %{buildroot}%{_licensedir}/%{name}/ - -%post -/usr/bin/fc-cache -fv >/dev/null 2>&1 || : - -%postun -/usr/bin/fc-cache -fv >/dev/null 2>&1 || : - -%files -%{_fontdir}/variable-fonts/MaterialSymbolsRounded*ttf -%license %{_licensedir}/%{name}/LICENSE - -%changelog -%autochangelog - diff --git a/sdata/dist-fedora/SPECS/ttf-roboto-flex.spec b/sdata/dist-fedora/SPECS/ttf-roboto-flex.spec deleted file mode 100644 index e95917bf1..000000000 --- a/sdata/dist-fedora/SPECS/ttf-roboto-flex.spec +++ /dev/null @@ -1,42 +0,0 @@ -Name: ttf-roboto-flex -Version: 3.200 -Release: %autorelease -Summary: Roboto Flex - -License: OFL-1.1 -URL: https://github.com/googlefonts/roboto-flex -Source0: %{name} - -BuildRequires: fonts-rpm-macros -BuildArch: noarch - -%description -: - -%prep -wget --content-disposition -q -N -P %{_sourcedir} %{url}/raw/refs/heads/main/fonts/RobotoFlex%5BGRAD,XOPQ,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC,opsz,slnt,wdth,wght%5D.ttf -wget -q -O %{_sourcedir}/OFL.txt %{url}/raw/refs/heads/main/OFL.txt - -%build -: - -%install -install -d -m 0755 %{buildroot}%{_fontdir} -install -m 0644 %{_sourcedir}/RobotoFlex*ttf %{buildroot}%{_fontdir} - -install -d -m 0755 %{buildroot}%{_licensedir}/%{name} -install -m 0644 %{_sourcedir}/OFL.txt %{buildroot}%{_licensedir}/%{name}/ - -%post -/usr/bin/fc-cache -fv >/dev/null 2>&1 || : - -%postun -/usr/bin/fc-cache -fv >/dev/null 2>&1 || : - -%files -%{_fontdir}/RobotoFlex*ttf -%license %{_licensedir}/%{name}/OFL.txt - -%changelog -%autochangelog - diff --git a/sdata/dist-fedora/SPECS/ttf-rubik-variable.spec b/sdata/dist-fedora/SPECS/ttf-rubik-variable.spec deleted file mode 100644 index ec276be74..000000000 --- a/sdata/dist-fedora/SPECS/ttf-rubik-variable.spec +++ /dev/null @@ -1,46 +0,0 @@ -%global commit0 e337a5f69a9bea30e58d05bd40184d79cc099628 -%global shortcommit0 %(c=%{commit0}; echo ${c:0:7}) -%global bumpver 100 - -Name: ttf-rubik-variable -Version: 1.0%{?bumpver:^%{bumpver}.git%{shortcommit0}} -Release: %autorelease -Summary: Rubik fonts variable - -License: OFL-1.1 -URL: https://github.com/googlefonts/rubik -Source0: rubik-%{shortcommit0}.tar.gz - -BuildRequires: fonts-rpm-macros -BuildArch: noarch - -%description -: - -%prep -wget --content-disposition -q -N -P %{_sourcedir} https://codeload.github.com/googlefonts/rubik/tar.gz/%{shortcommit0} -%setup -q -n rubik-%{shortcommit0} - -%build -: - -%install -install -d -m 0755 %{buildroot}%{_fontdir}/variable-fonts -install -m 0644 fonts/variable/Rubik*ttf %{buildroot}%{_fontdir}/variable-fonts/ - -install -d -m 0755 %{buildroot}%{_licensedir}/%{name} -install -m 0644 OFL.txt %{buildroot}%{_licensedir}/%{name}/ - -%post -/usr/bin/fc-cache -fv >/dev/null 2>&1 || : - -%postun -/usr/bin/fc-cache -fv >/dev/null 2>&1 || : - -%files -%{_fontdir}/variable-fonts/Rubik*ttf -%license %{_licensedir}/%{name}/OFL.txt - -%changelog -%autochangelog - From be1ce37014e192c148f2fcc0e4963e96bed25d55 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 16 Nov 2025 09:44:11 +0100 Subject: [PATCH 68/85] easyeffects: update headless launch flags --- dots/.config/hypr/hyprland/execs.conf | 2 +- dots/.config/quickshell/ii/services/EasyEffects.qml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dots/.config/hypr/hyprland/execs.conf b/dots/.config/hypr/hyprland/execs.conf index 4bb9c86e5..bb5dd7225 100644 --- a/dots/.config/hypr/hyprland/execs.conf +++ b/dots/.config/hypr/hyprland/execs.conf @@ -14,7 +14,7 @@ exec-once = sleep 1 && dbus-update-activation-environment --systemd WAYLAND_DISP exec-once = hyprpm reload # Audio -exec-once = easyeffects --gapplication-service +exec-once = easyeffects --hide-window --service-mode # Clipboard: history # exec-once = wl-paste --watch cliphist store & diff --git a/dots/.config/quickshell/ii/services/EasyEffects.qml b/dots/.config/quickshell/ii/services/EasyEffects.qml index 4117e50c4..e21a0a67f 100644 --- a/dots/.config/quickshell/ii/services/EasyEffects.qml +++ b/dots/.config/quickshell/ii/services/EasyEffects.qml @@ -30,7 +30,7 @@ Singleton { function enable() { root.active = true - Quickshell.execDetached(["bash", "-c", "easyeffects --gapplication-service || flatpak run com.github.wwmm.easyeffects --gapplication-service"]) + Quickshell.execDetached(["bash", "-c", "easyeffects --hide-window --service-mode || flatpak run com.github.wwmm.easyeffects --hide-window --service-mode"]) } function toggle() { From 803f2ecb427c7e44310e24be16ae67f7f439b58b Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 16 Nov 2025 12:04:21 +0100 Subject: [PATCH 69/85] remove unused imports --- .../quickshell/ii/modules/common/widgets/ToolbarTabBar.qml | 1 - dots/.config/quickshell/ii/modules/ii/cheatsheet/Cheatsheet.qml | 1 - .../quickshell/ii/modules/ii/overlay/resources/Resources.qml | 1 - 3 files changed, 3 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/widgets/ToolbarTabBar.qml b/dots/.config/quickshell/ii/modules/common/widgets/ToolbarTabBar.qml index 4d4d56335..1bca18463 100644 --- a/dots/.config/quickshell/ii/modules/common/widgets/ToolbarTabBar.qml +++ b/dots/.config/quickshell/ii/modules/common/widgets/ToolbarTabBar.qml @@ -5,7 +5,6 @@ import qs.services import QtQuick import QtQuick.Controls import QtQuick.Layouts -import Qt.labs.synchronizer Item { id: root diff --git a/dots/.config/quickshell/ii/modules/ii/cheatsheet/Cheatsheet.qml b/dots/.config/quickshell/ii/modules/ii/cheatsheet/Cheatsheet.qml index f44efcb3e..d133fa654 100644 --- a/dots/.config/quickshell/ii/modules/ii/cheatsheet/Cheatsheet.qml +++ b/dots/.config/quickshell/ii/modules/ii/cheatsheet/Cheatsheet.qml @@ -5,7 +5,6 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Qt5Compat.GraphicalEffects -import Qt.labs.synchronizer import Quickshell.Io import Quickshell import Quickshell.Wayland diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/resources/Resources.qml b/dots/.config/quickshell/ii/modules/ii/overlay/resources/Resources.qml index 8bec779bd..512307fc1 100644 --- a/dots/.config/quickshell/ii/modules/ii/overlay/resources/Resources.qml +++ b/dots/.config/quickshell/ii/modules/ii/overlay/resources/Resources.qml @@ -5,7 +5,6 @@ import QtQuick.Layouts import Quickshell import Quickshell.Hyprland import Qt5Compat.GraphicalEffects -import Qt.labs.synchronizer import qs import qs.services import qs.modules.common From c71a2498d0c9c9d1ea1263c778ceba4e70cc18d1 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 16 Nov 2025 12:04:54 +0100 Subject: [PATCH 70/85] bar: refractor tray model into a service --- .../quickshell/ii/modules/ii/bar/SysTray.qml | 14 ++++------ .../ii/modules/ii/bar/SysTrayItem.qml | 12 ++++----- .../quickshell/ii/services/TrayService.qml | 26 +++++++++++++++++++ 3 files changed, 36 insertions(+), 16 deletions(-) create mode 100644 dots/.config/quickshell/ii/services/TrayService.qml diff --git a/dots/.config/quickshell/ii/modules/ii/bar/SysTray.qml b/dots/.config/quickshell/ii/modules/ii/bar/SysTray.qml index 0233b2405..56d33e0d4 100644 --- a/dots/.config/quickshell/ii/modules/ii/bar/SysTray.qml +++ b/dots/.config/quickshell/ii/modules/ii/bar/SysTray.qml @@ -1,10 +1,11 @@ -import qs.modules.common -import qs.modules.common.widgets import QtQuick import QtQuick.Layouts import Quickshell import Quickshell.Hyprland import Quickshell.Services.SystemTray +import qs.services +import qs.modules.common +import qs.modules.common.widgets Item { id: root @@ -17,13 +18,8 @@ Item { property bool showOverflowMenu: true property var activeMenu: null - property bool smartTray: Config.options.bar.tray.filterPassive - property list itemsInUserList: SystemTray.items.values.filter(i => (Config.options.bar.tray.pinnedItems.includes(i.id) && (!smartTray || i.status !== Status.Passive))) - property list itemsNotInUserList: SystemTray.items.values.filter(i => (!Config.options.bar.tray.pinnedItems.includes(i.id) && (!smartTray || i.status !== Status.Passive))) - - property bool invertPins: Config.options.bar.tray.invertPinnedItems - property list pinnedItems: invertPins ? itemsNotInUserList : itemsInUserList - property list unpinnedItems: invertPins ? itemsInUserList : itemsNotInUserList + property list pinnedItems: TrayService.pinnedItems + property list unpinnedItems: TrayService.unpinnedItems onUnpinnedItemsChanged: { if (unpinnedItems.length == 0) root.closeOverflowMenu(); } diff --git a/dots/.config/quickshell/ii/modules/ii/bar/SysTrayItem.qml b/dots/.config/quickshell/ii/modules/ii/bar/SysTrayItem.qml index 1fe5df5f3..40549e6fe 100644 --- a/dots/.config/quickshell/ii/modules/ii/bar/SysTrayItem.qml +++ b/dots/.config/quickshell/ii/modules/ii/bar/SysTrayItem.qml @@ -1,11 +1,12 @@ -import qs.modules.common -import qs.modules.common.widgets -import qs.modules.common.functions import QtQuick import Quickshell import Quickshell.Services.SystemTray import Quickshell.Widgets import Qt5Compat.GraphicalEffects +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.common.functions MouseArea { id: root @@ -31,10 +32,7 @@ MouseArea { event.accepted = true; } onEntered: { - tooltip.text = item.tooltipTitle.length > 0 ? item.tooltipTitle - : (item.title.length > 0 ? item.title : item.id); - if (item.tooltipDescription.length > 0) tooltip.text += " • " + item.tooltipDescription; - if (Config.options.bar.tray.showItemId) tooltip.text += "\n[" + item.id + "]"; + tooltip.text = TrayService.getTooltipForItem(root.item); } Loader { diff --git a/dots/.config/quickshell/ii/services/TrayService.qml b/dots/.config/quickshell/ii/services/TrayService.qml new file mode 100644 index 000000000..f957c46a6 --- /dev/null +++ b/dots/.config/quickshell/ii/services/TrayService.qml @@ -0,0 +1,26 @@ +pragma Singleton + +import qs.modules.common +import QtQuick +import Quickshell +import Quickshell.Services.SystemTray + +Singleton { + id: root + + property bool smartTray: Config.options.bar.tray.filterPassive + property list itemsInUserList: SystemTray.items.values.filter(i => (Config.options.bar.tray.pinnedItems.includes(i.id) && (!smartTray || i.status !== Status.Passive))) + property list itemsNotInUserList: SystemTray.items.values.filter(i => (!Config.options.bar.tray.pinnedItems.includes(i.id) && (!smartTray || i.status !== Status.Passive))) + + property bool invertPins: Config.options.bar.tray.invertPinnedItems + property list pinnedItems: invertPins ? itemsNotInUserList : itemsInUserList + property list unpinnedItems: invertPins ? itemsInUserList : itemsNotInUserList + + function getTooltipForItem(item) { + var result = item.tooltipTitle.length > 0 ? item.tooltipTitle + : (item.title.length > 0 ? item.title : item.id); + if (item.tooltipDescription.length > 0) result += " • " + item.tooltipDescription; + if (Config.options.bar.tray.showItemId) result += "\n[" + item.id + "]"; + return result; + } +} From 5b699959455fb10bdb9396fcaea7f4ce573fc1ca Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 16 Nov 2025 12:05:09 +0100 Subject: [PATCH 71/85] wbar: tray --- .../ii/assets/icons/fluent/chevron-down.svg | 1 + .../ii/modules/waffle/bar/AppButton.qml | 2 +- .../ii/modules/waffle/bar/BarButton.qml | 17 +++--- .../ii/modules/waffle/bar/BarIconButton.qml | 40 +++++++++++++ .../ii/modules/waffle/bar/BarPopup.qml | 19 +++++- .../ii/modules/waffle/bar/UpdatesButton.qml | 43 +++++--------- .../modules/waffle/bar/WaffleBarContent.qml | 2 + .../ii/modules/waffle/bar/tasks/Tasks.qml | 9 ++- .../ii/modules/waffle/bar/tray/Tray.qml | 59 +++++++++++++++++++ .../ii/modules/waffle/bar/tray/TrayButton.qml | 45 ++++++++++++++ .../waffle/bar/tray/TrayOverflowMenu.qml | 59 +++++++++++++++++++ .../ii/modules/waffle/looks/Looks.qml | 8 +++ 12 files changed, 264 insertions(+), 40 deletions(-) create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/chevron-down.svg create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/BarIconButton.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/tray/Tray.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayButton.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/chevron-down.svg b/dots/.config/quickshell/ii/assets/icons/fluent/chevron-down.svg new file mode 100644 index 000000000..604bf9887 --- /dev/null +++ b/dots/.config/quickshell/ii/assets/icons/fluent/chevron-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml index e29c13a44..7f527c97d 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml @@ -75,7 +75,7 @@ BarButton { component BackgroundAcrylicRectangle: AcrylicRectangle { shiny: ((root.hovered && !root.down) || root.checked) - color: root.colBackground + color: root.color border.width: 1 border.color: root.colBackgroundBorder diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml index c98d57baf..f8192389a 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml @@ -11,8 +11,11 @@ Button { property var altAction: () => {} property var middleClickAction: () => {} - property color colBackground + property color colBackground: ColorUtils.transparentize(Looks.colors.bg1) + property color colBackgroundHover: Looks.colors.bg1Hover + property color colBackgroundActive: Looks.colors.bg1Active property color colBackgroundBorder + property color color Layout.fillHeight: true topInset: 4 bottomInset: 4 @@ -37,14 +40,14 @@ Button { } } - colBackgroundBorder: ColorUtils.transparentize(Looks.colors.bg1Border, root.checked ? Looks.contentTransparency : 1) - colBackground: { + colBackgroundBorder: ColorUtils.transparentize(Looks.colors.bg1Border, (root.checked || root.hovered) ? Looks.contentTransparency : 1) + color: { if (root.down) { - return Looks.colors.bg1Active + return root.colBackgroundActive } else if ((root.hovered && !root.down) || root.checked) { - return Looks.colors.bg1Hover + return root.colBackgroundHover } else { - return ColorUtils.transparentize(Looks.colors.bg1) + return root.colBackground } } @@ -66,7 +69,7 @@ Button { background: AcrylicRectangle { shiny: ((root.hovered && !root.down) || root.checked) - color: root.colBackground + color: root.color radius: Looks.radius.medium border.width: 1 border.color: root.colBackgroundBorder diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarIconButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarIconButton.qml new file mode 100644 index 000000000..5b4b327b6 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarIconButton.qml @@ -0,0 +1,40 @@ +import QtQuick +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.waffle.looks +import qs.modules.waffle.bar + +BarButton { + id: root + + property alias iconName: iconContent.icon + property alias iconSource: iconContent.source + property alias iconSize: iconContent.implicitSize + property alias iconRotation: iconContent.rotation + property alias iconMonochrome: iconContent.monochrome + property alias tooltipText: tooltip.text + property alias overlayingItems: iconContent.data + + implicitWidth: 32 + + contentItem: Item { + anchors.centerIn: parent + implicitWidth: iconContent.implicitWidth + implicitHeight: iconContent.implicitHeight + + FluentIcon { + id: iconContent + anchors.centerIn: parent + implicitSize: 16 + icon: root.iconName + monochrome: false + } + } + + BarToolTip { + id: tooltip + extraVisibleCondition: root.shouldShowTooltip && text !== "" + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml index 512b3b2bd..f000c92b0 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml @@ -13,12 +13,23 @@ Loader { required property var contentItem property real padding: Looks.radius.large - Looks.radius.medium property bool noSmoothClosing: !Config.options.waffles.smootherAnimations + property bool closeOnFocusLost: true + signal focusCleared() property Item anchorItem: parent property real visualMargin: 12 readonly property bool barAtBottom: Config.options.waffles.bar.bottom property real ambientShadowWidth: 1 + onFocusCleared: { + if (!root.closeOnFocusLost) return; + root.close() + } + + function grabFocus() { // Doesn't work + item.grabFocus(); + } + function close() { item.close(); } @@ -43,9 +54,7 @@ Loader { id: focusGrab active: true windows: [popupWindow] - onCleared: { - root.close() - } + onCleared: root.focusCleared(); } function close() { @@ -53,6 +62,10 @@ Loader { else closeAnim.start(); } + function grabFocus() { + focusGrab.active = true; // Doesn't work + } + implicitWidth: realContent.implicitWidth + (ambientShadow.border.width * 2) + (root.visualMargin * 2) implicitHeight: realContent.implicitHeight + (ambientShadow.border.width * 2) + (root.visualMargin * 2) diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/UpdatesButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/UpdatesButton.qml index 232f025c3..54286ac88 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/UpdatesButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/UpdatesButton.qml @@ -4,43 +4,30 @@ import qs import qs.services import qs.modules.common import qs.modules.waffle.looks +import qs.modules.waffle.bar.tray -BarButton { +BarIconButton { id: root - visible: Updates.available && Updates.updateAdvised + visible: Updates.updateAdvised || Updates.updateStronglyAdvised padding: 4 + iconName: "arrow-sync" + iconSize: 20 // Needed because the icon appears to have some padding + tooltipText: Translation.tr("Get the latest features and security improvements with\nthe newest feature update.\n\n%1 packages").arg(Updates.count) onClicked: { Quickshell.execDetached(["bash", "-c", Config.options.apps.update]); } - contentItem: Item { - anchors.centerIn: parent - implicitWidth: iconContent.implicitWidth - implicitHeight: iconContent.implicitHeight - - FluentIcon { - id: iconContent - anchors.centerIn: parent - icon: "arrow-sync" - - Rectangle { - anchors { - right: parent.right - bottom: parent.bottom - margins: 1 - } - implicitWidth: 8 - implicitHeight: implicitWidth - radius: height / 2 - color: Updates.updateStronglyAdvised ? Looks.colors.warning : Looks.colors.accent - } + overlayingItems: Rectangle { + anchors { + right: parent.right + bottom: parent.bottom + margins: 1 } - } - - BarToolTip { - extraVisibleCondition: root.shouldShowTooltip - text: Translation.tr("Get the latest features and security improvements with\nthe newest feature update.\n\n%1 packages").arg(Updates.count) + implicitWidth: 8 + implicitHeight: implicitWidth + radius: height / 2 + color: Updates.updateStronglyAdvised ? Looks.colors.warning : Looks.colors.accent } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml index 2ac4dc944..cfbc52779 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml @@ -4,6 +4,7 @@ import qs.modules.common import qs.modules.common.widgets import qs.modules.waffle.looks import qs.modules.waffle.bar.tasks +import qs.modules.waffle.bar.tray Rectangle { id: root @@ -68,6 +69,7 @@ Rectangle { shown: Config.options.waffles.bar.leftAlignApps sourceComponent: WidgetsButton {} } + Tray {} UpdatesButton {} SystemButton {} TimeButton {} diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml index ad42a93fa..f33c6e12a 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml @@ -17,10 +17,17 @@ MouseArea { previewPopup.show(appEntry, button); } + Behavior on implicitWidth { + animation: Looks.transition.move.createObject(this) + } + // Apps row RowLayout { id: row - anchors.fill: parent + anchors { + top: parent.top + bottom: parent.bottom + } spacing: 0 Repeater { diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tray/Tray.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tray/Tray.qml new file mode 100644 index 000000000..b98d7c475 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tray/Tray.qml @@ -0,0 +1,59 @@ +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Layouts +import Qt.labs.synchronizer +import Quickshell +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.waffle.looks +import qs.modules.waffle.bar + +RowLayout { + id: root + + property bool overflowOpen: false + + Layout.fillHeight: true + spacing: 0 + + BarIconButton { + id: overflowButton + + visible: TrayService.unpinnedItems.length > 0 + checked: root.overflowOpen + + iconName: "chevron-down" + iconMonochrome: true + iconRotation: (Config.options.waffles.bar.bottom ? 180 : 0) + (root.overflowOpen ? 180 : 0) + Behavior on iconRotation { + animation: Looks.transition.rotate.createObject(this) + } + + onClicked: { + root.overflowOpen = !root.overflowOpen; + } + + TrayOverflowMenu { + id: trayOverflowLayout + Synchronizer on active { + property alias source: root.overflowOpen + } + } + + BarToolTip { + extraVisibleCondition: overflowButton.shouldShowTooltip + text: qsTr("Show hidden icons") + } + } + + Repeater { + model: ScriptModel { + values: TrayService.pinnedItems + } + delegate: TrayButton { + required property var modelData + item: modelData + } + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayButton.qml new file mode 100644 index 000000000..f7fa7bb1f --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayButton.qml @@ -0,0 +1,45 @@ +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Services.SystemTray +import qs.services +import qs.modules.common +import qs.modules.common.widgets +import qs.modules.waffle.looks +import qs.modules.waffle.bar + +BarIconButton { + id: root + + required property SystemTrayItem item + property alias menuOpen: menu.visible + readonly property bool barAtBottom: Config.options.waffles.bar.bottom + iconSource: item.icon + + onClicked: { + item.activate(); + } + + altAction: () => { + if (item.hasMenu) menu.open() + } + + // This is lazy, but it's not like tray menus on Windoes are consistent... + // TODO: Figure out how to do cascading menus then use a custom menu + QsMenuAnchor { + id: menu + menu: root.item.menu + anchor { + adjustment: PopupAdjustment.ResizeY | PopupAdjustment.SlideX + item: root + gravity: root.barAtBottom ? Edges.Top : Edges.Bottom + edges: root.barAtBottom ? Edges.Top : Edges.Bottom + } + } + + BarToolTip { + extraVisibleCondition: root.shouldShowTooltip + text: TrayService.getTooltipForItem(root.item) + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml new file mode 100644 index 000000000..98f449122 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml @@ -0,0 +1,59 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell +import Quickshell.Hyprland +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.waffle.looks +import qs.modules.waffle.bar + +BarPopup { + id: root + + closeOnFocusLost: false + onFocusCleared: { + print("uwu") + print(contentItem.children) + const hasMenuOpen = contentItem.children.some(c => (c.menuOpen)); + if (!hasMenuOpen) root.close(); + else root.grabFocus(); + } + + contentItem: GridLayout { + id: contentItem + anchors.centerIn: parent + columns: Math.ceil(Math.sqrt(TrayService.unpinnedItems.length)) + columnSpacing: 0 + rowSpacing: 0 + + Repeater { + model: TrayService.unpinnedItems + delegate: TrayButton { + required property var modelData + item: modelData + + topInset: 0 + bottomInset: 0 + implicitWidth: 40 + implicitHeight: 40 + + colBackground: ColorUtils.transparentize(Looks.colors.bg2) + colBackgroundHover: Looks.colors.bg2Hover + colBackgroundActive: Looks.colors.bg2Active + + onMenuOpenChanged: { + // The overflow menu should only be closed when the user clicks outside + // However the focus grab refuses to reactivate, so we can't have that + // But most of the time the user dismisses the menu by clicking outside anyway, + // so this is acceptable. + if (!menuOpen) { + root.close(); + } + } + } + } + } +} + diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml index d2f67fea7..c21e15ed1 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml @@ -117,6 +117,14 @@ Singleton { } } + property Component rotate: Component { + NumberAnimation { + duration: 170 + easing.type: Easing.BezierSpline + easing.bezierCurve: transition.easing.bezierCurve.easeInOut + } + } + property Component anchor: Component { AnchorAnimation { duration: 160 From 1271f147ede7026d8d980ac967d934be86c8e972 Mon Sep 17 00:00:00 2001 From: Elysia <1391048988@qq.com> Date: Sun, 16 Nov 2025 19:40:41 +0800 Subject: [PATCH 72/85] Use copr repositories to replace local builds as much as possible. --- .../SPECS/hyprland-qt-support.spec | 1 - sdata/dist-fedora/SPECS/quickshell-git.spec | 6 +- sdata/dist-fedora/install-deps.sh | 60 ++++++++++--------- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/sdata/dist-fedora/SPECS/hyprland-qt-support.spec b/sdata/dist-fedora/SPECS/hyprland-qt-support.spec index c4f8bf057..4cae243ae 100644 --- a/sdata/dist-fedora/SPECS/hyprland-qt-support.spec +++ b/sdata/dist-fedora/SPECS/hyprland-qt-support.spec @@ -25,7 +25,6 @@ BuildRequires: pkgconfig(hyprlang) %{summary}. %prep -wget --content-disposition -q -N -P %{_sourcedir} %{url}/archive/v%{version}/%{name}-%{version}.tar.gz %autosetup -p1 %build diff --git a/sdata/dist-fedora/SPECS/quickshell-git.spec b/sdata/dist-fedora/SPECS/quickshell-git.spec index a0b23bfd8..e90bdebe2 100644 --- a/sdata/dist-fedora/SPECS/quickshell-git.spec +++ b/sdata/dist-fedora/SPECS/quickshell-git.spec @@ -3,18 +3,19 @@ %bcond_with asan %global commit db1777c20b936a86528c1095cbcb1ebd92801402 +%global shortcommit %(c=%{commit}; echo ${c:0:7}) %global commits 699 %global snapdate 20251030 %global tag 0.2.1 Name: quickshell-git -Version: %{tag}^%{commits}.git%(c=%{commit}; echo ${c:0:7}) +Version: %{tag}^%{commits}.git%{shortcommit} Release: 0%{?dist} Summary: Flexible QtQuick based desktop shell toolkit License: LGPL-3.0-only AND GPL-3.0-only URL: https://github.com/quickshell-mirror/quickshell -Source0: %{url}/archive/%{commit}/quickshell-%{commit}.tar.gz +Source0: %{url}/archive/%{commit}/quickshell-%{shortcommit}.tar.gz Conflicts: quickshell <= %{tag} @@ -53,7 +54,6 @@ Flexible toolkit for making desktop shells with QtQuick, targeting Wayland and X11. %prep -wget --content-disposition -q -N -P %{_sourcedir} %{url}/archive/%{commit}/quickshell-%{commit}.tar.gz %autosetup -n quickshell-%{commit} -p1 %build diff --git a/sdata/dist-fedora/install-deps.sh b/sdata/dist-fedora/install-deps.sh index 6374d5e7e..474e6c279 100644 --- a/sdata/dist-fedora/install-deps.sh +++ b/sdata/dist-fedora/install-deps.sh @@ -8,8 +8,8 @@ fi # Update System case $SKIP_SYSUPDATE in - true) sleep 0;; - *) v sudo dnf upgrade --refresh -y;; +true) sleep 0 ;; +*) v sudo dnf upgrade --refresh -y ;; esac # Remove version lock @@ -19,9 +19,8 @@ v sudo dnf versionlock delete quickshell-git 2>/dev/null v sudo dnf install @development-tools fedora-packager rpmdevtools fonts-rpm-macros qt6-rpm-macros -y # COPR repositories +v sudo dnf copr enable ririko66z/dots-hyprland -y v sudo dnf copr enable solopasha/hyprland -y -v sudo dnf copr enable errornointernet/quickshell -y -v sudo dnf copr enable errornointernet/packages -y v sudo dnf copr enable deltacopy/darkly -y v sudo dnf copr enable alternateved/eza -y v sudo dnf copr enable atim/starship -y @@ -35,15 +34,19 @@ v sudo dnf install geoclue2 brightnessctl ddcutil -y # Basic v sudo dnf install bc coreutils cliphist cmake curl wget2 ripgrep jq xdg-utils rsync yq -y +# Cursor themes +v sudo dnf install bibata-cursor-theme -y + # Fonts & Themes themes_deps=( - adw-gtk3-theme breeze-cursor-theme grub2-breeze-theme breeze-icon-theme{,-fedora} - kf6-breeze-icons sddm-breeze darkly eza fish fontconfig kitty matugen starship - jetbrains-mono-nl-fonts material-icons-fonts twitter-twemoji-fonts + adw-gtk3-theme breeze-cursor-theme grub2-breeze-theme breeze-icon-theme{,-fedora} kf6-breeze-icons + sddm-breeze breeze-plus-icon-theme darkly eza fish fontconfig kitty matugen florian-karsten-space-grotesk-fonts + starship gabarito-fonts jetbrains-mono-nerd-fonts google-material-symbols-vf-rounded-fonts material-icons-fonts + readex-pro-fonts-all google-roboto-flex-fonts google-rubik-vf-fonts twitter-twemoji-fonts ) -v sudo dnf install ${themes_deps[@]} -y +sudo dnf install ${themes_deps[@]} -y -# Hyprland +# Hyprland hyprland_deps=( hyprland hyprsunset @@ -56,8 +59,8 @@ v sudo dnf install hyprlang-devel -y # KDE v sudo dnf install bluedevil gnome-keyring NetworkManager plasma-nm polkit-kde dolphin plasma-systemsettings -y -# Microtex-git -v sudo dnf install --setopt="install_weak_deps=False" tinyxml2-devel gtkmm3.0-devel gtksourceviewmm3-devel cairomm-devel -y +# MicroTeX-git +v sudo dnf install microtex -y # Portal v sudo dnf install xdg-desktop-portal{,-gtk,-kde,-hyprland} -y @@ -69,14 +72,13 @@ v sudo dnf install python3{,.12}{,-devel} -y # Quickshell-git quickshell_deps=( - qt6-qtdeclarative qt6-qtbase jemalloc qt6-qtsvg pipewire-libs - libxcb wayland-devel qt6-qtwayland qt5-qtwayland libdrm breakpad + qt6-qtdeclarative qt6-qtbase jemalloc qt6-qtsvg pipewire-libs libxcb wayland-devel qt6-qtwayland + qt5-qtwayland libdrm breakpad ) # NOTE: Below are custom dependencies of illogical-impulse quickshell_custom_deps=( - qt6-qt5compat qt6-qtimageformats qt6-qtpositioning - qt6-qtquicktimeline qt6-qtsensors qt6-qttools qt6-qttranslations - qt6-qtvirtualkeyboard qt6-qtwayland kdialog kf6-syntax-highlighting + qt6-qt5compat qt6-qtimageformats qt6-qtpositioning qt6-qtquicktimeline qt6-qtsensors qt6-qttools + qt6-qttranslations qt6-qtvirtualkeyboard qt6-qtwayland kdialog kf6-syntax-highlighting ) quickshell_build_deps=( breakpad-static breakpad-devel gcc-c++ ninja-build mesa-libgbm-devel cli11-devel glib2-devel @@ -102,24 +104,24 @@ v sudo dnf install --setopt="install_weak_deps=False" mpvpaper plasma-systemmoni # Start building the missing RPM package locally. install_RPMS() { - rpmbuildroot=${REPO_ROOT}/cache/rpmbuild - x mkdir -p $rpmbuildroot/{BUILD,RPMS,SOURCES} - x cp -r ${REPO_ROOT}/sdata/dist-fedora/SPECS $rpmbuildroot/ - x cd $rpmbuildroot/SPECS - mapfile -t -d '' local_specs < <(find "$rpmbuildroot/SPECS" -maxdepth 1 -type f -name "*.spec" -print0) - for spec_file in ${local_specs[@]}; do - x rpmbuild -bb --define "_topdir $rpmbuildroot" $spec_file - done - mapfile -t -d '' local_rpms < <(find "$rpmbuildroot/RPMS" -maxdepth 2 -type f -name '*.rpm' -not -name '*debug*' -print0) - echo -e "${STY_BLUE}Next command:${STY_RST} sudo dnf install ${local_rpms[@]} -y" - x sudo dnf install "${local_rpms[@]}" -y - x cd ${REPO_ROOT} + rpmbuildroot=${REPO_ROOT}/cache/rpmbuild + x mkdir -p $rpmbuildroot/{BUILD,RPMS,SOURCES} + x cp -r ${REPO_ROOT}/sdata/dist-fedora/SPECS $rpmbuildroot/ + x cd $rpmbuildroot/SPECS + mapfile -t -d '' local_specs < <(find "$rpmbuildroot/SPECS" -maxdepth 1 -type f -name "*.spec" -print0) + for spec_file in ${local_specs[@]}; do + x spectool -g -C "$rpmbuildroot/SOURCES" $spec_file + x rpmbuild -bb --define "_topdir $rpmbuildroot" $spec_file + done + mapfile -t -d '' local_rpms < <(find "$rpmbuildroot/RPMS" -maxdepth 2 -type f -name '*.rpm' -not -name '*debug*' -print0) + echo -e "${STY_BLUE}Next command:${STY_RST} sudo dnf install ${local_rpms[@]} -y" + x sudo dnf install "${local_rpms[@]}" -y + x cd ${REPO_ROOT} } showfun install_RPMS v install_RPMS - # hyprland-qtutils depends on hyprland-qt-support v sudo dnf install hyprland-qtutils -y From f33bc7663ebae9b99ef9a75279e1eab34fb161c5 Mon Sep 17 00:00:00 2001 From: Elysia <1391048988@qq.com> Date: Sun, 16 Nov 2025 19:42:21 +0800 Subject: [PATCH 73/85] Update dependencies for sync-dist-arch. --- sdata/dist-fedora/install-deps.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdata/dist-fedora/install-deps.sh b/sdata/dist-fedora/install-deps.sh index 474e6c279..df82d6b37 100644 --- a/sdata/dist-fedora/install-deps.sh +++ b/sdata/dist-fedora/install-deps.sh @@ -78,7 +78,7 @@ quickshell_deps=( # NOTE: Below are custom dependencies of illogical-impulse quickshell_custom_deps=( qt6-qt5compat qt6-qtimageformats qt6-qtpositioning qt6-qtquicktimeline qt6-qtsensors qt6-qttools - qt6-qttranslations qt6-qtvirtualkeyboard qt6-qtwayland kdialog kf6-syntax-highlighting + qt6-qttranslations qt6-qtvirtualkeyboard qt6-qtwayland kdialog kf6-syntax-highlighting kf6-kirigami ) quickshell_build_deps=( breakpad-static breakpad-devel gcc-c++ ninja-build mesa-libgbm-devel cli11-devel glib2-devel From 8574dbcb02d85d58b63e3e1bd16027b008ebd975 Mon Sep 17 00:00:00 2001 From: Elysia <1391048988@qq.com> Date: Sun, 16 Nov 2025 19:45:59 +0800 Subject: [PATCH 74/85] This may improve compatibility --- sdata/subcmd-install/2.setups.sh | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/sdata/subcmd-install/2.setups.sh b/sdata/subcmd-install/2.setups.sh index 2e585832c..adb7c08a5 100644 --- a/sdata/subcmd-install/2.setups.sh +++ b/sdata/subcmd-install/2.setups.sh @@ -2,19 +2,22 @@ # It's not for directly running. function prepare_systemd_user_service(){ - if [[ ! -d "${XDG_CONFIG_HOME}/systemd/user" ]]; then - x mkdir -p "${XDG_CONFIG_HOME}/systemd/user" - fi - if [[ ! -e "${XDG_CONFIG_HOME}/systemd/user/ydotool.service" ]]; then - x ln -s /usr/lib/systemd/system/ydotool.service "${XDG_CONFIG_HOME}/systemd/user/ydotool.service" + if [[ ! -e "/usr/lib/systemd/user/ydotool.service" ]]; then + x ln -s /usr/lib/systemd/{system,user}/ydotool.service fi } function setup_user_group(){ - if [[ -z $(getent group i2c) ]]; then + if [[ -z $(getent group i2c) ]] && [[ "$OS_GROUP_ID" != "fedora" ]]; then x sudo groupadd i2c fi - x sudo usermod -aG video,i2c,input "$(whoami)" + + if [[ "$OS_GROUP_ID" == "fedora" ]]; then + # TODO: I'm not sure what the video group is for. I didn't join it, and it doesn't seem to be affecting anything. I may need to remove it later + x sudo usermod -aG video,input "$(whoami)" + else + x sudo usermod -aG video,i2c,input "$(whoami)" + fi } ##################################################################################### # These python packages are installed using uv into the venv (virtual environment). Once the folder of the venv gets deleted, they are all gone cleanly. So it's considered as setups, not dependencies. From 5aa384e90639f275eb7baf0211e19ded7d112499 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 16 Nov 2025 13:01:39 +0100 Subject: [PATCH 75/85] wbar: make tray menu more rectangular --- .../ii/modules/waffle/bar/tray/TrayOverflowMenu.qml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml index 98f449122..cc4561b1d 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml @@ -14,8 +14,6 @@ BarPopup { closeOnFocusLost: false onFocusCleared: { - print("uwu") - print(contentItem.children) const hasMenuOpen = contentItem.children.some(c => (c.menuOpen)); if (!hasMenuOpen) root.close(); else root.grabFocus(); @@ -24,7 +22,8 @@ BarPopup { contentItem: GridLayout { id: contentItem anchors.centerIn: parent - columns: Math.ceil(Math.sqrt(TrayService.unpinnedItems.length)) + rows: Math.floor(Math.sqrt(TrayService.unpinnedItems.length)) + columns: Math.ceil(TrayService.unpinnedItems.length / rows) columnSpacing: 0 rowSpacing: 0 From a23ee83aad9a1e5f93970f7775ac888f503beb9d Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 16 Nov 2025 13:02:04 +0100 Subject: [PATCH 76/85] waffles: add notes --- .../quickshell/ii/modules/waffle/README.md | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 dots/.config/quickshell/ii/modules/waffle/README.md diff --git a/dots/.config/quickshell/ii/modules/waffle/README.md b/dots/.config/quickshell/ii/modules/waffle/README.md new file mode 100644 index 000000000..299635be9 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/README.md @@ -0,0 +1,37 @@ +## Waffle + +A recreation of Windoes. It's WIP! + +- If you install illogical-impulse fully, you can press Super+Alt+W to switch to this style. +- If you're just copying the Quickshell config, run the config as usual (`qs -c ii`) then run `qs -c ii ipc call panelFamily cycle` + +## From EWW version to Quickshell + +Just a reflection, in case anyone's interested. My blog is probably a better place for this, but it does not exist. Besides, this is going to change as I do more stuff. Currently there's just the bar. + +### Improvements + +- QtQuick's `Button` has the `{top/bottom/left/right}Inset` properties, so we can have clickable regions expanding beyond the button background for free. With EWW it was annoying to wrap the button content with an `eventbox` that has some padding, then somehow use CSS selectors to make sure hovering effects work. I have to admit, (a large) part of that annoyance was with how bad my copy-pasting coding practice was at the time, but still... + +- Fancy effects: Gtk3 CSS does not support transformations. In QtQuick we can smack `rotation` and `scale` almost everywhere, so it's simple to make bouncy icons and rotating chevrons + +- Quickshell provides a system tray service (EWW does now but didn't at the time I created the EWW Windoes version), so now there's no Waybar needed for the tray. + +- QtQuick has `Loader`s, so we can have this live-switchable from the main style without killing the widget system, moving styles to the correct folder, and relaunching. + +- This time my computer is powerful enough to run a VM, so I don't have to occasionally reboot to take quick screenshots for reference. I try to make everything pixel-perfect so this is necessary. Speaking about pixel-perfectness, in the EWW version I hardcoded sizes, but this time I'm still doing that (lol), BUT that's normal and not a problem because Qt has the `QT_SCALE_FACTOR` env var for scaling. (Please feel free to prove me wrong in saying Gtk3 doesn't have that magic) + +### Challenges + +- Qt is not Gtk and definitely not React + - We don't get directional border on QtQuick `Rectangle`s like in CSS. I was able to get around this with manual drawing, but it was a bit more work + +- Fluent Icons is difficult to use, compared to Material Symbols + - No React, so no clean use via a library. + - If we use the font, there's no proper, searchable **codepoint** cheatsheet like Nerd Fonts, and there's no ligatures + - I resorted to downloading individual SVGs. Not that nice, but it's better than scanning the whole table of icons every time I want one. For this we have fluenticon.com and fluenticons.co, but icons are awkwardly named and there's no alias. Why is the reload/refresh icon called "arrow-sync"? Well, the name is not misleading, but arguably reload/refresh are more common actions. From Fluent Design's [page on Iconography](https://fluent2.microsoft.design/iconography): + + > Fluent system icons are literal metaphors and are named for the shape or object they represent, not the functionality they provide + + "sync" is functionality. + From 9adf310738b4456536cbc4e71ec4853ace332c72 Mon Sep 17 00:00:00 2001 From: ririko6z <165703299+ririko6z@users.noreply.github.com> Date: Sun, 16 Nov 2025 21:16:53 +0800 Subject: [PATCH 77/85] Update 2.setups.sh: Added some comments --- sdata/subcmd-install/2.setups.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sdata/subcmd-install/2.setups.sh b/sdata/subcmd-install/2.setups.sh index adb7c08a5..11dc189f1 100644 --- a/sdata/subcmd-install/2.setups.sh +++ b/sdata/subcmd-install/2.setups.sh @@ -3,12 +3,13 @@ function prepare_systemd_user_service(){ if [[ ! -e "/usr/lib/systemd/user/ydotool.service" ]]; then - x ln -s /usr/lib/systemd/{system,user}/ydotool.service + x sudo ln -s /usr/lib/systemd/{system,user}/ydotool.service fi } function setup_user_group(){ if [[ -z $(getent group i2c) ]] && [[ "$OS_GROUP_ID" != "fedora" ]]; then + # On Fedora this is not needed. Tested with desktop computer with NVIDIA video card. x sudo groupadd i2c fi @@ -30,6 +31,7 @@ v setup_user_group if [[ ! -z $(systemctl --version) ]]; then # TODO: Why fedora does not add i2c-dev? # TODO: Why fedora add uinput and udev rules? + # Regarding uinput and udev rules: the former is required for the virtual keyboard to function, while the latter enables input group users to utilize it. if [[ "$OS_GROUP_ID" == "fedora" ]]; then v bash -c "echo uinput | sudo tee /etc/modules-load.d/uinput.conf" v bash -c 'echo SUBSYSTEM==\"misc\", KERNEL==\"uinput\", MODE=\"0660\", GROUP=\"input\" | sudo tee /etc/udev/rules.d/99-uinput.rules' From 2ce060484a5bab95bcfb4327e96b202ec8c647ce Mon Sep 17 00:00:00 2001 From: Elysia <1391048988@qq.com> Date: Sun, 16 Nov 2025 21:24:02 +0800 Subject: [PATCH 78/85] fix a bug --- sdata/dist-fedora/install-deps.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdata/dist-fedora/install-deps.sh b/sdata/dist-fedora/install-deps.sh index df82d6b37..624fba6ca 100644 --- a/sdata/dist-fedora/install-deps.sh +++ b/sdata/dist-fedora/install-deps.sh @@ -8,8 +8,8 @@ fi # Update System case $SKIP_SYSUPDATE in -true) sleep 0 ;; -*) v sudo dnf upgrade --refresh -y ;; + true) sleep 0 ;; + *) v sudo dnf upgrade --refresh -y ;; esac # Remove version lock @@ -44,7 +44,7 @@ themes_deps=( starship gabarito-fonts jetbrains-mono-nerd-fonts google-material-symbols-vf-rounded-fonts material-icons-fonts readex-pro-fonts-all google-roboto-flex-fonts google-rubik-vf-fonts twitter-twemoji-fonts ) -sudo dnf install ${themes_deps[@]} -y +v sudo dnf install ${themes_deps[@]} -y # Hyprland hyprland_deps=( From 11dd8c9efba66df6c650b70c982db7ab75eef8a7 Mon Sep 17 00:00:00 2001 From: "Celestial.y" Date: Sun, 16 Nov 2025 21:46:48 +0800 Subject: [PATCH 79/85] Apply suggestion from @clsty --- sdata/subcmd-install/2.setups.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/sdata/subcmd-install/2.setups.sh b/sdata/subcmd-install/2.setups.sh index 11dc189f1..27033cbd2 100644 --- a/sdata/subcmd-install/2.setups.sh +++ b/sdata/subcmd-install/2.setups.sh @@ -14,7 +14,6 @@ function setup_user_group(){ fi if [[ "$OS_GROUP_ID" == "fedora" ]]; then - # TODO: I'm not sure what the video group is for. I didn't join it, and it doesn't seem to be affecting anything. I may need to remove it later x sudo usermod -aG video,input "$(whoami)" else x sudo usermod -aG video,i2c,input "$(whoami)" From d2692cc95e8933b638542f80e546924f53f72d0d Mon Sep 17 00:00:00 2001 From: "Celestial.y" Date: Sun, 16 Nov 2025 21:48:29 +0800 Subject: [PATCH 80/85] Apply suggestion from @clsty --- sdata/subcmd-install/2.setups.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sdata/subcmd-install/2.setups.sh b/sdata/subcmd-install/2.setups.sh index 27033cbd2..c321bd752 100644 --- a/sdata/subcmd-install/2.setups.sh +++ b/sdata/subcmd-install/2.setups.sh @@ -28,9 +28,7 @@ showfun setup_user_group v setup_user_group if [[ ! -z $(systemctl --version) ]]; then - # TODO: Why fedora does not add i2c-dev? - # TODO: Why fedora add uinput and udev rules? - # Regarding uinput and udev rules: the former is required for the virtual keyboard to function, while the latter enables input group users to utilize it. + # For Fedora, uinput is required for the virtual keyboard to function, and udev rules enable input group users to utilize it. if [[ "$OS_GROUP_ID" == "fedora" ]]; then v bash -c "echo uinput | sudo tee /etc/modules-load.d/uinput.conf" v bash -c 'echo SUBSYSTEM==\"misc\", KERNEL==\"uinput\", MODE=\"0660\", GROUP=\"input\" | sudo tee /etc/udev/rules.d/99-uinput.rules' From 869f9529f680300af3cf823a26cc114f61b8af58 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 16 Nov 2025 21:05:32 +0100 Subject: [PATCH 81/85] update fluent icons note --- dots/.config/quickshell/ii/assets/icons/fluent/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/README.md b/dots/.config/quickshell/ii/assets/icons/fluent/README.md index 5f4d3eaa2..c8fbd90e8 100644 --- a/dots/.config/quickshell/ii/assets/icons/fluent/README.md +++ b/dots/.config/quickshell/ii/assets/icons/fluent/README.md @@ -1,5 +1,5 @@ -The "search" and "task view" icons are from here, with modifications +The "start-here", "search" and "task view" icons are from here, with modifications -https://www.figma.com/community/file/1123040825921884189/windows-11 +[Windows 11 by Joshua Oghenekaro Okwe - Figma](https://www.figma.com/community/file/1123040825921884189/windows-11) -License: CC BY 4.0 +License: [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/deed.en) From 986461f5903c7a8c1d9dff6fe7087effd603ab12 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 16 Nov 2025 21:07:42 +0100 Subject: [PATCH 82/85] wbar: drag to pin tray item --- .../quickshell/ii/modules/common/Config.qml | 16 ++++--- .../ii/modules/ii/bar/SysTrayItem.qml | 4 +- .../ii/modules/settings/BarConfig.qml | 8 ++-- .../ii/modules/waffle/bar/tray/Tray.qml | 47 +++++++++++++++++++ .../waffle/bar/tray/TrayOverflowMenu.qml | 4 +- .../quickshell/ii/services/TrayService.qml | 29 ++++++++++-- 6 files changed, 89 insertions(+), 19 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml index c71b77cc9..ec47c514b 100644 --- a/dots/.config/quickshell/ii/modules/common/Config.qml +++ b/dots/.config/quickshell/ii/modules/common/Config.qml @@ -3,6 +3,7 @@ pragma ComponentBehavior: Bound import QtQuick import Quickshell import Quickshell.Io +import qs.modules.common.functions Singleton { id: root @@ -238,13 +239,6 @@ Singleton { property bool showPerformanceProfileToggle: false property bool showScreenRecord: false } - property JsonObject tray: JsonObject { - property bool monochromeIcons: true - property bool showItemId: false - property bool invertPinnedItems: true // Makes the below a whitelist for the tray and blacklist for the pinned area - property list pinnedItems: [ ] - property bool filterPassive: true - } property JsonObject workspaces: JsonObject { property bool monochromeIcons: true property int shown: 10 @@ -431,6 +425,14 @@ Singleton { property int historyLength: 60 } + property JsonObject tray: JsonObject { + property bool monochromeIcons: true + property bool showItemId: false + property bool invertPinnedItems: true // Makes the below a whitelist for the tray and blacklist for the pinned area + property list pinnedItems: [ "Fcitx" ] + property bool filterPassive: true + } + property JsonObject musicRecognition: JsonObject { property int timeout: 16 property int interval: 4 diff --git a/dots/.config/quickshell/ii/modules/ii/bar/SysTrayItem.qml b/dots/.config/quickshell/ii/modules/ii/bar/SysTrayItem.qml index 40549e6fe..6230de0f8 100644 --- a/dots/.config/quickshell/ii/modules/ii/bar/SysTrayItem.qml +++ b/dots/.config/quickshell/ii/modules/ii/bar/SysTrayItem.qml @@ -63,7 +63,7 @@ MouseArea { IconImage { id: trayIcon - visible: !Config.options.bar.tray.monochromeIcons + visible: !Config.options.tray.monochromeIcons source: root.item.icon anchors.centerIn: parent width: parent.width @@ -71,7 +71,7 @@ MouseArea { } Loader { - active: Config.options.bar.tray.monochromeIcons + active: Config.options.tray.monochromeIcons anchors.fill: trayIcon sourceComponent: Item { Desaturate { diff --git a/dots/.config/quickshell/ii/modules/settings/BarConfig.qml b/dots/.config/quickshell/ii/modules/settings/BarConfig.qml index 06e694bc8..bfe4c256e 100644 --- a/dots/.config/quickshell/ii/modules/settings/BarConfig.qml +++ b/dots/.config/quickshell/ii/modules/settings/BarConfig.qml @@ -148,18 +148,18 @@ ContentPage { ConfigSwitch { buttonIcon: "keep" text: Translation.tr('Make icons pinned by default') - checked: Config.options.bar.tray.invertPinnedItems + checked: Config.options.tray.invertPinnedItems onCheckedChanged: { - Config.options.bar.tray.invertPinnedItems = checked; + Config.options.tray.invertPinnedItems = checked; } } ConfigSwitch { buttonIcon: "colors" text: Translation.tr('Tint icons') - checked: Config.options.bar.tray.monochromeIcons + checked: Config.options.tray.monochromeIcons onCheckedChanged: { - Config.options.bar.tray.monochromeIcons = checked; + Config.options.tray.monochromeIcons = checked; } } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tray/Tray.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tray/Tray.qml index b98d7c475..a98d9b786 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tray/Tray.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tray/Tray.qml @@ -45,6 +45,14 @@ RowLayout { extraVisibleCondition: overflowButton.shouldShowTooltip text: qsTr("Show hidden icons") } + + DropArea { + id: pinDropArea + anchors.fill: parent + property bool willPin: false + onEntered: willPin = true + onExited: willPin = false + } } Repeater { @@ -52,8 +60,47 @@ RowLayout { values: TrayService.pinnedItems } delegate: TrayButton { + id: trayButton required property var modelData item: modelData + + Drag.active: dragArea.drag.active + Drag.hotSpot.x: width / 2 + Drag.hotSpot.y: height / 2 + property real initialX + property real initialY + + Behavior on x { + animation: Looks.transition.move.createObject(this) + } + + MouseArea { + id: dragArea + anchors.fill: parent + drag.target: parent + drag.axis: Drag.XAxis + + onPressed: (event) => { + trayButton.initialX = trayButton.x; + trayButton.initialY = trayButton.y; + trayButton.Drag.active = true; + } + onReleased: { + if (!dragArea.drag.active) { + trayButton.click(); + } else { + if (pinDropArea.containsDrag && pinDropArea.willPin) { + // Quickshell would crash if we don't hide this item first. Took me fucking 3 hours to figure out... + trayButton.visible = false; + TrayService.togglePin(trayButton.item.id); + pinDropArea.willPin = false; + } else { + trayButton.x = trayButton.initialX; + trayButton.y = trayButton.initialY; + } + } + } + } } } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml index cc4561b1d..3c7f5f466 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml @@ -28,7 +28,9 @@ BarPopup { rowSpacing: 0 Repeater { - model: TrayService.unpinnedItems + model: ScriptModel { + values: TrayService.unpinnedItems + } delegate: TrayButton { required property var modelData item: modelData diff --git a/dots/.config/quickshell/ii/services/TrayService.qml b/dots/.config/quickshell/ii/services/TrayService.qml index f957c46a6..a874c6c11 100644 --- a/dots/.config/quickshell/ii/services/TrayService.qml +++ b/dots/.config/quickshell/ii/services/TrayService.qml @@ -8,11 +8,11 @@ import Quickshell.Services.SystemTray Singleton { id: root - property bool smartTray: Config.options.bar.tray.filterPassive - property list itemsInUserList: SystemTray.items.values.filter(i => (Config.options.bar.tray.pinnedItems.includes(i.id) && (!smartTray || i.status !== Status.Passive))) - property list itemsNotInUserList: SystemTray.items.values.filter(i => (!Config.options.bar.tray.pinnedItems.includes(i.id) && (!smartTray || i.status !== Status.Passive))) + property bool smartTray: Config.options.tray.filterPassive + property list itemsInUserList: SystemTray.items.values.filter(i => (Config.options.tray.pinnedItems.includes(i.id) && (!smartTray || i.status !== Status.Passive))) + property list itemsNotInUserList: SystemTray.items.values.filter(i => (!Config.options.tray.pinnedItems.includes(i.id) && (!smartTray || i.status !== Status.Passive))) - property bool invertPins: Config.options.bar.tray.invertPinnedItems + property bool invertPins: Config.options.tray.invertPinnedItems property list pinnedItems: invertPins ? itemsNotInUserList : itemsInUserList property list unpinnedItems: invertPins ? itemsInUserList : itemsNotInUserList @@ -20,7 +20,26 @@ Singleton { var result = item.tooltipTitle.length > 0 ? item.tooltipTitle : (item.title.length > 0 ? item.title : item.id); if (item.tooltipDescription.length > 0) result += " • " + item.tooltipDescription; - if (Config.options.bar.tray.showItemId) result += "\n[" + item.id + "]"; + if (Config.options.tray.showItemId) result += "\n[" + item.id + "]"; return result; } + + // Pinning + function pin(itemId) { + var pins = Config.options.tray.pinnedItems; + if (pins.includes(itemId)) return; + Config.options.tray.pinnedItems.push(itemId); + } + function unpin(itemId) { + Config.options.tray.pinnedItems = Config.options.tray.pinnedItems.filter(id => id !== itemId); + } + function togglePin(itemId) { + var pins = Config.options.tray.pinnedItems; + if (pins.includes(itemId)) { + unpin(itemId) + } else { + pin(itemId) + } + } + } From 28bf94904f3e67c5f84410b68c6a6bab89bd66ce Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 16 Nov 2025 21:59:42 +0100 Subject: [PATCH 83/85] wbar: unpin and stuff i realized i mixed up pinning and unpinning, but whatever --- .../modules/common/widgets/PopupToolTip.qml | 4 + .../ii/modules/waffle/bar/BarIconButton.qml | 1 + .../ii/modules/waffle/bar/tray/Tray.qml | 38 ++++-- .../ii/modules/waffle/bar/tray/TrayButton.qml | 9 +- .../waffle/bar/tray/TrayOverflowMenu.qml | 121 +++++++++++++----- .../ii/modules/waffle/looks/WPopupToolTip.qml | 18 ++- 6 files changed, 141 insertions(+), 50 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/common/widgets/PopupToolTip.qml b/dots/.config/quickshell/ii/modules/common/widgets/PopupToolTip.qml index bc72ee416..afc9957a4 100644 --- a/dots/.config/quickshell/ii/modules/common/widgets/PopupToolTip.qml +++ b/dots/.config/quickshell/ii/modules/common/widgets/PopupToolTip.qml @@ -14,6 +14,10 @@ Item { property real horizontalPadding: 10 property real verticalPadding: 5 + function updateAnchor() { + tooltipLoader.item?.anchor.updateAnchor(); + } + readonly property bool internalVisibleCondition: (extraVisibleCondition && (parent.hovered === undefined || parent?.hovered)) || alternativeVisibleCondition property var anchorEdges: Edges.Top property var anchorGravity: anchorEdges diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarIconButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarIconButton.qml index 5b4b327b6..311e5e4c9 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/BarIconButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarIconButton.qml @@ -14,6 +14,7 @@ BarButton { property alias iconSize: iconContent.implicitSize property alias iconRotation: iconContent.rotation property alias iconMonochrome: iconContent.monochrome + property alias iconScale: iconContent.scale property alias tooltipText: tooltip.text property alias overlayingItems: iconContent.data diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tray/Tray.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tray/Tray.qml index a98d9b786..f05f2593e 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tray/Tray.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tray/Tray.qml @@ -13,6 +13,7 @@ RowLayout { id: root property bool overflowOpen: false + property bool dragging: false Layout.fillHeight: true spacing: 0 @@ -20,7 +21,7 @@ RowLayout { BarIconButton { id: overflowButton - visible: TrayService.unpinnedItems.length > 0 + visible: (TrayService.unpinnedItems.length > 0 || root.dragging) checked: root.overflowOpen iconName: "chevron-down" @@ -29,11 +30,11 @@ RowLayout { Behavior on iconRotation { animation: Looks.transition.rotate.createObject(this) } - + onClicked: { root.overflowOpen = !root.overflowOpen; } - + TrayOverflowMenu { id: trayOverflowLayout Synchronizer on active { @@ -64,27 +65,25 @@ RowLayout { required property var modelData item: modelData - Drag.active: dragArea.drag.active - Drag.hotSpot.x: width / 2 - Drag.hotSpot.y: height / 2 property real initialX property real initialY - Behavior on x { - animation: Looks.transition.move.createObject(this) - } - MouseArea { id: dragArea anchors.fill: parent drag.target: parent drag.axis: Drag.XAxis + drag.threshold: 2 - onPressed: (event) => { + onPressed: event => { + trayButton.Drag.hotSpot.x = event.x; trayButton.initialX = trayButton.x; - trayButton.initialY = trayButton.y; + root.dragging = true; trayButton.Drag.active = true; } + onPositionChanged: { + pinTooltip.updateAnchor(); + } onReleased: { if (!dragArea.drag.active) { trayButton.click(); @@ -96,9 +95,22 @@ RowLayout { pinDropArea.willPin = false; } else { trayButton.x = trayButton.initialX; - trayButton.y = trayButton.initialY; } } + trayButton.Drag.active = false; + root.dragging = false; + } + } + + BarToolTip { + id: pinTooltip + extraVisibleCondition: trayButton.Drag.active && pinDropArea.containsDrag && pinDropArea.willPin + realContentHorizontalPadding: 6 + realContentVerticalPadding: 6 + realContentItem: FluentIcon { + anchors.centerIn: parent + icon: "pin-off" + implicitSize: 18 } } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayButton.qml index f7fa7bb1f..e3c85e290 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayButton.qml @@ -16,6 +16,13 @@ BarIconButton { property alias menuOpen: menu.visible readonly property bool barAtBottom: Config.options.waffles.bar.bottom iconSource: item.icon + iconScale: 0 + Component.onCompleted: { + root.iconScale = 1 + } + Behavior on iconScale { + animation: Looks.transition.enter.createObject(this) + } onClicked: { item.activate(); @@ -39,7 +46,7 @@ BarIconButton { } BarToolTip { - extraVisibleCondition: root.shouldShowTooltip + extraVisibleCondition: root.shouldShowTooltip && !root.Drag.active text: TrayService.getTooltipForItem(root.item) } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml index 3c7f5f466..f4d5d96d8 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml @@ -1,3 +1,4 @@ +pragma ComponentBehavior: Bound import QtQuick import QtQuick.Controls import QtQuick.Layouts @@ -15,46 +16,108 @@ BarPopup { closeOnFocusLost: false onFocusCleared: { const hasMenuOpen = contentItem.children.some(c => (c.menuOpen)); - if (!hasMenuOpen) root.close(); - else root.grabFocus(); + if (!hasMenuOpen) + root.close(); + else + root.grabFocus(); } - contentItem: GridLayout { + contentItem: Item { id: contentItem anchors.centerIn: parent - rows: Math.floor(Math.sqrt(TrayService.unpinnedItems.length)) - columns: Math.ceil(TrayService.unpinnedItems.length / rows) - columnSpacing: 0 - rowSpacing: 0 + implicitWidth: contentGrid.implicitWidth + implicitHeight: contentGrid.implicitHeight + GridLayout { + id: contentGrid + anchors.centerIn: parent + rows: Math.floor(Math.sqrt(TrayService.unpinnedItems.length)) + columns: Math.ceil(TrayService.unpinnedItems.length / rows) + columnSpacing: 0 + rowSpacing: 0 - Repeater { - model: ScriptModel { - values: TrayService.unpinnedItems - } - delegate: TrayButton { - required property var modelData - item: modelData + Repeater { + model: ScriptModel { + values: TrayService.unpinnedItems + onValuesChanged: { + if (values.length === 0) { + root.close(); + } + } + } + delegate: TrayButton { + id: trayButton + required property var modelData + item: modelData - topInset: 0 - bottomInset: 0 - implicitWidth: 40 - implicitHeight: 40 + topInset: 0 + bottomInset: 0 + implicitWidth: 40 + implicitHeight: 40 - colBackground: ColorUtils.transparentize(Looks.colors.bg2) - colBackgroundHover: Looks.colors.bg2Hover - colBackgroundActive: Looks.colors.bg2Active + colBackground: ColorUtils.transparentize(Looks.colors.bg2) + colBackgroundHover: Looks.colors.bg2Hover + colBackgroundActive: Looks.colors.bg2Active - onMenuOpenChanged: { - // The overflow menu should only be closed when the user clicks outside - // However the focus grab refuses to reactivate, so we can't have that - // But most of the time the user dismisses the menu by clicking outside anyway, - // so this is acceptable. - if (!menuOpen) { - root.close(); + onMenuOpenChanged: { + // The overflow menu should only be closed when the user clicks outside + // However the focus grab refuses to reactivate, so we can't have that + // But most of the time the user dismisses the menu by clicking outside anyway, + // so this is acceptable. + if (!menuOpen) { + root.close(); + } + } + + property real initialX + property real initialY + + Behavior on x { + animation: Looks.transition.move.createObject(this) + } + Behavior on y { + animation: Looks.transition.move.createObject(this) + } + + MouseArea { + id: dragArea + anchors.fill: parent + drag.target: parent + drag.threshold: 2 + + onPressed: event => { + trayButton.Drag.hotSpot.x = event.x; + trayButton.Drag.hotSpot.y = event.y; + trayButton.initialX = trayButton.x; + trayButton.initialY = trayButton.y; + trayButton.Drag.active = true; + } + onReleased: { + if (!dragArea.drag.active) { + trayButton.click(); + } else { + if (!unpinDropArea.containsDrag && unpinDropArea.willUnpin) { + // Quickshell would crash if we don't hide this item first. Took me fucking 3 hours to figure out... + trayButton.visible = false; + TrayService.togglePin(trayButton.item.id); + unpinDropArea.willUnpin = false; + } else { + trayButton.x = trayButton.initialX; + trayButton.y = trayButton.initialY; + } + } + trayButton.Drag.active = false; + } } } } } + + DropArea { + id: unpinDropArea + anchors.fill: parent + property bool willUnpin: false + onEntered: willUnpin = false + onExited: willUnpin = true + } } } - diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml index 6b89d4f24..ff633dec0 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml @@ -10,9 +10,17 @@ import qs.modules.waffle.looks PopupToolTip { id: root + property Item realContentItem + realContentItem: WText { + text: root.text + anchors.centerIn: parent + } + property real visualMargin: 11 verticalPadding: visualMargin horizontalPadding: visualMargin + property real realContentVerticalPadding: 8 + property real realContentHorizontalPadding: 10 contentItem: Item { anchors.centerIn: parent @@ -36,16 +44,12 @@ PopupToolTip { id: realContent z: 1 anchors.centerIn: parent - implicitWidth: tooltipText.implicitWidth + 10 * 2 - implicitHeight: tooltipText.implicitHeight + 8 * 2 + implicitWidth: root.realContentItem.implicitWidth + root.realContentHorizontalPadding * 2 + implicitHeight: root.realContentItem.implicitHeight + root.realContentVerticalPadding * 2 color: Looks.colors.bg1 radius: Looks.radius.medium - WText { - id: tooltipText - text: root.text - anchors.centerIn: parent - } + children: [root.realContentItem] } } } From 71e0538cf54cd34bd7b98b2707b4ec4d6d4bcdd2 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 16 Nov 2025 22:06:30 +0100 Subject: [PATCH 84/85] wbar: update anchor position when pinning tray items --- dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml | 4 ++++ .../ii/modules/waffle/bar/tray/TrayOverflowMenu.qml | 1 + 2 files changed, 5 insertions(+) diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml index f000c92b0..a98a34d62 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml @@ -34,6 +34,10 @@ Loader { item.close(); } + function updateAnchor() { + item?.anchor.updateAnchor(); + } + active: false visible: active sourceComponent: PopupWindow { diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml index f4d5d96d8..2b3044643 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tray/TrayOverflowMenu.qml @@ -39,6 +39,7 @@ BarPopup { model: ScriptModel { values: TrayService.unpinnedItems onValuesChanged: { + root.updateAnchor(); if (values.length === 0) { root.close(); } From 2d65af70ad16f06fed534babe527fd80c2b99082 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 16 Nov 2025 23:52:07 +0100 Subject: [PATCH 85/85] waffles: add action center window --- dots/.config/hypr/hyprland/rules.conf | 2 + .../ii/assets/icons/fluent/settings.svg | 1 + .../actionCenter/ActionCenterContent.qml | 77 +++++++++++++++++ .../actionCenter/WaffleActionCenter.qml | 85 +++++++++++++++++++ .../ii/modules/waffle/bar/BarPopup.qml | 17 +--- .../ii/modules/waffle/bar/SystemButton.qml | 4 +- .../ii/modules/waffle/bar/WaffleBar.qml | 5 +- .../modules/waffle/bar/tasks/TaskPreview.qml | 14 +-- .../ii/modules/waffle/looks/Looks.qml | 6 +- .../modules/waffle/looks/WAmbientShadow.qml | 25 ++++++ .../waffle/looks/WBarAttachedPanelContent.qml | 79 +++++++++++++++++ .../waffle/looks/WPanelFooterButton.qml | 32 +++++++ .../ii/modules/waffle/looks/WPopupToolTip.qml | 13 +-- dots/.config/quickshell/ii/shell.qml | 4 +- 14 files changed, 321 insertions(+), 43 deletions(-) create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/settings.svg create mode 100644 dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterContent.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/actionCenter/WaffleActionCenter.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/looks/WAmbientShadow.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/looks/WBarAttachedPanelContent.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/looks/WPanelFooterButton.qml diff --git a/dots/.config/hypr/hyprland/rules.conf b/dots/.config/hypr/hyprland/rules.conf index 01ac1056d..ea9e6fd72 100644 --- a/dots/.config/hypr/hyprland/rules.conf +++ b/dots/.config/hypr/hyprland/rules.conf @@ -133,12 +133,14 @@ layerrule = blurpopups, quickshell:.* layerrule = blur, quickshell:.* layerrule = ignorealpha 0.79, quickshell:.* layerrule = animation slide, quickshell:bar +layerrule = noanim, quickshell:actionCenter layerrule = animation slide bottom, quickshell:cheatsheet layerrule = animation slide bottom, quickshell:dock layerrule = animation popin 120%, quickshell:screenCorners layerrule = noanim, quickshell:lockWindowPusher layerrule = animation fade, quickshell:notificationPopup layerrule = noanim, quickshell:overlay +layerrule = ignorealpha 1, quickshell:overlay layerrule = noanim, quickshell:overview layerrule = animation slide bottom, quickshell:osk layerrule = noanim, quickshell:polkit diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/settings.svg b/dots/.config/quickshell/ii/assets/icons/fluent/settings.svg new file mode 100644 index 000000000..f1e568829 --- /dev/null +++ b/dots/.config/quickshell/ii/assets/icons/fluent/settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterContent.qml b/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterContent.qml new file mode 100644 index 000000000..6d2e528db --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterContent.qml @@ -0,0 +1,77 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.waffle.looks + +WBarAttachedPanelContent { + id: root + + contentItem: ColumnLayout { + anchors.centerIn: parent + spacing: 0 + + Rectangle { + Layout.fillHeight: true + Layout.fillWidth: true + topLeftRadius: root.border.radius - root.border.border.width + topRightRadius: topLeftRadius + color: Looks.colors.bgPanelBody + + implicitWidth: 360 + implicitHeight: 380 + } + + Rectangle { + Layout.fillHeight: false + Layout.fillWidth: true + color: Looks.colors.bgPanelSeparator + implicitHeight: 1 + } + + Rectangle { + Layout.fillHeight: false + Layout.fillWidth: true + bottomLeftRadius: root.border.radius - root.border.border.width + bottomRightRadius: bottomLeftRadius + color: Looks.colors.bgPanelFooter + + implicitWidth: 360 + implicitHeight: 47 + + // Battery button + WPanelFooterButton { + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: 12 + + contentItem: Row { + spacing: 4 + + FluentIcon { + anchors.verticalCenter: parent.verticalCenter + icon: WIcons.batteryIcon + } + WText { + anchors.verticalCenter: parent.verticalCenter + text: `${Math.round(Battery.percentage * 100) || 0}%` + } + } + } + + // Settings button + WPanelFooterButton { + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 12 + + contentItem: FluentIcon { + icon: "settings" + } + } + } + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/actionCenter/WaffleActionCenter.qml b/dots/.config/quickshell/ii/modules/waffle/actionCenter/WaffleActionCenter.qml new file mode 100644 index 000000000..86e610238 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/actionCenter/WaffleActionCenter.qml @@ -0,0 +1,85 @@ +import QtQuick +import Quickshell +import Quickshell.Io +import Quickshell.Wayland +import Quickshell.Hyprland +import qs +import qs.services +import qs.modules.common +import qs.modules.common.widgets + +Scope { + id: root + + Connections { + target: GlobalStates + + function onSidebarLeftOpenChanged() { + if (GlobalStates.sidebarLeftOpen) barLoader.active = true; + } + } + + Loader { + id: barLoader + active: GlobalStates.sidebarLeftOpen + sourceComponent: PanelWindow { + id: panelWindow + exclusiveZone: 0 + WlrLayershell.namespace: "quickshell:actionCenter" + WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand + color: "transparent" + + anchors { + bottom: Config.options.waffles.bar.bottom + top: !Config.options.waffles.bar.bottom + right: true + } + + implicitWidth: content.implicitWidth + content.visualMargin * 2 + implicitHeight: content.implicitHeight + content.visualMargin * 2 + + HyprlandFocusGrab { + id: focusGrab + active: true + windows: [panelWindow] + onCleared: content.close(); + } + + Connections { + target: GlobalStates + function onSidebarLeftOpenChanged() { + if (!GlobalStates.sidebarLeftOpen) content.close(); + } + } + + ActionCenterContent { + id: content + anchors.centerIn: parent + + onClosed: { + barLoader.active = false; + GlobalStates.sidebarLeftOpen = false; + } + } + } + } + + function toggleOpen() { + GlobalStates.sidebarLeftOpen = !GlobalStates.sidebarLeftOpen; + } + + IpcHandler { + target: "sidebarLeft" + + function toggle() { + root.toggleOpen(); + } + } + + GlobalShortcut { + name: "sidebarLeftToggle" + description: "Toggles left sidebar on press" + + onPressed: root.toggleOpen(); + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml index a98a34d62..a46811b82 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarPopup.qml @@ -70,8 +70,8 @@ Loader { focusGrab.active = true; // Doesn't work } - implicitWidth: realContent.implicitWidth + (ambientShadow.border.width * 2) + (root.visualMargin * 2) - implicitHeight: realContent.implicitHeight + (ambientShadow.border.width * 2) + (root.visualMargin * 2) + implicitWidth: realContent.implicitWidth + (root.ambientShadowWidth * 2) + (root.visualMargin * 2) + implicitHeight: realContent.implicitHeight + (root.ambientShadowWidth * 2) + (root.visualMargin * 2) property real sourceEdgeMargin: -implicitHeight PropertyAnimation { @@ -101,17 +101,8 @@ Loader { } color: "transparent" - Rectangle { - id: ambientShadow - z: 0 - anchors { - fill: realContent - margins: -border.width - } - border.color: ColorUtils.transparentize(Looks.colors.ambientShadow, Looks.shadowTransparency) - border.width: root.ambientShadowWidth - color: "transparent" - radius: realContent.radius + border.width + WAmbientShadow { + target: realContent } Rectangle { diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml index 53caca6ed..2ce1cd862 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml @@ -8,9 +8,9 @@ import qs.modules.waffle.looks BarButton { id: root - checked: GlobalStates.sidebarRightOpen + checked: GlobalStates.sidebarLeftOpen onClicked: { - GlobalStates.sidebarRightOpen = !GlobalStates.sidebarRightOpen; // For now... + GlobalStates.sidebarLeftOpen = !GlobalStates.sidebarLeftOpen; } contentItem: Item { diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml index aa5f51f68..2326a47f7 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml @@ -9,9 +9,8 @@ import qs.modules.common import qs.modules.common.widgets Scope { - id: bar - property bool showBarBackground: Config.options.bar.showBackground - + id: root + LazyLoader { id: barLoader active: GlobalStates.barOpen && !GlobalStates.screenLocked diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml index 0228ee755..18b11caee 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml @@ -36,7 +36,7 @@ PopupWindow { ///////////////////// Internals ///////////////////// readonly property bool bottom: Config.options.waffles.bar.bottom property real visualMargin: 12 - property alias ambientShadowWidth: ambientShadow.border.width + property real ambientShadowWidth: 1 visible: false color: "transparent" @@ -64,16 +64,8 @@ PopupWindow { hoverEnabled: true // Shadow - Rectangle { - id: ambientShadow - anchors { - fill: contentItem - margins: -border.width - } - border.color: ColorUtils.transparentize(Looks.colors.ambientShadow, Looks.shadowTransparency) - border.width: 1 - color: "transparent" - radius: Looks.radius.large + border.width + WAmbientShadow { + target: contentItem } Rectangle { diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml index c21e15ed1..a01628d4a 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml @@ -17,10 +17,12 @@ Singleton { property real backgroundTransparency: 0.17 property real contentTransparency: 0.25 - property real shadowTransparency: 0.6 colors: QtObject { id: colors - property color ambientShadow: ColorUtils.transparentize("#000000", 0.4) + property color ambientShadow: ColorUtils.transparentize("#000000", 0.75) + property color bgPanelFooter: root.dark ? "#1C1C1C" : "#EEEEEE" + property color bgPanelBody: root.dark ? "#242424" : "#F2F2F2" + property color bgPanelSeparator: root.dark ? "#191919" : "#E0E0E0" property color bg0: root.dark ? "#1C1C1C" : "#EEEEEE" property color bg0Border: root.dark ? "#404040" : "#BEBEBE" property color bg1: root.dark ? "#2C2C2C" : "#F7F7F7" diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WAmbientShadow.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WAmbientShadow.qml new file mode 100644 index 000000000..79a3ca857 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WAmbientShadow.qml @@ -0,0 +1,25 @@ +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Controls +import Quickshell +import Quickshell.Hyprland +import qs.modules.common +import qs.modules.common.functions +import qs.modules.waffle.looks + +Rectangle { + id: root + + required property var target + z: 0 + + anchors { + fill: target + margins: -border.width + } + + border.color: Looks.colors.ambientShadow + border.width: 1 + color: "transparent" + radius: target.radius + border.width +} diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WBarAttachedPanelContent.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WBarAttachedPanelContent.qml new file mode 100644 index 000000000..3350c5887 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WBarAttachedPanelContent.qml @@ -0,0 +1,79 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.waffle.looks + +Item { + id: root + + signal closed() + + property alias border: borderRect + required default property Item contentItem + property real visualMargin: 12 + + function close() { + closeAnim.start(); + } + + readonly property bool barAtBottom: Config.options.waffles.bar.bottom + + implicitHeight: borderRect.implicitHeight + implicitWidth: borderRect.implicitWidth + + Rectangle { + id: borderRect + + color: "transparent" + radius: Looks.radius.large + border.color: Looks.colors.bg2Border + border.width: 1 + implicitWidth: contentItem.implicitWidth + border.width * 2 + implicitHeight: contentItem.implicitHeight + border.width * 2 + children: [root.contentItem] + + anchors { + left: parent.left + right: parent.right + top: root.barAtBottom ? undefined : parent.top + bottom: root.barAtBottom ? parent.bottom : undefined + // Opening anim + bottomMargin: root.barAtBottom ? sourceEdgeMargin : 0 + topMargin: root.barAtBottom ? 0 : sourceEdgeMargin + } + + Component.onCompleted: { + openAnim.start(); + } + + property real sourceEdgeMargin: -(implicitHeight + root.visualMargin) + PropertyAnimation { + id: openAnim + target: borderRect + property: "sourceEdgeMargin" + to: 0 + duration: 200 + easing.type: Easing.BezierSpline + easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn + } + SequentialAnimation { + id: closeAnim + PropertyAnimation { + target: borderRect + property: "sourceEdgeMargin" + to: -(implicitHeight + root.visualMargin) + duration: 150 + easing.type: Easing.BezierSpline + easing.bezierCurve: Looks.transition.easing.bezierCurve.easeOut + } + ScriptAction { + script: { + root.closed(); + } + } + } + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WPanelFooterButton.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WPanelFooterButton.qml new file mode 100644 index 000000000..9b017d75f --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WPanelFooterButton.qml @@ -0,0 +1,32 @@ +import QtQuick +import QtQuick.Controls +import Quickshell +import qs.modules.common +import qs.modules.common.functions +import qs.modules.waffle.looks + +Button { + id: root + + implicitHeight: 36 + + property color colBackground: ColorUtils.transparentize(Looks.colors.bg1) + property color colBackgroundHover: Looks.colors.bg1Hover + property color colBackgroundActive: Looks.colors.bg1Active + property color color + property color colForeground: Looks.colors.fg + color: { + if (root.down) { + return root.colBackgroundActive + } else if ((root.hovered && !root.down) || root.checked) { + return root.colBackgroundHover + } else { + return root.colBackground + } + } + + background: Rectangle { + radius: Looks.radius.medium + color: root.color + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml index ff633dec0..feddc3793 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml @@ -27,17 +27,8 @@ PopupToolTip { implicitWidth: realContent.implicitWidth + 2 * 2 implicitHeight: realContent.implicitHeight + 2 * 2 - Rectangle { - id: ambientShadow - z: 0 - anchors { - fill: realContent - margins: -border.width - } - border.color: ColorUtils.transparentize(Looks.colors.ambientShadow, Looks.shadowTransparency) - border.width: 1 - color: "transparent" - radius: realContent.radius + border.width + WAmbientShadow { + target: realContent } Rectangle { diff --git a/dots/.config/quickshell/ii/shell.qml b/dots/.config/quickshell/ii/shell.qml index 746c1003d..766728cf5 100644 --- a/dots/.config/quickshell/ii/shell.qml +++ b/dots/.config/quickshell/ii/shell.qml @@ -28,6 +28,7 @@ import qs.modules.ii.overlay import qs.modules.ii.verticalBar import qs.modules.ii.wallpaperSelector +import qs.modules.waffle.actionCenter import qs.modules.waffle.background import qs.modules.waffle.bar @@ -75,6 +76,7 @@ ShellRoot { PanelLoader { identifier: "iiSidebarRight"; component: SidebarRight {} } PanelLoader { identifier: "iiVerticalBar"; extraCondition: Config.options.bar.vertical; component: VerticalBar {} } PanelLoader { identifier: "iiWallpaperSelector"; component: WallpaperSelector {} } + PanelLoader { identifier: "wActionCenter"; component: WaffleActionCenter {} } PanelLoader { identifier: "wBar"; component: WaffleBar {} } PanelLoader { identifier: "wBackground"; component: WaffleBackground {} } @@ -88,7 +90,7 @@ ShellRoot { property list families: ["ii", "waffle"] property var panelFamilies: ({ "ii": ["iiBar", "iiBackground", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiScreenCorners", "iiSessionScreen", "iiSidebarLeft", "iiSidebarRight", "iiVerticalBar", "iiWallpaperSelector"], - "waffle": ["wBar", "wBackground", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiSessionScreen", "iiSidebarLeft", "iiSidebarRight", "iiWallpaperSelector"], + "waffle": ["wBar", "wBackground", "wActionCenter", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiSessionScreen", "iiSidebarRight", "iiWallpaperSelector"], }) function cyclePanelFamily() { const currentIndex = families.indexOf(Config.options.panelFamily)