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] 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)