mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-06 05:25:41 -05:00
feat: add configurable per-monitor workspace filtering and system tray monitor selection (#163)
This commit is contained in:
@@ -50,6 +50,10 @@ Singleton {
|
||||
function moddedAppId(appId: string): string {
|
||||
if (appId === "Spotify")
|
||||
return "spotify-launcher"
|
||||
if (appId === "beepertexts")
|
||||
return "beeper"
|
||||
if (appId === "home assistant desktop")
|
||||
return "homeassistant-desktop"
|
||||
return appId
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ Singleton {
|
||||
property bool showWorkspacePadding: false
|
||||
property bool showWorkspaceApps: false
|
||||
property int maxWorkspaceIcons: 3
|
||||
property bool workspacesPerMonitor: true
|
||||
property var workspaceNameIcons: ({})
|
||||
property bool clockCompactMode: false
|
||||
property bool focusedWindowCompactMode: false
|
||||
@@ -199,6 +200,7 @@ Singleton {
|
||||
showWorkspaceApps = settings.showWorkspaceApps !== undefined ? settings.showWorkspaceApps : false
|
||||
maxWorkspaceIcons = settings.maxWorkspaceIcons !== undefined ? settings.maxWorkspaceIcons : 3
|
||||
workspaceNameIcons = settings.workspaceNameIcons !== undefined ? settings.workspaceNameIcons : ({})
|
||||
workspacesPerMonitor = settings.workspacesPerMonitor !== undefined ? settings.workspacesPerMonitor : true
|
||||
clockCompactMode = settings.clockCompactMode !== undefined ? settings.clockCompactMode : false
|
||||
focusedWindowCompactMode = settings.focusedWindowCompactMode !== undefined ? settings.focusedWindowCompactMode : false
|
||||
runningAppsCompactMode = settings.runningAppsCompactMode !== undefined ? settings.runningAppsCompactMode : true
|
||||
@@ -307,6 +309,8 @@ Singleton {
|
||||
"showWorkspaceIndex": showWorkspaceIndex,
|
||||
"showWorkspacePadding": showWorkspacePadding,
|
||||
"showWorkspaceApps": showWorkspaceApps,
|
||||
"maxWorkspaceIcons": maxWorkspaceIcons,
|
||||
"workspacesPerMonitor": workspacesPerMonitor,
|
||||
"workspaceNameIcons": workspaceNameIcons,
|
||||
"clockCompactMode": clockCompactMode,
|
||||
"focusedWindowCompactMode": focusedWindowCompactMode,
|
||||
@@ -370,6 +374,11 @@ Singleton {
|
||||
saveSettings()
|
||||
}
|
||||
|
||||
function setWorkspacesPerMonitor(enabled) {
|
||||
workspacesPerMonitor = enabled
|
||||
saveSettings()
|
||||
}
|
||||
|
||||
function setWorkspaceNameIcon(workspaceName, iconData) {
|
||||
var iconMap = JSON.parse(JSON.stringify(workspaceNameIcons))
|
||||
iconMap[workspaceName] = iconData
|
||||
|
||||
@@ -44,6 +44,11 @@ Item {
|
||||
"name": "Notepad Slideout",
|
||||
"description": "Quick note-taking slideout panel",
|
||||
"icon": "sticky_note_2"
|
||||
}, {
|
||||
"id": "systemTray",
|
||||
"name": "System Tray",
|
||||
"description": "System tray icons",
|
||||
"icon": "notifications"
|
||||
}]
|
||||
|
||||
function getScreenPreferences(componentId) {
|
||||
|
||||
@@ -284,6 +284,16 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
text: "Per-Monitor Workspaces"
|
||||
description: "Show only workspaces belonging to each specific monitor."
|
||||
checked: SettingsData.workspacesPerMonitor
|
||||
onToggled: checked => {
|
||||
return SettingsData.setWorkspacesPerMonitor(checked);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -729,6 +729,7 @@ PanelWindow {
|
||||
parentWindow: root
|
||||
parentScreen: root.screen
|
||||
widgetHeight: root.widgetHeight
|
||||
visible: SettingsData.getFilteredScreens("systemTray").includes(root.screen)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ Rectangle {
|
||||
if (CompositorService.isNiri) {
|
||||
return getNiriActiveWorkspace()
|
||||
} else if (CompositorService.isHyprland) {
|
||||
return Hyprland.focusedWorkspace ? Hyprland.focusedWorkspace.id : 1
|
||||
return getHyprlandActiveWorkspace()
|
||||
}
|
||||
return 1
|
||||
}
|
||||
@@ -26,15 +26,8 @@ Rectangle {
|
||||
return SettingsData.showWorkspacePadding ? padWorkspaces(baseList) : baseList
|
||||
}
|
||||
if (CompositorService.isHyprland) {
|
||||
const workspaces = Hyprland.workspaces?.values || []
|
||||
if (workspaces.length === 0) {
|
||||
return [{
|
||||
"id": 1,
|
||||
"name": "1"
|
||||
}]
|
||||
}
|
||||
const sorted = workspaces.slice().sort((a, b) => a.id - b.id)
|
||||
return SettingsData.showWorkspacePadding ? padWorkspaces(sorted) : sorted
|
||||
const baseList = getHyprlandWorkspaces()
|
||||
return SettingsData.showWorkspacePadding ? padWorkspaces(baseList) : baseList
|
||||
}
|
||||
return [1]
|
||||
}
|
||||
@@ -61,7 +54,8 @@ Rectangle {
|
||||
return []
|
||||
}
|
||||
|
||||
const wins = CompositorService.isNiri ? (NiriService.windows || []) : (Hyprland.clients?.values || [])
|
||||
const wins = CompositorService.isNiri ? (NiriService.windows || []) : CompositorService.sortedToplevels
|
||||
|
||||
|
||||
const byApp = {}
|
||||
const isActiveWs = CompositorService.isNiri ? NiriService.allWorkspaces.some(ws => ws.id === targetWorkspaceId && ws.is_active) : targetWorkspaceId === root.currentWorkspace
|
||||
@@ -71,13 +65,22 @@ Rectangle {
|
||||
return
|
||||
}
|
||||
|
||||
const winWs = CompositorService.isNiri ? w.workspace_id : (w.workspace?.id ?? w.workspaceId)
|
||||
let winWs = null
|
||||
if (CompositorService.isNiri) {
|
||||
winWs = w.workspace_id
|
||||
} else {
|
||||
// For Hyprland, we need to find the corresponding Hyprland toplevel to get workspace
|
||||
const hyprlandToplevels = Array.from(Hyprland.toplevels?.values || [])
|
||||
const hyprToplevel = hyprlandToplevels.find(ht => ht.wayland === w)
|
||||
winWs = hyprToplevel?.workspace?.id
|
||||
}
|
||||
|
||||
|
||||
if (winWs === undefined || winWs === null || winWs !== targetWorkspaceId) {
|
||||
return
|
||||
}
|
||||
|
||||
const keyBase = (w.app_id || w.appId || w.class || w.windowClass || w.exe || "unknown").toLowerCase()
|
||||
const keyBase = (w.appId || w.class || w.windowClass || "unknown").toLowerCase()
|
||||
const key = isActiveWs ? `${keyBase}_${i}` : keyBase
|
||||
|
||||
if (!byApp[key]) {
|
||||
@@ -85,14 +88,14 @@ Rectangle {
|
||||
byApp[key] = {
|
||||
"type": "icon",
|
||||
"icon": icon,
|
||||
"active": !!(w.is_focused || w.activated),
|
||||
"active": !!(w.activated || (CompositorService.isNiri && w.is_focused)),
|
||||
"count": 1,
|
||||
"windowId": w.id || w.address,
|
||||
"fallbackText": w.app_id || w.appId || w.class || w.title || ""
|
||||
"windowId": w.address || w.id,
|
||||
"fallbackText": w.appId || w.class || w.title || ""
|
||||
}
|
||||
} else {
|
||||
byApp[key].count++
|
||||
if (w.is_focused || w.activated) {
|
||||
if (w.activated || (CompositorService.isNiri && w.is_focused)) {
|
||||
byApp[key].active = true
|
||||
}
|
||||
}
|
||||
@@ -118,7 +121,7 @@ Rectangle {
|
||||
return [1, 2]
|
||||
}
|
||||
|
||||
if (!root.screenName) {
|
||||
if (!root.screenName || !SettingsData.workspacesPerMonitor) {
|
||||
return NiriService.getCurrentOutputWorkspaceNumbers()
|
||||
}
|
||||
|
||||
@@ -131,7 +134,7 @@ Rectangle {
|
||||
return 1
|
||||
}
|
||||
|
||||
if (!root.screenName) {
|
||||
if (!root.screenName || !SettingsData.workspacesPerMonitor) {
|
||||
return NiriService.getCurrentWorkspaceNumber()
|
||||
}
|
||||
|
||||
@@ -139,6 +142,53 @@ Rectangle {
|
||||
return activeWs ? activeWs.idx + 1 : 1
|
||||
}
|
||||
|
||||
function getHyprlandWorkspaces() {
|
||||
const workspaces = Hyprland.workspaces?.values || []
|
||||
|
||||
if (!root.screenName || !SettingsData.workspacesPerMonitor) {
|
||||
// Show all workspaces on all monitors if per-monitor filtering is disabled
|
||||
const sorted = workspaces.slice().sort((a, b) => a.id - b.id)
|
||||
return sorted.length > 0 ? sorted : [{
|
||||
"id": 1,
|
||||
"name": "1"
|
||||
}]
|
||||
}
|
||||
|
||||
// Filter workspaces for this specific monitor using lastIpcObject.monitor
|
||||
// This matches the approach from the original kyle-config
|
||||
const monitorWorkspaces = workspaces.filter(ws => {
|
||||
return ws.lastIpcObject && ws.lastIpcObject.monitor === root.screenName
|
||||
})
|
||||
|
||||
if (monitorWorkspaces.length === 0) {
|
||||
// Fallback if no workspaces exist for this monitor
|
||||
return [{
|
||||
"id": 1,
|
||||
"name": "1"
|
||||
}]
|
||||
}
|
||||
|
||||
// Return all workspaces for this monitor, sorted by ID
|
||||
return monitorWorkspaces.sort((a, b) => a.id - b.id)
|
||||
}
|
||||
|
||||
function getHyprlandActiveWorkspace() {
|
||||
if (!root.screenName || !SettingsData.workspacesPerMonitor) {
|
||||
return Hyprland.focusedWorkspace ? Hyprland.focusedWorkspace.id : 1
|
||||
}
|
||||
|
||||
// Find the monitor object for this screen
|
||||
const monitors = Hyprland.monitors?.values || []
|
||||
const currentMonitor = monitors.find(monitor => monitor.name === root.screenName)
|
||||
|
||||
if (!currentMonitor) {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Use the monitor's active workspace ID (like original config)
|
||||
return currentMonitor.activeWorkspace?.id ?? 1
|
||||
}
|
||||
|
||||
readonly property real padding: (widgetHeight - workspaceRow.implicitHeight) / 2
|
||||
|
||||
function getRealWorkspaces() {
|
||||
|
||||
Reference in New Issue
Block a user