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 } } }