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)