1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-24 21:42:51 -05:00

paths: show dms icon & title for dms windows

This commit is contained in:
bbedward
2025-11-23 15:57:03 -05:00
parent c49a875ec2
commit 8130feb2a0
4 changed files with 680 additions and 641 deletions

View File

@@ -6,60 +6,74 @@ import QtCore
Singleton { Singleton {
id: root id: root
readonly property url home: StandardPaths.standardLocations( readonly property url home: StandardPaths.standardLocations(StandardPaths.HomeLocation)[0]
StandardPaths.HomeLocation)[0] readonly property url pictures: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0]
readonly property url pictures: StandardPaths.standardLocations(
StandardPaths.PicturesLocation)[0]
readonly property url data: `${StandardPaths.standardLocations( readonly property url data: `${StandardPaths.standardLocations(StandardPaths.GenericDataLocation)[0]}/DankMaterialShell`
StandardPaths.GenericDataLocation)[0]}/DankMaterialShell` readonly property url state: `${StandardPaths.standardLocations(StandardPaths.GenericStateLocation)[0]}/DankMaterialShell`
readonly property url state: `${StandardPaths.standardLocations( readonly property url cache: `${StandardPaths.standardLocations(StandardPaths.GenericCacheLocation)[0]}/DankMaterialShell`
StandardPaths.GenericStateLocation)[0]}/DankMaterialShell` readonly property url config: `${StandardPaths.standardLocations(StandardPaths.GenericConfigLocation)[0]}/DankMaterialShell`
readonly property url cache: `${StandardPaths.standardLocations(
StandardPaths.GenericCacheLocation)[0]}/DankMaterialShell`
readonly property url config: `${StandardPaths.standardLocations(
StandardPaths.GenericConfigLocation)[0]}/DankMaterialShell`
readonly property url imagecache: `${cache}/imagecache` readonly property url imagecache: `${cache}/imagecache`
function stringify(path: url): string { function stringify(path: url): string {
return path.toString().replace(/%20/g, " ") return path.toString().replace(/%20/g, " ");
} }
function expandTilde(path: string): string { function expandTilde(path: string): string {
return strip(path.replace("~", stringify(root.home))) return strip(path.replace("~", stringify(root.home)));
} }
function shortenHome(path: string): string { function shortenHome(path: string): string {
return path.replace(strip(root.home), "~") return path.replace(strip(root.home), "~");
} }
function strip(path: url): string { function strip(path: url): string {
return stringify(path).replace("file://", "") return stringify(path).replace("file://", "");
} }
function toFileUrl(path: string): string { function toFileUrl(path: string): string {
return path.startsWith("file://") ? path : "file://" + path return path.startsWith("file://") ? path : "file://" + path;
} }
function mkdir(path: url): void { function mkdir(path: url): void {
Quickshell.execDetached(["mkdir", "-p", strip(path)]) Quickshell.execDetached(["mkdir", "-p", strip(path)]);
} }
function copy(from: url, to: url): void { function copy(from: url, to: url): void {
Quickshell.execDetached(["cp", strip(from), strip(to)]) Quickshell.execDetached(["cp", strip(from), strip(to)]);
} }
// ! Spotify and maybe some other apps report the wrong app id in toplevels, hardcode special case
function moddedAppId(appId: string): string { function moddedAppId(appId: string): string {
if (appId === "Spotify") if (appId === "Spotify")
return "spotify" return "spotify";
if (appId === "beepertexts") if (appId === "beepertexts")
return "beeper" return "beeper";
if (appId === "home assistant desktop") if (appId === "home assistant desktop")
return "homeassistant-desktop" return "homeassistant-desktop";
if (appId.includes("com.transmissionbt.transmission")) if (appId.includes("com.transmissionbt.transmission"))
return "transmission-gtk" return "transmission-gtk";
return appId return appId;
}
function getAppIcon(appId: string, desktopEntry: var): string {
if (appId === "org.quickshell") {
return Qt.resolvedUrl("../assets/danklogo.svg");
}
const moddedId = moddedAppId(appId);
if (moddedId.toLowerCase().includes("steam_app")) {
return "";
}
return desktopEntry && desktopEntry.icon ? Quickshell.iconPath(desktopEntry.icon, true) : "";
}
function getAppName(appId: string, desktopEntry: var): string {
if (appId === "org.quickshell") {
return "dms";
}
return desktopEntry && desktopEntry.name ? desktopEntry.name : appId;
} }
} }

View File

