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,
hoverToReveal: dock.hoverToReveal,
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 hoverRegionHeight: 2
property bool hoverToReveal: true
property list<string> ignoredAppRegexes: []
property list<string> pinnedApps: ["org.kde.dolphin", "kitty",]
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.Drawing as Drawing
import qs.Modules.Settings as Settings
import qs.Modules.Dock as Dock
Shape {
id: root
@@ -24,6 +25,7 @@ Shape {
anchors.fill: parent
anchors.margins: Config.barConfig.border
anchors.topMargin: bar.implicitHeight
asynchronous: true
preferredRendererType: Shape.CurveRenderer
Drawing.Background {
@@ -93,4 +95,12 @@ Shape {
startY: 0
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) {
root.bar.checkPopout(x);
}
@@ -145,6 +148,9 @@ CustomMouseArea {
root.panels.osd.hovered = false;
}
}
if (root.visibilities.launcher)
root.visibilities.dock = false;
}
function onOsdChanged() {
+12
View File
@@ -12,6 +12,7 @@ import qs.Modules.Launcher as Launcher
import qs.Modules.Resources as Resources
import qs.Modules.Settings as Settings
import qs.Modules.Drawing as Drawing
import qs.Modules.Dock as Dock
import qs.Config
Item {
@@ -19,6 +20,7 @@ Item {
required property Item bar
readonly property alias dashboard: dashboard
readonly property alias dock: dock
readonly property alias drawing: drawing
required property Canvas drawingItem
readonly property alias launcher: launcher
@@ -143,4 +145,14 @@ Item {
panels: root
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
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"
contentItem.focus: true
mask: visibilities.isDrawing ? null : region
@@ -94,7 +94,7 @@ Variants {
HyprlandFocusGrab {
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]
onCleared: {
@@ -104,6 +104,7 @@ Variants {
visibilities.osd = false;
visibilities.settings = false;
visibilities.resources = false;
visibilities.dock = false;
panels.popouts.hasCurrent = false;
}
}
@@ -113,6 +114,7 @@ Variants {
property bool bar
property bool dashboard
property bool dock
property bool isDrawing
property bool launcher
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 QtQuick
import qs.Modules.Dock.Parts
import qs.Components
import qs.Helpers
import qs.Config
@@ -17,12 +18,29 @@ Item {
implicitHeight: Config.dock.height + root.padding * 2
implicitWidth: dockRow.implicitWidth + root.padding * 2
RowLayout {
CustomListView {
id: dockRow
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
spacing: Appearance.spacing.small
anchors.centerIn: parent
implicitHeight: Config.dock.height
implicitWidth: contentWidth
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
}