1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-29 16:02:51 -05:00

apps: fix sorting and reactivity

This commit is contained in:
bbedward
2025-10-25 12:42:15 -04:00
parent 7e75c9e510
commit 62df30ed6c
4 changed files with 163 additions and 61 deletions

View File

@@ -49,9 +49,9 @@ jobs:
set -e set -e
PREVIOUS_TAG=$(git describe --tags --abbrev=0 "${TAG}^" 2>/dev/null || echo "") PREVIOUS_TAG=$(git describe --tags --abbrev=0 "${TAG}^" 2>/dev/null || echo "")
if [ -z "$PREVIOUS_TAG" ]; then if [ -z "$PREVIOUS_TAG" ]; then
CHANGELOG=$(git log --oneline --pretty=format:"- %s (%h)" | head -50) CHANGELOG=$(git log --oneline --pretty=format:"- %s (%h)" --author='^(?!github-actions\[bot\])' | head -50)
else else
CHANGELOG=$(git log --oneline --pretty=format:"- %s (%h)" "${PREVIOUS_TAG}..${TAG}") CHANGELOG=$(git log --oneline --pretty=format:"- %s (%h)" --author='^(?!github-actions\[bot\])' "${PREVIOUS_TAG}..${TAG}")
fi fi
cat > RELEASE_BODY.md << 'EOF' cat > RELEASE_BODY.md << 'EOF'

View File

