add bg, taskbar items

This commit is contained in:
end-4
2025-11-11 20:23:09 +01:00
parent dec65aea17
commit a412688af2
16 changed files with 424 additions and 126 deletions
@@ -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
@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="63.999989"
height="61.62962"
viewBox="0 0 26.999999 26"
fill="none"
version="1.1"
id="svg3"
sodipodi:docname="task-view-dark.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview3"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="6.0349946"
inkscape:cx="29.328941"
inkscape:cy="30.820243"
inkscape:window-width="1403"
inkscape:window-height="734"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="g3" />
<g
id="g3"
transform="translate(0.03879728,0.03736111)">
<rect
opacity="0.9"
x="9.4441719"
width="17.938911"
height="15.248073"
rx="0.89694548"
fill="#ffffff"
id="rect1"
y="0.8962484"
style="fill:url(#linearGradient4);fill-opacity:1;stroke:#e2e2e2;stroke-width:0.179719;stroke-dasharray:none;stroke-opacity:1"
transform="translate(-2.3652457,0.93944352)" />
<rect
y="9"
width="20"
height="17"
rx="1"
fill="url(#paint0_linear_505_17)"
id="rect2"
x="0"
style="mix-blend-mode:exclusion;stroke-width:1.00007574;stroke-dasharray:none;fill:url(#paint0_linear_505_17-3)"
transform="matrix(0.89768213,0,0,0.89768213,1.8147076,0.83970922)" />
<g
id="g1"
transform="translate(-2.3652457,0.93944351)">
<g
style="mix-blend-mode:exclusion;stroke-width:1.00007574;stroke-dasharray:none"
id="g2"
transform="matrix(0.89768215,0,0,0.89768215,4.1799533,-0.09973431)" />
</g>
</g>
<defs
id="defs3">
<linearGradient
id="paint0_linear_505_17"
x1="-2.75374e-08"
y1="9.2399397"
x2="18.808399"
y2="26.838499"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#717171"
id="stop2"
offset="0"
style="stop-color:#717171;stop-opacity:0.73333335;" />
<stop
offset="1"
stop-color="#4F4F4F"
id="stop3"
style="stop-color:#4f4f4f;stop-opacity:0.73333335;" />
</linearGradient>
<linearGradient
id="paint0_linear_505_17-3"
x1="-2.75374e-08"
y1="9.2399397"
x2="18.808399"
y2="26.838499"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#717171"
id="stop2-6"
offset="0"
style="stop-color:#717171;stop-opacity:0.60000002;" />
<stop
offset="1"
stop-color="#4F4F4F"
id="stop3-7"
style="stop-color:#565656;stop-opacity:0.60000002;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1"
id="linearGradient4"
x1="7.1907158"
y1="8.3216944"
x2="24.995911"
y2="10.507897"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(2.3203156,-0.89451377)" />
<linearGradient
id="linearGradient1"
inkscape:collect="always">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop1" />
<stop
style="stop-color:#e6e6e6;stop-opacity:1;"
offset="1"
id="stop4" />
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="63.999989"
height="61.62962"
viewBox="0 0 26.999999 26"
fill="none"
version="1.1"
id="svg3"
sodipodi:docname="task-view-light.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview3"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="4.7640337"
inkscape:cx="73.677061"
inkscape:cy="43.030762"
inkscape:window-width="1439"
inkscape:window-height="1020"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="g3" />
<g
id="g3"
transform="translate(0.03879728,0.03736111)">
<g
style="mix-blend-mode:exclusion;stroke-width:0.999982;stroke-dasharray:none"
id="g2"
transform="matrix(0.89768215,0,0,0.89768215,1.8596377,0.79477946)">
<rect
y="9"
width="20"
height="17"
rx="1"
fill="url(#paint0_linear_505_17)"
id="rect2"
x="0"
style="fill:url(#paint0_linear_505_17);stroke-width:0.999982;stroke-dasharray:none" />
</g>
<rect
opacity="0.9"
x="7.1238561"
width="17.938911"
height="15.248073"
rx="0.89694548"
fill="#ffffff"
id="rect1"
y="1.7907622"
style="fill:url(#linearGradient4);fill-opacity:1;stroke-width:0.17971878;stroke-dasharray:none;stroke:#d4d4d4;stroke-opacity:1" />
</g>
<defs
id="defs3">
<linearGradient
id="linearGradient1"
inkscape:collect="always">
<stop
style="stop-color:#ffffff;stop-opacity:0.80000001;"
offset="0"
id="stop1" />
<stop
style="stop-color:#e6e6e6;stop-opacity:0.80000001;"
offset="1"
id="stop4" />
</linearGradient>
<linearGradient
id="paint0_linear_505_17"
x1="-2.75374e-08"
y1="9.2399397"
x2="18.808399"
y2="26.838499"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#717171"
id="stop2"
offset="0"
style="stop-color:#464543;stop-opacity:1;" />
<stop
offset="1"
stop-color="#4F4F4F"
id="stop3"
style="stop-color:#1f1f1f;stop-opacity:1;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1"
id="linearGradient4"
x1="7.1729918"
y1="8.4772339"
x2="25.013634"
y2="10.352362"
gradientUnits="userSpaceOnUse" />
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

