This commit is contained in:
Zacharias-Brohn
2026-03-12 16:27:02 +01:00
parent 9e9708ed12
commit 0b935a3096
10 changed files with 247 additions and 8 deletions
+2 -1
View File
@@ -160,7 +160,8 @@ Singleton {
hoverRegionHeight: dock.hoverRegionHeight, hoverRegionHeight: dock.hoverRegionHeight,
hoverToReveal: dock.hoverToReveal, hoverToReveal: dock.hoverToReveal,
pinnedApps: dock.pinnedApps, pinnedApps: dock.pinnedApps,
pinnedOnStartup: dock.pinnedOnStartup pinnedOnStartup: dock.pinnedOnStartup,
ignoredAppRegexes: dock.ignoredAppRegexes
}; };
} }
+1
View File
@@ -5,6 +5,7 @@ JsonObject {
property real height: 60 property real height: 60
property real hoverRegionHeight: 2 property real hoverRegionHeight: 2
property bool hoverToReveal: true property bool hoverToReveal: true
property list<string> ignoredAppRegexes: []
property list<string> pinnedApps: ["org.kde.dolphin", "kitty",] property list<string> pinnedApps: ["org.kde.dolphin", "kitty",]
property bool pinnedOnStartup: false property bool pinnedOnStartup: false
} }
+10
View File
@@ -13,6 +13,7 @@ import qs.Modules.Launcher as Launcher
import qs.Modules.Resources as Resources import qs.Modules.Resources as Resources
import qs.Modules.Drawing as Drawing import qs.Modules.Drawing as Drawing
import qs.Modules.Settings as Settings import qs.Modules.Settings as Settings
import qs.Modules.Dock as Dock
Shape { Shape {
id: root id: root
@@ -24,6 +25,7 @@ Shape {
anchors.fill: parent anchors.fill: parent
anchors.margins: Config.barConfig.border anchors.margins: Config.barConfig.border
anchors.topMargin: bar.implicitHeight anchors.topMargin: bar.implicitHeight
asynchronous: true
preferredRendererType: Shape.CurveRenderer preferredRendererType: Shape.CurveRenderer
Drawing.Background { Drawing.Background {
@@ -93,4 +95,12 @@ Shape {
startY: 0 startY: 0
wrapper: root.panels.settings wrapper: root.panels.settings
} }
Dock.Background {
id: dock
startX: (root.width - wrapper.width) / 2 - rounding
startY: root.height
wrapper: root.panels.dock
}
} }
+6
View File
@@ -107,6 +107,9 @@ CustomMouseArea {
} }
} }
if (!visibilities.dock && !visibilities.launcher && inBottomPanel(panels.dock, x, y))
visibilities.dock = true;
if (y < root.bar.implicitHeight) { if (y < root.bar.implicitHeight) {
root.bar.checkPopout(x); root.bar.checkPopout(x);
} }
@@ -145,6 +148,9 @@ CustomMouseArea {
root.panels.osd.hovered = false; root.panels.osd.hovered = false;
} }
} }
if (root.visibilities.launcher)
root.visibilities.dock = false;
} }
function onOsdChanged() { function onOsdChanged() {
+12
View File
@@ -12,6 +12,7 @@ import qs.Modules.Launcher as Launcher
import qs.Modules.Resources as Resources import qs.Modules.Resources as Resources
import qs.Modules.Settings as Settings import qs.Modules.Settings as Settings
import qs.Modules.Drawing as Drawing import qs.Modules.Drawing as Drawing
import qs.Modules.Dock as Dock
import qs.Config import qs.Config
Item { Item {
@@ -19,6 +20,7 @@ Item {
required property Item bar required property Item bar
readonly property alias dashboard: dashboard readonly property alias dashboard: dashboard
readonly property alias dock: dock
readonly property alias drawing: drawing readonly property alias drawing: drawing
required property Canvas drawingItem required property Canvas drawingItem
readonly property alias launcher: launcher readonly property alias launcher: launcher
@@ -143,4 +145,14 @@ Item {
panels: root panels: root
visibilities: root.visibilities visibilities: root.visibilities
} }
Dock.Wrapper {
id: dock
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
panels: root
screen: root.screen
visibilities: root.visibilities
}
} }
+4 -2
View File
@@ -33,7 +33,7 @@ Variants {
property var root: Quickshell.shellDir property var root: Quickshell.shellDir
WlrLayershell.exclusionMode: ExclusionMode.Ignore WlrLayershell.exclusionMode: ExclusionMode.Ignore
WlrLayershell.keyboardFocus: visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || visibilities.resources ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None WlrLayershell.keyboardFocus: visibilities.dock || visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || visibilities.resources ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
color: "transparent" color: "transparent"
contentItem.focus: true contentItem.focus: true
mask: visibilities.isDrawing ? null : region mask: visibilities.isDrawing ? null : region
@@ -94,7 +94,7 @@ Variants {
HyprlandFocusGrab { HyprlandFocusGrab {
id: focusGrab id: focusGrab
active: visibilities.resources || visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || (panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu")) active: visibilities.dock || visibilities.resources || visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || (panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu"))
windows: [win] windows: [win]
onCleared: { onCleared: {
@@ -104,6 +104,7 @@ Variants {
visibilities.osd = false; visibilities.osd = false;
visibilities.settings = false; visibilities.settings = false;
visibilities.resources = false; visibilities.resources = false;
visibilities.dock = false;
panels.popouts.hasCurrent = false; panels.popouts.hasCurrent = false;
} }
} }
@@ -113,6 +114,7 @@ Variants {
property bool bar property bool bar
property bool dashboard property bool dashboard
property bool dock
property bool isDrawing property bool isDrawing
property bool launcher property bool launcher
property bool notif: NotifServer.popups.length > 0 property bool notif: NotifServer.popups.length > 0
+86
View File
@@ -0,0 +1,86 @@
pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Wayland
import qs.Config
Singleton {
id: root
property list<var> apps: {
var map = new Map();
// Pinned apps
const pinnedApps = Config.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.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;
}
function isPinned(appId) {
return Config.dock.pinnedApps.indexOf(appId) !== -1;
}
function togglePin(appId) {
if (root.isPinned(appId)) {
Config.dock.pinnedApps = Config.dock.pinnedApps.filter(id => id !== appId);
} else {
Config.dock.pinnedApps = Config.dock.pinnedApps.concat([appId]);
}
}
Component {
id: appEntryComp
TaskbarAppEntry {
}
}
component TaskbarAppEntry: QtObject {
id: wrapper
required property string appId
required property bool pinned
required property list<var> toplevels
}
}
+23 -5
View File
@@ -2,6 +2,7 @@ pragma ComponentBehavior: Bound
import Quickshell import Quickshell
import QtQuick import QtQuick
import qs.Modules.Dock.Parts
import qs.Components import qs.Components
import qs.Helpers import qs.Helpers
import qs.Config import qs.Config
@@ -17,12 +18,29 @@ Item {
implicitHeight: Config.dock.height + root.padding * 2 implicitHeight: Config.dock.height + root.padding * 2
implicitWidth: dockRow.implicitWidth + root.padding * 2 implicitWidth: dockRow.implicitWidth + root.padding * 2
RowLayout { CustomListView {
id: dockRow id: dockRow
anchors.bottom: parent.bottom anchors.centerIn: parent
anchors.horizontalCenter: parent.horizontalCenter implicitHeight: Config.dock.height
anchors.top: parent.top implicitWidth: contentWidth
spacing: Appearance.spacing.small orientation: ListView.Horizontal
spacing: Appearance.padding.smaller
delegate: DockAppButton {
required property var modelData
appListRoot: root
appToplevel: modelData
visibilities: root.visibilities
}
Behavior on implicitWidth {
Anim {
}
}
model: ScriptModel {
objectProp: "appId"
values: TaskbarApps.apps
}
} }
} }
+91
View File
@@ -0,0 +1,91 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Widgets
import qs.Components
import qs.Helpers
import qs.Config
CustomRect {
id: root
property bool appIsActive: appToplevel.toplevels.find(t => (t.activated == true)) !== undefined
property var appListRoot
property var appToplevel
property real countDotHeight: 4
property real countDotWidth: 10
property var desktopEntry: DesktopEntries.heuristicLookup(appToplevel.appId)
property real iconSize: implicitHeight - 20
readonly property bool isSeparator: appToplevel.appId === "SEPARATOR"
property int lastFocused: -1
required property PersistentProperties visibilities
implicitHeight: Config.dock.height
implicitWidth: isSeparator ? 1 : implicitHeight
radius: Appearance.rounding.normal - Appearance.padding.small
Loader {
active: !isSeparator
anchors.centerIn: parent
sourceComponent: ColumnLayout {
IconImage {
id: icon
Layout.alignment: Qt.AlignHCenter
implicitSize: root.iconSize
source: Quickshell.iconPath(AppSearch.guessIcon(appToplevel.appId), "image-missing")
}
RowLayout {
Layout.alignment: Qt.AlignHCenter
spacing: 3
Repeater {
model: Math.min(appToplevel.toplevels.length, 3)
delegate: Rectangle {
required property int index
color: appIsActive ? DynamicColors.palette.m3primary : DynamicColors.tPalette.m3primary
implicitHeight: root.countDotHeight
implicitWidth: (appToplevel.toplevels.length <= 3) ? root.countDotWidth : root.countDotHeight // Circles when too many
radius: Appearance.rounding.full
}
}
}
}
}
StateLayer {
onClicked: {
if (appToplevel.toplevels.length === 0) {
root.desktopEntry?.execute();
root.visibilities.dock = false;
return;
}
lastFocused = (lastFocused + 1) % appToplevel.toplevels.length;
appToplevel.toplevels[lastFocused].activate();
root.visibilities.dock = false;
}
}
Connections {
function onApplicationsChanged() {
root.desktopEntry = DesktopEntries.heuristicLookup(appToplevel.appId);
}
target: DesktopEntries
}
Loader {
active: isSeparator
sourceComponent: DockSeparator {
}
anchors {
fill: parent
}
}
}
+12
View File
@@ -0,0 +1,12 @@
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
CustomRect {
Layout.bottomMargin: dockRow.padding + Appearance.rounding.normal
Layout.fillHeight: true
Layout.topMargin: dockRow.padding + Appearance.rounding.normal
color: DynamicColors.palette.m3outlineVariant
implicitWidth: 1
}