@@ -1,4 +1,5 @@
import QtQuick import QtQuick
import QtQuick.Effects
import Quickshell import Quickshell
import Quickshell.Wayland import Quickshell.Wayland
import Quickshell.Widgets import Quickshell.Widgets
@@ -22,86 +23,87 @@ BasePill {
readonly property real minTooltipY: { readonly property real minTooltipY: {
if (!parentScreen || !isVerticalOrientation) { if (!parentScreen || !isVerticalOrientation) {
return 0 return 0;
} }
if (isAutoHideBar) { if (isAutoHideBar) {
return 0 return 0;
} }
if (parentScreen.y > 0) { if (parentScreen.y > 0) {
return barThickness + (barSpacing || 4) return barThickness + (barSpacing || 4);
} }
return 0 return 0;
} }
Component.onCompleted: { Component.onCompleted: {
updateDesktopEntry() updateDesktopEntry();
} }
Connections { Connections {
target: DesktopEntries target: DesktopEntries
function onApplicationsChanged() { function onApplicationsChanged() {
root.updateDesktopEntry() root.updateDesktopEntry();
} }
} }
Connections { Connections {
target: root target: root
function onActiveWindowChanged() { function onActiveWindowChanged() {
root.updateDesktopEntry() root.updateDesktopEntry();
} }
} }
function updateDesktopEntry() { function updateDesktopEntry() {
if (activeWindow && activeWindow.appId) { if (activeWindow && activeWindow.appId) {
const moddedId = Paths.moddedAppId(activeWindow.appId) const moddedId = Paths.moddedAppId(activeWindow.appId);
activeDesktopEntry = DesktopEntries.heuristicLookup(moddedId) activeDesktopEntry = DesktopEntries.heuristicLookup(moddedId);
} else { } else {
activeDesktopEntry = null activeDesktopEntry = null;
} }
} }
readonly property bool hasWindowsOnCurrentWorkspace: { readonly property bool hasWindowsOnCurrentWorkspace: {
if (CompositorService.isNiri) { if (CompositorService.isNiri) {
let currentWorkspaceId = null let currentWorkspaceId = null;
for (var i = 0; i < NiriService.allWorkspaces.length; i++) { for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
const ws = NiriService.allWorkspaces[i] const ws = NiriService.allWorkspaces[i];
if (ws.is_focused) { if (ws.is_focused) {
currentWorkspaceId = ws.id currentWorkspaceId = ws.id;
break break;
} }
} }
if (!currentWorkspaceId) { if (!currentWorkspaceId) {
return false return false;
} }
const workspaceWindows = NiriService.windows.filter(w => w.workspace_id === currentWorkspaceId) const workspaceWindows = NiriService.windows.filter(w => w.workspace_id === currentWorkspaceId);
return workspaceWindows.length > 0 && activeWindow && activeWindow.title return workspaceWindows.length > 0 && activeWindow && activeWindow.title;
} }
if (CompositorService.isHyprland) { if (CompositorService.isHyprland) {
if (!Hyprland.focusedWorkspace || !activeWindow || !activeWindow.title) { if (!Hyprland.focusedWorkspace || !activeWindow || !activeWindow.title) {
return false return false;
} }
try { try {
if (!Hyprland.toplevels) return false if (!Hyprland.toplevels)
const hyprlandToplevels = Array.from(Hyprland.toplevels.values) return false;
const activeHyprToplevel = hyprlandToplevels.find(t => t?.wayland === activeWindow) const hyprlandToplevels = Array.from(Hyprland.toplevels.values);
const activeHyprToplevel = hyprlandToplevels.find(t => t?.wayland === activeWindow);
if (!activeHyprToplevel || !activeHyprToplevel.workspace) { if (!activeHyprToplevel || !activeHyprToplevel.workspace) {
return false return false;
} }
return activeHyprToplevel.workspace.id === Hyprland.focusedWorkspace.id return activeHyprToplevel.workspace.id === Hyprland.focusedWorkspace.id;
} catch (e) { } catch (e) {
return false return false;
} }
} }
return activeWindow && activeWindow.title return activeWindow && activeWindow.title;
} }
width: hasWindowsOnCurrentWorkspace ? (isVerticalOrientation ? barThickness : visualWidth) : 0 width: hasWindowsOnCurrentWorkspace ? (isVerticalOrientation ? barThickness : visualWidth) : 0
@@ -111,10 +113,12 @@ BasePill {
content: Component { content: Component {
Item { Item {
implicitWidth: { implicitWidth: {
if (!root.hasWindowsOnCurrentWorkspace) return 0 if (!root.hasWindowsOnCurrentWorkspace)
if (root.isVerticalOrientation) return root.widgetThickness - root.horizontalPadding * 2 return 0;
const baseWidth = contentRow.implicitWidth if (root.isVerticalOrientation)
return compactMode ? Math.min(baseWidth, maxCompactWidth - root.horizontalPadding * 2) : Math.min(baseWidth, maxNormalWidth - root.horizontalPadding * 2) return root.widgetThickness - root.horizontalPadding * 2;
const baseWidth = contentRow.implicitWidth;
return compactMode ? Math.min(baseWidth, maxCompactWidth - root.horizontalPadding * 2) : Math.min(baseWidth, maxNormalWidth - root.horizontalPadding * 2);
} }
implicitHeight: root.widgetThickness - root.horizontalPadding * 2 implicitHeight: root.widgetThickness - root.horizontalPadding * 2
clip: false clip: false
@@ -126,14 +130,21 @@ BasePill {
height: 18 height: 18
visible: root.isVerticalOrientation && activeWindow && status === Image.Ready visible: root.isVerticalOrientation && activeWindow && status === Image.Ready
source: { source: {
if (!activeWindow || !activeWindow.appId) return "" if (!activeWindow || !activeWindow.appId)
const moddedId = Paths.moddedAppId(activeWindow.appId) return "";
if (moddedId.toLowerCase().includes("steam_app")) return "" return Paths.getAppIcon(activeWindow.appId, activeDesktopEntry);
return Quickshell.iconPath(activeDesktopEntry?.icon, true)
} }
smooth: true smooth: true
mipmap: true mipmap: true
asynchronous: true asynchronous: true
layer.enabled: activeWindow && activeWindow.appId === "org.quickshell"
layer.smooth: true
layer.mipmap: true
layer.effect: MultiEffect {
saturation: 0
colorization: 1
colorizationColor: Theme.primary
}
} }
DankIcon { DankIcon {
@@ -142,26 +153,28 @@ BasePill {
name: "sports_esports" name: "sports_esports"
color: Theme.widgetTextColor color: Theme.widgetTextColor
visible: { visible: {
if (!root.isVerticalOrientation || !activeWindow || !activeWindow.appId) return false if (!root.isVerticalOrientation || !activeWindow || !activeWindow.appId)
const moddedId = Paths.moddedAppId(activeWindow.appId) return false;
return moddedId.toLowerCase().includes("steam_app") const moddedId = Paths.moddedAppId(activeWindow.appId);
return moddedId.toLowerCase().includes("steam_app");
} }
} }
Text { Text {
anchors.centerIn: parent anchors.centerIn: parent
visible: { visible: {
if (!root.isVerticalOrientation || !activeWindow || !activeWindow.appId) return false if (!root.isVerticalOrientation || !activeWindow || !activeWindow.appId)
if (appIcon.status === Image.Ready) return false return false;
const moddedId = Paths.moddedAppId(activeWindow.appId) if (appIcon.status === Image.Ready)
return !moddedId.toLowerCase().includes("steam_app") return false;
const moddedId = Paths.moddedAppId(activeWindow.appId);
return !moddedId.toLowerCase().includes("steam_app");
} }
text: { text: {
if (!activeWindow || !activeWindow.appId) return "?" if (!activeWindow || !activeWindow.appId)
if (activeDesktopEntry && activeDesktopEntry.name) { return "?";
return activeDesktopEntry.name.charAt(0).toUpperCase() const appName = Paths.getAppName(activeWindow.appId, activeDesktopEntry);
} return appName.charAt(0).toUpperCase();
return activeWindow.appId.charAt(0).toUpperCase()
} }
font.pixelSize: 10 font.pixelSize: 10
color: Theme.widgetTextColor color: Theme.widgetTextColor
@@ -176,12 +189,9 @@ BasePill {
StyledText { StyledText {
id: appText id: appText
text: { text: {
if (!activeWindow || !activeWindow.appId) { if (!activeWindow || !activeWindow.appId)
return ""; return "";
} return Paths.getAppName(activeWindow.appId, activeDesktopEntry);
const desktopEntry = DesktopEntries.heuristicLookup(activeWindow.appId);
return desktopEntry && desktopEntry.name ? desktopEntry.name : activeWindow.appId;
} }
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale) font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale)
color: Theme.widgetTextColor color: Theme.widgetTextColor
@@ -238,31 +248,31 @@ BasePill {
acceptedButtons: Qt.NoButton acceptedButtons: Qt.NoButton
onEntered: { onEntered: {
if (root.isVerticalOrientation && activeWindow && activeWindow.appId && root.parentScreen) { if (root.isVerticalOrientation && activeWindow && activeWindow.appId && root.parentScreen) {
tooltipLoader.active = true tooltipLoader.active = true;
if (tooltipLoader.item) { if (tooltipLoader.item) {
const globalPos = mapToGlobal(width / 2, height / 2) const globalPos = mapToGlobal(width / 2, height / 2);
const currentScreen = root.parentScreen const currentScreen = root.parentScreen;
const screenX = currentScreen ? currentScreen.x : 0 const screenX = currentScreen ? currentScreen.x : 0;
const screenY = currentScreen ? currentScreen.y : 0 const screenY = currentScreen ? currentScreen.y : 0;
const relativeY = globalPos.y - screenY const relativeY = globalPos.y - screenY;
// Add minTooltipY offset to account for top bar // Add minTooltipY offset to account for top bar
const adjustedY = relativeY + root.minTooltipY const adjustedY = relativeY + root.minTooltipY;
const tooltipX = root.axis?.edge === "left" ? (Theme.barHeight + (barConfig?.spacing ?? 4) + Theme.spacingXS) : (currentScreen.width - Theme.barHeight - (barConfig?.spacing ?? 4) - Theme.spacingXS) const tooltipX = root.axis?.edge === "left" ? (Theme.barHeight + (barConfig?.spacing ?? 4) + Theme.spacingXS) : (currentScreen.width - Theme.barHeight - (barConfig?.spacing ?? 4) - Theme.spacingXS);
const appName = activeDesktopEntry && activeDesktopEntry.name ? activeDesktopEntry.name : activeWindow.appId const appName = Paths.getAppName(activeWindow.appId, activeDesktopEntry);
const title = activeWindow.title || "" const title = activeWindow.title || "";
const tooltipText = appName + (title ? " • " + title : "") const tooltipText = appName + (title ? " • " + title : "");
const isLeft = root.axis?.edge === "left" const isLeft = root.axis?.edge === "left";
tooltipLoader.item.show(tooltipText, screenX + tooltipX, adjustedY, currentScreen, isLeft, !isLeft) tooltipLoader.item.show(tooltipText, screenX + tooltipX, adjustedY, currentScreen, isLeft, !isLeft);
} }
} }
} }
onExited: { onExited: {
if (tooltipLoader.item) { if (tooltipLoader.item) {
tooltipLoader.item.hide() tooltipLoader.item.hide();
} }
tooltipLoader.active = false tooltipLoader.active = false;
} }
} }

View File

@@ -1,7 +1,7 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Effects
import Quickshell import Quickshell
import Quickshell.Hyprland
import Quickshell.Wayland import Quickshell.Wayland
import Quickshell.Widgets import Quickshell.Widgets
import qs.Common import qs.Common
@@ -27,105 +27,112 @@ Item {
readonly property real effectiveBarThickness: { readonly property real effectiveBarThickness: {
if (barThickness > 0 && barSpacing > 0) { if (barThickness > 0 && barSpacing > 0) {
return barThickness + barSpacing return barThickness + barSpacing;
} }
const innerPadding = barConfig?.innerPadding ?? 4 const innerPadding = barConfig?.innerPadding ?? 4;
const spacing = barConfig?.spacing ?? 4 const spacing = barConfig?.spacing ?? 4;
return Math.max(26 + innerPadding * 0.6, Theme.barHeight - 4 - (8 - innerPadding)) + spacing return Math.max(26 + innerPadding * 0.6, Theme.barHeight - 4 - (8 - innerPadding)) + spacing;
} }
readonly property var barBounds: { readonly property var barBounds: {
if (!parentScreen || !barConfig) { if (!parentScreen || !barConfig) {
return { "x": 0, "y": 0, "width": 0, "height": 0, "wingSize": 0 } return {
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"wingSize": 0
};
} }
const barPosition = axis.edge === "left" ? 2 : (axis.edge === "right" ? 3 : (axis.edge === "top" ? 0 : 1)) const barPosition = axis.edge === "left" ? 2 : (axis.edge === "right" ? 3 : (axis.edge === "top" ? 0 : 1));
return SettingsData.getBarBounds(parentScreen, effectiveBarThickness, barPosition, barConfig) return SettingsData.getBarBounds(parentScreen, effectiveBarThickness, barPosition, barConfig);
} }
readonly property real barY: barBounds.y readonly property real barY: barBounds.y
readonly property real minTooltipY: { readonly property real minTooltipY: {
if (!parentScreen || !isVertical) { if (!parentScreen || !isVertical) {
return 0 return 0;
} }
if (isAutoHideBar) { if (isAutoHideBar) {
return 0 return 0;
} }
if (parentScreen.y > 0) { if (parentScreen.y > 0) {
return effectiveBarThickness return effectiveBarThickness;
} }
return 0 return 0;
} }
property int _desktopEntriesUpdateTrigger: 0 property int _desktopEntriesUpdateTrigger: 0
property int _toplevelsUpdateTrigger: 0 property int _toplevelsUpdateTrigger: 0
readonly property var sortedToplevels: { readonly property var sortedToplevels: {
_toplevelsUpdateTrigger _toplevelsUpdateTrigger;
const toplevels = CompositorService.sortedToplevels const toplevels = CompositorService.sortedToplevels;
if (!toplevels || toplevels.length === 0) return [] if (!toplevels || toplevels.length === 0)
return [];
if (SettingsData.runningAppsCurrentWorkspace) { if (SettingsData.runningAppsCurrentWorkspace) {
return CompositorService.filterCurrentWorkspace(toplevels, parentScreen?.name) || [] return CompositorService.filterCurrentWorkspace(toplevels, parentScreen?.name) || [];
} }
return toplevels return toplevels;
} }
Connections { Connections {
target: CompositorService target: CompositorService
function onToplevelsChanged() { function onToplevelsChanged() {
_toplevelsUpdateTrigger++ _toplevelsUpdateTrigger++;
} }
} }
Connections { Connections {
target: DesktopEntries target: DesktopEntries
function onApplicationsChanged() { function onApplicationsChanged() {
_desktopEntriesUpdateTrigger++ _desktopEntriesUpdateTrigger++;
} }
} }
readonly property var groupedWindows: { readonly property var groupedWindows: {
if (!SettingsData.runningAppsGroupByApp) { if (!SettingsData.runningAppsGroupByApp) {
return [] return [];
} }
try { try {
if (!sortedToplevels || sortedToplevels.length === 0) { if (!sortedToplevels || sortedToplevels.length === 0) {
return [] return [];
} }
const appGroups = new Map() const appGroups = new Map();
sortedToplevels.forEach((toplevel, index) => { sortedToplevels.forEach((toplevel, index) => {
if (!toplevel) if (!toplevel)
return return;
const appId = toplevel?.appId || "unknown" const appId = toplevel?.appId || "unknown";
if (!appGroups.has(appId)) { if (!appGroups.has(appId)) {
appGroups.set(appId, { appGroups.set(appId, {
"appId": appId, "appId": appId,
"windows": [] "windows": []
}) });
} }
appGroups.get(appId).windows.push({ appGroups.get(appId).windows.push({
"toplevel": toplevel, "toplevel": toplevel,
"windowId": index, "windowId": index,
"windowTitle": toplevel?.title || "(Unnamed)" "windowTitle": toplevel?.title || "(Unnamed)"
}) });
}) });
return Array.from(appGroups.values()) return Array.from(appGroups.values());
} catch (e) { } catch (e) {
return [] return [];
} }
} }
readonly property int windowCount: SettingsData.runningAppsGroupByApp ? (groupedWindows?.length || 0) : (sortedToplevels?.length || 0) readonly property int windowCount: SettingsData.runningAppsGroupByApp ? (groupedWindows?.length || 0) : (sortedToplevels?.length || 0)
readonly property int calculatedSize: { readonly property int calculatedSize: {
if (windowCount === 0) { if (windowCount === 0) {
return 0 return 0;
} }
if (SettingsData.runningAppsCompactMode) { if (SettingsData.runningAppsCompactMode) {
return windowCount * 24 + (windowCount - 1) * Theme.spacingXS + horizontalPadding * 2 return windowCount * 24 + (windowCount - 1) * Theme.spacingXS + horizontalPadding * 2;
} else { } else {
return windowCount * (24 + Theme.spacingXS + 120) + (windowCount - 1) * Theme.spacingXS + horizontalPadding * 2 return windowCount * (24 + Theme.spacingXS + 120) + (windowCount - 1) * Theme.spacingXS + horizontalPadding * 2;
} }
} }
@@ -133,7 +140,6 @@ Item {
height: windowCount > 0 ? (isVertical ? calculatedSize : barThickness) : 0 height: windowCount > 0 ? (isVertical ? calculatedSize : barThickness) : 0
visible: windowCount > 0 visible: windowCount > 0
Rectangle { Rectangle {
id: visualBackground id: visualBackground
width: root.isVertical ? root.widgetThickness : root.calculatedSize width: root.isVertical ? root.widgetThickness : root.calculatedSize
@@ -143,19 +149,19 @@ Item {
clip: false clip: false
color: { color: {
if (windowCount === 0) { if (windowCount === 0) {
return "transparent" return "transparent";
} }
if ((barConfig?.noBackground ?? false)) { if ((barConfig?.noBackground ?? false)) {
return "transparent" return "transparent";
} }
const baseColor = Theme.widgetBaseBackgroundColor const baseColor = Theme.widgetBaseBackgroundColor;
if (Theme.widgetBackgroundHasAlpha) { if (Theme.widgetBackgroundHasAlpha) {
return baseColor return baseColor;
} }
const transparency = (root.barConfig && root.barConfig.widgetTransparency !== undefined) ? root.barConfig.widgetTransparency : 1.0 const transparency = (root.barConfig && root.barConfig.widgetTransparency !== undefined) ? root.barConfig.widgetTransparency : 1.0;
return Theme.withAlpha(baseColor, transparency) return Theme.withAlpha(baseColor, transparency);
} }
} }
@@ -168,82 +174,82 @@ Item {
property real touchpadThreshold: 500 property real touchpadThreshold: 500
onWheel: wheel => { onWheel: wheel => {
const deltaY = wheel.angleDelta.y const deltaY = wheel.angleDelta.y;
const isMouseWheel = Math.abs(deltaY) >= 120 && (Math.abs(deltaY) % 120) === 0 const isMouseWheel = Math.abs(deltaY) >= 120 && (Math.abs(deltaY) % 120) === 0;
const windows = root.sortedToplevels const windows = root.sortedToplevels;
if (windows.length < 2) { if (windows.length < 2) {
return return;
} }
if (isMouseWheel) { if (isMouseWheel) {
// Direct mouse wheel action // Direct mouse wheel action
let currentIndex = -1 let currentIndex = -1;
for (var i = 0; i < windows.length; i++) { for (var i = 0; i < windows.length; i++) {
if (windows[i].activated) { if (windows[i].activated) {
currentIndex = i currentIndex = i;
break break;
} }
} }
let nextIndex let nextIndex;
if (deltaY < 0) { if (deltaY < 0) {
if (currentIndex === -1) { if (currentIndex === -1) {
nextIndex = 0 nextIndex = 0;
} else { } else {
nextIndex = Math.min(currentIndex + 1, windows.length - 1) nextIndex = Math.min(currentIndex + 1, windows.length - 1);
} }
} else { } else {
if (currentIndex === -1) { if (currentIndex === -1) {
nextIndex = windows.length - 1 nextIndex = windows.length - 1;
} else { } else {
nextIndex = Math.max(currentIndex - 1, 0) nextIndex = Math.max(currentIndex - 1, 0);
} }
} }
const nextWindow = windows[nextIndex] const nextWindow = windows[nextIndex];
if (nextWindow) { if (nextWindow) {
nextWindow.activate() nextWindow.activate();
} }
} else { } else {
// Touchpad - accumulate small deltas // Touchpad - accumulate small deltas
scrollAccumulator += deltaY scrollAccumulator += deltaY;
if (Math.abs(scrollAccumulator) >= touchpadThreshold) { if (Math.abs(scrollAccumulator) >= touchpadThreshold) {
let currentIndex = -1 let currentIndex = -1;
for (var i = 0; i < windows.length; i++) { for (var i = 0; i < windows.length; i++) {
if (windows[i].activated) { if (windows[i].activated) {
currentIndex = i currentIndex = i;
break break;
} }
} }
let nextIndex let nextIndex;
if (scrollAccumulator < 0) { if (scrollAccumulator < 0) {
if (currentIndex === -1) { if (currentIndex === -1) {
nextIndex = 0 nextIndex = 0;
} else { } else {
nextIndex = Math.min(currentIndex + 1, windows.length - 1) nextIndex = Math.min(currentIndex + 1, windows.length - 1);
} }
} else { } else {
if (currentIndex === -1) { if (currentIndex === -1) {
nextIndex = windows.length - 1 nextIndex = windows.length - 1;
} else { } else {
nextIndex = Math.max(currentIndex - 1, 0) nextIndex = Math.max(currentIndex - 1, 0);
} }
} }
const nextWindow = windows[nextIndex] const nextWindow = windows[nextIndex];
if (nextWindow) { if (nextWindow) {
nextWindow.activate() nextWindow.activate();
} }
scrollAccumulator = 0 scrollAccumulator = 0;
} }
} }
wheel.accepted = true wheel.accepted = true;
} }
} }
Loader { Loader {
@@ -276,16 +282,14 @@ Item {
property var toplevelObject: toplevelData property var toplevelObject: toplevelData
property int windowCount: isGrouped ? modelData.windows.length : 1 property int windowCount: isGrouped ? modelData.windows.length : 1
property string tooltipText: { property string tooltipText: {
root._desktopEntriesUpdateTrigger root._desktopEntriesUpdateTrigger;
let appName = "Unknown" const desktopEntry = appId ? DesktopEntries.heuristicLookup(appId) : null;
if (appId) { const appName = appId ? Paths.getAppName(appId, desktopEntry) : "Unknown";
const desktopEntry = DesktopEntries.heuristicLookup(appId)
appName = desktopEntry && desktopEntry.name ? desktopEntry.name : appId
}
if (isGrouped && windowCount > 1) { if (isGrouped && windowCount > 1) {
return appName + " (" + windowCount + " windows)" return appName + " (" + windowCount + " windows)";
} }
return appName + (windowTitle ? " • " + windowTitle : "") return appName + (windowTitle ? " • " + windowTitle : "");
} }
readonly property real visualWidth: SettingsData.runningAppsCompactMode ? 24 : (24 + Theme.spacingXS + 120) readonly property real visualWidth: SettingsData.runningAppsCompactMode ? 24 : (24 + Theme.spacingXS + 120)
@@ -300,9 +304,9 @@ Item {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
if (isFocused) { if (isFocused) {
return mouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) return mouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2);
} else { } else {
return mouseArea.containsMouse ? Qt.rgba(Theme.primaryHover.r, Theme.primaryHover.g, Theme.primaryHover.b, 0.1) : "transparent" return mouseArea.containsMouse ? Qt.rgba(Theme.primaryHover.r, Theme.primaryHover.g, Theme.primaryHover.b, 0.1) : "transparent";
} }
} }
@@ -315,17 +319,24 @@ Item {
width: Theme.barIconSize(root.barThickness) width: Theme.barIconSize(root.barThickness)
height: Theme.barIconSize(root.barThickness) height: Theme.barIconSize(root.barThickness)
source: { source: {
root._desktopEntriesUpdateTrigger root._desktopEntriesUpdateTrigger;
const moddedId = Paths.moddedAppId(appId) if (!appId)
if (moddedId.toLowerCase().includes("steam_app")) { return "";
return "" const desktopEntry = DesktopEntries.heuristicLookup(appId);
} return Paths.getAppIcon(appId, desktopEntry);
return Quickshell.iconPath(DesktopEntries.heuristicLookup(moddedId)?.icon, true)
} }
smooth: true smooth: true
mipmap: true mipmap: true
asynchronous: true asynchronous: true
visible: status === Image.Ready visible: status === Image.Ready
layer.enabled: appId === "org.quickshell"
layer.smooth: true
layer.mipmap: true
layer.effect: MultiEffect {
saturation: 0
colorization: 1
colorizationColor: Theme.primary
}
} }
DankIcon { DankIcon {
@@ -336,8 +347,8 @@ Item {
name: "sports_esports" name: "sports_esports"
color: Theme.widgetTextColor color: Theme.widgetTextColor
visible: { visible: {
const moddedId = Paths.moddedAppId(appId) const moddedId = Paths.moddedAppId(appId);
return moddedId.toLowerCase().includes("steam_app") return moddedId.toLowerCase().includes("steam_app");
} }
} }
@@ -345,22 +356,18 @@ Item {
Text { Text {
anchors.centerIn: parent anchors.centerIn: parent
visible: { visible: {
const moddedId = Paths.moddedAppId(appId) const moddedId = Paths.moddedAppId(appId);
const isSteamApp = moddedId.toLowerCase().includes("steam_app") const isSteamApp = moddedId.toLowerCase().includes("steam_app");
return !iconImg.visible && !isSteamApp return !iconImg.visible && !isSteamApp;
} }
text: { text: {
root._desktopEntriesUpdateTrigger root._desktopEntriesUpdateTrigger;
if (!appId) { if (!appId)
return "?" return "?";
}
const desktopEntry = DesktopEntries.heuristicLookup(appId) const desktopEntry = DesktopEntries.heuristicLookup(appId);
if (desktopEntry && desktopEntry.name) { const appName = Paths.getAppName(appId, desktopEntry);
return desktopEntry.name.charAt(0).toUpperCase() return appName.charAt(0).toUpperCase();
}
return appId.charAt(0).toUpperCase()
} }
font.pixelSize: 10 font.pixelSize: 10
color: Theme.widgetTextColor color: Theme.widgetTextColor
@@ -409,86 +416,84 @@ Item {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: mouse => { onClicked: mouse => {
if (mouse.button === Qt.LeftButton) { if (mouse.button === Qt.LeftButton) {
if (isGrouped && windowCount > 1) { if (isGrouped && windowCount > 1) {
let currentIndex = -1 let currentIndex = -1;
for (var i = 0; i < groupData.windows.length; i++) { for (var i = 0; i < groupData.windows.length; i++) {
if (groupData.windows[i].toplevel.activated) { if (groupData.windows[i].toplevel.activated) {
currentIndex = i currentIndex = i;
break break;
} }
} }
const nextIndex = (currentIndex + 1) % groupData.windows.length const nextIndex = (currentIndex + 1) % groupData.windows.length;
groupData.windows[nextIndex].toplevel.activate() groupData.windows[nextIndex].toplevel.activate();
} else if (toplevelObject) { } else if (toplevelObject) {
toplevelObject.activate() toplevelObject.activate();
} }
} else if (mouse.button === Qt.RightButton) { } else if (mouse.button === Qt.RightButton) {
if (tooltipLoader.item) { if (tooltipLoader.item) {
tooltipLoader.item.hide() tooltipLoader.item.hide();
} }
tooltipLoader.active = false tooltipLoader.active = false;
windowContextMenuLoader.active = true windowContextMenuLoader.active = true;
if (windowContextMenuLoader.item) { if (windowContextMenuLoader.item) {
windowContextMenuLoader.item.currentWindow = toplevelObject windowContextMenuLoader.item.currentWindow = toplevelObject;
// Pass bar context // Pass bar context
windowContextMenuLoader.item.triggerBarConfig = root.barConfig windowContextMenuLoader.item.triggerBarConfig = root.barConfig;
windowContextMenuLoader.item.triggerBarPosition = root.axis.edge === "left" ? 2 : (root.axis.edge === "right" ? 3 : (root.axis.edge === "top" ? 0 : 1)) windowContextMenuLoader.item.triggerBarPosition = root.axis.edge === "left" ? 2 : (root.axis.edge === "right" ? 3 : (root.axis.edge === "top" ? 0 : 1));
windowContextMenuLoader.item.triggerBarThickness = root.barThickness windowContextMenuLoader.item.triggerBarThickness = root.barThickness;
windowContextMenuLoader.item.triggerBarSpacing = root.barSpacing windowContextMenuLoader.item.triggerBarSpacing = root.barSpacing;
if (root.isVertical) { if (root.isVertical) {
const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, delegateItem.height / 2) const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, delegateItem.height / 2);
const screenX = root.parentScreen ? root.parentScreen.x : 0 const screenX = root.parentScreen ? root.parentScreen.x : 0;
const screenY = root.parentScreen ? root.parentScreen.y : 0 const screenY = root.parentScreen ? root.parentScreen.y : 0;
const relativeY = globalPos.y - screenY const relativeY = globalPos.y - screenY;
// Add minTooltipY offset to account for top bar // Add minTooltipY offset to account for top bar
const adjustedY = relativeY + root.minTooltipY const adjustedY = relativeY + root.minTooltipY;
const xPos = root.axis?.edge === "left" ? (root.barThickness + root.barSpacing + Theme.spacingXS) : (root.parentScreen.width - root.barThickness - root.barSpacing - Theme.spacingXS) const xPos = root.axis?.edge === "left" ? (root.barThickness + root.barSpacing + Theme.spacingXS) : (root.parentScreen.width - root.barThickness - root.barSpacing - Theme.spacingXS);
windowContextMenuLoader.item.showAt(xPos, adjustedY, true, root.axis?.edge) windowContextMenuLoader.item.showAt(xPos, adjustedY, true, root.axis?.edge);
} else { } else {
const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, 0) const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, 0);
const screenX = root.parentScreen ? root.parentScreen.x : 0 const screenX = root.parentScreen ? root.parentScreen.x : 0;
const relativeX = globalPos.x - screenX const relativeX = globalPos.x - screenX;
const yPos = root.barThickness + root.barSpacing - 7 const yPos = root.barThickness + root.barSpacing - 7;
windowContextMenuLoader.item.showAt(relativeX, yPos, false, "top") windowContextMenuLoader.item.showAt(relativeX, yPos, false, "top");
} }
} }
} }
} }
onEntered: { onEntered: {
root.hoveredItem = delegateItem root.hoveredItem = delegateItem;
tooltipLoader.active = true tooltipLoader.active = true;
if (tooltipLoader.item) { if (tooltipLoader.item) {
if (root.isVertical) { if (root.isVertical) {
const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, delegateItem.height / 2) const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, delegateItem.height / 2);
const screenX = root.parentScreen ? root.parentScreen.x : 0 const screenX = root.parentScreen ? root.parentScreen.x : 0;
const screenY = root.parentScreen ? root.parentScreen.y : 0 const screenY = root.parentScreen ? root.parentScreen.y : 0;
const relativeY = globalPos.y - screenY const relativeY = globalPos.y - screenY;
const tooltipX = root.axis?.edge === "left" ? (Theme.barHeight + (barConfig?.spacing ?? 4) + Theme.spacingXS) : (root.parentScreen.width - Theme.barHeight - (barConfig?.spacing ?? 4) - Theme.spacingXS) const tooltipX = root.axis?.edge === "left" ? (Theme.barHeight + (barConfig?.spacing ?? 4) + Theme.spacingXS) : (root.parentScreen.width - Theme.barHeight - (barConfig?.spacing ?? 4) - Theme.spacingXS);
const isLeft = root.axis?.edge === "left" const isLeft = root.axis?.edge === "left";
const adjustedY = relativeY + root.minTooltipY const adjustedY = relativeY + root.minTooltipY;
const finalX = screenX + tooltipX const finalX = screenX + tooltipX;
tooltipLoader.item.show(delegateItem.tooltipText, finalX, adjustedY, root.parentScreen, isLeft, !isLeft) tooltipLoader.item.show(delegateItem.tooltipText, finalX, adjustedY, root.parentScreen, isLeft, !isLeft);
} else { } else {
const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, delegateItem.height) const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, delegateItem.height);
const screenHeight = root.parentScreen ? root.parentScreen.height : Screen.height const screenHeight = root.parentScreen ? root.parentScreen.height : Screen.height;
const isBottom = root.axis?.edge === "bottom" const isBottom = root.axis?.edge === "bottom";
const tooltipY = isBottom const tooltipY = isBottom ? (screenHeight - Theme.barHeight - (barConfig?.spacing ?? 4) - Theme.spacingXS - 35) : (Theme.barHeight + (barConfig?.spacing ?? 4) + Theme.spacingXS);
? (screenHeight - Theme.barHeight - (barConfig?.spacing ?? 4) - Theme.spacingXS - 35) tooltipLoader.item.show(delegateItem.tooltipText, globalPos.x, tooltipY, root.parentScreen, false, false);
: (Theme.barHeight + (barConfig?.spacing ?? 4) + Theme.spacingXS)
tooltipLoader.item.show(delegateItem.tooltipText, globalPos.x, tooltipY, root.parentScreen, false, false)
} }
} }
} }
onExited: { onExited: {
if (root.hoveredItem === delegateItem) { if (root.hoveredItem === delegateItem) {
root.hoveredItem = null root.hoveredItem = null;
if (tooltipLoader.item) { if (tooltipLoader.item) {
tooltipLoader.item.hide() tooltipLoader.item.hide();
} }
tooltipLoader.active = false tooltipLoader.active = false;
} }
} }
} }
@@ -521,16 +526,14 @@ Item {
property var toplevelObject: toplevelData property var toplevelObject: toplevelData
property int windowCount: isGrouped ? modelData.windows.length : 1 property int windowCount: isGrouped ? modelData.windows.length : 1
property string tooltipText: { property string tooltipText: {
root._desktopEntriesUpdateTrigger root._desktopEntriesUpdateTrigger;
let appName = "Unknown" const desktopEntry = appId ? DesktopEntries.heuristicLookup(appId) : null;
if (appId) { const appName = appId ? Paths.getAppName(appId, desktopEntry) : "Unknown";
const desktopEntry = DesktopEntries.heuristicLookup(appId)
appName = desktopEntry && desktopEntry.name ? desktopEntry.name : appId
}
if (isGrouped && windowCount > 1) { if (isGrouped && windowCount > 1) {
return appName + " (" + windowCount + " windows)" return appName + " (" + windowCount + " windows)";
} }
return appName + (windowTitle ? " • " + windowTitle : "") return appName + (windowTitle ? " • " + windowTitle : "");
} }
readonly property real visualWidth: SettingsData.runningAppsCompactMode ? 24 : (24 + Theme.spacingXS + 120) readonly property real visualWidth: SettingsData.runningAppsCompactMode ? 24 : (24 + Theme.spacingXS + 120)
@@ -545,9 +548,9 @@ Item {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
if (isFocused) { if (isFocused) {
return mouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) return mouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2);
} else { } else {
return mouseArea.containsMouse ? Qt.rgba(Theme.primaryHover.r, Theme.primaryHover.g, Theme.primaryHover.b, 0.1) : "transparent" return mouseArea.containsMouse ? Qt.rgba(Theme.primaryHover.r, Theme.primaryHover.g, Theme.primaryHover.b, 0.1) : "transparent";
} }
} }
@@ -559,17 +562,24 @@ Item {
width: Theme.barIconSize(root.barThickness) width: Theme.barIconSize(root.barThickness)
height: Theme.barIconSize(root.barThickness) height: Theme.barIconSize(root.barThickness)
source: { source: {
root._desktopEntriesUpdateTrigger root._desktopEntriesUpdateTrigger;
const moddedId = Paths.moddedAppId(appId) if (!appId)
if (moddedId.toLowerCase().includes("steam_app")) { return "";
return "" const desktopEntry = DesktopEntries.heuristicLookup(appId);
} return Paths.getAppIcon(appId, desktopEntry);
return Quickshell.iconPath(DesktopEntries.heuristicLookup(moddedId)?.icon, true)
} }
smooth: true smooth: true
mipmap: true mipmap: true
asynchronous: true asynchronous: true
visible: status === Image.Ready visible: status === Image.Ready
layer.enabled: appId === "org.quickshell"
layer.smooth: true
layer.mipmap: true
layer.effect: MultiEffect {
saturation: 0
colorization: 1
colorizationColor: Theme.primary
}
} }
DankIcon { DankIcon {
@@ -580,30 +590,26 @@ Item {
name: "sports_esports" name: "sports_esports"
color: Theme.widgetTextColor color: Theme.widgetTextColor
visible: { visible: {
const moddedId = Paths.moddedAppId(appId) const moddedId = Paths.moddedAppId(appId);
return moddedId.toLowerCase().includes("steam_app") return moddedId.toLowerCase().includes("steam_app");
} }
} }
Text { Text {
anchors.centerIn: parent anchors.centerIn: parent
visible: { visible: {
const moddedId = Paths.moddedAppId(appId) const moddedId = Paths.moddedAppId(appId);
const isSteamApp = moddedId.toLowerCase().includes("steam_app") const isSteamApp = moddedId.toLowerCase().includes("steam_app");
return !iconImg.visible && !isSteamApp return !iconImg.visible && !isSteamApp;
} }
text: { text: {
root._desktopEntriesUpdateTrigger root._desktopEntriesUpdateTrigger;
if (!appId) { if (!appId)
return "?" return "?";
}
const desktopEntry = DesktopEntries.heuristicLookup(appId) const desktopEntry = DesktopEntries.heuristicLookup(appId);
if (desktopEntry && desktopEntry.name) { const appName = Paths.getAppName(appId, desktopEntry);
return desktopEntry.name.charAt(0).toUpperCase() return appName.charAt(0).toUpperCase();
}
return appId.charAt(0).toUpperCase()
} }
font.pixelSize: 10 font.pixelSize: 10
color: Theme.widgetTextColor color: Theme.widgetTextColor
@@ -651,86 +657,84 @@ Item {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: mouse => { onClicked: mouse => {
if (mouse.button === Qt.LeftButton) { if (mouse.button === Qt.LeftButton) {
if (isGrouped && windowCount > 1) { if (isGrouped && windowCount > 1) {
let currentIndex = -1 let currentIndex = -1;
for (var i = 0; i < groupData.windows.length; i++) { for (var i = 0; i < groupData.windows.length; i++) {
if (groupData.windows[i].toplevel.activated) { if (groupData.windows[i].toplevel.activated) {
currentIndex = i currentIndex = i;
break break;
} }
} }
const nextIndex = (currentIndex + 1) % groupData.windows.length const nextIndex = (currentIndex + 1) % groupData.windows.length;
groupData.windows[nextIndex].toplevel.activate() groupData.windows[nextIndex].toplevel.activate();
} else if (toplevelObject) { } else if (toplevelObject) {
toplevelObject.activate() toplevelObject.activate();
} }
} else if (mouse.button === Qt.RightButton) { } else if (mouse.button === Qt.RightButton) {
if (tooltipLoader.item) { if (tooltipLoader.item) {
tooltipLoader.item.hide() tooltipLoader.item.hide();
} }
tooltipLoader.active = false tooltipLoader.active = false;
windowContextMenuLoader.active = true windowContextMenuLoader.active = true;
if (windowContextMenuLoader.item) { if (windowContextMenuLoader.item) {
windowContextMenuLoader.item.currentWindow = toplevelObject windowContextMenuLoader.item.currentWindow = toplevelObject;
// Pass bar context // Pass bar context
windowContextMenuLoader.item.triggerBarConfig = root.barConfig windowContextMenuLoader.item.triggerBarConfig = root.barConfig;
windowContextMenuLoader.item.triggerBarPosition = root.axis.edge === "left" ? 2 : (root.axis.edge === "right" ? 3 : (root.axis.edge === "top" ? 0 : 1)) windowContextMenuLoader.item.triggerBarPosition = root.axis.edge === "left" ? 2 : (root.axis.edge === "right" ? 3 : (root.axis.edge === "top" ? 0 : 1));
windowContextMenuLoader.item.triggerBarThickness = root.barThickness windowContextMenuLoader.item.triggerBarThickness = root.barThickness;
windowContextMenuLoader.item.triggerBarSpacing = root.barSpacing windowContextMenuLoader.item.triggerBarSpacing = root.barSpacing;
if (root.isVertical) { if (root.isVertical) {
const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, delegateItem.height / 2) const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, delegateItem.height / 2);
const screenX = root.parentScreen ? root.parentScreen.x : 0 const screenX = root.parentScreen ? root.parentScreen.x : 0;
const screenY = root.parentScreen ? root.parentScreen.y : 0 const screenY = root.parentScreen ? root.parentScreen.y : 0;
const relativeY = globalPos.y - screenY const relativeY = globalPos.y - screenY;
// Add minTooltipY offset to account for top bar // Add minTooltipY offset to account for top bar
const adjustedY = relativeY + root.minTooltipY const adjustedY = relativeY + root.minTooltipY;
const xPos = root.axis?.edge === "left" ? (root.barThickness + root.barSpacing + Theme.spacingXS) : (root.parentScreen.width - root.barThickness - root.barSpacing - Theme.spacingXS) const xPos = root.axis?.edge === "left" ? (root.barThickness + root.barSpacing + Theme.spacingXS) : (root.parentScreen.width - root.barThickness - root.barSpacing - Theme.spacingXS);
windowContextMenuLoader.item.showAt(xPos, adjustedY, true, root.axis?.edge) windowContextMenuLoader.item.showAt(xPos, adjustedY, true, root.axis?.edge);
} else { } else {
const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, 0) const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, 0);
const screenX = root.parentScreen ? root.parentScreen.x : 0 const screenX = root.parentScreen ? root.parentScreen.x : 0;
const relativeX = globalPos.x - screenX const relativeX = globalPos.x - screenX;
const yPos = root.barThickness + root.barSpacing - 7 const yPos = root.barThickness + root.barSpacing - 7;
windowContextMenuLoader.item.showAt(relativeX, yPos, false, "top") windowContextMenuLoader.item.showAt(relativeX, yPos, false, "top");
} }
} }
} }
} }
onEntered: { onEntered: {
root.hoveredItem = delegateItem root.hoveredItem = delegateItem;
tooltipLoader.active = true tooltipLoader.active = true;
if (tooltipLoader.item) { if (tooltipLoader.item) {
if (root.isVertical) { if (root.isVertical) {
const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, delegateItem.height / 2) const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, delegateItem.height / 2);
const screenX = root.parentScreen ? root.parentScreen.x : 0 const screenX = root.parentScreen ? root.parentScreen.x : 0;
const screenY = root.parentScreen ? root.parentScreen.y : 0 const screenY = root.parentScreen ? root.parentScreen.y : 0;
const relativeY = globalPos.y - screenY const relativeY = globalPos.y - screenY;
const tooltipX = root.axis?.edge === "left" ? (root.barThickness + root.barSpacing + Theme.spacingXS) : (root.parentScreen.width - root.barThickness - root.barSpacing - Theme.spacingXS) const tooltipX = root.axis?.edge === "left" ? (root.barThickness + root.barSpacing + Theme.spacingXS) : (root.parentScreen.width - root.barThickness - root.barSpacing - Theme.spacingXS);
const isLeft = root.axis?.edge === "left" const isLeft = root.axis?.edge === "left";
const adjustedY = relativeY + root.minTooltipY const adjustedY = relativeY + root.minTooltipY;
const finalX = screenX + tooltipX const finalX = screenX + tooltipX;
tooltipLoader.item.show(delegateItem.tooltipText, finalX, adjustedY, root.parentScreen, isLeft, !isLeft) tooltipLoader.item.show(delegateItem.tooltipText, finalX, adjustedY, root.parentScreen, isLeft, !isLeft);
} else { } else {
const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, delegateItem.height) const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, delegateItem.height);
const screenHeight = root.parentScreen ? root.parentScreen.height : Screen.height const screenHeight = root.parentScreen ? root.parentScreen.height : Screen.height;
const isBottom = root.axis?.edge === "bottom" const isBottom = root.axis?.edge === "bottom";
const tooltipY = isBottom const tooltipY = isBottom ? (screenHeight - root.barThickness - root.barSpacing - Theme.spacingXS - 35) : (root.barThickness + root.barSpacing + Theme.spacingXS);
? (screenHeight - root.barThickness - root.barSpacing - Theme.spacingXS - 35) tooltipLoader.item.show(delegateItem.tooltipText, globalPos.x, tooltipY, root.parentScreen, false, false);
: (root.barThickness + root.barSpacing + Theme.spacingXS)
tooltipLoader.item.show(delegateItem.tooltipText, globalPos.x, tooltipY, root.parentScreen, false, false)
} }
} }
} }
onExited: { onExited: {
if (root.hoveredItem === delegateItem) { if (root.hoveredItem === delegateItem) {
root.hoveredItem = null root.hoveredItem = null;
if (tooltipLoader.item) { if (tooltipLoader.item) {
tooltipLoader.item.hide() tooltipLoader.item.hide();
} }
tooltipLoader.active = false tooltipLoader.active = false;
} }
} }
} }
@@ -767,33 +771,39 @@ Item {
readonly property real effectiveBarThickness: { readonly property real effectiveBarThickness: {
if (triggerBarThickness > 0 && triggerBarSpacing > 0) { if (triggerBarThickness > 0 && triggerBarSpacing > 0) {
return triggerBarThickness + triggerBarSpacing return triggerBarThickness + triggerBarSpacing;
} }
return Math.max(26 + (barConfig?.innerPadding ?? 4) * 0.6, Theme.barHeight - 4 - (8 - (barConfig?.innerPadding ?? 4))) + (barConfig?.spacing ?? 4) return Math.max(26 + (barConfig?.innerPadding ?? 4) * 0.6, Theme.barHeight - 4 - (8 - (barConfig?.innerPadding ?? 4))) + (barConfig?.spacing ?? 4);
} }
property var barBounds: { property var barBounds: {
if (!contextMenuWindow.screen || !triggerBarConfig) { if (!contextMenuWindow.screen || !triggerBarConfig) {
return { "x": 0, "y": 0, "width": 0, "height": 0, "wingSize": 0 } return {
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"wingSize": 0
};
} }
return SettingsData.getBarBounds(contextMenuWindow.screen, effectiveBarThickness, triggerBarPosition, triggerBarConfig) return SettingsData.getBarBounds(contextMenuWindow.screen, effectiveBarThickness, triggerBarPosition, triggerBarConfig);
} }
property real barY: barBounds.y property real barY: barBounds.y
function showAt(x, y, vertical, barEdge) { function showAt(x, y, vertical, barEdge) {
screen = root.parentScreen screen = root.parentScreen;
anchorPos = Qt.point(x, y) anchorPos = Qt.point(x, y);
isVertical = vertical ?? false isVertical = vertical ?? false;
edge = barEdge ?? "top" edge = barEdge ?? "top";
isVisible = true isVisible = true;
visible = true visible = true;
} }
function close() { function close() {
isVisible = false isVisible = false;
visible = false visible = false;
windowContextMenuLoader.active = false windowContextMenuLoader.active = false;
} }
implicitWidth: 100 implicitWidth: 100
@@ -821,25 +831,25 @@ Item {
x: { x: {
if (contextMenuWindow.isVertical) { if (contextMenuWindow.isVertical) {
if (contextMenuWindow.edge === "left") { if (contextMenuWindow.edge === "left") {
return Math.min(contextMenuWindow.width - width - 10, contextMenuWindow.anchorPos.x) return Math.min(contextMenuWindow.width - width - 10, contextMenuWindow.anchorPos.x);
} else { } else {
return Math.max(10, contextMenuWindow.anchorPos.x - width) return Math.max(10, contextMenuWindow.anchorPos.x - width);
} }
} else { } else {
const left = 10 const left = 10;
const right = contextMenuWindow.width - width - 10 const right = contextMenuWindow.width - width - 10;
const want = contextMenuWindow.anchorPos.x - width / 2 const want = contextMenuWindow.anchorPos.x - width / 2;
return Math.max(left, Math.min(right, want)) return Math.max(left, Math.min(right, want));
} }
} }
y: { y: {
if (contextMenuWindow.isVertical) { if (contextMenuWindow.isVertical) {
const top = Math.max(barY, 10) const top = Math.max(barY, 10);
const bottom = contextMenuWindow.height - height - 10 const bottom = contextMenuWindow.height - height - 10;
const want = contextMenuWindow.anchorPos.y - height / 2 const want = contextMenuWindow.anchorPos.y - height / 2;
return Math.max(top, Math.min(bottom, want)) return Math.max(top, Math.min(bottom, want));
} else { } else {
return contextMenuWindow.anchorPos.y return contextMenuWindow.anchorPos.y;
} }
} }
width: 100 width: 100
@@ -869,9 +879,9 @@ Item {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (contextMenuWindow.currentWindow) { if (contextMenuWindow.currentWindow) {
contextMenuWindow.currentWindow.close() contextMenuWindow.currentWindow.close();
} }
contextMenuWindow.close() contextMenuWindow.close();
} }
} }
} }