@@ -22,6 +22,7 @@ Item {
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 2 : Theme.spacingS readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 2 : Theme.spacingS
property Item windowRoot: (Window.window ? Window.window.contentItem : null) property Item windowRoot: (Window.window ? Window.window.contentItem : null)
property int _workspaceUpdateTrigger: 0 property int _workspaceUpdateTrigger: 0
property int _desktopEntriesUpdateTrigger: 0
readonly property var sortedToplevels: { readonly property var sortedToplevels: {
_workspaceUpdateTrigger _workspaceUpdateTrigger
const toplevels = CompositorService.sortedToplevels const toplevels = CompositorService.sortedToplevels
@@ -34,6 +35,13 @@ Item {
} }
return toplevels return toplevels
} }
Connections {
target: DesktopEntries
function onApplicationsChanged() {
_desktopEntriesUpdateTrigger++
}
}
readonly property var groupedWindows: { readonly property var groupedWindows: {
if (!SettingsData.runningAppsGroupByApp) { if (!SettingsData.runningAppsGroupByApp) {
return [] return []
@@ -247,6 +255,7 @@ 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
let appName = "Unknown" let appName = "Unknown"
if (appId) { if (appId) {
const desktopEntry = DesktopEntries.heuristicLookup(appId) const desktopEntry = DesktopEntries.heuristicLookup(appId)
@@ -285,6 +294,7 @@ Item {
width: 18 width: 18
height: 18 height: 18
source: { source: {
root._desktopEntriesUpdateTrigger
const moddedId = Paths.moddedAppId(appId) const moddedId = Paths.moddedAppId(appId)
if (moddedId.toLowerCase().includes("steam_app")) { if (moddedId.toLowerCase().includes("steam_app")) {
return "" return ""
@@ -319,6 +329,7 @@ Item {
return !iconImg.visible && !isSteamApp return !iconImg.visible && !isSteamApp
} }
text: { text: {
root._desktopEntriesUpdateTrigger
if (!appId) { if (!appId) {
return "?" return "?"
} }
@@ -473,6 +484,7 @@ 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
let appName = "Unknown" let appName = "Unknown"
if (appId) { if (appId) {
const desktopEntry = DesktopEntries.heuristicLookup(appId) const desktopEntry = DesktopEntries.heuristicLookup(appId)
@@ -510,6 +522,7 @@ Item {
width: 18 width: 18
height: 18 height: 18
source: { source: {
root._desktopEntriesUpdateTrigger
const moddedId = Paths.moddedAppId(appId) const moddedId = Paths.moddedAppId(appId)
if (moddedId.toLowerCase().includes("steam_app")) { if (moddedId.toLowerCase().includes("steam_app")) {
return "" return ""
@@ -543,6 +556,7 @@ Item {
return !iconImg.visible && !isSteamApp return !iconImg.visible && !isSteamApp
} }
text: { text: {
root._desktopEntriesUpdateTrigger
if (!appId) { if (!appId) {
return "?" return "?"
} }

View File

@@ -76,6 +76,10 @@ Singleton {
target: Hyprland target: Hyprland
function onFocusedWorkspaceChanged() { root.scheduleSort() } function onFocusedWorkspaceChanged() { root.scheduleSort() }
} }
Connections {
target: NiriService
function onWindowsChanged() { root.scheduleSort() }
}
Component.onCompleted: { Component.onCompleted: {
detectCompositor() detectCompositor()

View File

@@ -177,49 +177,47 @@ Singleton {
} }
function sortWindowsByLayout(windowList) { function sortWindowsByLayout(windowList) {
return [...windowList].sort((a, b) => { const enriched = windowList.map(w => {
const aWorkspace = workspaces[a.workspace_id] const ws = workspaces[w.workspace_id]
const bWorkspace = workspaces[b.workspace_id] if (!ws) {
return {
window: w,
outputX: 999999,
outputY: 999999,
wsIdx: 999999,
col: 999999,
row: 999999
}
}
if (aWorkspace && bWorkspace) { const outputInfo = outputs[ws.output]
const aOutput = aWorkspace.output const outputX = (outputInfo && outputInfo.logical) ? outputInfo.logical.x : 999999
const bOutput = bWorkspace.output const outputY = (outputInfo && outputInfo.logical) ? outputInfo.logical.y : 999999
const aOutputInfo = outputs[aOutput] const pos = w.layout?.pos_in_scrolling_layout
const bOutputInfo = outputs[bOutput] const col = (pos && pos.length >= 2) ? pos[0] : 999999
const row = (pos && pos.length >= 2) ? pos[1] : 999999
if (aOutputInfo && bOutputInfo && aOutputInfo.logical && bOutputInfo.logical) { return {
if (aOutputInfo.logical.x !== bOutputInfo.logical.x) { window: w,
return aOutputInfo.logical.x - bOutputInfo.logical.x outputX: outputX,
} outputY: outputY,
if (aOutputInfo.logical.y !== bOutputInfo.logical.y) { wsIdx: ws.idx,
return aOutputInfo.logical.y - bOutputInfo.logical.y col: col,
} row: row
} }
})
if (aOutput === bOutput && aWorkspace.idx !== bWorkspace.idx) { enriched.sort((a, b) => {
return aWorkspace.idx - bWorkspace.idx if (a.outputX !== b.outputX) return a.outputX - b.outputX
} if (a.outputY !== b.outputY) return a.outputY - b.outputY
} if (a.wsIdx !== b.wsIdx) return a.wsIdx - b.wsIdx
if (a.col !== b.col) return a.col - b.col
if (a.row !== b.row) return a.row - b.row
return a.window.id - b.window.id
})
if (a.workspace_id === b.workspace_id && a.layout && b.layout) { return enriched.map(e => e.window)
if (a.layout.pos_in_scrolling_layout && b.layout.pos_in_scrolling_layout) {
const aPos = a.layout.pos_in_scrolling_layout
const bPos = b.layout.pos_in_scrolling_layout
if (aPos.length > 1 && bPos.length > 1) {
if (aPos[0] !== bPos[0]) {
return aPos[0] - bPos[0]
}
if (aPos[1] !== bPos[1]) {
return aPos[1] - bPos[1]
}
}
}
}
return a.id - b.id
})
} }
function handleNiriEvent(event) { function handleNiriEvent(event) {
@@ -235,6 +233,9 @@ Singleton {
case 'WorkspaceActiveWindowChanged': case 'WorkspaceActiveWindowChanged':
handleWorkspaceActiveWindowChanged(event.WorkspaceActiveWindowChanged) handleWorkspaceActiveWindowChanged(event.WorkspaceActiveWindowChanged)
break break
case 'WindowFocusChanged':
handleWindowFocusChanged(event.WindowFocusChanged)
break
case 'WindowsChanged': case 'WindowsChanged':
handleWindowsChanged(event.WindowsChanged) handleWindowsChanged(event.WindowsChanged)
break break
@@ -269,14 +270,18 @@ Singleton {
} }
function handleWorkspacesChanged(data) { function handleWorkspacesChanged(data) {
const workspaces = {} const newWorkspaces = {}
for (const ws of data.workspaces) { for (const ws of data.workspaces) {
workspaces[ws.id] = ws const oldWs = root.workspaces[ws.id]
newWorkspaces[ws.id] = ws
if (oldWs && oldWs.active_window_id !== undefined) {
newWorkspaces[ws.id].active_window_id = oldWs.active_window_id
}
} }
root.workspaces = workspaces root.workspaces = newWorkspaces
allWorkspaces = [...data.workspaces].sort((a, b) => a.idx - b.idx) allWorkspaces = Object.values(newWorkspaces).sort((a, b) => a.idx - b.idx)
focusedWorkspaceIndex = allWorkspaces.findIndex(w => w.is_focused) focusedWorkspaceIndex = allWorkspaces.findIndex(w => w.is_focused)
if (focusedWorkspaceIndex >= 0) { if (focusedWorkspaceIndex >= 0) {
@@ -298,33 +303,101 @@ Singleton {
} }
const output = ws.output const output = ws.output
const updatedWorkspaces = {}
for (const id in root.workspaces) { for (const id in root.workspaces) {
const workspace = root.workspaces[id] const workspace = root.workspaces[id]
const got_activated = workspace.id === data.id const got_activated = workspace.id === data.id
const updatedWs = {}
for (let prop in workspace) {
updatedWs[prop] = workspace[prop]
}
if (workspace.output === output) { if (workspace.output === output) {
workspace.is_active = got_activated updatedWs.is_active = got_activated
} }
if (data.focused) { if (data.focused) {
workspace.is_focused = got_activated updatedWs.is_focused = got_activated
} }
updatedWorkspaces[id] = updatedWs
} }
root.workspaces = updatedWorkspaces
focusedWorkspaceId = data.id focusedWorkspaceId = data.id
focusedWorkspaceIndex = allWorkspaces.findIndex(w => w.id === data.id) focusedWorkspaceIndex = Object.values(updatedWorkspaces).findIndex(w => w.id === data.id)
if (focusedWorkspaceIndex >= 0) { if (focusedWorkspaceIndex >= 0) {
currentOutput = allWorkspaces[focusedWorkspaceIndex].output || "" const ws = Object.values(updatedWorkspaces)[focusedWorkspaceIndex]
currentOutput = ws.output || ""
} }
allWorkspaces = Object.values(root.workspaces).sort((a, b) => a.idx - b.idx) allWorkspaces = Object.values(updatedWorkspaces).sort((a, b) => a.idx - b.idx)
updateCurrentOutputWorkspaces() updateCurrentOutputWorkspaces()
workspacesChanged() }
function handleWindowFocusChanged(data) {
const focusedWindowId = data.id
let focusedWindow = null
const updatedWindows = []
for (var i = 0; i < windows.length; i++) {
const w = windows[i]
const updatedWindow = {}
for (let prop in w) {
updatedWindow[prop] = w[prop]
}
updatedWindow.is_focused = (w.id === focusedWindowId)
if (updatedWindow.is_focused) {
focusedWindow = updatedWindow
}
updatedWindows.push(updatedWindow)
}
windows = updatedWindows
if (focusedWindow) {
const ws = root.workspaces[focusedWindow.workspace_id]
if (ws && ws.active_window_id !== focusedWindowId) {
const updatedWs = {}
for (let prop in ws) {
updatedWs[prop] = ws[prop]
}
updatedWs.active_window_id = focusedWindowId
const updatedWorkspaces = {}
for (const id in root.workspaces) {
updatedWorkspaces[id] = id === focusedWindow.workspace_id ? updatedWs : root.workspaces[id]
}
root.workspaces = updatedWorkspaces
}
}
} }
function handleWorkspaceActiveWindowChanged(data) { function handleWorkspaceActiveWindowChanged(data) {
const ws = root.workspaces[data.workspace_id]
if (ws) {
const updatedWs = {}
for (let prop in ws) {
updatedWs[prop] = ws[prop]
}
updatedWs.active_window_id = data.active_window_id
const updatedWorkspaces = {}
for (const id in root.workspaces) {
updatedWorkspaces[id] = id === data.workspace_id ? updatedWs : root.workspaces[id]
}
root.workspaces = updatedWorkspaces
}
const updatedWindows = [] const updatedWindows = []
for (var i = 0; i < windows.length; i++) { for (var i = 0; i < windows.length; i++) {
@@ -366,10 +439,9 @@ Singleton {
const updatedWindows = [...windows] const updatedWindows = [...windows]
updatedWindows[existingIndex] = window updatedWindows[existingIndex] = window
windows = sortWindowsByLayout(updatedWindows) windows = sortWindowsByLayout(updatedWindows)
return } else {
windows = sortWindowsByLayout([...windows, window])
} }
windows = sortWindowsByLayout([...windows, window])
} }
function handleWindowLayoutsChanged(data) { function handleWindowLayoutsChanged(data) {
@@ -400,7 +472,6 @@ Singleton {
return return
windows = sortWindowsByLayout(updatedWindows) windows = sortWindowsByLayout(updatedWindows)
windowsChanged()
} }
function handleOutputsChanged(data) { function handleOutputsChanged(data) {
@@ -452,12 +523,19 @@ Singleton {
if (!ws) if (!ws)
return return
ws.is_urgent = data.urgent const updatedWs = {}
for (let prop in ws) {
const idx = allWorkspaces.findIndex(w => w.id === data.id) updatedWs[prop] = ws[prop]
if (idx >= 0) {
allWorkspaces[idx].is_urgent = data.urgent
} }
updatedWs.is_urgent = data.urgent
const updatedWorkspaces = {}
for (const id in root.workspaces) {
updatedWorkspaces[id] = id === data.id ? updatedWs : root.workspaces[id]
}
root.workspaces = updatedWorkspaces
allWorkspaces = Object.values(updatedWorkspaces).sort((a, b) => a.idx - b.idx)
windowUrgentChanged() windowUrgentChanged()
} }
@@ -637,10 +715,13 @@ Singleton {
usedToplevels.add(bestMatch) usedToplevels.add(bestMatch)
const workspace = workspaces[niriWindow.workspace_id]
const isFocused = niriWindow.is_focused ?? (workspace && workspace.active_window_id === niriWindow.id) ?? false
const enrichedToplevel = { const enrichedToplevel = {
"appId": bestMatch.appId, "appId": bestMatch.appId,
"title": bestMatch.title, "title": bestMatch.title,
"activated": niriWindow.is_focused ?? false, "activated": isFocused,
"niriWindowId": niriWindow.id, "niriWindowId": niriWindow.id,
"niriWorkspaceId": niriWindow.workspace_id, "niriWorkspaceId": niriWindow.workspace_id,
"activate": function () { "activate": function () {
@@ -723,10 +804,13 @@ Singleton {
usedToplevels.add(bestMatch) usedToplevels.add(bestMatch)
const workspace = workspaces[niriWindow.workspace_id]
const isFocused = niriWindow.is_focused ?? (workspace && workspace.active_window_id === niriWindow.id) ?? false
const enrichedToplevel = { const enrichedToplevel = {
"appId": bestMatch.appId, "appId": bestMatch.appId,
"title": bestMatch.title, "title": bestMatch.title,
"activated": niriWindow.is_focused ?? false, "activated": isFocused,
"niriWindowId": niriWindow.id, "niriWindowId": niriWindow.id,
"niriWorkspaceId": niriWindow.workspace_id, "niriWorkspaceId": niriWindow.workspace_id,
"activate": function () { "activate": function () {