Fixed Hyprland active window

This commit is contained in:
Ly-sec 2025-08-19 23:38:33 +02:00
parent a9fceee62d
commit c4380ec885
2 changed files with 28 additions and 132 deletions

View file

@ -29,27 +29,18 @@ Row {
Connections { Connections {
target: CompositorService target: CompositorService
function onActiveWindowChanged() { function onActiveWindowChanged() {
try {
// Check if window actually changed // Check if window actually changed
if (CompositorService.focusedWindowIndex !== lastWindowIndex) { if (CompositorService.focusedWindowIndex !== lastWindowIndex) {
lastWindowIndex = CompositorService.focusedWindowIndex lastWindowIndex = CompositorService.focusedWindowIndex
showingFullTitle = true showingFullTitle = true
fullTitleTimer.restart() fullTitleTimer.restart()
} }
} catch (e) {
console.error("ActiveWindow: Error in activeWindowChanged:", e)
}
} }
} }
function getTitle() { function getTitle() {
try {
const focusedWindow = CompositorService.getFocusedWindow() const focusedWindow = CompositorService.getFocusedWindow()
return focusedWindow ? (focusedWindow.title || focusedWindow.appId || "") : "" return focusedWindow ? (focusedWindow.title || focusedWindow.appId || "") : ""
} catch (e) {
console.error("ActiveWindow: Error getting title:", e)
return ""
}
} }
// A hidden text element to safely measure the full title width // A hidden text element to safely measure the full title width

View file

@ -28,18 +28,6 @@ Singleton {
signal overviewStateChanged signal overviewStateChanged
signal windowListChanged signal windowListChanged
// Throttle timer to prevent too frequent window updates
Timer {
id: windowUpdateTimer
interval: 100 // 100ms debounce
repeat: false
onTriggered: {
if (isHyprland) {
updateHyprlandWindows()
}
}
}
// Compositor detection // Compositor detection
Component.onCompleted: { Component.onCompleted: {
detectCompositor() detectCompositor()
@ -48,52 +36,37 @@ Singleton {
// Hyprland connections // Hyprland connections
Connections { Connections {
target: Hyprland.workspaces target: Hyprland.workspaces
enabled: isHyprland && Hyprland && Hyprland.workspaces enabled: isHyprland
function onValuesChanged() { function onValuesChanged() {
try {
updateHyprlandWorkspaces() updateHyprlandWorkspaces()
workspaceChanged() workspaceChanged()
} catch (e) {
Logger.error("Compositor", "Error in workspaces valuesChanged:", e)
}
} }
} }
Connections { Connections {
target: Hyprland.toplevels target: Hyprland.toplevels
enabled: isHyprland && Hyprland && Hyprland.toplevels enabled: isHyprland
function onValuesChanged() { function onValuesChanged() {
try { updateHyprlandWindows()
// Use throttled update to prevent rapid-fire updates causing crashes
windowUpdateTimer.restart()
windowListChanged() windowListChanged()
} catch (e) {
Logger.error("Compositor", "Error in toplevels valuesChanged:", e)
}
} }
} }
Connections { Connections {
target: Hyprland target: Hyprland
enabled: isHyprland && Hyprland enabled: isHyprland
function onRawEvent(event) { function onRawEvent(event) {
try {
// Only update workspaces on raw events, not windows (too frequent)
updateHyprlandWorkspaces() updateHyprlandWorkspaces()
workspaceChanged() workspaceChanged()
// Remove automatic window updates on raw events to prevent crashes updateHyprlandWindows()
// updateHyprlandWindows() windowListChanged()
// windowListChanged()
} catch (e) {
Logger.error("Compositor", "Error in rawEvent:", e)
}
} }
} }
function detectCompositor() { function detectCompositor() {
try { try {
// Try Hyprland first - add extra safety checks // Try Hyprland first
if (Hyprland && Hyprland.eventSocketPath) { if (Hyprland.eventSocketPath) {
compositorType = "hyprland" compositorType = "hyprland"
isHyprland = true isHyprland = true
isNiri = false isNiri = false
@ -101,7 +74,7 @@ Singleton {
return return
} }
} catch (e) { } catch (e) {
Logger.warn("Compositor", "Hyprland detection failed:", e)
// Hyprland not available // Hyprland not available
} }
@ -122,26 +95,8 @@ Singleton {
// Hyprland integration // Hyprland integration
function initHyprland() { function initHyprland() {
try { try {
Logger.log("Compositor", "Starting Hyprland initialization...")
// Add safety checks before calling refresh functions
if (!Hyprland) {
throw new Error("Hyprland object is null")
}
if (typeof Hyprland.refreshWorkspaces === 'function') {
Hyprland.refreshWorkspaces() Hyprland.refreshWorkspaces()
} else {
Logger.warn("Compositor", "Hyprland.refreshWorkspaces not available")
}
if (typeof Hyprland.refreshToplevels === 'function') {
Hyprland.refreshToplevels() Hyprland.refreshToplevels()
} else {
Logger.warn("Compositor", "Hyprland.refreshToplevels not available")
}
// Update with safety checks
updateHyprlandWorkspaces() updateHyprlandWorkspaces()
updateHyprlandWindows() updateHyprlandWindows()
setupHyprlandConnections() setupHyprlandConnections()
@ -150,7 +105,6 @@ Singleton {
Logger.error("Compositor", "Error initializing Hyprland:", e) Logger.error("Compositor", "Error initializing Hyprland:", e)
compositorType = "unknown" compositorType = "unknown"
isHyprland = false isHyprland = false
isNiri = false
} }
} }
@ -163,31 +117,16 @@ Singleton {
workspaces.clear() workspaces.clear()
try { try {
// Add null checks for Hyprland objects
if (!Hyprland || !Hyprland.workspaces || !Hyprland.workspaces.values) {
Logger.warn("Compositor", "Hyprland workspaces not available")
return
}
const hlWorkspaces = Hyprland.workspaces.values const hlWorkspaces = Hyprland.workspaces.values
for (var i = 0; i < hlWorkspaces.length; i++) { for (var i = 0; i < hlWorkspaces.length; i++) {
const ws = hlWorkspaces[i] const ws = hlWorkspaces[i]
// Add null checks for workspace properties
if (!ws) {
continue
}
// Only append workspaces with id >= 1 // Only append workspaces with id >= 1
if (ws.id >= 1) { if (ws.id >= 1) {
// Safe property access with proper null checks
const monitorName = ws.monitor && ws.monitor.name ? ws.monitor.name : ""
workspaces.append({ workspaces.append({
"id": i, "id": i,
"idx": ws.id, "idx": ws.id,
"name": ws.name || "", "name": ws.name || "",
"output": monitorName, "output": ws.monitor?.name || "",
"isActive": ws.active === true, "isActive": ws.active === true,
"isFocused": ws.focused === true, "isFocused": ws.focused === true,
"isUrgent": ws.urgent === true "isUrgent": ws.urgent === true
@ -204,43 +143,17 @@ Singleton {
return return
try { try {
// Add null checks for Hyprland objects
if (!Hyprland || !Hyprland.toplevels || !Hyprland.toplevels.values) {
Logger.warn("Compositor", "Hyprland toplevels not available")
return
}
const hlToplevels = Hyprland.toplevels.values const hlToplevels = Hyprland.toplevels.values
const windowsList = [] const windowsList = []
for (var i = 0; i < hlToplevels.length; i++) { for (var i = 0; i < hlToplevels.length; i++) {
const toplevel = hlToplevels[i] const toplevel = hlToplevels[i]
// Add null checks for toplevel properties
if (!toplevel) {
continue
}
// Safe property access with proper null checks
const workspaceId = toplevel.workspace && toplevel.workspace.id !== undefined ? toplevel.workspace.id : null
// Extra safety for activeToplevel access - this is often the source of crashes
let isFocused = false
try {
if (Hyprland && Hyprland.activeToplevel && toplevel.address) {
isFocused = Hyprland.activeToplevel.address === toplevel.address
}
} catch (e) {
// activeToplevel access failed, default to false
isFocused = false
}
windowsList.push({ windowsList.push({
"id": toplevel.address || "", "id": toplevel.address || "",
"title": toplevel.title || "", "title": toplevel.title || "",
"appId": toplevel.class || toplevel.initialClass || "", "appId": toplevel.class || toplevel.initialClass || "",
"workspaceId": workspaceId, "workspaceId": toplevel.workspace?.id || null,
"isFocused": isFocused "isFocused": toplevel.activated === true
}) })
} }
@ -259,10 +172,6 @@ Singleton {
activeWindowChanged() activeWindowChanged()
} catch (e) { } catch (e) {
Logger.error("Compositor", "Error updating Hyprland windows:", e) Logger.error("Compositor", "Error updating Hyprland windows:", e)
// Reset to safe state on error
windows = []
focusedWindowIndex = -1
updateFocusedWindowTitle()
} }
} }
@ -519,13 +428,9 @@ Singleton {
// Get focused window // Get focused window
function getFocusedWindow() { function getFocusedWindow() {
try { if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.length) {
if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.length && windows) {
return windows[focusedWindowIndex] return windows[focusedWindowIndex]
} }
} catch (e) {
Logger.error("Compositor", "Error getting focused window:", e)
}
return null return null
} }
} }