View File

@@ -1,8 +1,7 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Effects
import Quickshell import Quickshell
import Quickshell.Wayland import Quickshell.Wayland
import Quickshell.Hyprland
import Quickshell.Widgets import Quickshell.Widgets
import qs.Common import qs.Common
import qs.Services import qs.Services
@@ -32,11 +31,11 @@ Item {
function updateDesktopEntry() { function updateDesktopEntry() {
if (!appData || appData.appId === "__SEPARATOR__") { if (!appData || appData.appId === "__SEPARATOR__") {
cachedDesktopEntry = null cachedDesktopEntry = null;
return return;
} }
const moddedId = Paths.moddedAppId(appData.appId) const moddedId = Paths.moddedAppId(appData.appId);
cachedDesktopEntry = DesktopEntries.heuristicLookup(moddedId) cachedDesktopEntry = DesktopEntries.heuristicLookup(moddedId);
} }
Component.onCompleted: updateDesktopEntry() Component.onCompleted: updateDesktopEntry()
@@ -46,80 +45,81 @@ Item {
Connections { Connections {
target: DesktopEntries target: DesktopEntries
function onApplicationsChanged() { function onApplicationsChanged() {
updateDesktopEntry() updateDesktopEntry();
} }
} }
property bool isWindowFocused: { property bool isWindowFocused: {
if (!appData) { if (!appData) {
return false return false;
} }
if (appData.type === "window") { if (appData.type === "window") {
const toplevel = getToplevelObject() const toplevel = getToplevelObject();
if (!toplevel) { if (!toplevel) {
return false return false;
} }
return toplevel.activated return toplevel.activated;
} else if (appData.type === "grouped") { } else if (appData.type === "grouped") {
// For grouped apps, check if any window is focused // For grouped apps, check if any window is focused
const allToplevels = ToplevelManager.toplevels.values const allToplevels = ToplevelManager.toplevels.values;
for (let i = 0; i < allToplevels.length; i++) { for (let i = 0; i < allToplevels.length; i++) {
const toplevel = allToplevels[i] const toplevel = allToplevels[i];
if (toplevel.appId === appData.appId && toplevel.activated) { if (toplevel.appId === appData.appId && toplevel.activated) {
return true return true;
} }
} }
} }
return false return false;
} }
property string tooltipText: { property string tooltipText: {
if (!appData) { if (!appData || !appData.appId) {
return "" return "";
} }
const appName = Paths.getAppName(appData.appId, cachedDesktopEntry);
if ((appData.type === "window" && showWindowTitle) || (appData.type === "grouped" && appData.windowTitle)) { if ((appData.type === "window" && showWindowTitle) || (appData.type === "grouped" && appData.windowTitle)) {
const appName = cachedDesktopEntry && cachedDesktopEntry.name ? cachedDesktopEntry.name : appData.appId const title = appData.type === "window" ? windowTitle : appData.windowTitle;
const title = appData.type === "window" ? windowTitle : appData.windowTitle return appName + (title ? "" + title : "");
return appName + (title ? " • " + title : "")
} }
if (!appData.appId) { return appName;
return ""
}
return cachedDesktopEntry && cachedDesktopEntry.name ? cachedDesktopEntry.name : appData.appId
} }
function getToplevelObject() { function getToplevelObject() {
return appData?.toplevel || null return appData?.toplevel || null;
} }
function getGroupedToplevels() { function getGroupedToplevels() {
return appData?.allWindows?.map(w => w.toplevel).filter(t => t !== null) || [] return appData?.allWindows?.map(w => w.toplevel).filter(t => t !== null) || [];
} }
onIsHoveredChanged: { onIsHoveredChanged: {
if (mouseArea.pressed) return if (mouseArea.pressed)
return;
if (isHovered) { if (isHovered) {
exitAnimation.stop() exitAnimation.stop();
if (!bounceAnimation.running) { if (!bounceAnimation.running) {
bounceAnimation.restart() bounceAnimation.restart();
} }
} else { } else {
bounceAnimation.stop() bounceAnimation.stop();
exitAnimation.restart() exitAnimation.restart();
} }
} }
readonly property bool animateX: SettingsData.dockPosition === SettingsData.Position.Left || SettingsData.dockPosition === SettingsData.Position.Right readonly property bool animateX: SettingsData.dockPosition === SettingsData.Position.Left || SettingsData.dockPosition === SettingsData.Position.Right
readonly property real animationDistance: actualIconSize readonly property real animationDistance: actualIconSize
readonly property real animationDirection: { readonly property real animationDirection: {
if (SettingsData.dockPosition === SettingsData.Position.Bottom) return -1 if (SettingsData.dockPosition === SettingsData.Position.Bottom)
if (SettingsData.dockPosition === SettingsData.Position.Top) return 1 return -1;
if (SettingsData.dockPosition === SettingsData.Position.Right) return -1 if (SettingsData.dockPosition === SettingsData.Position.Top)
if (SettingsData.dockPosition === SettingsData.Position.Left) return 1 return 1;
return -1 if (SettingsData.dockPosition === SettingsData.Position.Right)
return -1;
if (SettingsData.dockPosition === SettingsData.Position.Left)
return 1;
return -1;
} }
SequentialAnimation { SequentialAnimation {
@@ -165,7 +165,7 @@ Item {
repeat: false repeat: false
onTriggered: { onTriggered: {
if (appData && appData.isPinned) { if (appData && appData.isPinned) {
longPressing = true longPressing = true;
} }
} }
} }
@@ -180,134 +180,134 @@ Item {
cursorShape: longPressing ? Qt.DragMoveCursor : Qt.PointingHandCursor cursorShape: longPressing ? Qt.DragMoveCursor : Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
onPressed: mouse => { onPressed: mouse => {
if (mouse.button === Qt.LeftButton && appData && appData.isPinned) { if (mouse.button === Qt.LeftButton && appData && appData.isPinned) {
dragStartPos = Qt.point(mouse.x, mouse.y) dragStartPos = Qt.point(mouse.x, mouse.y);
longPressTimer.start() longPressTimer.start();
} }
} }
onReleased: mouse => { onReleased: mouse => {
longPressTimer.stop() longPressTimer.stop();
if (longPressing) { if (longPressing) {
if (dragging && targetIndex >= 0 && targetIndex !== originalIndex && dockApps) { if (dragging && targetIndex >= 0 && targetIndex !== originalIndex && dockApps) {
dockApps.movePinnedApp(originalIndex, targetIndex) dockApps.movePinnedApp(originalIndex, targetIndex);
} }
longPressing = false longPressing = false;
dragging = false dragging = false;
dragOffset = Qt.point(0, 0) dragOffset = Qt.point(0, 0);
targetIndex = -1 targetIndex = -1;
originalIndex = -1 originalIndex = -1;
}
}
onPositionChanged: mouse => {
if (longPressing && !dragging) {
const distance = Math.sqrt(Math.pow(mouse.x - dragStartPos.x, 2) + Math.pow(mouse.y - dragStartPos.y, 2));
if (distance > 5) {
dragging = true;
targetIndex = index;
originalIndex = index;
}
}
if (dragging) {
dragOffset = Qt.point(mouse.x - dragStartPos.x, mouse.y - dragStartPos.y);
if (dockApps) {
const threshold = actualIconSize;
let newTargetIndex = targetIndex;
if (dragOffset.x > threshold && targetIndex < dockApps.pinnedAppCount - 1) {
newTargetIndex = targetIndex + 1;
} else if (dragOffset.x < -threshold && targetIndex > 0) {
newTargetIndex = targetIndex - 1;
}
if (newTargetIndex !== targetIndex) {
targetIndex = newTargetIndex;
dragStartPos = Qt.point(mouse.x, mouse.y);
}
}
}
}
onClicked: mouse => {
if (!appData || longPressing) {
return;
}
if (mouse.button === Qt.LeftButton) {
if (appData.type === "pinned") {
if (appData && appData.appId) {
const desktopEntry = cachedDesktopEntry;
if (desktopEntry) {
AppUsageHistoryData.addAppUsage({
"id": appData.appId,
"name": desktopEntry.name || appData.appId,
"icon": desktopEntry.icon || "",
"exec": desktopEntry.exec || "",
"comment": desktopEntry.comment || ""
});
}
SessionService.launchDesktopEntry(desktopEntry);
}
} else if (appData.type === "window") {
const toplevel = getToplevelObject();
if (toplevel) {
toplevel.activate();
}
} else if (appData.type === "grouped") {
if (appData.windowCount === 0) {
if (appData && appData.appId) {
const desktopEntry = cachedDesktopEntry;
if (desktopEntry) {
AppUsageHistoryData.addAppUsage({
"id": appData.appId,
"name": desktopEntry.name || appData.appId,
"icon": desktopEntry.icon || "",
"exec": desktopEntry.exec || "",
"comment": desktopEntry.comment || ""
});
}
SessionService.launchDesktopEntry(desktopEntry);
}
} else if (appData.windowCount === 1) {
// For single window, activate directly
const toplevel = getToplevelObject();
if (toplevel) {
console.log("Activating grouped app window:", appData.windowTitle);
toplevel.activate();
} else {
console.warn("No toplevel found for grouped app");
}
} else {
if (contextMenu) {
contextMenu.showForButton(root, appData, root.height + 25, true, cachedDesktopEntry, parentDockScreen);
} }
} }
onPositionChanged: mouse => { }
if (longPressing && !dragging) { } else if (mouse.button === Qt.MiddleButton) {
const distance = Math.sqrt(Math.pow(mouse.x - dragStartPos.x, 2) + Math.pow(mouse.y - dragStartPos.y, 2)) if (appData?.type === "window") {
if (distance > 5) { appData?.toplevel?.close();
dragging = true } else if (appData?.type === "grouped") {
targetIndex = index if (contextMenu) {
originalIndex = index contextMenu.showForButton(root, appData, root.height, false, cachedDesktopEntry, parentDockScreen);
} }
} } else if (appData && appData.appId) {
if (dragging) { const desktopEntry = cachedDesktopEntry;
dragOffset = Qt.point(mouse.x - dragStartPos.x, mouse.y - dragStartPos.y) if (desktopEntry) {
if (dockApps) { AppUsageHistoryData.addAppUsage({
const threshold = actualIconSize "id": appData.appId,
let newTargetIndex = targetIndex "name": desktopEntry.name || appData.appId,
if (dragOffset.x > threshold && targetIndex < dockApps.pinnedAppCount - 1) { "icon": desktopEntry.icon || "",
newTargetIndex = targetIndex + 1 "exec": desktopEntry.exec || "",
} else if (dragOffset.x < -threshold && targetIndex > 0) { "comment": desktopEntry.comment || ""
newTargetIndex = targetIndex - 1 });
} }
if (newTargetIndex !== targetIndex) { SessionService.launchDesktopEntry(desktopEntry);
targetIndex = newTargetIndex }
dragStartPos = Qt.point(mouse.x, mouse.y) } else if (mouse.button === Qt.RightButton) {
} if (contextMenu && appData) {
} contextMenu.showForButton(root, appData, root.height, false, cachedDesktopEntry, parentDockScreen);
} } else {
} console.warn("No context menu or appData available");
onClicked: mouse => { }
if (!appData || longPressing) { }
return }
}
if (mouse.button === Qt.LeftButton) {
if (appData.type === "pinned") {
if (appData && appData.appId) {
const desktopEntry = cachedDesktopEntry
if (desktopEntry) {
AppUsageHistoryData.addAppUsage({
"id": appData.appId,
"name": desktopEntry.name || appData.appId,
"icon": desktopEntry.icon || "",
"exec": desktopEntry.exec || "",
"comment": desktopEntry.comment || ""
})
}
SessionService.launchDesktopEntry(desktopEntry)
}
} else if (appData.type === "window") {
const toplevel = getToplevelObject()
if (toplevel) {
toplevel.activate()
}
} else if (appData.type === "grouped") {
if (appData.windowCount === 0) {
if (appData && appData.appId) {
const desktopEntry = cachedDesktopEntry
if (desktopEntry) {
AppUsageHistoryData.addAppUsage({
"id": appData.appId,
"name": desktopEntry.name || appData.appId,
"icon": desktopEntry.icon || "",
"exec": desktopEntry.exec || "",
"comment": desktopEntry.comment || ""
})
}
SessionService.launchDesktopEntry(desktopEntry)
}
} else if (appData.windowCount === 1) {
// For single window, activate directly
const toplevel = getToplevelObject()
if (toplevel) {
console.log("Activating grouped app window:", appData.windowTitle)
toplevel.activate()
} else {
console.warn("No toplevel found for grouped app")
}
} else {
if (contextMenu) {
contextMenu.showForButton(root, appData, root.height + 25, true, cachedDesktopEntry, parentDockScreen)
}
}
}
} else if (mouse.button === Qt.MiddleButton) {
if (appData?.type === "window") {
appData?.toplevel?.close()
} else if (appData?.type === "grouped") {
if (contextMenu) {
contextMenu.showForButton(root, appData, root.height, false, cachedDesktopEntry, parentDockScreen)
}
} else if (appData && appData.appId) {
const desktopEntry = cachedDesktopEntry
if (desktopEntry) {
AppUsageHistoryData.addAppUsage({
"id": appData.appId,
"name": desktopEntry.name || appData.appId,
"icon": desktopEntry.icon || "",
"exec": desktopEntry.exec || "",
"comment": desktopEntry.comment || ""
})
}
SessionService.launchDesktopEntry(desktopEntry)
}
} else if (mouse.button === Qt.RightButton) {
if (contextMenu && appData) {
contextMenu.showForButton(root, appData, root.height, false, cachedDesktopEntry, parentDockScreen)
} else {
console.warn("No context menu or appData available")
}
}
}
} }
Item { Item {
@@ -336,19 +336,23 @@ Item {
anchors.centerIn: parent anchors.centerIn: parent
implicitSize: actualIconSize implicitSize: actualIconSize
source: { source: {
if (appData.appId === "__SEPARATOR__") { if (!appData || appData.appId === "__SEPARATOR__") {
return "" return "";
} }
const moddedId = Paths.moddedAppId(appData.appId) return Paths.getAppIcon(appData.appId, cachedDesktopEntry);
if (moddedId.toLowerCase().includes("steam_app")) {
return ""
}
return cachedDesktopEntry && cachedDesktopEntry.icon ? Quickshell.iconPath(cachedDesktopEntry.icon, true) : ""
} }
mipmap: true mipmap: true
smooth: true smooth: true
asynchronous: true asynchronous: true
visible: status === Image.Ready visible: status === Image.Ready
layer.enabled: appData && appData.appId === "org.quickshell"
layer.smooth: true
layer.mipmap: true
layer.effect: MultiEffect {
saturation: 0
colorization: 1
colorizationColor: Theme.primary
}
} }
DankIcon { DankIcon {
@@ -358,10 +362,10 @@ Item {
color: Theme.surfaceText color: Theme.surfaceText
visible: { visible: {
if (!appData || !appData.appId || appData.appId === "__SEPARATOR__") { if (!appData || !appData.appId || appData.appId === "__SEPARATOR__") {
return false return false;
} }
const moddedId = Paths.moddedAppId(appData.appId) const moddedId = Paths.moddedAppId(appData.appId);
return moddedId.toLowerCase().includes("steam_app") return moddedId.toLowerCase().includes("steam_app");
} }
} }
@@ -379,15 +383,11 @@ Item {
anchors.centerIn: parent anchors.centerIn: parent
text: { text: {
if (!appData || !appData.appId) { if (!appData || !appData.appId) {
return "?" return "?";
} }
const desktopEntry = cachedDesktopEntry const appName = Paths.getAppName(appData.appId, cachedDesktopEntry);
if (desktopEntry && desktopEntry.name) { return appName.charAt(0).toUpperCase();
return desktopEntry.name.charAt(0).toUpperCase()
}
return appData.appId.charAt(0).toUpperCase()
} }
font.pixelSize: Math.max(8, parent.width * 0.35) font.pixelSize: Math.max(8, parent.width * 0.35)
color: Theme.primary color: Theme.primary
@@ -410,10 +410,13 @@ Item {
sourceComponent: SettingsData.dockPosition === SettingsData.Position.Left || SettingsData.dockPosition === SettingsData.Position.Right ? columnIndicator : rowIndicator sourceComponent: SettingsData.dockPosition === SettingsData.Position.Left || SettingsData.dockPosition === SettingsData.Position.Right ? columnIndicator : rowIndicator
visible: { visible: {
if (!appData) return false if (!appData)
if (appData.type === "window") return true return false;
if (appData.type === "grouped") return appData.windowCount > 0 if (appData.type === "window")
return appData.isRunning return true;
if (appData.type === "grouped")
return appData.windowCount > 0;
return appData.isRunning;
} }
} }
} }
@@ -426,49 +429,50 @@ Item {
Repeater { Repeater {
model: { model: {
if (!appData) return 0 if (!appData)
return 0;
if (appData.type === "grouped") { if (appData.type === "grouped") {
return Math.min(appData.windowCount, 4) return Math.min(appData.windowCount, 4);
} else if (appData.type === "window" || appData.isRunning) { } else if (appData.type === "window" || appData.isRunning) {
return 1 return 1;
} }
return 0 return 0;
} }
Rectangle { Rectangle {
width: { width: {
if (SettingsData.dockIndicatorStyle === "circle") { if (SettingsData.dockIndicatorStyle === "circle") {
return Math.max(4, actualIconSize * 0.1) return Math.max(4, actualIconSize * 0.1);
} }
return appData && appData.type === "grouped" && appData.windowCount > 1 ? Math.max(3, actualIconSize * 0.1) : Math.max(6, actualIconSize * 0.2) return appData && appData.type === "grouped" && appData.windowCount > 1 ? Math.max(3, actualIconSize * 0.1) : Math.max(6, actualIconSize * 0.2);
} }
height: { height: {
if (SettingsData.dockIndicatorStyle === "circle") { if (SettingsData.dockIndicatorStyle === "circle") {
return Math.max(4, actualIconSize * 0.1) return Math.max(4, actualIconSize * 0.1);
} }
return Math.max(2, actualIconSize * 0.05) return Math.max(2, actualIconSize * 0.05);
} }
radius: SettingsData.dockIndicatorStyle === "circle" ? width / 2 : Theme.cornerRadius radius: SettingsData.dockIndicatorStyle === "circle" ? width / 2 : Theme.cornerRadius
color: { color: {
if (!appData) { if (!appData) {
return "transparent" return "transparent";
} }
if (appData.type !== "grouped" || appData.windowCount === 1) { if (appData.type !== "grouped" || appData.windowCount === 1) {
if (isWindowFocused) { if (isWindowFocused) {
return Theme.primary return Theme.primary;
} }
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6);
} }
if (appData.type === "grouped" && appData.windowCount > 1) { if (appData.type === "grouped" && appData.windowCount > 1) {
const groupToplevels = getGroupedToplevels() const groupToplevels = getGroupedToplevels();
if (index < groupToplevels.length && groupToplevels[index].activated) { if (index < groupToplevels.length && groupToplevels[index].activated) {
return Theme.primary return Theme.primary;
} }
} }
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6);
} }
} }
} }
@@ -483,49 +487,50 @@ Item {
Repeater { Repeater {
model: { model: {
if (!appData) return 0 if (!appData)
return 0;
if (appData.type === "grouped") { if (appData.type === "grouped") {
return Math.min(appData.windowCount, 4) return Math.min(appData.windowCount, 4);
} else if (appData.type === "window" || appData.isRunning) { } else if (appData.type === "window" || appData.isRunning) {
return 1 return 1;
} }
return 0 return 0;
} }
Rectangle { Rectangle {
width: { width: {
if (SettingsData.dockIndicatorStyle === "circle") { if (SettingsData.dockIndicatorStyle === "circle") {
return Math.max(4, actualIconSize * 0.1) return Math.max(4, actualIconSize * 0.1);
} }
return Math.max(2, actualIconSize * 0.05) return Math.max(2, actualIconSize * 0.05);
} }
height: { height: {
if (SettingsData.dockIndicatorStyle === "circle") { if (SettingsData.dockIndicatorStyle === "circle") {
return Math.max(4, actualIconSize * 0.1) return Math.max(4, actualIconSize * 0.1);
} }
return appData && appData.type === "grouped" && appData.windowCount > 1 ? Math.max(3, actualIconSize * 0.1) : Math.max(6, actualIconSize * 0.2) return appData && appData.type === "grouped" && appData.windowCount > 1 ? Math.max(3, actualIconSize * 0.1) : Math.max(6, actualIconSize * 0.2);
} }
radius: SettingsData.dockIndicatorStyle === "circle" ? width / 2 : Theme.cornerRadius radius: SettingsData.dockIndicatorStyle === "circle" ? width / 2 : Theme.cornerRadius
color: { color: {
if (!appData) { if (!appData) {
return "transparent" return "transparent";
} }
if (appData.type !== "grouped" || appData.windowCount === 1) { if (appData.type !== "grouped" || appData.windowCount === 1) {
if (isWindowFocused) { if (isWindowFocused) {
return Theme.primary return Theme.primary;
} }
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6);
} }
if (appData.type === "grouped" && appData.windowCount > 1) { if (appData.type === "grouped" && appData.windowCount > 1) {
const groupToplevels = getGroupedToplevels() const groupToplevels = getGroupedToplevels();
if (index < groupToplevels.length && groupToplevels[index].activated) { if (index < groupToplevels.length && groupToplevels[index].activated) {
return Theme.primary return Theme.primary;
} }
} }
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6);
} }
} }
} }