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

niri: improve toplevel sorting

This commit is contained in:
bbedward
2025-10-23 10:33:24 -04:00
parent beab1a7b01
commit 4e43c797e2
2 changed files with 186 additions and 103 deletions

View File

@@ -37,7 +37,7 @@ Singleton {
property bool matugenSuppression: false property bool matugenSuppression: false
property bool configGenerationPending: false property bool configGenerationPending: false
signal windowUrgentChanged() signal windowUrgentChanged
Component.onCompleted: fetchOutputs() Component.onCompleted: fetchOutputs()
@@ -140,7 +140,8 @@ Singleton {
} }
function fetchOutputs() { function fetchOutputs() {
if (!CompositorService.isNiri) return if (!CompositorService.isNiri)
return
Proc.runCommand("niri-fetch-outputs", ["niri", "msg", "-j", "outputs"], (output, exitCode) => { Proc.runCommand("niri-fetch-outputs", ["niri", "msg", "-j", "outputs"], (output, exitCode) => {
if (exitCode !== 0) { if (exitCode !== 0) {
console.warn("NiriService: Failed to fetch outputs, exit code:", exitCode) console.warn("NiriService: Failed to fetch outputs, exit code:", exitCode)
@@ -161,7 +162,8 @@ Singleton {
} }
function updateDisplayScales() { function updateDisplayScales() {
if (!outputs || Object.keys(outputs).length === 0) return if (!outputs || Object.keys(outputs).length === 0)
return
const scales = {} const scales = {}
for (const outputName in outputs) { for (const outputName in outputs) {
@@ -354,7 +356,8 @@ Singleton {
} }
function handleWindowOpenedOrChanged(data) { function handleWindowOpenedOrChanged(data) {
if (!data.window) return if (!data.window)
return
const window = data.window const window = data.window
const existingIndex = windows.findIndex(w => w.id === window.id) const existingIndex = windows.findIndex(w => w.id === window.id)
@@ -370,7 +373,8 @@ Singleton {
} }
function handleWindowLayoutsChanged(data) { function handleWindowLayoutsChanged(data) {
if (!data.changes) return if (!data.changes)
return
const updatedWindows = [...windows] const updatedWindows = [...windows]
let hasChanges = false let hasChanges = false
@@ -380,7 +384,8 @@ Singleton {
const layoutData = change[1] const layoutData = change[1]
const windowIndex = updatedWindows.findIndex(w => w.id === windowId) const windowIndex = updatedWindows.findIndex(w => w.id === windowId)
if (windowIndex < 0) continue if (windowIndex < 0)
continue
const updatedWindow = {} const updatedWindow = {}
for (var prop in updatedWindows[windowIndex]) { for (var prop in updatedWindows[windowIndex]) {
@@ -391,14 +396,16 @@ Singleton {
hasChanges = true hasChanges = true
} }
if (!hasChanges) return if (!hasChanges)
return
windows = sortWindowsByLayout(updatedWindows) windows = sortWindowsByLayout(updatedWindows)
windowsChanged() windowsChanged()
} }
function handleOutputsChanged(data) { function handleOutputsChanged(data) {
if (!data.outputs) return if (!data.outputs)
return
outputs = data.outputs outputs = data.outputs
updateDisplayScales() updateDisplayScales()
windows = sortWindowsByLayout(windows) windows = sortWindowsByLayout(windows)
@@ -442,7 +449,8 @@ Singleton {
function handleWorkspaceUrgencyChanged(data) { function handleWorkspaceUrgencyChanged(data) {
const ws = root.workspaces[data.id] const ws = root.workspaces[data.id]
if (!ws) return if (!ws)
return
ws.is_urgent = data.urgent ws.is_urgent = data.urgent
@@ -465,41 +473,86 @@ Singleton {
} }
function send(request) { function send(request) {
if (!CompositorService.isNiri || !requestSocket.connected) return false if (!CompositorService.isNiri || !requestSocket.connected)
return false
requestSocket.send(request) requestSocket.send(request)
return true return true
} }
function doScreenTransition() { function doScreenTransition() {
return send({"Action": {"DoScreenTransition": {"delay_ms": 0}}}) return send({
"Action": {
"DoScreenTransition": {
"delay_ms": 0
}
}
})
} }
function toggleOverview() { function toggleOverview() {
return send({"Action": {"ToggleOverview": {}}}) return send({
"Action": {
"ToggleOverview": {}
}
})
} }
function switchToWorkspace(workspaceIndex) { function switchToWorkspace(workspaceIndex) {
return send({"Action": {"FocusWorkspace": {"reference": {"Index": workspaceIndex}}}}) return send({
"Action": {
"FocusWorkspace": {
"reference": {
"Index": workspaceIndex
}
}
}
})
} }
function focusWindow(windowId) { function focusWindow(windowId) {
return send({"Action": {"FocusWindow": {"id": windowId}}}) return send({
"Action": {
"FocusWindow": {
"id": windowId
}
}
})
} }
function powerOffMonitors() { function powerOffMonitors() {
return send({"Action": {"PowerOffMonitors": {}}}) return send({
"Action": {
"PowerOffMonitors": {}
}
})
} }
function powerOnMonitors() { function powerOnMonitors() {
return send({"Action": {"PowerOnMonitors": {}}}) return send({
"Action": {
"PowerOnMonitors": {}
}
})
} }
function cycleKeyboardLayout() { function cycleKeyboardLayout() {
return send({"Action": {"SwitchLayout": {"layout": "Next"}}}) return send({
"Action": {
"SwitchLayout": {
"layout": "Next"
}
}
})
} }
function quit() { function quit() {
return send({"Action": {"Quit": {"skip_confirmation": true}}}) return send({
"Action": {
"Quit": {
"skip_confirmation": true
}
}
})
} }
function getCurrentOutputWorkspaceNumbers() { function getCurrentOutputWorkspaceNumbers() {
@@ -526,13 +579,17 @@ Singleton {
} }
function findNiriWindow(toplevel) { function findNiriWindow(toplevel) {
if (!toplevel.appId) return null if (!toplevel.appId)
return null
for (var j = 0; j < windows.length; j++) { for (var j = 0; j < windows.length; j++) {
const niriWindow = windows[j] const niriWindow = windows[j]
if (niriWindow.app_id === toplevel.appId) { if (niriWindow.app_id === toplevel.appId) {
if (!niriWindow.title || niriWindow.title === toplevel.title) { if (!niriWindow.title || niriWindow.title === toplevel.title) {
return {"niriIndex": j, "niriWindow": niriWindow} return {
"niriIndex": j,
"niriWindow": niriWindow
}
} }
} }
} }
@@ -549,35 +606,47 @@ Singleton {
for (const niriWindow of sortWindowsByLayout(windows)) { for (const niriWindow of sortWindowsByLayout(windows)) {
let bestMatch = null let bestMatch = null
let bestScore = -1
for (const toplevel of toplevels) { for (const toplevel of toplevels) {
if (usedToplevels.has(toplevel)) continue if (usedToplevels.has(toplevel))
continue
if (toplevel.appId === niriWindow.app_id) { if (toplevel.appId === niriWindow.app_id) {
if (niriWindow.title && toplevel.title === niriWindow.title) { let score = 1
bestMatch = toplevel
break if (niriWindow.title && toplevel.title) {
if (toplevel.title === niriWindow.title) {
score = 3
} else if (toplevel.title.includes(niriWindow.title) || niriWindow.title.includes(toplevel.title)) {
score = 2
} }
if (!niriWindow.title && !bestMatch) { }
if (score > bestScore) {
bestScore = score
bestMatch = toplevel bestMatch = toplevel
if (score === 3)
break
} }
} }
} }
if (!bestMatch) continue if (!bestMatch)
continue
usedToplevels.add(bestMatch) usedToplevels.add(bestMatch)
const enrichedToplevel = { const enrichedToplevel = {
appId: bestMatch.appId, "appId": bestMatch.appId,
title: bestMatch.title, "title": bestMatch.title,
activated: bestMatch.activated, "activated": bestMatch.activated,
niriWindowId: niriWindow.id, "niriWindowId": niriWindow.id,
niriWorkspaceId: niriWindow.workspace_id, "niriWorkspaceId": niriWindow.workspace_id,
activate: function() { "activate": function () {
return NiriService.focusWindow(niriWindow.id) return NiriService.focusWindow(niriWindow.id)
}, },
close: function() { "close": function () {
if (bestMatch.close) { if (bestMatch.close) {
return bestMatch.close() return bestMatch.close()
} }
@@ -614,7 +683,8 @@ Singleton {
} }
} }
if (currentWorkspaceId === null) return toplevels if (currentWorkspaceId === null)
return toplevels
const workspaceWindows = windows.filter(niriWindow => niriWindow.workspace_id === currentWorkspaceId) const workspaceWindows = windows.filter(niriWindow => niriWindow.workspace_id === currentWorkspaceId)
const usedToplevels = new Set() const usedToplevels = new Set()
@@ -622,35 +692,47 @@ Singleton {
for (const niriWindow of workspaceWindows) { for (const niriWindow of workspaceWindows) {
let bestMatch = null let bestMatch = null
let bestScore = -1
for (const toplevel of toplevels) { for (const toplevel of toplevels) {
if (usedToplevels.has(toplevel)) continue if (usedToplevels.has(toplevel))
continue
if (toplevel.appId === niriWindow.app_id) { if (toplevel.appId === niriWindow.app_id) {
if (niriWindow.title && toplevel.title === niriWindow.title) { let score = 1
bestMatch = toplevel
break if (niriWindow.title && toplevel.title) {
if (toplevel.title === niriWindow.title) {
score = 3
} else if (toplevel.title.includes(niriWindow.title) || niriWindow.title.includes(toplevel.title)) {
score = 2
} }
if (!niriWindow.title && !bestMatch) { }
if (score > bestScore) {
bestScore = score
bestMatch = toplevel bestMatch = toplevel
if (score === 3)
break
} }
} }
} }
if (!bestMatch) continue if (!bestMatch)
continue
usedToplevels.add(bestMatch) usedToplevels.add(bestMatch)
const enrichedToplevel = { const enrichedToplevel = {
appId: bestMatch.appId, "appId": bestMatch.appId,
title: bestMatch.title, "title": bestMatch.title,
activated: bestMatch.activated, "activated": bestMatch.activated,
niriWindowId: niriWindow.id, "niriWindowId": niriWindow.id,
niriWorkspaceId: niriWindow.workspace_id, "niriWorkspaceId": niriWindow.workspace_id,
activate: function() { "activate": function () {
return NiriService.focusWindow(niriWindow.id) return NiriService.focusWindow(niriWindow.id)
}, },
close: function() { "close": function () {
if (bestMatch.close) { if (bestMatch.close) {
return bestMatch.close() return bestMatch.close()
} }
@@ -672,8 +754,10 @@ Singleton {
function generateNiriLayoutConfig() { function generateNiriLayoutConfig() {
const niriSocket = Quickshell.env("NIRI_SOCKET") const niriSocket = Quickshell.env("NIRI_SOCKET")
if (!niriSocket || niriSocket.length === 0) return if (!niriSocket || niriSocket.length === 0)
if (configGenerationPending) return return
if (configGenerationPending)
return
configGenerationPending = true configGenerationPending = true
configGenerationDebounce.restart() configGenerationDebounce.restart()
@@ -696,7 +780,6 @@ Singleton {
width 2 width 2
} }
} }
window-rule { window-rule {
geometry-corner-radius ${cornerRadius} geometry-corner-radius ${cornerRadius}
clip-to-geometry true clip-to-geometry true

View File

@@ -1,6 +1,6 @@
pragma Singleton pragma Singleton
pragma ComponentBehavior pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import Quickshell import Quickshell