diff --git a/Common/Proc.qml b/Common/Proc.qml index f694772f..11b31ff4 100644 --- a/Common/Proc.qml +++ b/Common/Proc.qml @@ -10,17 +10,18 @@ Singleton { property int defaultDebounceMs: 50 property int defaultTimeoutMs: 10000 - property var _procDebouncers: ({}) // id -> { timer, command, callback, waitMs } + property var _procDebouncers: ({}) function runCommand(id, command, callback, debounceMs, timeoutMs) { const wait = (typeof debounceMs === "number" && debounceMs >= 0) ? debounceMs : defaultDebounceMs const timeout = (typeof timeoutMs === "number" && timeoutMs > 0) ? timeoutMs : defaultTimeoutMs let procId = id ? id : Math.random() + const isRandomId = !id if (!_procDebouncers[procId]) { const t = Qt.createQmlObject('import QtQuick; Timer { repeat: false }', root) - t.triggered.connect(function() { _launchProc(procId) }) - _procDebouncers[procId] = { timer: t, command: command, callback: callback, waitMs: wait, timeoutMs: timeout } + t.triggered.connect(function() { _launchProc(procId, isRandomId) }) + _procDebouncers[procId] = { timer: t, command: command, callback: callback, waitMs: wait, timeoutMs: timeout, isRandomId: isRandomId } } else { _procDebouncers[procId].command = command _procDebouncers[procId].callback = callback @@ -33,7 +34,7 @@ Singleton { entry.timer.restart() } - function _launchProc(id) { + function _launchProc(id, isRandomId) { const entry = _procDebouncers[id] if (!entry) return @@ -92,6 +93,15 @@ Singleton { } try { proc.destroy() } catch (_) {} try { timeoutTimer.destroy() } catch (_) {} + + if (isRandomId || entry.isRandomId) { + Qt.callLater(function() { + if (_procDebouncers[id]) { + try { _procDebouncers[id].timer.destroy() } catch (_) {} + delete _procDebouncers[id] + } + }) + } } proc.running = true diff --git a/Services/CompositorService.qml b/Services/CompositorService.qml index 71362890..439890e7 100644 --- a/Services/CompositorService.qml +++ b/Services/CompositorService.qml @@ -29,6 +29,9 @@ Singleton { property bool _hasRefreshedOnce: false property var _coordCache: ({}) + property int _refreshCount: 0 + property real _refreshWindowStart: 0 + readonly property int _maxRefreshesPerSecond: 3 function getScreenScale(screen) { if (!screen) return 1 @@ -77,6 +80,19 @@ Singleton { function scheduleRefresh() { if (!isHyprland) return if (_refreshScheduled) return + + const now = Date.now() + if (now - _refreshWindowStart > 1000) { + _refreshCount = 0 + _refreshWindowStart = now + } + + if (_refreshCount >= _maxRefreshesPerSecond) { + console.warn("CompositorService: Refresh rate limit exceeded, skipping refresh") + return + } + + _refreshCount++ _refreshScheduled = true refreshTimer.restart() } @@ -158,6 +174,18 @@ Singleton { } catch(e) { return fb } } + let currentAddresses = new Set() + for (let i = 0; i < items.length; i++) { + const addr = items[i]?.address + if (addr) currentAddresses.add(addr) + } + + for (let cachedAddr in _coordCache) { + if (!currentAddresses.has(cachedAddr)) { + delete _coordCache[cachedAddr] + } + } + let snap = [] let missingAnyPosition = false let hasNewWindow = false diff --git a/Services/HyprKeybindsService.qml b/Services/HyprKeybindsService.qml index 01469cda..70f230eb 100644 --- a/Services/HyprKeybindsService.qml +++ b/Services/HyprKeybindsService.qml @@ -19,7 +19,7 @@ Singleton { Process { id: getKeybinds - running: true + running: false command: [root.scriptPath, "--path", root.hyprConfigPath] stdout: SplitParser { @@ -31,9 +31,22 @@ Singleton { } } } + + onExited: (code) => { + if (code !== 0) { + console.warn("[HyprKeybindsService] Process exited with code:", code) + } + } + } + + Component.onCompleted: { + getKeybinds.running = true } function reload() { - getKeybinds.running = true + getKeybinds.running = false + Qt.callLater(function() { + getKeybinds.running = true + }) } }