From 945c6a07821c206b0d1bdb9dbecfce55de6e3130 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 12 Nov 2025 21:38:30 +0100 Subject: [PATCH] wbar: add tooltip and stuff --- .../modules/common/widgets/PopupToolTip.qml | 28 +++--- .../volumeMixer/VolumeDialogContent.qml | 2 +- .../ii/modules/waffle/bar/AppButton.qml | 44 ++++++++- .../ii/modules/waffle/bar/AppIcon.qml | 3 +- .../ii/modules/waffle/bar/BarButton.qml | 66 ++++++++++++-- .../ii/modules/waffle/bar/BarToolTip.qml | 8 ++ .../ii/modules/waffle/bar/SearchButton.qml | 11 +++ .../ii/modules/waffle/bar/StartButton.qml | 11 +++ .../ii/modules/waffle/bar/SystemButton.qml | 90 +++++++++++++++---- .../ii/modules/waffle/bar/TaskAppButton.qml | 25 ------ .../ii/modules/waffle/bar/TaskViewButton.qml | 5 ++ .../ii/modules/waffle/bar/TimeButton.qml | 6 ++ .../modules/waffle/bar/WaffleBarContent.qml | 1 + .../ii/modules/waffle/bar/WidgetsButton.qml | 5 ++ .../waffle/bar/tasks/TaskAppButton.qml | 71 +++++++++++++++ .../waffle/bar/{ => tasks}/TaskPreview.qml | 2 +- .../modules/waffle/bar/{ => tasks}/Tasks.qml | 8 +- .../waffle/bar/{ => tasks}/WindowPreview.qml | 1 + .../ii/modules/waffle/looks/Looks.qml | 7 +- .../ii/modules/waffle/looks/WPopupToolTip.qml | 51 +++++++++++ .../quickshell/ii/services/AppSearch.qml | 5 +- 21 files changed, 377 insertions(+), 73 deletions(-) create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/BarToolTip.qml delete mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/TaskAppButton.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml rename dots/.config/quickshell/ii/modules/waffle/bar/{ => tasks}/TaskPreview.qml (99%) rename dots/.config/quickshell/ii/modules/waffle/bar/{ => tasks}/Tasks.qml (81%) rename dots/.config/quickshell/ii/modules/waffle/bar/{ => tasks}/WindowPreview.qml (99%) create mode 100644 dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml diff --git a/dots/.config/quickshell/ii/modules/common/widgets/PopupToolTip.qml b/dots/.config/quickshell/ii/modules/common/widgets/PopupToolTip.qml index 741b4556c..bc72ee416 100644 --- a/dots/.config/quickshell/ii/modules/common/widgets/PopupToolTip.qml +++ b/dots/.config/quickshell/ii/modules/common/widgets/PopupToolTip.qml @@ -1,3 +1,4 @@ +pragma ComponentBehavior: Bound import qs.modules.common import qs.modules.common.widgets import QtQuick @@ -13,15 +14,24 @@ Item { property real horizontalPadding: 10 property real verticalPadding: 5 + readonly property bool internalVisibleCondition: (extraVisibleCondition && (parent.hovered === undefined || parent?.hovered)) || alternativeVisibleCondition property var anchorEdges: Edges.Top property var anchorGravity: anchorEdges - readonly property bool internalVisibleCondition: (extraVisibleCondition && (parent.hovered === undefined || parent?.hovered)) || alternativeVisibleCondition + property Item contentItem: StyledToolTipContent { + id: contentItem + anchors.centerIn: parent + text: root.text + shown: false + Component.onCompleted: shown = true + horizontalPadding: root.horizontalPadding + verticalPadding: root.verticalPadding + } Loader { id: tooltipLoader anchors.fill: parent - active: internalVisibleCondition + active: root.internalVisibleCondition sourceComponent: PopupWindow { visible: true anchor { @@ -35,18 +45,10 @@ Item { } color: "transparent" - implicitWidth: contentItem.implicitWidth + root.horizontalPadding * 2 - implicitHeight: contentItem.implicitHeight + root.verticalPadding * 2 + implicitWidth: root.contentItem.implicitWidth + root.horizontalPadding * 2 + implicitHeight: root.contentItem.implicitHeight + root.verticalPadding * 2 - StyledToolTipContent { - id: contentItem - anchors.centerIn: parent - text: root.text - shown: false - Component.onCompleted: shown = true - horizontalPadding: root.horizontalPadding - verticalPadding: root.verticalPadding - } + data: [root.contentItem] } } } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/volumeMixer/VolumeDialogContent.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/volumeMixer/VolumeDialogContent.qml index 46d83f7de..5eb409ecb 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/volumeMixer/VolumeDialogContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/volumeMixer/VolumeDialogContent.qml @@ -44,7 +44,7 @@ ColumnLayout { Layout.fillHeight: false Layout.fillWidth: true Layout.bottomMargin: 6 - model: root.devices.map(node => node.description) + model: root.devices.map(node => (node.nickname || node.description || Translation.tr("Unknown"))) currentIndex: root.devices.findIndex(item => { if (root.isSink) { return item.id === Pipewire.preferredDefaultAudioSink?.id diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml index 90d0cc007..a35e12a2e 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml @@ -1,5 +1,6 @@ import QtQuick import QtQuick.Layouts +import Qt5Compat.GraphicalEffects import org.kde.kirigami as Kirigami import qs.services import qs.modules.common @@ -9,7 +10,9 @@ BarButton { id: root required property string iconName + property bool multiple: false property bool separateLightDark: false + property alias tryCustomIcon: iconWidget.tryCustomIcon leftInset: 2 rightInset: 2 implicitWidth: height - topInset - bottomInset + leftInset + rightInset @@ -20,9 +23,37 @@ BarButton { contentItem.scale = root.down ? 5/6 : 1 // If/When we do dragging, the scale is 1.25 } + background: Item { + BackgroundAcrylicRectangle { + id: mainBgRect + anchors.fill: parent + layer.enabled: root.multiple + layer.effect: OpacityMask { + invert: true + maskSource: Item { + width: mainBgRect.width + height: mainBgRect.height + Rectangle { + anchors.fill: parent + anchors.rightMargin: 3 + radius: mainBgRect.radius + } + } + } + } + Loader { + anchors.fill: parent + anchors.rightMargin: 5 + active: root.multiple + sourceComponent: BackgroundAcrylicRectangle { + + } + } + } + contentItem: Item { id: contentItem - anchors.centerIn: root.background + anchors.centerIn: parent implicitHeight: iconWidget.implicitHeight implicitWidth: iconWidget.implicitWidth @@ -41,4 +72,15 @@ BarButton { separateLightDark: root.separateLightDark } } + + component BackgroundAcrylicRectangle: AcrylicRectangle { + shiny: ((root.hovered && !root.down) || root.checked) + color: root.colBackground + border.width: 1 + border.color: root.colBackgroundBorder + + Behavior on border.color { + animation: Looks.transition.color.createObject(this) + } + } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml b/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml index fc5c75426..f70a80603 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml @@ -8,11 +8,12 @@ Kirigami.Icon { id: root required property string iconName property bool separateLightDark: false + property bool tryCustomIcon: true property real implicitSize: 26 implicitWidth: implicitSize implicitHeight: implicitSize roundToIconSize: false - source: `${Looks.iconsPath}/${root.iconName}${!root.separateLightDark ? "" : Looks.dark ? "-dark" : "-light"}.svg` 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/BarButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml index 52e5164aa..ce1a4cdc7 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml @@ -8,20 +8,70 @@ import qs.modules.waffle.looks Button { id: root + signal altAction() + signal middleClickAction() + + property color colBackground + property color colBackgroundBorder Layout.fillHeight: true topInset: 4 bottomInset: 4 + signal hoverTimedOut() + property bool shouldShowTooltip: false + property Timer hoverTimer: Timer { + id: hoverTimer + running: root.hovered + interval: 400 + onTriggered: { + root.hoverTimedOut() + } + } + onHoverTimedOut: { + root.shouldShowTooltip = true + } + onHoveredChanged: { + if (!root.hovered) { + root.shouldShowTooltip = false + root.hoverTimer.stop() + } + } + + colBackground: { + if (root.down) { + return Looks.colors.bg1Active + } else if ((root.hovered && !root.down) || root.checked) { + return Looks.colors.bg1Hover + } else { + return ColorUtils.transparentize(Looks.colors.bg1) + } + } + colBackgroundBorder: ColorUtils.transparentize(Looks.colors.bg1Border, root.checked ? Looks.contentTransparency : 1) + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton + onPressed: (event) => { + root.down = true; + } + onReleased: (event) => { + root.down = false; + } + onClicked: (event) => { + if (event.button === Qt.LeftButton) root.clicked(); + if (event.button === Qt.RightButton) root.altAction(); + if (event.button === Qt.MiddleButton) root.middleClickAction(); + } + } + background: AcrylicRectangle { shiny: ((root.hovered && !root.down) || root.checked) - color: { - if (root.down) { - return Looks.colors.bg1Active - } else if ((root.hovered && !root.down) || root.checked) { - return Looks.colors.bg1Hover - } else { - return ColorUtils.transparentize(Looks.colors.bg1) - } + color: root.colBackground + border.width: 1 + border.color: root.colBackgroundBorder + + Behavior on border.color { + animation: Looks.transition.color.createObject(this) } } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarToolTip.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarToolTip.qml new file mode 100644 index 000000000..d38566fdd --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarToolTip.qml @@ -0,0 +1,8 @@ +import QtQuick +import Quickshell +import qs.modules.common +import qs.modules.waffle.looks + +WPopupToolTip { + anchorEdges: Config.options.waffles.bar.bottom ? Edges.Top : Edges.Bottom +} diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml index d1b59b85b..a86faaece 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml @@ -1,6 +1,7 @@ import QtQuick import QtQuick.Layouts import org.kde.kirigami as Kirigami +import qs import qs.services import qs.modules.common import qs.modules.waffle.looks @@ -10,4 +11,14 @@ AppButton { iconName: "system-search" separateLightDark: true + + onClicked: { + GlobalStates.overviewOpen = !GlobalStates.overviewOpen; // For now... + } + + BarToolTip { + id: tooltip + text: Translation.tr("Search") + extraVisibleCondition: root.shouldShowTooltip + } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml index d5a4e0f97..4595802ee 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml @@ -1,6 +1,7 @@ import QtQuick import QtQuick.Layouts import org.kde.kirigami as Kirigami +import qs import qs.services import qs.modules.common import qs.modules.waffle.looks @@ -10,4 +11,14 @@ AppButton { leftInset: Config.options.waffles.bar.leftAlignApps ? 12 : 0 iconName: "start-here" + + onClicked: { + GlobalStates.overviewOpen = !GlobalStates.overviewOpen; // For now... + } + + BarToolTip { + id: tooltip + text: Translation.tr("Start") + extraVisibleCondition: root.shouldShowTooltip + } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml index e1bb83684..1de9654d5 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml @@ -1,5 +1,6 @@ import QtQuick import QtQuick.Layouts +import qs import qs.services import qs.modules.common import qs.modules.waffle.looks @@ -7,35 +8,88 @@ import qs.modules.waffle.looks BarButton { id: root - // padding: 12 + checked: GlobalStates.sidebarRightOpen + onClicked: { + GlobalStates.sidebarRightOpen = !GlobalStates.sidebarRightOpen; // For now... + } contentItem: Item { - anchors.centerIn: root.background + anchors.fill: parent implicitHeight: column.implicitHeight implicitWidth: column.implicitWidth Row { id: column - anchors.centerIn: parent - spacing: 4 - - FluentIcon { - icon: WIcons.internetIcon + anchors { + top: parent.top + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter } - - FluentIcon { - icon: { - const muted = Audio.sink?.audio.muted ?? false; - const volume = Audio.sink?.audio.volume ?? 0; - if (muted) return volume > 0 ? "speaker-off" : "speaker-none"; - if (volume == 0) return "speaker-none"; - if (volume < 0.5) return "speaker-1"; - return "speaker"; + spacing: 4 + + IconHoverArea { + id: internetHoverArea + iconItem: FluentIcon { + anchors.verticalCenter: parent.verticalCenter + icon: WIcons.internetIcon } } - FluentIcon { - icon: WIcons.batteryIcon + IconHoverArea { + id: volumeHoverArea + iconItem: FluentIcon { + anchors.verticalCenter: parent.verticalCenter + icon: { + const muted = Audio.sink?.audio.muted ?? false; + const volume = Audio.sink?.audio.volume ?? 0; + if (muted) + return volume > 0 ? "speaker-off" : "speaker-none"; + if (volume == 0) + return "speaker-none"; + if (volume < 0.5) + return "speaker-1"; + return "speaker"; + } + } + } + + IconHoverArea { + id: batteryHoverArea + iconItem: FluentIcon { + anchors.verticalCenter: parent.verticalCenter + icon: WIcons.batteryIcon + } } } } + + component IconHoverArea: MouseArea { + id: hoverArea + required property var iconItem + anchors { + top: parent.top + bottom: parent.bottom + } + hoverEnabled: true + implicitHeight: hoverArea.iconItem.implicitHeight + implicitWidth: hoverArea.iconItem.implicitWidth + + onPressed: (event) => event.accepted = false; // Don't consume clicks + + children: [iconItem] + } + + BarToolTip { + extraVisibleCondition: root.shouldShowTooltip && internetHoverArea.containsMouse + text: Translation.tr("%1\nInternet access").arg(Network.ethernet ? Translation.tr("Network") : Network.networkName) + } + 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}%`) // + } + BarToolTip { + extraVisibleCondition: root.shouldShowTooltip && batteryHoverArea.containsMouse + text: Translation.tr("Battery: %1").arg(`${Math.round(Battery.percentage * 100) || 0}%`) + } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/TaskAppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/TaskAppButton.qml deleted file mode 100644 index 7363b0387..000000000 --- a/dots/.config/quickshell/ii/modules/waffle/bar/TaskAppButton.qml +++ /dev/null @@ -1,25 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import qs.services -import qs.modules.common -import qs.modules.waffle.looks -import Quickshell - -AppButton { - id: root - - required property var appEntry - readonly property bool isSeparator: appEntry.appId === "SEPARATOR" - readonly property var desktopEntry: DesktopEntries.heuristicLookup(appEntry.appId) - - signal hoverPreviewRequested() - - iconName: AppSearch.guessIcon(appEntry.appId) - Timer { - running: root.hovered - interval: 250 - onTriggered: { - root.hoverPreviewRequested() - } - } -} diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml index c3a4853f0..cc35c8b41 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml @@ -16,4 +16,9 @@ AppButton { onClicked: { GlobalStates.overviewOpen = !GlobalStates.overviewOpen; } + + BarToolTip { + extraVisibleCondition: root.shouldShowTooltip + text: Translation.tr("Task View") // Should be a preview of workspaces, but we'll have this for now... + } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/TimeButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/TimeButton.qml index f8e2f38cc..bb813c85c 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/TimeButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/TimeButton.qml @@ -33,4 +33,10 @@ BarButton { } } } + + BarToolTip { + id: tooltip + extraVisibleCondition: root.shouldShowTooltip + text: `${Qt.locale().toString(DateTime.clock.date, "dddd, MMMM d, yyyy")}\n\n${Qt.locale().toString(DateTime.clock.date, "ddd hh:mm AP")}` + } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml index 5228abb5c..aa064118a 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml @@ -3,6 +3,7 @@ import QtQuick.Layouts import qs.modules.common import qs.modules.common.widgets import qs.modules.waffle.looks +import qs.modules.waffle.bar.tasks Rectangle { id: root diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml index 7107cfafd..1c6c11859 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml @@ -52,4 +52,9 @@ AppButton { } } } + + BarToolTip { + extraVisibleCondition: root.shouldShowTooltip + text: Translation.tr("Widgets") + } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml new file mode 100644 index 000000000..10fdbdf38 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml @@ -0,0 +1,71 @@ +import QtQuick +import QtQuick.Layouts +import qs.services +import qs.modules.common +import qs.modules.waffle.looks +import qs.modules.waffle.bar +import Quickshell + +AppButton { + id: root + + required property var appEntry + readonly property bool isSeparator: appEntry.appId === "SEPARATOR" + readonly property var desktopEntry: DesktopEntries.heuristicLookup(appEntry.appId) + property bool active: root.appEntry.toplevels.some(t => t.activated) + property bool hasWindows: appEntry.toplevels.length > 0 + + signal hoverPreviewRequested() + + multiple: appEntry.toplevels.length > 1 + checked: active + iconName: AppSearch.guessIcon(appEntry.appId) + tryCustomIcon: false + + onHoverTimedOut: { + root.hoverPreviewRequested() + } + + onClicked: { + root.hoverTimer.stop() // Prevents preview showing up when clicking to focus + if (root.multiple) { + root.hoverPreviewRequested() + } else if (root.appEntry.toplevels.length === 1) { + root.appEntry.toplevels[0].activate() + } else { + root.desktopEntry.execute() + } + } + + // Active indicator + Rectangle { + id: activeIndicator + opacity: root.hasWindows ? 1 : 0 + anchors { + horizontalCenter: root.background.horizontalCenter + bottom: root.background.bottom + bottomMargin: 1 + } + + implicitWidth: root.active ? 16 : 6 + implicitHeight: 3 + radius: height / 2 + + color: root.active ? Looks.colors.accent : Looks.colors.accentUnfocused + + Behavior on implicitWidth { + animation: Looks.transition.enter.createObject(this) + } + Behavior on color { + animation: Looks.transition.color.createObject(this) + } + Behavior on opacity { + animation: Looks.transition.opacity.createObject(this) + } + } + + BarToolTip { + extraVisibleCondition: root.shouldShowTooltip && !root.hasWindows + text: desktopEntry ? desktopEntry.name : appEntry.appId + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/TaskPreview.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml similarity index 99% rename from dots/.config/quickshell/ii/modules/waffle/bar/TaskPreview.qml rename to dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskPreview.qml index 3c03563a3..6d8aeba1a 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/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.contentTransparency) + border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.shadowTransparency) border.width: 1 color: "transparent" radius: Looks.radius.large + border.width diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/Tasks.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml similarity index 81% rename from dots/.config/quickshell/ii/modules/waffle/bar/Tasks.qml rename to dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml index eac963722..895b1353f 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/Tasks.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/Tasks.qml @@ -13,6 +13,10 @@ MouseArea { implicitWidth: row.implicitWidth hoverEnabled: true + function showPreviewPopup(appEntry, button) { + previewPopup.show(appEntry, button); + } + // Apps row RowLayout { id: row @@ -20,7 +24,7 @@ MouseArea { spacing: 0 Repeater { - // TODO: Include only apps (and windows) in current workspace only + // TODO: Include only apps (and windows) in current workspace only | wait, does that even make sense in a Hyprland workflow? model: ScriptModel { objectProp: "appId" values: TaskbarApps.apps.filter(app => app.appId !== "SEPARATOR") @@ -30,7 +34,7 @@ MouseArea { appEntry: modelData onHoverPreviewRequested: { - previewPopup.show(appEntry, this) + root.showPreviewPopup(appEntry, this) } } } diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WindowPreview.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/WindowPreview.qml similarity index 99% rename from dots/.config/quickshell/ii/modules/waffle/bar/WindowPreview.qml rename to dots/.config/quickshell/ii/modules/waffle/bar/tasks/WindowPreview.qml index b1944c350..2839a6747 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/WindowPreview.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/WindowPreview.qml @@ -6,6 +6,7 @@ import qs.services import qs.modules.common import qs.modules.common.functions import qs.modules.waffle.looks +import qs.modules.waffle.bar import Quickshell import Quickshell.Wayland diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml index df7df8187..09176830f 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml @@ -17,6 +17,7 @@ Singleton { property real backgroundTransparency: 0.17 property real contentTransparency: 0.25 + property real shadowTransparency: 0.6 colors: QtObject { id: colors property color bg0: root.dark ? "#1C1C1C" : "#EEEEEE" @@ -33,7 +34,9 @@ Singleton { property color fg1: root.dark ? "#D1D1D1" : "#626262" property color danger: "#C42B1C" property color dangerActive: "#B62D1F" - property color brand: Appearance.m3colors.m3primary + // property color accent: root.dark ? "#A5C6D8" : "#5377A3" + property color accent: Appearance.m3colors.m3primary + property color accentUnfocused: root.dark ? "#989898" : "#848484" } radius: QtObject { @@ -106,7 +109,7 @@ Singleton { property Component move: Component { NumberAnimation { - duration: 100 + duration: 170 easing.type: Easing.BezierSpline easing.bezierCurve: transition.easing.bezierCurve.easeInOut } diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml new file mode 100644 index 000000000..b35258204 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WPopupToolTip.qml @@ -0,0 +1,51 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets +import qs.modules.waffle.looks + +PopupToolTip { + id: root + + property real padding: 2 + verticalPadding: padding + horizontalPadding: padding + + contentItem: Item { + anchors.centerIn: parent + implicitWidth: realContent.implicitWidth + root.verticalPadding * 2 + implicitHeight: realContent.implicitHeight + root.horizontalPadding * 2 + + Rectangle { + id: ambientShadow + z: 0 + anchors { + fill: realContent + margins: -border.width + } + border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.shadowTransparency) + border.width: 1 + color: "transparent" + radius: realContent.radius + border.width + } + + Rectangle { + id: realContent + z: 1 + anchors.centerIn: parent + implicitWidth: tooltipText.implicitWidth + 10 * 2 + implicitHeight: tooltipText.implicitHeight + 8 * 2 + color: Looks.colors.bg1 + radius: Looks.radius.medium + + WText { + id: tooltipText + text: root.text + anchors.centerIn: parent + } + } + } +} diff --git a/dots/.config/quickshell/ii/services/AppSearch.qml b/dots/.config/quickshell/ii/services/AppSearch.qml index 7d8c375a6..d67919890 100644 --- a/dots/.config/quickshell/ii/services/AppSearch.qml +++ b/dots/.config/quickshell/ii/services/AppSearch.qml @@ -94,7 +94,7 @@ Singleton { if (!str || str.length == 0) return "image-missing"; // Quickshell's desktop entry lookup - const entry = DesktopEntries.heuristicLookup(str); + const entry = DesktopEntries.byId(str); if (entry) return entry.icon; // Normal substitutions @@ -149,6 +149,9 @@ Singleton { if (iconExists(guess)) return guess; } + // Quickshell's desktop entry lookup + const heuristicEntry = DesktopEntries.heuristicLookup(str); + if (heuristicEntry) return heuristicEntry.icon; // Give up return "application-x-executable";