pragma Singleton pragma ComponentBehavior: Bound import QtCore import QtQuick import Quickshell import Quickshell.Hyprland import qs.Common Singleton { id: root readonly property string configDir: Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation)) readonly property string hyprDmsDir: configDir + "/hypr/dms" readonly property string outputsPath: hyprDmsDir + "/outputs.conf" function getOutputIdentifier(output, outputName) { if (SettingsData.displayNameMode === "model" && output.make && output.model) { return "desc:" + output.make + " " + output.model } return outputName } function generateOutputsConfig(outputsData) { if (!outputsData || Object.keys(outputsData).length === 0) return let lines = ["# Auto-generated by DMS - do not edit manually", ""] for (const outputName in outputsData) { const output = outputsData[outputName] if (!output) continue let resolution = "preferred" if (output.modes && output.current_mode !== undefined) { const mode = output.modes[output.current_mode] if (mode) resolution = mode.width + "x" + mode.height + "@" + (mode.refresh_rate / 1000).toFixed(3) } const x = output.logical?.x ?? 0 const y = output.logical?.y ?? 0 const position = x + "x" + y const scale = output.logical?.scale ?? 1.0 const identifier = getOutputIdentifier(output, outputName) let monitorLine = "monitor = " + identifier + ", " + resolution + ", " + position + ", " + scale const transform = transformToHyprland(output.logical?.transform ?? "Normal") if (transform !== 0) monitorLine += ", transform, " + transform if (output.vrr_supported && output.vrr_enabled) monitorLine += ", vrr, 1" lines.push(monitorLine) } lines.push("") const content = lines.join("\n") Proc.runCommand("hypr-write-outputs", ["sh", "-c", `mkdir -p "${hyprDmsDir}" && cat > "${outputsPath}" << 'EOF'\n${content}EOF`], (output, exitCode) => { if (exitCode !== 0) { console.warn("HyprlandService: Failed to write outputs config:", output) return } console.info("HyprlandService: Generated outputs config at", outputsPath) if (CompositorService.isHyprland) reloadConfig() }) } function reloadConfig() { Proc.runCommand("hyprctl-reload", ["hyprctl", "reload"], (output, exitCode) => { if (exitCode !== 0) console.warn("HyprlandService: hyprctl reload failed:", output) }) } function transformToHyprland(transform) { switch (transform) { case "Normal": return 0 case "90": return 1 case "180": return 2 case "270": return 3 case "Flipped": return 4 case "Flipped90": return 5 case "Flipped180": return 6 case "Flipped270": return 7 default: return 0 } } function hyprlandToTransform(value) { switch (value) { case 0: return "Normal" case 1: return "90" case 2: return "180" case 3: return "270" case 4: return "Flipped" case 5: return "Flipped90" case 6: return "Flipped180" case 7: return "Flipped270" default: return "Normal" } } }