mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-06 05:25:41 -05:00
274 lines
8.4 KiB
QML
274 lines
8.4 KiB
QML
pragma Singleton
|
|
pragma ComponentBehavior: Bound
|
|
|
|
import QtQuick
|
|
import Quickshell
|
|
|
|
Singleton {
|
|
id: root
|
|
|
|
property bool extWorkspaceAvailable: false
|
|
property var groups: []
|
|
property var _cachedWorkspaces: ({})
|
|
|
|
signal stateChanged()
|
|
|
|
Connections {
|
|
target: DMSService
|
|
function onCapabilitiesReceived() {
|
|
checkCapabilities()
|
|
}
|
|
function onConnectionStateChanged() {
|
|
if (DMSService.isConnected) {
|
|
checkCapabilities()
|
|
} else {
|
|
extWorkspaceAvailable = false
|
|
}
|
|
}
|
|
function onExtWorkspaceStateUpdate(data) {
|
|
if (extWorkspaceAvailable) {
|
|
handleStateUpdate(data)
|
|
}
|
|
}
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
if (DMSService.dmsAvailable) {
|
|
checkCapabilities()
|
|
}
|
|
}
|
|
|
|
function checkCapabilities() {
|
|
if (!DMSService.capabilities || !Array.isArray(DMSService.capabilities)) {
|
|
extWorkspaceAvailable = false
|
|
return
|
|
}
|
|
|
|
const hasExtWorkspace = DMSService.capabilities.includes("extworkspace")
|
|
if (hasExtWorkspace && !extWorkspaceAvailable) {
|
|
if (typeof CompositorService !== "undefined") {
|
|
const useExtWorkspace = DMSService.forceExtWorkspace || (!CompositorService.isNiri && !CompositorService.isHyprland && !CompositorService.isDwl && !CompositorService.isSway)
|
|
if (!useExtWorkspace) {
|
|
console.info("ExtWorkspaceService: ext-workspace available but compositor has native support")
|
|
extWorkspaceAvailable = false
|
|
return
|
|
}
|
|
}
|
|
extWorkspaceAvailable = true
|
|
console.info("ExtWorkspaceService: ext-workspace capability detected")
|
|
DMSService.addSubscription("extworkspace")
|
|
requestState()
|
|
} else if (!hasExtWorkspace) {
|
|
extWorkspaceAvailable = false
|
|
}
|
|
}
|
|
|
|
function requestState() {
|
|
if (!DMSService.isConnected || !extWorkspaceAvailable) {
|
|
return
|
|
}
|
|
|
|
DMSService.sendRequest("extworkspace.getState", null, response => {
|
|
if (response.result) {
|
|
handleStateUpdate(response.result)
|
|
}
|
|
})
|
|
}
|
|
|
|
function handleStateUpdate(state) {
|
|
groups = state.groups || []
|
|
if (groups.length === 0) {
|
|
console.warn("ExtWorkspaceService: Received empty workspace groups from backend")
|
|
} else {
|
|
console.log("ExtWorkspaceService: Updated with", groups.length, "workspace groups")
|
|
}
|
|
stateChanged()
|
|
}
|
|
|
|
function activateWorkspace(workspaceID, groupID = "") {
|
|
if (!DMSService.isConnected || !extWorkspaceAvailable) {
|
|
return
|
|
}
|
|
|
|
DMSService.sendRequest("extworkspace.activateWorkspace", {
|
|
"workspaceID": workspaceID,
|
|
"groupID": groupID
|
|
}, response => {
|
|
if (response.error) {
|
|
console.warn("ExtWorkspaceService: activateWorkspace error:", response.error)
|
|
}
|
|
})
|
|
}
|
|
|
|
function deactivateWorkspace(workspaceID, groupID = "") {
|
|
if (!DMSService.isConnected || !extWorkspaceAvailable) {
|
|
return
|
|
}
|
|
|
|
DMSService.sendRequest("extworkspace.deactivateWorkspace", {
|
|
"workspaceID": workspaceID,
|
|
"groupID": groupID
|
|
}, response => {
|
|
if (response.error) {
|
|
console.warn("ExtWorkspaceService: deactivateWorkspace error:", response.error)
|
|
}
|
|
})
|
|
}
|
|
|
|
function removeWorkspace(workspaceID, groupID = "") {
|
|
if (!DMSService.isConnected || !extWorkspaceAvailable) {
|
|
return
|
|
}
|
|
|
|
DMSService.sendRequest("extworkspace.removeWorkspace", {
|
|
"workspaceID": workspaceID,
|
|
"groupID": groupID
|
|
}, response => {
|
|
if (response.error) {
|
|
console.warn("ExtWorkspaceService: removeWorkspace error:", response.error)
|
|
}
|
|
})
|
|
}
|
|
|
|
function createWorkspace(groupID, name) {
|
|
if (!DMSService.isConnected || !extWorkspaceAvailable) {
|
|
return
|
|
}
|
|
|
|
DMSService.sendRequest("extworkspace.createWorkspace", {
|
|
"groupID": groupID,
|
|
"name": name
|
|
}, response => {
|
|
if (response.error) {
|
|
console.warn("ExtWorkspaceService: createWorkspace error:", response.error)
|
|
}
|
|
})
|
|
}
|
|
|
|
function getGroupForOutput(outputName) {
|
|
for (const group of groups) {
|
|
if (group.outputs && group.outputs.includes(outputName)) {
|
|
return group
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
function getWorkspacesForOutput(outputName) {
|
|
const group = getGroupForOutput(outputName)
|
|
return group ? (group.workspaces || []) : []
|
|
}
|
|
|
|
function getActiveWorkspaces() {
|
|
const active = []
|
|
for (const group of groups) {
|
|
if (!group.workspaces) continue
|
|
for (const ws of group.workspaces) {
|
|
if (ws.active) {
|
|
active.push({
|
|
workspace: ws,
|
|
group: group,
|
|
outputs: group.outputs || []
|
|
})
|
|
}
|
|
}
|
|
}
|
|
return active
|
|
}
|
|
|
|
function getActiveWorkspaceForOutput(outputName) {
|
|
const group = getGroupForOutput(outputName)
|
|
if (!group || !group.workspaces) return null
|
|
|
|
for (const ws of group.workspaces) {
|
|
if (ws.active) {
|
|
return ws
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
function getVisibleWorkspaces(outputName) {
|
|
const workspaces = getWorkspacesForOutput(outputName)
|
|
let visible = workspaces.filter(ws => !ws.hidden)
|
|
|
|
const hasValidCoordinates = visible.some(ws => ws.coordinates && ws.coordinates.length > 0)
|
|
if (hasValidCoordinates) {
|
|
visible = visible.sort((a, b) => {
|
|
const coordsA = a.coordinates || [0, 0]
|
|
const coordsB = b.coordinates || [0, 0]
|
|
if (coordsA[0] !== coordsB[0]) return coordsA[0] - coordsB[0]
|
|
return coordsA[1] - coordsB[1]
|
|
})
|
|
}
|
|
|
|
const cacheKey = outputName
|
|
if (!_cachedWorkspaces[cacheKey]) {
|
|
_cachedWorkspaces[cacheKey] = {
|
|
workspaces: [],
|
|
lastNames: []
|
|
}
|
|
}
|
|
|
|
const cache = _cachedWorkspaces[cacheKey]
|
|
const currentNames = visible.map(ws => ws.name || ws.id)
|
|
const namesChanged = JSON.stringify(cache.lastNames) !== JSON.stringify(currentNames)
|
|
|
|
if (namesChanged || cache.workspaces.length !== visible.length) {
|
|
cache.workspaces = visible.map(ws => ({
|
|
id: ws.id,
|
|
name: ws.name,
|
|
coordinates: ws.coordinates,
|
|
state: ws.state,
|
|
active: ws.active,
|
|
urgent: ws.urgent,
|
|
hidden: ws.hidden
|
|
}))
|
|
cache.lastNames = currentNames
|
|
return cache.workspaces
|
|
}
|
|
|
|
for (let i = 0; i < visible.length; i++) {
|
|
const src = visible[i]
|
|
const dst = cache.workspaces[i]
|
|
dst.id = src.id
|
|
dst.name = src.name
|
|
dst.coordinates = src.coordinates
|
|
dst.state = src.state
|
|
dst.active = src.active
|
|
dst.urgent = src.urgent
|
|
dst.hidden = src.hidden
|
|
}
|
|
|
|
return cache.workspaces
|
|
}
|
|
|
|
function getUrgentWorkspaces() {
|
|
const urgent = []
|
|
for (const group of groups) {
|
|
if (!group.workspaces) continue
|
|
for (const ws of group.workspaces) {
|
|
if (ws.urgent) {
|
|
urgent.push({
|
|
workspace: ws,
|
|
group: group,
|
|
outputs: group.outputs || []
|
|
})
|
|
}
|
|
}
|
|
}
|
|
return urgent
|
|
}
|
|
|
|
function switchToWorkspace(outputName, workspaceName) {
|
|
const workspaces = getWorkspacesForOutput(outputName)
|
|
for (const ws of workspaces) {
|
|
if (ws.name === workspaceName || ws.id === workspaceName) {
|
|
activateWorkspace(ws.name || ws.id)
|
|
return
|
|
}
|
|
}
|
|
console.warn("ExtWorkspaceService: workspace not found:", workspaceName)
|
|
}
|
|
}
|