Add CompositorService, make Logger look a bit nicer

This commit is contained in:
Ly-sec 2025-08-17 10:19:51 +02:00
parent c991ac85b4
commit 05f9acdc5d
9 changed files with 473 additions and 297 deletions

View file

@ -4,150 +4,46 @@ pragma ComponentBehavior
import QtQuick
import Quickshell
import Quickshell.Io
import Quickshell.Hyprland
import qs.Commons
import qs.Services
Singleton {
id: root
// Delegate to CompositorService for all workspace operations
property ListModel workspaces: ListModel {}
property bool isHyprland: false
property bool isNiri: false
property var hlWorkspaces: Hyprland.workspaces.values
// Detect which compositor we're using
Component.onCompleted: {
detectCompositor()
}
function detectCompositor() {
try {
try {
if (Hyprland.eventSocketPath) {
isHyprland = true
isNiri = false
initHyprland()
return
}
} catch (e) {
}
if (typeof NiriService !== "undefined") {
isHyprland = false
isNiri = true
initNiri()
return
}
} catch (e) {
Logger.error("WorkspacesService", "Error detecting compositor:", e)
}
}
// Initialize Hyprland integration
function initHyprland() {
try {
// Fixes the odd workspace issue.
Hyprland.refreshWorkspaces()
// hlWorkspaces = Hyprland.workspaces.values;
// updateHyprlandWorkspaces();
return true
} catch (e) {
Logger.error("WorkspacesService", "Error initializing Hyprland:", e)
isHyprland = false
return false
}
}
onHlWorkspacesChanged: {
updateHyprlandWorkspaces()
// Connect to CompositorService workspace changes
CompositorService.workspaceChanged.connect(updateWorkspaces)
// Initial sync
updateWorkspaces()
}
// Listen to compositor detection changes
Connections {
target: Hyprland.workspaces
function onValuesChanged() {
updateHyprlandWorkspaces()
target: CompositorService
function onIsHyprlandChanged() {
isHyprland = CompositorService.isHyprland
}
function onIsNiriChanged() {
isNiri = CompositorService.isNiri
}
}
Connections {
target: Hyprland
function onRawEvent(event) {
updateHyprlandWorkspaces()
}
}
function updateHyprlandWorkspaces() {
function updateWorkspaces() {
workspaces.clear()
try {
for (var i = 0; i < hlWorkspaces.length; i++) {
const ws = hlWorkspaces[i]
// Only append workspaces with id >= 1
if (ws.id >= 1) {
workspaces.append({
"id": i,
"idx": ws.id,
"name": ws.name || "",
"output": ws.monitor?.name || "",
"isActive": ws.active === true,
"isFocused": ws.focused === true,
"isUrgent": ws.urgent === true
})
}
}
workspacesChanged()
} catch (e) {
Logger.error("WorkspacesService", "Error updating Hyprland workspaces:", e)
for (var i = 0; i < CompositorService.workspaces.count; i++) {
const ws = CompositorService.workspaces.get(i)
workspaces.append(ws)
}
}
function initNiri() {
updateNiriWorkspaces()
}
Connections {
target: NiriService
function onWorkspacesChanged() {
updateNiriWorkspaces()
}
}
function updateNiriWorkspaces() {
const niriWorkspaces = NiriService.workspaces || []
workspaces.clear()
for (var i = 0; i < niriWorkspaces.length; i++) {
const ws = niriWorkspaces[i]
workspaces.append({
"id": ws.id,
"idx": ws.idx || 1,
"name": ws.name || "",
"output": ws.output || "",
"isFocused": ws.isFocused === true,
"isActive": ws.isActive === true,
"isUrgent": ws.isUrgent === true,
"isOccupied": ws.isOccupied === true
})
}
// Explicitly trigger the signal to ensure the Workspace module gets notified
workspacesChanged()
}
function switchToWorkspace(workspaceId) {
if (isHyprland) {
try {
Hyprland.dispatch(`workspace ${workspaceId}`)
} catch (e) {
Logger.error("WorkspacesService", "Error switching Hyprland workspace:", e)
}
} else if (isNiri) {
try {
Quickshell.execDetached(["niri", "msg", "action", "focus-workspace", workspaceId.toString()])
} catch (e) {
Logger.error("WorkspacesService", "Error switching Niri workspace:", e)
}
} else {
Logger.warn("WorkspacesService", "No supported compositor detected for workspace switching")
}
CompositorService.switchToWorkspace(workspaceId)
}
}