@@ -1,79 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="63.999989"
height="61.62962"
viewBox="0 0 26.999999 26"
fill="none"
version="1.1"
id="svg3"
sodipodi:docname="Group 6.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview3"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="4.7640336"
inkscape:cx="36.628625"
inkscape:cy="33.794892"
inkscape:window-width="1340"
inkscape:window-height="968"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg3" />
<g
id="g3"
transform="translate(0.03879728,0.03736111)">
<rect
opacity="0.9"
x="7.8752632"
width="17.187504"
height="14.609377"
rx="0.85937512"
fill="#ffffff"
id="rect1"
y="1.7907622"
style="stroke-width:0.859375" />
<g
style="mix-blend-mode:exclusion"
id="g2"
transform="matrix(0.85937512,0,0,0.85937512,1.8596377,1.7907622)">
<rect
y="9"
width="20"
height="17"
rx="1"
fill="url(#paint0_linear_505_17)"
id="rect2"
x="0"
style="fill:url(#paint0_linear_505_17)" />
</g>
</g>
<defs
id="defs3">
<linearGradient
id="paint0_linear_505_17"
x1="-2.75374e-08"
y1="9.2399397"
x2="18.808399"
y2="26.838499"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#717171"
id="stop2" />
<stop
offset="1"
stop-color="#4F4F4F"
id="stop3" />
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

@@ -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
}
}
}
@@ -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
@@ -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
@@ -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
}
}
}
@@ -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
}
@@ -10,6 +10,7 @@ AppButton {
id: root
iconName: "task-view"
separateLightDark: true
checked: GlobalStates.overviewOpen
onClicked: {
@@ -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
}
@@ -23,7 +23,7 @@ Scope {
screen: modelData
exclusionMode: ExclusionMode.Ignore
exclusiveZone: implicitHeight
WlrLayershell.namespace: "quickshell:wBar"
WlrLayershell.namespace: "quickshell:bar"
anchors {
left: true
@@ -57,6 +57,7 @@ Rectangle {
StartButton {}
SearchButton {}
TaskViewButton {}
Tasks {}
}
BarGroupRow {
@@ -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")
}
}
}
}
}
@@ -0,0 +1,60 @@
pragma Singleton
import qs.modules.common
import QtQuick
import Quickshell
import Quickshell.Wayland
Singleton {
id: root
property list<var> 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<var> toplevels
required property bool pinned
}
Component {
id: appEntryComp
TaskbarAppEntry {}
}
}
+3 -1
View File
@@ -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<string> 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)