From 58980959aa4e3604b992d90eaa25b218f7a1e288 Mon Sep 17 00:00:00 2001
From: end-4 <97237370+end-4@users.noreply.github.com>
Date: Mon, 10 Nov 2025 20:45:38 +0100
Subject: [PATCH 01/12] init waffles
---
.../ii/assets/icons/fluent/speaker-0.svg | 12 +++
.../ii/assets/icons/fluent/speaker-1.svg | 12 +++
.../ii/assets/icons/fluent/speaker.svg | 6 ++
.../quickshell/ii/modules/common/Config.qml | 8 ++
.../background/widgets/clock/ClockWidget.qml | 2 +-
.../quickshell/ii/modules/ii/bar/Bar.qml | 18 ++--
.../ii/modules/ii/bar/ClockWidget.qml | 2 +-
.../modules/ii/overlay/OverlayBackground.qml | 2 +-
.../ii/modules/waffle/bar/BarButton.qml | 78 ++++++++++++++++
.../ii/modules/waffle/bar/SystemButton.qml | 25 ++++++
.../ii/modules/waffle/bar/TimeButton.qml | 30 +++++++
.../ii/modules/waffle/bar/WaffleBar.qml | 89 +++++++++++++++++++
.../modules/waffle/bar/WaffleBarContent.qml | 46 ++++++++++
.../ii/modules/waffle/looks/FluentIcon.qml | 17 ++++
.../ii/modules/waffle/looks/Looks.qml | 77 ++++++++++++++++
.../ii/modules/waffle/looks/WText.qml | 15 ++++
.../quickshell/ii/services/DateTime.qml | 3 +-
dots/.config/quickshell/ii/shell.qml | 35 ++++++++
18 files changed, 463 insertions(+), 14 deletions(-)
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/speaker-0.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/speaker-1.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/speaker.svg
create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml
create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml
create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/TimeButton.qml
create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml
create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
create mode 100644 dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml
create mode 100644 dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
create mode 100644 dots/.config/quickshell/ii/modules/waffle/looks/WText.qml
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/speaker-0.svg b/dots/.config/quickshell/ii/assets/icons/fluent/speaker-0.svg
new file mode 100644
index 000000000..0ff116afd
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/speaker-0.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/speaker-1.svg b/dots/.config/quickshell/ii/assets/icons/fluent/speaker-1.svg
new file mode 100644
index 000000000..eff9b6d0c
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/speaker-1.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/speaker.svg b/dots/.config/quickshell/ii/assets/icons/fluent/speaker.svg
new file mode 100644
index 000000000..477b04792
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/speaker.svg
@@ -0,0 +1,6 @@
+
+
\ 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 1b13540ef..ffc67805a 100644
--- a/dots/.config/quickshell/ii/modules/common/Config.qml
+++ b/dots/.config/quickshell/ii/modules/common/Config.qml
@@ -80,6 +80,7 @@ Singleton {
property list enabledPanels: [
"iiBar", "iiBackground", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiScreenCorners", "iiSessionScreen", "iiSidebarLeft", "iiSidebarRight", "iiVerticalBar", "iiWallpaperSelector"
]
+ property string panelFamily: "ii" // "ii", "w"
property JsonObject policies: JsonObject {
property int ai: 1 // 0: No | 1: Yes | 2: Local
@@ -521,6 +522,7 @@ Singleton {
// https://doc.qt.io/qt-6/qtime.html#toString
property string format: "hh:mm"
property string shortDateFormat: "dd/MM"
+ property string dateWithYearFormat: "dd/MM/yyyy"
property string dateFormat: "ddd, dd/MM"
property JsonObject pomodoro: JsonObject {
property int breakTime: 300
@@ -555,6 +557,12 @@ Singleton {
property list linkKeywords: ["hentai", "porn", "sukebei", "hitomi.la", "rule34", "gelbooru", "fanbox", "dlsite"]
}
}
+
+ property JsonObject waffles: JsonObject {
+ property JsonObject bar: JsonObject {
+ property bool bottom: true
+ }
+ }
}
}
}
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..c5803b6e2 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
@@ -70,7 +70,7 @@ AbstractBackgroundWidget {
}
ClockText {
Layout.topMargin: -5
- text: DateTime.date
+ text: DateTime.longDate
}
StyledText {
// Somehow gets fucked up if made a ClockText???
diff --git a/dots/.config/quickshell/ii/modules/ii/bar/Bar.qml b/dots/.config/quickshell/ii/modules/ii/bar/Bar.qml
index 74f8b5f1b..71a64d76d 100644
--- a/dots/.config/quickshell/ii/modules/ii/bar/Bar.qml
+++ b/dots/.config/quickshell/ii/modules/ii/bar/Bar.qml
@@ -14,12 +14,14 @@ Scope {
Variants {
// For each monitor
- model: {
- const screens = Quickshell.screens;
- const list = Config.options.bar.screenList;
- if (!list || list.length === 0)
- return screens;
- return screens.filter(screen => list.includes(screen.name));
+ model: ScriptModel {
+ values: {
+ const screens = Quickshell.screens;
+ const list = Config.options.bar.screenList;
+ if (!list || list.length === 0)
+ return screens;
+ return screens.filter(screen => list.includes(screen.name));
+ }
}
LazyLoader {
id: barLoader
@@ -29,10 +31,6 @@ Scope {
id: barRoot
screen: barLoader.modelData
- property var brightnessMonitor: Brightness.getMonitorForScreen(barLoader.modelData)
- property real useShortenedForm: (Appearance.sizes.barHellaShortenScreenWidthThreshold >= screen.width) ? 2 : (Appearance.sizes.barShortenScreenWidthThreshold >= screen.width) ? 1 : 0
- readonly property int centerSideModuleWidth: (useShortenedForm == 2) ? Appearance.sizes.barCenterSideModuleWidthHellaShortened : (useShortenedForm == 1) ? Appearance.sizes.barCenterSideModuleWidthShortened : Appearance.sizes.barCenterSideModuleWidth
-
Timer {
id: showBarTimer
interval: (Config?.options.bar.autoHide.showWhenPressingSuper.delay ?? 100)
diff --git a/dots/.config/quickshell/ii/modules/ii/bar/ClockWidget.qml b/dots/.config/quickshell/ii/modules/ii/bar/ClockWidget.qml
index 895ad9be0..958695a86 100644
--- a/dots/.config/quickshell/ii/modules/ii/bar/ClockWidget.qml
+++ b/dots/.config/quickshell/ii/modules/ii/bar/ClockWidget.qml
@@ -33,7 +33,7 @@ Item {
visible: root.showDate
font.pixelSize: Appearance.font.pixelSize.small
color: Appearance.colors.colOnLayer1
- text: DateTime.date
+ text: DateTime.longDate
}
}
diff --git a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayBackground.qml b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayBackground.qml
index 205307cab..d91e4cbba 100644
--- a/dots/.config/quickshell/ii/modules/ii/overlay/OverlayBackground.qml
+++ b/dots/.config/quickshell/ii/modules/ii/overlay/OverlayBackground.qml
@@ -4,5 +4,5 @@ import qs.modules.common
Rectangle {
id: contentItem
anchors.fill: parent
- color: Appearance.m3colors.m3surfaceContainer
+ color: Appearance.colors.colSurfaceContainer
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml
new file mode 100644
index 000000000..1ea789fcb
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml
@@ -0,0 +1,78 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import qs.modules.common
+import qs.modules.common.functions
+import qs.modules.waffle.looks
+
+Button {
+ id: root
+
+ Layout.fillHeight: true
+ topInset: 4
+ bottomInset: 4
+
+ property color borderColor: ColorUtils.transparentize(Looks.colors.bg1Border, (root.hovered && !root.down) ? Looks.fluentContentTransparency : 1)
+ Behavior on borderColor {
+ animation: Looks.transition.color.createObject(this)
+ }
+ onBorderColorChanged: {
+ borderCanvas.requestPaint();
+ }
+
+ background: Rectangle {
+ id: background
+ color: {
+ if (root.down) {
+ return Looks.colors.bg1Active
+ } else if (root.hovered) {
+ return Looks.colors.bg1Hover
+ } else {
+ return ColorUtils.transparentize(Looks.colors.bg1)
+ }
+ }
+ radius: Looks.radius.medium
+ Behavior on color {
+ animation: Looks.transition.color.createObject(this)
+ }
+
+ // Top 1px border with color
+ Canvas {
+ id: borderCanvas
+ anchors.fill: parent
+ onPaint: {
+ var ctx = getContext("2d");
+ ctx.clearRect(0, 0, width, height);
+
+ var borderColor = root.borderColor;
+
+ var r = background.radius;
+ var fadeLength = Math.max(1, r);
+ var fadeLengthPercent = fadeLength / width;
+
+ // Compute normalized stops
+ var leftFadeStop = fadeLengthPercent;
+ var rightFadeStop = 1 - fadeLengthPercent;
+
+ var grad = ctx.createLinearGradient(0, 0, width, 0);
+ grad.addColorStop(0, Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0));
+ grad.addColorStop(leftFadeStop, borderColor);
+ grad.addColorStop(rightFadeStop, borderColor);
+ grad.addColorStop(1, Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0));
+
+ ctx.strokeStyle = grad;
+ ctx.lineWidth = 1;
+
+ ctx.beginPath();
+ ctx.moveTo(r, 0.5);
+ ctx.lineTo(width - r, 0.5);
+ // Top-right curve
+ ctx.arcTo(width, 0.5, width, r + 0.5, r);
+ // Top-left curve
+ ctx.moveTo(width - r, 0.5);
+ ctx.arcTo(0, 0.5, 0, r + 0.5, r);
+ ctx.stroke();
+ }
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml
new file mode 100644
index 000000000..107bb00f6
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml
@@ -0,0 +1,25 @@
+import QtQuick
+import QtQuick.Layouts
+import qs.services
+import qs.modules.common
+import qs.modules.waffle.looks
+
+BarButton {
+ id: root
+
+ // padding: 12
+
+ contentItem: Item {
+ anchors.centerIn: root.background
+ implicitHeight: column.implicitHeight
+ implicitWidth: column.implicitWidth
+ Row {
+ id: column
+ anchors.centerIn: parent
+
+ FluentIcon {
+ icon: "speaker" // System icon
+ }
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/TimeButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/TimeButton.qml
new file mode 100644
index 000000000..53177da12
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/TimeButton.qml
@@ -0,0 +1,30 @@
+import QtQuick
+import QtQuick.Layouts
+import qs.services
+import qs.modules.common
+import qs.modules.waffle.looks
+
+BarButton {
+ id: root
+
+ rightInset: 12 // For now this is the rightmost button. Desktop peek is useless. (for now)
+ padding: 12
+
+ contentItem: Item {
+ anchors.centerIn: root.background
+ implicitHeight: column.implicitHeight
+ implicitWidth: column.implicitWidth
+ Column {
+ id: column
+ anchors.centerIn: parent
+ WText {
+ anchors.right: parent.right
+ text: DateTime.time
+ }
+ WText {
+ anchors.right: parent.right
+ text: DateTime.date
+ }
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml
new file mode 100644
index 000000000..241b5e66b
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml
@@ -0,0 +1,89 @@
+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: bar
+ property bool showBarBackground: Config.options.bar.showBackground
+
+ LazyLoader {
+ id: barLoader
+ active: GlobalStates.barOpen && !GlobalStates.screenLocked
+ component: Variants {
+ model: Quickshell.screens
+ delegate: PanelWindow { // Bar window
+ id: barRoot
+ required property var modelData
+ screen: modelData
+ exclusionMode: ExclusionMode.Ignore
+ exclusiveZone: implicitHeight
+ WlrLayershell.namespace: "quickshell:wbar"
+
+ anchors {
+ left: true
+ right: true
+ bottom: Config.options.waffles.bar.bottom
+ top: !Config.options.waffles.bar.bottom
+ }
+
+ color: "transparent"
+ implicitHeight: content.implicitHeight
+ implicitWidth: content.implicitWidth
+
+ WaffleBarContent {
+ id: content
+ anchors.fill: parent
+ }
+ }
+ }
+ }
+
+ IpcHandler {
+ target: "bar"
+
+ function toggle(): void {
+ GlobalStates.barOpen = !GlobalStates.barOpen
+ }
+
+ function close(): void {
+ GlobalStates.barOpen = false
+ }
+
+ function open(): void {
+ GlobalStates.barOpen = true
+ }
+ }
+
+ GlobalShortcut {
+ name: "barToggle"
+ description: "Toggles bar on press"
+
+ onPressed: {
+ GlobalStates.barOpen = !GlobalStates.barOpen;
+ }
+ }
+
+ GlobalShortcut {
+ name: "barOpen"
+ description: "Opens bar on press"
+
+ onPressed: {
+ GlobalStates.barOpen = true;
+ }
+ }
+
+ GlobalShortcut {
+ name: "barClose"
+ description: "Closes bar on press"
+
+ onPressed: {
+ GlobalStates.barOpen = false;
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
new file mode 100644
index 000000000..a2119ddde
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
@@ -0,0 +1,46 @@
+import QtQuick
+import QtQuick.Layouts
+import qs.modules.common
+import qs.modules.waffle.looks
+
+Rectangle {
+ id: root
+
+ color: Looks.colors.bg0
+ implicitHeight: 48
+
+ Rectangle {
+ id: border
+ anchors {
+ left: parent.left
+ right: parent.right
+ top: Config.options.waffles.bar.bottom ? parent.top : undefined
+ bottom: Config.options.waffles.bar.bottom ? undefined : parent.bottom
+ }
+ color: Looks.colors.bg0Border
+ implicitHeight: 1
+ }
+
+ BarGroupRow {
+ id: bloatRow
+ anchors.left: parent.left
+ }
+
+ BarGroupRow {
+ id: appsRow
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+
+ BarGroupRow {
+ id: systemRow
+ anchors.right: parent.right
+ SystemButton {}
+ TimeButton {}
+ }
+
+ component BarGroupRow: RowLayout {
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ spacing: 0
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml b/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml
new file mode 100644
index 000000000..892214cd7
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml
@@ -0,0 +1,17 @@
+import QtQuick
+import org.kde.kirigami as Kirigami
+import qs.modules.common
+import qs.modules.waffle.looks
+
+Kirigami.Icon {
+ id: root
+ required property string icon
+ property int implicitSize: 18 // Should be 16, but it appears the icons have some padding
+ implicitWidth: implicitSize
+ implicitHeight: implicitSize
+
+ roundToIconSize: false
+ color: Looks.colors.fg
+ isMask: true
+ source: `${Looks.iconsPath}/${root.icon}.svg`
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
new file mode 100644
index 000000000..3b451935f
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
@@ -0,0 +1,77 @@
+pragma ComponentBehavior: Bound
+pragma Singleton
+
+import QtQuick
+import Quickshell
+import qs.modules.common
+import qs.modules.common.functions
+
+Singleton {
+ id: root
+ property QtObject colors
+ property QtObject radius
+ property QtObject font
+ property QtObject transition
+ property string iconsPath: `${Directories.assetsPath}/icons/fluent`
+
+ property real fluentBackgroundTransparency: 0.17
+ property real fluentContentTransparency: 0.3
+ colors: QtObject {
+ id: colors
+ property color bg0: "#1C1C1C"
+ property color bg0Border: "#404040"
+ property color bg1: "#2E2E2E"
+ property color bg1Hover: "#292929"
+ property color bg1Active: "#252525"
+ property color bg1Border: "#333333"
+ property color fg: "#FFFFFF"
+ property color brand: Appearance.m3colors.m3primary
+ }
+
+ radius: QtObject {
+ id: radius
+ property int none: 0
+ property int small: 2
+ property int medium: 4
+ property int large: 8
+ property int xLarge: 12
+ }
+
+ font: QtObject {
+ id: font
+ property QtObject family: QtObject {
+ property string ui: "Noto Sans"
+ }
+ property QtObject weight: QtObject {
+ property int regular: Font.Normal
+ property int strong: Font.DemiBold
+ property int stronger: Font.Bold
+ }
+ property QtObject variableAxes: QtObject {
+
+ }
+ property QtObject pixelSize: QtObject {
+ property int small: 10
+ property int normal: 11
+ }
+ }
+
+ transition: QtObject {
+ id: transition
+ property QtObject easing: QtObject {
+ property QtObject bezierCurve: QtObject {
+ readonly property list easeInOut: [0.42,0.00,0.58,1.00]
+ readonly property list easeIn: [0,1,1,1]
+ readonly property list easeOut: [1,0,1,1]
+ }
+ }
+
+ property Component color: Component {
+ ColorAnimation {
+ duration: 80
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: transition.easing.bezierCurve.easeInOut
+ }
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WText.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WText.qml
new file mode 100644
index 000000000..240fd63be
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/WText.qml
@@ -0,0 +1,15 @@
+import QtQuick
+
+Text {
+ id: root
+
+ renderType: Text.NativeRendering
+ verticalAlignment: Text.AlignVCenter
+ color: Looks.colors.fg
+
+ font {
+ family: Looks.font.family.ui
+ pixelSize: Looks.font.pixelSize.normal
+ weight: Looks.font.weight.regular
+ }
+}
diff --git a/dots/.config/quickshell/ii/services/DateTime.qml b/dots/.config/quickshell/ii/services/DateTime.qml
index 62d296dbc..514da212b 100644
--- a/dots/.config/quickshell/ii/services/DateTime.qml
+++ b/dots/.config/quickshell/ii/services/DateTime.qml
@@ -20,7 +20,8 @@ Singleton {
}
property string time: Qt.locale().toString(clock.date, Config.options?.time.format ?? "hh:mm")
property string shortDate: Qt.locale().toString(clock.date, Config.options?.time.shortDateFormat ?? "dd/MM")
- property string date: Qt.locale().toString(clock.date, Config.options?.time.dateFormat ?? "dddd, dd/MM")
+ property string date: Qt.locale().toString(clock.date, Config.options?.time.dateWithYearFormat ?? "dd/MM/yyyy")
+ property string longDate: Qt.locale().toString(clock.date, Config.options?.time.dateFormat ?? "dddd, dd/MM")
property string collapsedCalendarFormat: Qt.locale().toString(clock.date, "dd MMMM yyyy")
property string uptime: "0h, 0m"
diff --git a/dots/.config/quickshell/ii/shell.qml b/dots/.config/quickshell/ii/shell.qml
index ee2217bf7..a23c84cca 100644
--- a/dots/.config/quickshell/ii/shell.qml
+++ b/dots/.config/quickshell/ii/shell.qml
@@ -28,12 +28,18 @@ import qs.modules.ii.overlay
import qs.modules.ii.verticalBar
import qs.modules.ii.wallpaperSelector
+import qs.modules.waffle.bar
+
import QtQuick
import QtQuick.Window
import Quickshell
+import Quickshell.Io
+import Quickshell.Hyprland
import qs.services
ShellRoot {
+ id: root
+
// Force initialization of some singletons
Component.onCompleted: {
MaterialThemeLoader.reapplyTheme()
@@ -67,11 +73,40 @@ ShellRoot {
PanelLoader { identifier: "iiSidebarRight"; component: SidebarRight {} }
PanelLoader { identifier: "iiVerticalBar"; extraCondition: Config.options.bar.vertical; component: VerticalBar {} }
PanelLoader { identifier: "iiWallpaperSelector"; component: WallpaperSelector {} }
+ PanelLoader { identifier: "wBar"; component: WaffleBar {} }
component PanelLoader: LazyLoader {
required property string identifier
property bool extraCondition: true
active: Config.ready && Config.options.enabledPanels.includes(identifier) && extraCondition
}
+
+ // Panel families
+ 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", "iiBackground", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiScreenCorners", "iiSessionScreen", "iiSidebarLeft", "iiSidebarRight", "iiWallpaperSelector"],
+ })
+ function cyclePanelFamily() {
+ const currentIndex = families.indexOf(Config.options.panelFamily)
+ const nextIndex = (currentIndex + 1) % families.length
+ Config.options.panelFamily = families[nextIndex]
+ Config.options.enabledPanels = panelFamilies[Config.options.panelFamily]
+ }
+
+ IpcHandler {
+ target: "panelFamily"
+
+ function cycle(): void {
+ root.cyclePanelFamily()
+ }
+ }
+
+ GlobalShortcut {
+ name: "panelFamilyCycle"
+ description: "Cycles panel family"
+
+ onPressed: root.cyclePanelFamily()
+ }
}
From 42919c59ec616012c7a5d755d7ee05abfa44daab Mon Sep 17 00:00:00 2001
From: end-4 <97237370+end-4@users.noreply.github.com>
Date: Mon, 10 Nov 2025 21:36:08 +0100
Subject: [PATCH 02/12] wbar: add volume and battery icons
---
.../ii/assets/icons/fluent/battery-1.svg | 12 +++++++
.../ii/assets/icons/fluent/battery-2.svg | 12 +++++++
.../ii/assets/icons/fluent/battery-3.svg | 12 +++++++
.../ii/assets/icons/fluent/battery-4.svg | 12 +++++++
.../ii/assets/icons/fluent/battery-5.svg | 12 +++++++
.../ii/assets/icons/fluent/battery-7.svg | 12 +++++++
.../ii/assets/icons/fluent/battery-8.svg | 12 +++++++
.../ii/assets/icons/fluent/battery-9.svg | 12 +++++++
.../ii/assets/icons/fluent/battery-charge.svg | 12 +++++++
.../ii/assets/icons/fluent/battery-full.svg | 12 +++++++
.../ii/assets/icons/fluent/battery-saver.svg | 12 +++++++
.../assets/icons/fluent/battery-warning.svg | 12 +++++++
.../icons/fluent/bluetooth-connected.svg | 12 +++++++
.../icons/fluent/bluetooth-searching.svg | 12 +++++++
.../ii/assets/icons/fluent/ethernet.svg | 12 +++++++
.../ii/assets/icons/fluent/mic-on.svg | 12 +++++++
.../ii/assets/icons/fluent/speaker-none.svg | 5 +++
.../ii/assets/icons/fluent/speaker-off.svg | 7 +++++
.../ii/assets/icons/fluent/wifi-1.svg | 12 +++++++
.../ii/assets/icons/fluent/wifi-2.svg | 12 +++++++
.../ii/assets/icons/fluent/wifi-3.svg | 12 +++++++
.../ii/assets/icons/fluent/wifi-4.svg | 12 +++++++
.../ii/assets/icons/fluent/wifi-off.svg | 1 +
.../ii/assets/icons/fluent/wifi-warning.svg | 1 +
.../ii/modules/waffle/bar/SystemButton.qml | 21 ++++++++++++-
.../ii/modules/waffle/looks/FluentIcon.qml | 7 +++--
.../ii/modules/waffle/looks/Looks.qml | 10 ++----
.../ii/modules/waffle/looks/WIcons.qml | 31 +++++++++++++++++++
28 files changed, 313 insertions(+), 10 deletions(-)
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/battery-1.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/battery-2.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/battery-3.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/battery-4.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/battery-5.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/battery-7.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/battery-8.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/battery-9.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/battery-charge.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/battery-full.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/battery-saver.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/battery-warning.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/bluetooth-connected.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/bluetooth-searching.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/ethernet.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/mic-on.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/speaker-none.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/speaker-off.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/wifi-1.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/wifi-2.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/wifi-3.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/wifi-4.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/wifi-off.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/wifi-warning.svg
create mode 100644 dots/.config/quickshell/ii/modules/waffle/looks/WIcons.qml
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/battery-1.svg b/dots/.config/quickshell/ii/assets/icons/fluent/battery-1.svg
new file mode 100644
index 000000000..caa369c58
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/battery-1.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/battery-2.svg b/dots/.config/quickshell/ii/assets/icons/fluent/battery-2.svg
new file mode 100644
index 000000000..b939043ea
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/battery-2.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/battery-3.svg b/dots/.config/quickshell/ii/assets/icons/fluent/battery-3.svg
new file mode 100644
index 000000000..a504a1ed5
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/battery-3.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/battery-4.svg b/dots/.config/quickshell/ii/assets/icons/fluent/battery-4.svg
new file mode 100644
index 000000000..6567ddf10
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/battery-4.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/battery-5.svg b/dots/.config/quickshell/ii/assets/icons/fluent/battery-5.svg
new file mode 100644
index 000000000..1bf4d914f
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/battery-5.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/battery-7.svg b/dots/.config/quickshell/ii/assets/icons/fluent/battery-7.svg
new file mode 100644
index 000000000..a5197ce94
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/battery-7.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/battery-8.svg b/dots/.config/quickshell/ii/assets/icons/fluent/battery-8.svg
new file mode 100644
index 000000000..c83bc5fb6
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/battery-8.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/battery-9.svg b/dots/.config/quickshell/ii/assets/icons/fluent/battery-9.svg
new file mode 100644
index 000000000..7f4937b99
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/battery-9.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/battery-charge.svg b/dots/.config/quickshell/ii/assets/icons/fluent/battery-charge.svg
new file mode 100644
index 000000000..512a78b1b
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/battery-charge.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/battery-full.svg b/dots/.config/quickshell/ii/assets/icons/fluent/battery-full.svg
new file mode 100644
index 000000000..4749fc178
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/battery-full.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/battery-saver.svg b/dots/.config/quickshell/ii/assets/icons/fluent/battery-saver.svg
new file mode 100644
index 000000000..397061caf
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/battery-saver.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/battery-warning.svg b/dots/.config/quickshell/ii/assets/icons/fluent/battery-warning.svg
new file mode 100644
index 000000000..7ccade277
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/battery-warning.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/bluetooth-connected.svg b/dots/.config/quickshell/ii/assets/icons/fluent/bluetooth-connected.svg
new file mode 100644
index 000000000..b491276df
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/bluetooth-connected.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/bluetooth-searching.svg b/dots/.config/quickshell/ii/assets/icons/fluent/bluetooth-searching.svg
new file mode 100644
index 000000000..e0d9eab70
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/bluetooth-searching.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/ethernet.svg b/dots/.config/quickshell/ii/assets/icons/fluent/ethernet.svg
new file mode 100644
index 000000000..904d9720e
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/ethernet.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/mic-on.svg b/dots/.config/quickshell/ii/assets/icons/fluent/mic-on.svg
new file mode 100644
index 000000000..3f680d2e3
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/mic-on.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/speaker-none.svg b/dots/.config/quickshell/ii/assets/icons/fluent/speaker-none.svg
new file mode 100644
index 000000000..364af84cb
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/speaker-none.svg
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/speaker-off.svg b/dots/.config/quickshell/ii/assets/icons/fluent/speaker-off.svg
new file mode 100644
index 000000000..5fa19e406
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/speaker-off.svg
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/wifi-1.svg b/dots/.config/quickshell/ii/assets/icons/fluent/wifi-1.svg
new file mode 100644
index 000000000..47662e101
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/wifi-1.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/wifi-2.svg b/dots/.config/quickshell/ii/assets/icons/fluent/wifi-2.svg
new file mode 100644
index 000000000..9897c5d70
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/wifi-2.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/wifi-3.svg b/dots/.config/quickshell/ii/assets/icons/fluent/wifi-3.svg
new file mode 100644
index 000000000..8a4674bd4
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/wifi-3.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/wifi-4.svg b/dots/.config/quickshell/ii/assets/icons/fluent/wifi-4.svg
new file mode 100644
index 000000000..f14828bd8
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/wifi-4.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/wifi-off.svg b/dots/.config/quickshell/ii/assets/icons/fluent/wifi-off.svg
new file mode 100644
index 000000000..3c247ab12
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/wifi-off.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/wifi-warning.svg b/dots/.config/quickshell/ii/assets/icons/fluent/wifi-warning.svg
new file mode 100644
index 000000000..d573ddde0
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/wifi-warning.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml
index 107bb00f6..dcb56c30b 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml
@@ -16,9 +16,28 @@ BarButton {
Row {
id: column
anchors.centerIn: parent
+ spacing: 4
FluentIcon {
- icon: "speaker" // System icon
+ icon: WIcons.internetIcon
+ }
+
+ 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";
+ }
+ }
+
+ FluentIcon {
+ icon: {
+ print(WIcons.batteryIcon)
+ return WIcons.batteryIcon
+ }
}
}
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml b/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml
index 892214cd7..229df0458 100644
--- a/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml
@@ -6,12 +6,15 @@ import qs.modules.waffle.looks
Kirigami.Icon {
id: root
required property string icon
- property int implicitSize: 18 // Should be 16, but it appears the icons have some padding
+ // 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
implicitWidth: implicitSize
implicitHeight: implicitSize
+ source: `${Looks.iconsPath}/${root.icon}.svg`
roundToIconSize: false
color: Looks.colors.fg
isMask: true
- source: `${Looks.iconsPath}/${root.icon}.svg`
+ animated: true
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
index 3b451935f..9020b9d85 100644
--- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
@@ -42,17 +42,13 @@ Singleton {
property QtObject family: QtObject {
property string ui: "Noto Sans"
}
- property QtObject weight: QtObject {
- property int regular: Font.Normal
+ property QtObject weight: QtObject { // Noto is not Segoe, so we might use slightly different weights
+ property int regular: Font.Medium
property int strong: Font.DemiBold
property int stronger: Font.Bold
- }
- property QtObject variableAxes: QtObject {
-
}
property QtObject pixelSize: QtObject {
- property int small: 10
- property int normal: 11
+ property real normal: 11
}
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WIcons.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WIcons.qml
new file mode 100644
index 000000000..813b0a1ce
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/WIcons.qml
@@ -0,0 +1,31 @@
+pragma Singleton
+import QtQuick
+import Quickshell
+import qs.services
+
+Singleton {
+ id: root
+
+ property string internetIcon: {
+ if (Network.ethernet) return "ethernet";
+ if (Network.wifiEnabled) {
+ const strength = Network.networkStrength;
+ if (strength > 75) return "wifi-1";
+ if (strength > 50) return "wifi-2";
+ if (strength > 25) return "wifi-3";
+ return "wifi-4";
+ }
+ if (Network.wifiStatus === "connecting") return "wifi-4";
+ if (Network.wifiStatus === "disconnected") return "wifi-off";
+ if (Network.wifiStatus === "disabled") return "wifi-off";
+ return "wifi-warning";
+ }
+
+ property string batteryIcon: {
+ if (Battery.isCharging) return "battery-charge";
+ if (Battery.isCriticalAndNotCharging) return "battery-warning";
+ if (Battery.percentage >= 0.9) return "battery-full";
+ return `battery-${Math.ceil(Battery.percentage * 10)}`;
+ }
+
+}
From 694eaccfbfeee9118853716867ef92594393a8bd Mon Sep 17 00:00:00 2001
From: end-4 <97237370+end-4@users.noreply.github.com>
Date: Mon, 10 Nov 2025 22:48:04 +0100
Subject: [PATCH 03/12] add start and search icons
---
.../ii/assets/icons/fluent/battery-0.svg | 12 +++
.../ii/assets/icons/fluent/battery-6.svg | 12 +++
.../icons/fluent/system-search-dark.svg | 82 +++++++++++++++++++
.../icons/fluent/system-search-light.svg | 82 +++++++++++++++++++
.../quickshell/ii/modules/common/Config.qml | 1 +
.../ii/modules/waffle/bar/AppButton.qml | 40 +++++++++
.../ii/modules/waffle/bar/SearchButton.qml | 12 +++
.../ii/modules/waffle/bar/StartButton.qml | 13 +++
.../ii/modules/waffle/bar/SystemButton.qml | 5 +-
.../modules/waffle/bar/WaffleBarContent.qml | 24 ++++--
.../ii/modules/waffle/looks/FluentIcon.qml | 1 +
.../ii/modules/waffle/looks/Looks.qml | 33 ++++++++
12 files changed, 308 insertions(+), 9 deletions(-)
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/battery-0.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/battery-6.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/system-search-dark.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/system-search-light.svg
create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml
create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml
create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/battery-0.svg b/dots/.config/quickshell/ii/assets/icons/fluent/battery-0.svg
new file mode 100644
index 000000000..7fe9d7a3d
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/battery-0.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/battery-6.svg b/dots/.config/quickshell/ii/assets/icons/fluent/battery-6.svg
new file mode 100644
index 000000000..145d9a7de
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/battery-6.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
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
new file mode 100644
index 000000000..2d972a7b4
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/system-search-dark.svg
@@ -0,0 +1,82 @@
+
+
+
+
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/system-search-light.svg b/dots/.config/quickshell/ii/assets/icons/fluent/system-search-light.svg
new file mode 100644
index 000000000..b22f9c0ca
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/system-search-light.svg
@@ -0,0 +1,82 @@
+
+
+
+
diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml
index ffc67805a..2ac21aa40 100644
--- a/dots/.config/quickshell/ii/modules/common/Config.qml
+++ b/dots/.config/quickshell/ii/modules/common/Config.qml
@@ -561,6 +561,7 @@ Singleton {
property JsonObject waffles: JsonObject {
property JsonObject bar: JsonObject {
property bool bottom: true
+ property bool leftAlignApps: true
}
}
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml
new file mode 100644
index 000000000..808a8ba0a
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml
@@ -0,0 +1,40 @@
+import QtQuick
+import QtQuick.Layouts
+import org.kde.kirigami as Kirigami
+import qs.services
+import qs.modules.common
+import qs.modules.waffle.looks
+
+BarButton {
+ id: root
+
+ required property string iconName
+ implicitWidth: height - topInset - bottomInset + leftInset + rightInset
+
+ contentItem: Item {
+ id: contentItem
+ anchors.centerIn: root.background
+
+ implicitHeight: iconWidget.implicitHeight
+ implicitWidth: iconWidget.implicitWidth
+
+ scale: root.down ? 5/6 : 1 // If/When we do dragging, the scale is 1.25
+ Behavior on scale {
+ NumberAnimation {
+ duration: 90
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: root.down ? Looks.transition.easing.bezierCurve.easeIn : Looks.transition.easing.bezierCurve.easeOut
+ }
+ }
+
+ Kirigami.Icon {
+ id: iconWidget
+ anchors.centerIn: parent
+ implicitWidth: 26
+ implicitHeight: 26
+ roundToIconSize: false
+ source: `${Looks.iconsPath}/${root.iconName}-${Looks.dark ? "dark" : "light"}.svg`
+ fallback: root.iconName
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml
new file mode 100644
index 000000000..3bfd3a781
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml
@@ -0,0 +1,12 @@
+import QtQuick
+import QtQuick.Layouts
+import org.kde.kirigami as Kirigami
+import qs.services
+import qs.modules.common
+import qs.modules.waffle.looks
+
+AppButton {
+ id: root
+
+ iconName: "system-search"
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml
new file mode 100644
index 000000000..e3aea59d2
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml
@@ -0,0 +1,13 @@
+import QtQuick
+import QtQuick.Layouts
+import org.kde.kirigami as Kirigami
+import qs.services
+import qs.modules.common
+import qs.modules.waffle.looks
+
+AppButton {
+ id: root
+
+ leftInset: 12
+ iconName: "start-here"
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml
index dcb56c30b..e1bb83684 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml
@@ -34,10 +34,7 @@ BarButton {
}
FluentIcon {
- icon: {
- print(WIcons.batteryIcon)
- return WIcons.batteryIcon
- }
+ icon: WIcons.batteryIcon
}
}
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
index a2119ddde..f4881adf0 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
@@ -21,14 +21,28 @@ Rectangle {
implicitHeight: 1
}
- BarGroupRow {
- id: bloatRow
- anchors.left: parent.left
- }
-
BarGroupRow {
id: appsRow
+ spacing: 4
+ anchors.left: undefined
anchors.horizontalCenter: parent.horizontalCenter
+
+ states: State {
+ name: "left"
+ when: Config.options.waffles.bar.leftAlignApps
+ AnchorChanges {
+ target: appsRow
+ anchors.left: parent.left
+ anchors.horizontalCenter: undefined
+ }
+ }
+
+ transitions: Transition {
+ animations: Looks.transition.anchor.createObject(this)
+ }
+
+ StartButton {}
+ SearchButton {}
}
BarGroupRow {
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml b/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml
index 229df0458..81b6ebf08 100644
--- a/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/FluentIcon.qml
@@ -13,6 +13,7 @@ Kirigami.Icon {
implicitHeight: implicitSize
source: `${Looks.iconsPath}/${root.icon}.svg`
+ fallback: root.icon
roundToIconSize: false
color: Looks.colors.fg
isMask: true
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
index 9020b9d85..95693a05d 100644
--- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
@@ -13,6 +13,7 @@ Singleton {
property QtObject font
property QtObject transition
property string iconsPath: `${Directories.assetsPath}/icons/fluent`
+ property bool dark: Appearance.m3colors.darkmode
property real fluentBackgroundTransparency: 0.17
property real fluentContentTransparency: 0.3
@@ -66,6 +67,38 @@ Singleton {
ColorAnimation {
duration: 80
easing.type: Easing.BezierSpline
+ easing.bezierCurve: transition.easing.bezierCurve.easeIn
+ }
+ }
+
+ property Component enter: Component {
+ NumberAnimation {
+ duration: 250
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: transition.easing.bezierCurve.easeIn
+ }
+ }
+
+ property Component exit: Component {
+ NumberAnimation {
+ duration: 250
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: transition.easing.bezierCurve.easeOut
+ }
+ }
+
+ property Component move: Component {
+ NumberAnimation {
+ duration: 100
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: transition.easing.bezierCurve.easeInOut
+ }
+ }
+
+ property Component anchor: Component {
+ AnchorAnimation {
+ duration: 250
+ easing.type: Easing.BezierSpline
easing.bezierCurve: transition.easing.bezierCurve.easeInOut
}
}
From fdcb95b8a4b4fae45bd2e76b2544ebc033f1ad6c Mon Sep 17 00:00:00 2001
From: end-4 <97237370+end-4@users.noreply.github.com>
Date: Mon, 10 Nov 2025 23:41:15 +0100
Subject: [PATCH 04/12] wbar: add widgets, taskview, light theme
---
.../ii/assets/icons/fluent/task-view.svg | 79 ++++++++++++++++
.../ii/assets/icons/fluent/widgets.svg | 92 +++++++++++++++++++
.../ii/modules/waffle/bar/AppButton.qml | 9 +-
.../ii/modules/waffle/bar/AppIcon.qml | 16 ++++
.../ii/modules/waffle/bar/SearchButton.qml | 1 +
.../ii/modules/waffle/bar/StartButton.qml | 2 +-
.../ii/modules/waffle/bar/TaskViewButton.qml | 12 +++
.../modules/waffle/bar/WaffleBarContent.qml | 19 ++++
.../ii/modules/waffle/bar/WidgetsButton.qml | 39 ++++++++
.../ii/modules/waffle/looks/Looks.qml | 26 ++++--
10 files changed, 279 insertions(+), 16 deletions(-)
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/task-view.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/widgets.svg
create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml
create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml
create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/task-view.svg b/dots/.config/quickshell/ii/assets/icons/fluent/task-view.svg
new file mode 100644
index 000000000..4323e8421
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/task-view.svg
@@ -0,0 +1,79 @@
+
+
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/widgets.svg b/dots/.config/quickshell/ii/assets/icons/fluent/widgets.svg
new file mode 100644
index 000000000..0989033a7
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/widgets.svg
@@ -0,0 +1,92 @@
+
+
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml
index 808a8ba0a..017d8f931 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml
@@ -9,6 +9,7 @@ BarButton {
id: root
required property string iconName
+ property bool separateLightDark: false
implicitWidth: height - topInset - bottomInset + leftInset + rightInset
contentItem: Item {
@@ -27,14 +28,10 @@ BarButton {
}
}
- Kirigami.Icon {
+ AppIcon {
id: iconWidget
anchors.centerIn: parent
- implicitWidth: 26
- implicitHeight: 26
- roundToIconSize: false
- source: `${Looks.iconsPath}/${root.iconName}-${Looks.dark ? "dark" : "light"}.svg`
- fallback: root.iconName
+ iconName: root.iconName
}
}
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml b/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml
new file mode 100644
index 000000000..02c1da144
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml
@@ -0,0 +1,16 @@
+import QtQuick
+import org.kde.kirigami as Kirigami
+import qs.services
+import qs.modules.common
+import qs.modules.waffle.looks
+
+Kirigami.Icon {
+ id: iconWidget
+ required property string iconName
+
+ implicitWidth: 26
+ implicitHeight: 26
+ roundToIconSize: false
+ source: `${Looks.iconsPath}/${root.iconName}${!root.separateLightDark ? "" : Looks.dark ? "-dark" : "-light"}.svg`
+ fallback: root.iconName
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml
index 3bfd3a781..d1b59b85b 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/SearchButton.qml
@@ -9,4 +9,5 @@ AppButton {
id: root
iconName: "system-search"
+ separateLightDark: true
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml
index e3aea59d2..d5a4e0f97 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/StartButton.qml
@@ -8,6 +8,6 @@ import qs.modules.waffle.looks
AppButton {
id: root
- leftInset: 12
+ leftInset: Config.options.waffles.bar.leftAlignApps ? 12 : 0
iconName: "start-here"
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml
new file mode 100644
index 000000000..3211217fa
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml
@@ -0,0 +1,12 @@
+import QtQuick
+import QtQuick.Layouts
+import org.kde.kirigami as Kirigami
+import qs.services
+import qs.modules.common
+import qs.modules.waffle.looks
+
+AppButton {
+ id: root
+
+ iconName: "task-view"
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
index f4881adf0..989904e2f 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
@@ -1,6 +1,7 @@
import QtQuick
import QtQuick.Layouts
import qs.modules.common
+import qs.modules.common.widgets
import qs.modules.waffle.looks
Rectangle {
@@ -21,6 +22,18 @@ Rectangle {
implicitHeight: 1
}
+ BarGroupRow {
+ id: bloatRow
+ anchors.left: parent.left
+ opacity: Config.options.waffles.bar.leftAlignApps ? 0 : 1
+ visible: opacity > 0
+ Behavior on opacity {
+ animation: Looks.transition.opacity.createObject(this)
+ }
+
+ WidgetsButton {}
+ }
+
BarGroupRow {
id: appsRow
spacing: 4
@@ -43,11 +56,17 @@ Rectangle {
StartButton {}
SearchButton {}
+ TaskViewButton {}
}
BarGroupRow {
id: systemRow
anchors.right: parent.right
+ FadeLoader {
+ Layout.fillHeight: true
+ shown: Config.options.waffles.bar.leftAlignApps
+ sourceComponent: WidgetsButton {}
+ }
SystemButton {}
TimeButton {}
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml
new file mode 100644
index 000000000..94c194686
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml
@@ -0,0 +1,39 @@
+import QtQuick
+import QtQuick.Layouts
+import org.kde.kirigami as Kirigami
+import qs.services
+import qs.modules.common
+import qs.modules.waffle.looks
+
+AppButton {
+ id: root
+
+ readonly property bool expandedForm: Config.options.waffles.bar.leftAlignApps
+ leftInset: Config.options.waffles.bar.leftAlignApps ? 0 : 12
+ implicitWidth: expandedForm ? 148 : (height - topInset - bottomInset + leftInset + rightInset)
+ iconName: "widgets"
+
+ contentItem: Item {
+ anchors {
+ verticalCenter: parent.verticalCenter
+ left: root.expandedForm ? parent.left : undefined
+ horizontalCenter: root.expandedForm ? undefined : background.horizontalCenter
+ }
+ implicitHeight: row.implicitHeight
+ implicitWidth: row.implicitWidth
+ Row {
+ id: row
+ anchors {
+ verticalCenter: parent.verticalCenter
+ left: root.expandedForm ? parent.left : undefined
+ horizontalCenter: root.expandedForm ? undefined : parent.horizontalCenter
+ margins: 8
+ }
+
+ AppIcon {
+ id: iconWidget
+ iconName: root.iconName
+ }
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
index 95693a05d..ea225f093 100644
--- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
@@ -19,13 +19,13 @@ Singleton {
property real fluentContentTransparency: 0.3
colors: QtObject {
id: colors
- property color bg0: "#1C1C1C"
- property color bg0Border: "#404040"
- property color bg1: "#2E2E2E"
- property color bg1Hover: "#292929"
- property color bg1Active: "#252525"
- property color bg1Border: "#333333"
- property color fg: "#FFFFFF"
+ property color bg0: root.dark ? "#1C1C1C" : "#EEEEEE"
+ property color bg0Border: root.dark ? "#404040" : "#BEBEBE"
+ property color bg1: root.dark ? "#2E2E2E" : "#F7F7F7"
+ property color bg1Hover: root.dark ? "#292929" : "#F7F7F7"
+ property color bg1Active: root.dark ? "#252525" : "#F3F3F3"
+ property color bg1Border: root.dark ? "#333333" : "#E9E9E9"
+ property color fg: root.dark ? "#FFFFFF" : "#000000"
property color brand: Appearance.m3colors.m3primary
}
@@ -71,6 +71,14 @@ Singleton {
}
}
+ property Component opacity: Component {
+ NumberAnimation{
+ duration: 80
+ easing.type: Easing.BezierSpline
+ easing.bezierCurve: transition.easing.bezierCurve.easeIn
+ }
+ }
+
property Component enter: Component {
NumberAnimation {
duration: 250
@@ -97,9 +105,9 @@ Singleton {
property Component anchor: Component {
AnchorAnimation {
- duration: 250
+ duration: 160
easing.type: Easing.BezierSpline
- easing.bezierCurve: transition.easing.bezierCurve.easeInOut
+ easing.bezierCurve: transition.easing.bezierCurve.easeIn
}
}
}
From cbcb8cf8e13e6c8d03c769007e9f9c32e4f7eb22 Mon Sep 17 00:00:00 2001
From: end-4 <97237370+end-4@users.noreply.github.com>
Date: Tue, 11 Nov 2025 00:01:57 +0100
Subject: [PATCH 05/12] wbar: more interactions
---
dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml | 4 ++--
.../quickshell/ii/modules/waffle/bar/TaskViewButton.qml | 6 ++++++
.../.config/quickshell/ii/modules/waffle/bar/TimeButton.qml | 6 ++++++
dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml | 2 +-
4 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml
index 1ea789fcb..20929b1e6 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml
@@ -12,7 +12,7 @@ Button {
topInset: 4
bottomInset: 4
- property color borderColor: ColorUtils.transparentize(Looks.colors.bg1Border, (root.hovered && !root.down) ? Looks.fluentContentTransparency : 1)
+ property color borderColor: ColorUtils.transparentize(Looks.colors.bg1Border, ((root.hovered && !root.down) || root.checked) ? Looks.fluentContentTransparency : 1)
Behavior on borderColor {
animation: Looks.transition.color.createObject(this)
}
@@ -25,7 +25,7 @@ Button {
color: {
if (root.down) {
return Looks.colors.bg1Active
- } else if (root.hovered) {
+ } else if ((root.hovered && !root.down) || root.checked) {
return Looks.colors.bg1Hover
} else {
return ColorUtils.transparentize(Looks.colors.bg1)
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml
index 3211217fa..1239fed6f 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.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
@@ -9,4 +10,9 @@ AppButton {
id: root
iconName: "task-view"
+
+ checked: GlobalStates.overviewOpen
+ onClicked: {
+ GlobalStates.overviewOpen = !GlobalStates.overviewOpen;
+ }
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/TimeButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/TimeButton.qml
index 53177da12..f8e2f38cc 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/TimeButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/TimeButton.qml
@@ -1,5 +1,6 @@
import QtQuick
import QtQuick.Layouts
+import qs
import qs.services
import qs.modules.common
import qs.modules.waffle.looks
@@ -10,6 +11,11 @@ BarButton {
rightInset: 12 // For now this is the rightmost button. Desktop peek is useless. (for now)
padding: 12
+ checked: GlobalStates.sidebarRightOpen
+ onClicked: {
+ GlobalStates.sidebarRightOpen = !GlobalStates.sidebarRightOpen;
+ }
+
contentItem: Item {
anchors.centerIn: root.background
implicitHeight: column.implicitHeight
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml
index 241b5e66b..5c19c661f 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml
@@ -23,7 +23,7 @@ Scope {
screen: modelData
exclusionMode: ExclusionMode.Ignore
exclusiveZone: implicitHeight
- WlrLayershell.namespace: "quickshell:wbar"
+ WlrLayershell.namespace: "quickshell:wBar"
anchors {
left: true
From dec65aea17f8ac4a20e360f4be7ede94da7a6596 Mon Sep 17 00:00:00 2001
From: end-4 <97237370+end-4@users.noreply.github.com>
Date: Tue, 11 Nov 2025 00:03:19 +0100
Subject: [PATCH 06/12] update hyprland config
---
dots/.config/hypr/hyprland/general.conf | 4 ++--
dots/.config/hypr/hyprland/keybinds.conf | 1 +
dots/.config/hypr/hyprland/rules.conf | 2 ++
3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/dots/.config/hypr/hyprland/general.conf b/dots/.config/hypr/hyprland/general.conf
index 2c79a857f..14074b345 100644
--- a/dots/.config/hypr/hyprland/general.conf
+++ b/dots/.config/hypr/hyprland/general.conf
@@ -6,8 +6,8 @@ monitor=,preferred,auto,1
# monitor=HDMI-A-1,1920x1080@60,1920x0,1,mirror,eDP-1
gesture = 3, swipe, move,
+gesture = 3, pinch, float
gesture = 4, horizontal, workspace
-gesture = 4, pinch, float
gesture = 4, up, dispatcher, global, quickshell:overviewToggle
gesture = 4, down, dispatcher, global, quickshell:overviewClose
gestures {
@@ -62,7 +62,7 @@ decoration {
brightness = 1
noise = 0.04
contrast = 1
- popups = true
+ popups = false
popups_ignorealpha = 0.6
input_methods = true
input_methods_ignorealpha = 0.8
diff --git a/dots/.config/hypr/hyprland/keybinds.conf b/dots/.config/hypr/hyprland/keybinds.conf
index 294854d67..fdda9a714 100644
--- a/dots/.config/hypr/hyprland/keybinds.conf
+++ b/dots/.config/hypr/hyprland/keybinds.conf
@@ -53,6 +53,7 @@ bindd = Ctrl+Super, T, Toggle wallpaper selector, global, quickshell:wallpaperSe
bindd = Ctrl+Super+Alt, T, Select random wallpaper, global, quickshell:wallpaperSelectorRandom # Random wallpaper
bindd = Ctrl+Super, T, Change wallpaper, exec, qs -c $qsConfig ipc call TEST_ALIVE || ~/.config/quickshell/$qsConfig/scripts/colors/switchwall.sh # [hidden] Change wallpaper (fallback)
bind = Ctrl+Super, R, exec, killall ags agsv1 gjs ydotool qs quickshell; qs -c $qsConfig & # Restart widgets
+bind = Super+Alt, W, global, quickshell:panelFamilyCycle # Cycle panel family
##! Utilities
# Screenshot, Record, OCR, Color picker, Clipboard history
diff --git a/dots/.config/hypr/hyprland/rules.conf b/dots/.config/hypr/hyprland/rules.conf
index 01ac1056d..dc34a4a6b 100644
--- a/dots/.config/hypr/hyprland/rules.conf
+++ b/dots/.config/hypr/hyprland/rules.conf
@@ -154,6 +154,8 @@ layerrule = animation slide right, quickshell:sidebarRight
layerrule = animation slide left, quickshell:sidebarLeft
layerrule = animation slide, quickshell:verticalBar
layerrule = animation slide top, quickshell:wallpaperSelector
+# Quickshell - Waffles
+layerrule = animation slide, quickshell:wBar
# Launchers need to be FAST
layerrule = noanim, gtk4-layer-shell
From a412688af299a4b6adf8214e9da4965549e88807 Mon Sep 17 00:00:00 2001
From: end-4 <97237370+end-4@users.noreply.github.com>
Date: Tue, 11 Nov 2025 20:23:09 +0100
Subject: [PATCH 07/12] add bg, taskbar items
---
.../ii/assets/icons/fluent/README.md | 5 +
.../ii/assets/icons/fluent/task-view-dark.svg | 128 ++++++++++++++++++
.../assets/icons/fluent/task-view-light.svg | 104 ++++++++++++++
.../ii/assets/icons/fluent/task-view.svg | 79 -----------
.../quickshell/ii/modules/common/Config.qml | 4 +-
.../ii/modules/ii/dock/DockAppButton.qml | 4 +-
.../ii/modules/ii/dock/DockApps.qml | 46 +------
.../waffle/background/WaffleBackground.qml | 46 +++++++
.../ii/modules/waffle/bar/TaskAppButton.qml | 17 +++
.../ii/modules/waffle/bar/TaskViewButton.qml | 1 +
.../ii/modules/waffle/bar/Tasks.qml | 34 +++++
.../ii/modules/waffle/bar/WaffleBar.qml | 2 +-
.../modules/waffle/bar/WaffleBarContent.qml | 1 +
.../ii/modules/waffle/bar/WidgetsButton.qml | 15 ++
.../quickshell/ii/services/TaskbarApps.qml | 60 ++++++++
dots/.config/quickshell/ii/shell.qml | 4 +-
16 files changed, 424 insertions(+), 126 deletions(-)
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/README.md
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/task-view-dark.svg
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/task-view-light.svg
delete mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/task-view.svg
create mode 100644 dots/.config/quickshell/ii/modules/waffle/background/WaffleBackground.qml
create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/TaskAppButton.qml
create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/Tasks.qml
create mode 100644 dots/.config/quickshell/ii/services/TaskbarApps.qml
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/README.md b/dots/.config/quickshell/ii/assets/icons/fluent/README.md
new file mode 100644
index 000000000..5f4d3eaa2
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/README.md
@@ -0,0 +1,5 @@
+The "search" and "task view" icons are from here, with modifications
+
+https://www.figma.com/community/file/1123040825921884189/windows-11
+
+License: CC BY 4.0
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/task-view-dark.svg b/dots/.config/quickshell/ii/assets/icons/fluent/task-view-dark.svg
new file mode 100644
index 000000000..d38c927c8
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/task-view-dark.svg
@@ -0,0 +1,128 @@
+
+
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/task-view-light.svg b/dots/.config/quickshell/ii/assets/icons/fluent/task-view-light.svg
new file mode 100644
index 000000000..1f37c4aa4
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/task-view-light.svg
@@ -0,0 +1,104 @@
+
+
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/task-view.svg b/dots/.config/quickshell/ii/assets/icons/fluent/task-view.svg
deleted file mode 100644
index 4323e8421..000000000
--- a/dots/.config/quickshell/ii/assets/icons/fluent/task-view.svg
+++ /dev/null
@@ -1,79 +0,0 @@
-
-
diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml
index 2ac21aa40..a724c043d 100644
--- a/dots/.config/quickshell/ii/modules/common/Config.qml
+++ b/dots/.config/quickshell/ii/modules/common/Config.qml
@@ -389,7 +389,7 @@ Singleton {
property bool darkenScreen: true
property real clickthroughOpacity: 0.8
property JsonObject floatingImage: JsonObject {
- property string imageSource: "https://cdn.discordapp.com/attachments/961693710968557598/1369635662390759434/image.gif?ex=6911cb1c&is=6910799c&hm=4450244066c0a7a6e5d2bdd195f47388eb5e7f9dd53d3931e99ad9642c638a00&"
+ property string imageSource: "https://media.tenor.com/H5U5bJzj3oAAAAAi/kukuru.gif"
property real scale: 0.5
}
}
@@ -561,7 +561,7 @@ Singleton {
property JsonObject waffles: JsonObject {
property JsonObject bar: JsonObject {
property bool bottom: true
- property bool leftAlignApps: true
+ property bool leftAlignApps: false
}
}
}
diff --git a/dots/.config/quickshell/ii/modules/ii/dock/DockAppButton.qml b/dots/.config/quickshell/ii/modules/ii/dock/DockAppButton.qml
index 406eb3f57..41ed8cd07 100644
--- a/dots/.config/quickshell/ii/modules/ii/dock/DockAppButton.qml
+++ b/dots/.config/quickshell/ii/modules/ii/dock/DockAppButton.qml
@@ -17,8 +17,8 @@ DockButton {
property real countDotHeight: 4
property bool appIsActive: appToplevel.toplevels.find(t => (t.activated == true)) !== undefined
- property bool isSeparator: appToplevel.appId === "SEPARATOR"
- property var desktopEntry: DesktopEntries.heuristicLookup(appToplevel.appId)
+ readonly property bool isSeparator: appToplevel.appId === "SEPARATOR"
+ readonly property var desktopEntry: DesktopEntries.heuristicLookup(appToplevel.appId)
enabled: !isSeparator
implicitWidth: isSeparator ? 1 : implicitHeight - topInset - bottomInset
diff --git a/dots/.config/quickshell/ii/modules/ii/dock/DockApps.qml b/dots/.config/quickshell/ii/modules/ii/dock/DockApps.qml
index 2bba6553a..d575b7dd4 100644
--- a/dots/.config/quickshell/ii/modules/ii/dock/DockApps.qml
+++ b/dots/.config/quickshell/ii/modules/ii/dock/DockApps.qml
@@ -1,6 +1,3 @@
-import qs.modules.common
-import qs.modules.common.widgets
-import qs.modules.common.functions
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
@@ -8,6 +5,10 @@ import QtQuick.Layouts
import Quickshell
import Quickshell.Widgets
import Quickshell.Wayland
+import qs.services
+import qs.modules.common
+import qs.modules.common.widgets
+import qs.modules.common.functions
Item {
id: root
@@ -40,44 +41,7 @@ Item {
model: ScriptModel {
objectProp: "appId"
- values: {
- var map = new Map();
-
- // Pinned apps
- const pinnedApps = Config.options?.dock.pinnedApps ?? [];
- for (const appId of pinnedApps) {
- if (!map.has(appId.toLowerCase())) map.set(appId.toLowerCase(), ({
- pinned: true,
- toplevels: []
- }));
- }
-
- // Separator
- if (pinnedApps.length > 0) {
- map.set("SEPARATOR", { pinned: false, toplevels: [] });
- }
-
- // Ignored apps
- const ignoredRegexStrings = Config.options?.dock.ignoredAppRegexes ?? [];
- const ignoredRegexes = ignoredRegexStrings.map(pattern => new RegExp(pattern, "i"));
- // Open windows
- for (const toplevel of ToplevelManager.toplevels.values) {
- if (ignoredRegexes.some(re => re.test(toplevel.appId))) continue;
- if (!map.has(toplevel.appId.toLowerCase())) map.set(toplevel.appId.toLowerCase(), ({
- pinned: false,
- toplevels: []
- }));
- map.get(toplevel.appId.toLowerCase()).toplevels.push(toplevel);
- }
-
- var values = [];
-
- for (const [key, value] of map) {
- values.push({ appId: key, toplevels: value.toplevels, pinned: value.pinned });
- }
-
- return values;
- }
+ values: TaskbarApps.apps
}
delegate: DockAppButton {
required property var modelData
diff --git a/dots/.config/quickshell/ii/modules/waffle/background/WaffleBackground.qml b/dots/.config/quickshell/ii/modules/waffle/background/WaffleBackground.qml
new file mode 100644
index 000000000..caaff1707
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/background/WaffleBackground.qml
@@ -0,0 +1,46 @@
+pragma ComponentBehavior: Bound
+
+import qs
+import qs.services
+import qs.modules.common
+import qs.modules.common.widgets
+import qs.modules.common.widgets.widgetCanvas
+import QtQuick
+import QtQuick.Layouts
+import Qt5Compat.GraphicalEffects
+import Quickshell
+import Quickshell.Io
+import Quickshell.Wayland
+import Quickshell.Hyprland
+
+import qs.modules.ii.background.widgets
+import qs.modules.ii.background.widgets.clock
+import qs.modules.ii.background.widgets.weather
+
+Variants {
+ id: root
+ model: Quickshell.screens
+
+ PanelWindow {
+ id: panelRoot
+ required property var modelData
+
+ screen: modelData
+ exclusionMode: ExclusionMode.Ignore
+ WlrLayershell.layer: WlrLayer.Bottom
+ WlrLayershell.namespace: "quickshell:background"
+ anchors {
+ top: true
+ bottom: true
+ left: true
+ right: true
+ }
+ color: "transparent"
+
+ StyledImage {
+ anchors.fill: parent
+ source: Config.options.background.wallpaperPath
+ fillMode: Image.PreserveAspectCrop
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/TaskAppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/TaskAppButton.qml
new file mode 100644
index 000000000..241796f0f
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/TaskAppButton.qml
@@ -0,0 +1,17 @@
+import QtQuick
+import QtQuick.Layouts
+import qs.services
+import qs.modules.common
+import qs.modules.waffle.looks
+
+AppButton {
+ id: root
+
+ required property var toplevel
+ readonly property bool isSeparator: toplevel.appId === "SEPARATOR"
+ readonly property var desktopEntry: DesktopEntries.heuristicLookup(toplevel.appId)
+
+ Layout.fillHeight: true
+
+ iconName: toplevel.appId
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/TaskViewButton.qml
index 1239fed6f..c3a4853f0 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: "task-view"
+ separateLightDark: true
checked: GlobalStates.overviewOpen
onClicked: {
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/Tasks.qml b/dots/.config/quickshell/ii/modules/waffle/bar/Tasks.qml
new file mode 100644
index 000000000..ba8944999
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/Tasks.qml
@@ -0,0 +1,34 @@
+import QtQuick
+import QtQuick.Layouts
+import Quickshell
+import qs.services
+import qs.modules.common
+import qs.modules.waffle.looks
+
+Item {
+ id: root
+
+ Layout.fillHeight: true
+ implicitHeight: row.implicitHeight
+ implicitWidth: row.implicitWidth
+
+ // Apps row
+ RowLayout {
+ id: row
+ anchors.fill: parent
+ spacing: 4
+
+ Repeater {
+ model: ScriptModel {
+ objectProp: "appId"
+ values: TaskbarApps.apps.filter(app => app.appId !== "SEPARATOR")
+ }
+ delegate: TaskAppButton {
+ required property var modelData
+ toplevel: modelData
+ }
+ }
+ }
+
+ // TODO: Previews popup
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml
index 5c19c661f..aa5f51f68 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBar.qml
@@ -23,7 +23,7 @@ Scope {
screen: modelData
exclusionMode: ExclusionMode.Ignore
exclusiveZone: implicitHeight
- WlrLayershell.namespace: "quickshell:wBar"
+ WlrLayershell.namespace: "quickshell:bar"
anchors {
left: true
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
index 989904e2f..1a9763616 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
@@ -57,6 +57,7 @@ Rectangle {
StartButton {}
SearchButton {}
TaskViewButton {}
+ Tasks {}
}
BarGroupRow {
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml
index 94c194686..840f63c7a 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.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
@@ -13,6 +14,11 @@ AppButton {
implicitWidth: expandedForm ? 148 : (height - topInset - bottomInset + leftInset + rightInset)
iconName: "widgets"
+ checked: GlobalStates.sidebarLeftOpen
+ onClicked: {
+ GlobalStates.sidebarLeftOpen = !GlobalStates.sidebarLeftOpen
+ }
+
contentItem: Item {
anchors {
verticalCenter: parent.verticalCenter
@@ -29,11 +35,20 @@ AppButton {
horizontalCenter: root.expandedForm ? undefined : parent.horizontalCenter
margins: 8
}
+ spacing: 6
AppIcon {
id: iconWidget
+ anchors.verticalCenter: parent.verticalCenter
iconName: root.iconName
}
+
+ Column {
+ anchors.verticalCenter: parent.verticalCenter
+ WText {
+ text: Translation.tr("Widgets")
+ }
+ }
}
}
}
diff --git a/dots/.config/quickshell/ii/services/TaskbarApps.qml b/dots/.config/quickshell/ii/services/TaskbarApps.qml
new file mode 100644
index 000000000..0b5818b71
--- /dev/null
+++ b/dots/.config/quickshell/ii/services/TaskbarApps.qml
@@ -0,0 +1,60 @@
+pragma Singleton
+
+import qs.modules.common
+import QtQuick
+import Quickshell
+import Quickshell.Wayland
+
+Singleton {
+ id: root
+
+ property list apps: {
+ var map = new Map();
+
+ // Pinned apps
+ const pinnedApps = Config.options?.dock.pinnedApps ?? [];
+ for (const appId of pinnedApps) {
+ if (!map.has(appId.toLowerCase())) map.set(appId.toLowerCase(), ({
+ pinned: true,
+ toplevels: []
+ }));
+ }
+
+ // Separator
+ if (pinnedApps.length > 0) {
+ map.set("SEPARATOR", { pinned: false, toplevels: [] });
+ }
+
+ // Ignored apps
+ const ignoredRegexStrings = Config.options?.dock.ignoredAppRegexes ?? [];
+ const ignoredRegexes = ignoredRegexStrings.map(pattern => new RegExp(pattern, "i"));
+ // Open windows
+ for (const toplevel of ToplevelManager.toplevels.values) {
+ if (ignoredRegexes.some(re => re.test(toplevel.appId))) continue;
+ if (!map.has(toplevel.appId.toLowerCase())) map.set(toplevel.appId.toLowerCase(), ({
+ pinned: false,
+ toplevels: []
+ }));
+ map.get(toplevel.appId.toLowerCase()).toplevels.push(toplevel);
+ }
+
+ var values = [];
+
+ for (const [key, value] of map) {
+ values.push(appEntryComp.createObject(null, { appId: key, toplevels: value.toplevels, pinned: value.pinned }));
+ }
+
+ return values;
+ }
+
+ component TaskbarAppEntry: QtObject {
+ id: wrapper
+ required property string appId
+ required property list toplevels
+ required property bool pinned
+ }
+ Component {
+ id: appEntryComp
+ TaskbarAppEntry {}
+ }
+}
diff --git a/dots/.config/quickshell/ii/shell.qml b/dots/.config/quickshell/ii/shell.qml
index a23c84cca..dc0a9509f 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.background
import qs.modules.waffle.bar
import QtQuick
@@ -74,6 +75,7 @@ ShellRoot {
PanelLoader { identifier: "iiVerticalBar"; extraCondition: Config.options.bar.vertical; component: VerticalBar {} }
PanelLoader { identifier: "iiWallpaperSelector"; component: WallpaperSelector {} }
PanelLoader { identifier: "wBar"; component: WaffleBar {} }
+ PanelLoader { identifier: "wBackground"; component: WaffleBackground {} }
component PanelLoader: LazyLoader {
required property string identifier
@@ -85,7 +87,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", "iiBackground", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiScreenCorners", "iiSessionScreen", "iiSidebarLeft", "iiSidebarRight", "iiWallpaperSelector"],
+ "waffle": ["wBar", "wBackground", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiScreenCorners", "iiSessionScreen", "iiSidebarLeft", "iiSidebarRight", "iiWallpaperSelector"],
})
function cyclePanelFamily() {
const currentIndex = families.indexOf(Config.options.panelFamily)
From 20e1f0e0bb79cc796035e38558ea0aa09df7f93a Mon Sep 17 00:00:00 2001
From: end-4 <97237370+end-4@users.noreply.github.com>
Date: Wed, 12 Nov 2025 00:09:22 +0100
Subject: [PATCH 08/12] taskbar: window previews
---
.../ii/assets/icons/fluent/dismiss.svg | 1 +
.../ii/modules/waffle/bar/AppButton.qml | 13 +-
.../ii/modules/waffle/bar/AppIcon.qml | 8 +-
.../ii/modules/waffle/bar/BarButton.qml | 55 +------
.../ii/modules/waffle/bar/TaskAppButton.qml | 18 ++-
.../ii/modules/waffle/bar/TaskPreview.qml | 128 +++++++++++++++++
.../ii/modules/waffle/bar/Tasks.qml | 19 ++-
.../modules/waffle/bar/WaffleBarContent.qml | 1 -
.../ii/modules/waffle/bar/WindowPreview.qml | 135 ++++++++++++++++++
.../modules/waffle/looks/AcrylicRectangle.qml | 63 ++++++++
.../ii/modules/waffle/looks/Looks.qml | 25 ++--
.../quickshell/ii/services/AppSearch.qml | 2 +-
12 files changed, 390 insertions(+), 78 deletions(-)
create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/dismiss.svg
create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/TaskPreview.qml
create mode 100644 dots/.config/quickshell/ii/modules/waffle/bar/WindowPreview.qml
create mode 100644 dots/.config/quickshell/ii/modules/waffle/looks/AcrylicRectangle.qml
diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/dismiss.svg b/dots/.config/quickshell/ii/assets/icons/fluent/dismiss.svg
new file mode 100644
index 000000000..3cb3656dc
--- /dev/null
+++ b/dots/.config/quickshell/ii/assets/icons/fluent/dismiss.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 017d8f931..90d0cc007 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/AppButton.qml
@@ -10,8 +10,16 @@ BarButton {
required property string iconName
property bool separateLightDark: false
+ leftInset: 2
+ rightInset: 2
implicitWidth: height - topInset - bottomInset + leftInset + rightInset
+ 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: Item {
id: contentItem
anchors.centerIn: root.background
@@ -19,12 +27,10 @@ BarButton {
implicitHeight: iconWidget.implicitHeight
implicitWidth: iconWidget.implicitWidth
- scale: root.down ? 5/6 : 1 // If/When we do dragging, the scale is 1.25
Behavior on scale {
NumberAnimation {
- duration: 90
+ id: scaleAnim
easing.type: Easing.BezierSpline
- easing.bezierCurve: root.down ? Looks.transition.easing.bezierCurve.easeIn : Looks.transition.easing.bezierCurve.easeOut
}
}
@@ -32,6 +38,7 @@ BarButton {
id: iconWidget
anchors.centerIn: parent
iconName: root.iconName
+ separateLightDark: root.separateLightDark
}
}
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml b/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml
index 02c1da144..fc5c75426 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/AppIcon.qml
@@ -5,11 +5,13 @@ import qs.modules.common
import qs.modules.waffle.looks
Kirigami.Icon {
- id: iconWidget
+ id: root
required property string iconName
+ property bool separateLightDark: false
- implicitWidth: 26
- implicitHeight: 26
+ 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
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml
index 20929b1e6..52e5164aa 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/BarButton.qml
@@ -11,17 +11,9 @@ Button {
Layout.fillHeight: true
topInset: 4
bottomInset: 4
-
- property color borderColor: ColorUtils.transparentize(Looks.colors.bg1Border, ((root.hovered && !root.down) || root.checked) ? Looks.fluentContentTransparency : 1)
- Behavior on borderColor {
- animation: Looks.transition.color.createObject(this)
- }
- onBorderColorChanged: {
- borderCanvas.requestPaint();
- }
- background: Rectangle {
- id: background
+ background: AcrylicRectangle {
+ shiny: ((root.hovered && !root.down) || root.checked)
color: {
if (root.down) {
return Looks.colors.bg1Active
@@ -31,48 +23,5 @@ Button {
return ColorUtils.transparentize(Looks.colors.bg1)
}
}
- radius: Looks.radius.medium
- Behavior on color {
- animation: Looks.transition.color.createObject(this)
- }
-
- // Top 1px border with color
- Canvas {
- id: borderCanvas
- anchors.fill: parent
- onPaint: {
- var ctx = getContext("2d");
- ctx.clearRect(0, 0, width, height);
-
- var borderColor = root.borderColor;
-
- var r = background.radius;
- var fadeLength = Math.max(1, r);
- var fadeLengthPercent = fadeLength / width;
-
- // Compute normalized stops
- var leftFadeStop = fadeLengthPercent;
- var rightFadeStop = 1 - fadeLengthPercent;
-
- var grad = ctx.createLinearGradient(0, 0, width, 0);
- grad.addColorStop(0, Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0));
- grad.addColorStop(leftFadeStop, borderColor);
- grad.addColorStop(rightFadeStop, borderColor);
- grad.addColorStop(1, Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0));
-
- ctx.strokeStyle = grad;
- ctx.lineWidth = 1;
-
- ctx.beginPath();
- ctx.moveTo(r, 0.5);
- ctx.lineTo(width - r, 0.5);
- // Top-right curve
- ctx.arcTo(width, 0.5, width, r + 0.5, r);
- // Top-left curve
- ctx.moveTo(width - r, 0.5);
- ctx.arcTo(0, 0.5, 0, r + 0.5, r);
- ctx.stroke();
- }
- }
}
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/TaskAppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/TaskAppButton.qml
index 241796f0f..7363b0387 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/TaskAppButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/TaskAppButton.qml
@@ -3,15 +3,23 @@ import QtQuick.Layouts
import qs.services
import qs.modules.common
import qs.modules.waffle.looks
+import Quickshell
AppButton {
id: root
- required property var toplevel
- readonly property bool isSeparator: toplevel.appId === "SEPARATOR"
- readonly property var desktopEntry: DesktopEntries.heuristicLookup(toplevel.appId)
+ required property var appEntry
+ readonly property bool isSeparator: appEntry.appId === "SEPARATOR"
+ readonly property var desktopEntry: DesktopEntries.heuristicLookup(appEntry.appId)
- Layout.fillHeight: true
+ signal hoverPreviewRequested()
- iconName: toplevel.appId
+ iconName: AppSearch.guessIcon(appEntry.appId)
+ Timer {
+ running: root.hovered
+ interval: 250
+ onTriggered: {
+ root.hoverPreviewRequested()
+ }
+ }
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/TaskPreview.qml b/dots/.config/quickshell/ii/modules/waffle/bar/TaskPreview.qml
new file mode 100644
index 000000000..3c03563a3
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/TaskPreview.qml
@@ -0,0 +1,128 @@
+import QtQuick
+import QtQuick.Layouts
+import Qt5Compat.GraphicalEffects
+import qs.services
+import qs.modules.common
+import qs.modules.common.functions
+import qs.modules.waffle.looks
+import Quickshell
+
+PopupWindow {
+ id: root
+
+ ///////////////////// Properties ////////////////////
+ required property bool tasksHovered
+ property var appEntry
+ property Item anchorItem
+
+ //////////////////// Functions ////////////////////
+ function close() {
+ marginBehavior.enabled = false;
+ root.visible = false;
+ }
+
+ function open() {
+ marginBehavior.enabled = true;
+ root.visible = true;
+ }
+
+ function show(appEntry: var, button: Item) {
+ root.appEntry = appEntry;
+ root.anchorItem = button;
+ root.anchor.updateAnchor();
+ root.open();
+ }
+
+ ///////////////////// Internals /////////////////////
+ readonly property bool bottom: Config.options.waffles.bar.bottom
+ property real visualMargin: 12
+ property alias ambientShadowWidth: ambientShadow.border.width
+
+ visible: false
+ color: "transparent"
+ implicitWidth: contentItem.implicitWidth + ambientShadowWidth + (visualMargin * 2)
+ implicitHeight: contentItem.implicitHeight + ambientShadowWidth + (visualMargin * 2)
+ anchor {
+ adjustment: PopupAdjustment.Slide
+ item: root.anchorItem
+ gravity: bottom ? Edges.Top : Edges.Bottom
+ edges: bottom ? Edges.Top : Edges.Bottom
+ }
+
+ Timer {
+ interval: 250
+ running: root.visible && !hoverChecker.containsMouse && !root.tasksHovered
+ onTriggered: {
+ root.close();
+ }
+ }
+
+ // Content
+ MouseArea {
+ id: hoverChecker
+ anchors.fill: parent
+ hoverEnabled: true
+
+ // Shadow
+ Rectangle {
+ id: ambientShadow
+ anchors {
+ fill: contentItem
+ margins: -border.width
+ }
+ border.color: ColorUtils.transparentize(Looks.colors.bg0Border, Looks.contentTransparency)
+ border.width: 1
+ color: "transparent"
+ radius: Looks.radius.large + border.width
+ }
+
+ Rectangle {
+ id: contentItem
+ property real sourceEdgeMargin: root.visible ? (root.ambientShadowWidth + root.visualMargin) : -root.implicitHeight
+ Behavior on sourceEdgeMargin {
+ id: marginBehavior
+ animation: Looks.transition.enter.createObject(this)
+ }
+ anchors {
+ left: parent.left
+ right: parent.right
+ top: root.bottom ? undefined : parent.top
+ bottom: root.bottom ? parent.bottom : undefined
+ margins: root.ambientShadowWidth + root.visualMargin
+ // Opening anim
+ bottomMargin: root.bottom ? sourceEdgeMargin : (root.ambientShadowWidth + root.visualMargin)
+ topMargin: root.bottom ? (root.ambientShadowWidth + root.visualMargin) : sourceEdgeMargin
+ }
+ color: Looks.colors.bg1
+ radius: Looks.radius.large
+
+ layer.enabled: true
+ layer.effect: OpacityMask {
+ maskSource: Rectangle {
+ width: contentItem.width
+ height: contentItem.height
+ radius: contentItem.radius
+ }
+ }
+
+ // Testing
+ implicitHeight: Math.min(158, windowsRow.implicitHeight)
+ implicitWidth: windowsRow.implicitWidth
+
+ RowLayout {
+ id: windowsRow
+ anchors.fill: parent
+
+ Repeater {
+ model: ScriptModel {
+ values: root.appEntry?.toplevels ?? []
+ }
+ delegate: WindowPreview {
+ required property var modelData
+ toplevel: modelData
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/Tasks.qml b/dots/.config/quickshell/ii/modules/waffle/bar/Tasks.qml
index ba8944999..eac963722 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/Tasks.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/Tasks.qml
@@ -5,30 +5,41 @@ import qs.services
import qs.modules.common
import qs.modules.waffle.looks
-Item {
+MouseArea {
id: root
Layout.fillHeight: true
implicitHeight: row.implicitHeight
implicitWidth: row.implicitWidth
+ hoverEnabled: true
// Apps row
RowLayout {
id: row
anchors.fill: parent
- spacing: 4
+ spacing: 0
Repeater {
+ // TODO: Include only apps (and windows) in current workspace only
model: ScriptModel {
objectProp: "appId"
values: TaskbarApps.apps.filter(app => app.appId !== "SEPARATOR")
}
delegate: TaskAppButton {
required property var modelData
- toplevel: modelData
+ appEntry: modelData
+
+ onHoverPreviewRequested: {
+ previewPopup.show(appEntry, this)
+ }
}
}
}
- // TODO: Previews popup
+ // Previews popup
+ TaskPreview {
+ id: previewPopup
+ tasksHovered: root.containsMouse
+ anchor.window: root.QsWindow.window
+ }
}
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
index 1a9763616..5228abb5c 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/WaffleBarContent.qml
@@ -36,7 +36,6 @@ Rectangle {
BarGroupRow {
id: appsRow
- spacing: 4
anchors.left: undefined
anchors.horizontalCenter: parent.horizontalCenter
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WindowPreview.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WindowPreview.qml
new file mode 100644
index 000000000..b1944c350
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/WindowPreview.qml
@@ -0,0 +1,135 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import Qt5Compat.GraphicalEffects
+import qs.services
+import qs.modules.common
+import qs.modules.common.functions
+import qs.modules.waffle.looks
+import Quickshell
+import Quickshell.Wayland
+
+Button {
+ id: root
+
+ required property var toplevel
+ property real previewWidthConstraint: 200
+ property real previewHeightConstraint: 110
+ padding: 5
+ Layout.fillHeight: true
+
+ onClicked: {
+ root.toplevel.activate(); // TODO: make this work with those who disable focus on activate because telegram is abusive
+ }
+
+ background: Rectangle {
+ id: background
+ radius: Looks.radius.medium
+ color: root.down ? Looks.colors.bg2Active : (root.hovered ? Looks.colors.bg2Hover : ColorUtils.transparentize(Looks.colors.bg2))
+ Behavior on color {
+ animation: Looks.transition.color.createObject(this)
+ }
+ }
+
+ contentItem: ColumnLayout {
+ id: contentItem
+ anchors.fill: parent
+ anchors.margins: root.padding
+ spacing: 5
+
+ RowLayout {
+ Layout.fillWidth: true
+ Layout.fillHeight: false
+ spacing: 8
+
+ AppIcon {
+ id: appIcon
+ Layout.leftMargin: Looks.radius.large - root.padding + 2
+ Layout.alignment: Qt.AlignVCenter
+ iconName: AppSearch.guessIcon(root.toplevel.appId)
+ implicitSize: 16
+ }
+
+ Item {
+ id: appTitleContainer
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ implicitHeight: closeButton.implicitHeight // Enforce height, because closeButton doesn't contribute when it's invisible
+ WText {
+ id: appTitleText
+ anchors.fill: parent
+ text: root.toplevel.title
+ elide: Text.ElideRight
+ font.pixelSize: Looks.font.pixelSize.large
+ font.weight: Looks.font.weight.thin
+ color: Looks.colors.fg1
+ }
+ }
+
+ CloseButton {
+ id: closeButton
+ }
+ }
+
+ Item {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.margins: Looks.radius.large - root.padding
+ Layout.topMargin: 0
+ implicitWidth: Math.max(screencopyView.implicitWidth, 80)
+ implicitHeight: screencopyView.implicitHeight
+
+ ScreencopyView {
+ id: screencopyView
+ anchors.centerIn: parent
+ captureSource: root.toplevel
+ live: true
+ paintCursor: true
+ constraintSize: Qt.size(root.previewWidthConstraint, root.previewHeightConstraint)
+ }
+ }
+ }
+
+ component CloseButton: Button {
+ id: reusableCloseButton
+ visible: root.hovered
+ Layout.leftMargin: 4
+ implicitHeight: 30
+ implicitWidth: 30
+ onClicked: {
+ root.toplevel.close();
+ }
+
+ Rectangle {
+ z: 0
+ color: "transparent"
+ anchors.fill: closeButtonBg
+ anchors.margins: -1
+ opacity: closeButtonBg.opacity
+ border.width: 1
+ radius: closeButtonBg.radius + 1
+ border.color: Looks.colors.bg2Border
+ }
+
+ background: Rectangle {
+ id: closeButtonBg
+ z: 1
+ opacity: reusableCloseButton.hovered ? 1 : 0
+ radius: Looks.radius.large - root.padding
+ color: reusableCloseButton.pressed ? Looks.colors.dangerActive : Looks.colors.danger
+ Behavior on opacity {
+ animation: Looks.transition.opacity.createObject(this)
+ }
+ Behavior on color {
+ animation: Looks.transition.color.createObject(this)
+ }
+ }
+
+ contentItem: FluentIcon {
+ z: 2
+ anchors.centerIn: parent
+ icon: "dismiss"
+ implicitSize: 10
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/AcrylicRectangle.qml b/dots/.config/quickshell/ii/modules/waffle/looks/AcrylicRectangle.qml
new file mode 100644
index 000000000..3720d6186
--- /dev/null
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/AcrylicRectangle.qml
@@ -0,0 +1,63 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import qs.modules.common
+import qs.modules.common.functions
+import qs.modules.waffle.looks
+
+Rectangle {
+ id: root
+
+ property bool shiny: true // Top border
+ property color borderColor: ColorUtils.transparentize(Looks.colors.bg1Border, shiny ? Looks.contentTransparency : 1)
+ color: Looks.colors.bg1Hover
+ radius: Looks.radius.medium
+ Behavior on color {
+ animation: Looks.transition.color.createObject(this)
+ }
+ Behavior on borderColor {
+ animation: Looks.transition.color.createObject(this)
+ }
+ onBorderColorChanged: {
+ borderCanvas.requestPaint();
+ }
+
+ // Top 1px border with color
+ Canvas {
+ id: borderCanvas
+ anchors.fill: parent
+ onPaint: {
+ var ctx = getContext("2d");
+ ctx.clearRect(0, 0, width, height);
+
+ var borderColor = root.borderColor;
+
+ var r = root.radius;
+ var fadeLength = Math.max(1, r);
+ var fadeLengthPercent = fadeLength / width;
+
+ // Compute normalized stops
+ var leftFadeStop = fadeLengthPercent;
+ var rightFadeStop = 1 - fadeLengthPercent;
+
+ var grad = ctx.createLinearGradient(0, 0, width, 0);
+ grad.addColorStop(0, Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0));
+ grad.addColorStop(leftFadeStop, borderColor);
+ grad.addColorStop(rightFadeStop, borderColor);
+ grad.addColorStop(1, Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0));
+
+ ctx.strokeStyle = grad;
+ ctx.lineWidth = 1;
+
+ ctx.beginPath();
+ ctx.moveTo(r, 0.5);
+ ctx.lineTo(width - r, 0.5);
+ // Top-right curve
+ ctx.arcTo(width, 0.5, width, r + 0.5, r);
+ // Top-left curve
+ ctx.moveTo(width - r, 0.5);
+ ctx.arcTo(0, 0.5, 0, r + 0.5, r);
+ ctx.stroke();
+ }
+ }
+}
diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
index ea225f093..df7df8187 100644
--- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml
@@ -15,17 +15,24 @@ Singleton {
property string iconsPath: `${Directories.assetsPath}/icons/fluent`
property bool dark: Appearance.m3colors.darkmode
- property real fluentBackgroundTransparency: 0.17
- property real fluentContentTransparency: 0.3
+ property real backgroundTransparency: 0.17
+ property real contentTransparency: 0.25
colors: QtObject {
id: colors
property color bg0: root.dark ? "#1C1C1C" : "#EEEEEE"
property color bg0Border: root.dark ? "#404040" : "#BEBEBE"
- property color bg1: root.dark ? "#2E2E2E" : "#F7F7F7"
+ property color bg1: root.dark ? "#2C2C2C" : "#F7F7F7"
property color bg1Hover: root.dark ? "#292929" : "#F7F7F7"
property color bg1Active: root.dark ? "#252525" : "#F3F3F3"
property color bg1Border: root.dark ? "#333333" : "#E9E9E9"
+ property color bg2: root.dark ? "#313131" : "#FBFBFB"
+ property color bg2Hover: root.dark ? "#383838" : "#FDFDFD"
+ property color bg2Active: root.dark ? "#333333" : "#FDFDFD"
+ property color bg2Border: root.dark ? "#464646" : "#EEEEEE"
property color fg: root.dark ? "#FFFFFF" : "#000000"
+ property color fg1: root.dark ? "#D1D1D1" : "#626262"
+ property color danger: "#C42B1C"
+ property color dangerActive: "#B62D1F"
property color brand: Appearance.m3colors.m3primary
}
@@ -44,12 +51,14 @@ Singleton {
property string ui: "Noto Sans"
}
property QtObject weight: QtObject { // Noto is not Segoe, so we might use slightly different weights
+ property int thin: Font.Normal
property int regular: Font.Medium
property int strong: Font.DemiBold
property int stronger: Font.Bold
}
property QtObject pixelSize: QtObject {
property real normal: 11
+ property real large: 15
}
}
@@ -57,15 +66,15 @@ Singleton {
id: transition
property QtObject easing: QtObject {
property QtObject bezierCurve: QtObject {
- readonly property list easeInOut: [0.42,0.00,0.58,1.00]
- readonly property list easeIn: [0,1,1,1]
- readonly property list easeOut: [1,0,1,1]
+ readonly property list easeInOut: [0.42,0.00,0.58,1.00,1,1]
+ readonly property list easeIn: [0,1,1,1,1,1]
+ readonly property list easeOut: [1,0,1,1,1,1]
}
}
property Component color: Component {
ColorAnimation {
- duration: 80
+ duration: 120
easing.type: Easing.BezierSpline
easing.bezierCurve: transition.easing.bezierCurve.easeIn
}
@@ -73,7 +82,7 @@ Singleton {
property Component opacity: Component {
NumberAnimation{
- duration: 80
+ duration: 120
easing.type: Easing.BezierSpline
easing.bezierCurve: transition.easing.bezierCurve.easeIn
}
diff --git a/dots/.config/quickshell/ii/services/AppSearch.qml b/dots/.config/quickshell/ii/services/AppSearch.qml
index 196e1bed3..7d8c375a6 100644
--- a/dots/.config/quickshell/ii/services/AppSearch.qml
+++ b/dots/.config/quickshell/ii/services/AppSearch.qml
@@ -151,6 +151,6 @@ Singleton {
// Give up
- return str;
+ return "application-x-executable";
}
}
From 20cae142d7e34fd36b8b4d8cfdfce078e4bf4602 Mon Sep 17 00:00:00 2001
From: end-4 <97237370+end-4@users.noreply.github.com>
Date: Wed, 12 Nov 2025 00:16:32 +0100
Subject: [PATCH 09/12] fix widget button when on the left
---
dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml | 1 +
1 file changed, 1 insertion(+)
diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml
index 840f63c7a..7107cfafd 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/WidgetsButton.qml
@@ -44,6 +44,7 @@ AppButton {
}
Column {
+ visible: root.expandedForm
anchors.verticalCenter: parent.verticalCenter
WText {
text: Translation.tr("Widgets")
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 10/12] 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";
From 7bfbf011d2d0b317f127093999d93a935340b9c1 Mon Sep 17 00:00:00 2001
From: end-4 <97237370+end-4@users.noreply.github.com>
Date: Wed, 12 Nov 2025 21:40:21 +0100
Subject: [PATCH 11/12] taskbar: middle click to launch new instance
---
.../ii/modules/waffle/bar/tasks/TaskAppButton.qml | 6 ++++++
1 file changed, 6 insertions(+)
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 10fdbdf38..53b68b82c 100644
--- a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml
+++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml
@@ -37,6 +37,12 @@ AppButton {
}
}
+ onMiddleClickAction: {
+ if (root.desktopEntry) {
+ desktopEntry.execute()
+ }
+ }
+
// Active indicator
Rectangle {
id: activeIndicator
From df0c7bbbd68cad378d86aed0474e0d1b9a68b841 Mon Sep 17 00:00:00 2001
From: end-4 <97237370+end-4@users.noreply.github.com>
Date: Wed, 12 Nov 2025 21:49:12 +0100
Subject: [PATCH 12/12] Update rules.conf
---
dots/.config/hypr/hyprland/rules.conf | 2 --
1 file changed, 2 deletions(-)
diff --git a/dots/.config/hypr/hyprland/rules.conf b/dots/.config/hypr/hyprland/rules.conf
index dc34a4a6b..01ac1056d 100644
--- a/dots/.config/hypr/hyprland/rules.conf
+++ b/dots/.config/hypr/hyprland/rules.conf
@@ -154,8 +154,6 @@ layerrule = animation slide right, quickshell:sidebarRight
layerrule = animation slide left, quickshell:sidebarLeft
layerrule = animation slide, quickshell:verticalBar
layerrule = animation slide top, quickshell:wallpaperSelector
-# Quickshell - Waffles
-layerrule = animation slide, quickshell:wBar
# Launchers need to be FAST
layerrule = noanim, gtk4-layer-shell