mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-05 21:15:38 -05:00
wayland: add wlr-output-management-unstable-v1 service + labwc info
This commit is contained in:
@@ -56,7 +56,7 @@ BasePill {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IconImage {
|
IconImage {
|
||||||
visible: SettingsData.launcherLogoMode === "compositor" && (CompositorService.isNiri || CompositorService.isHyprland || CompositorService.isDwl || CompositorService.isSway)
|
visible: SettingsData.launcherLogoMode === "compositor" && (CompositorService.isNiri || CompositorService.isHyprland || CompositorService.isDwl || CompositorService.isSway || CompositorService.isLabwc)
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
width: Theme.barIconSize(root.barThickness, SettingsData.launcherLogoSizeOffset)
|
width: Theme.barIconSize(root.barThickness, SettingsData.launcherLogoSizeOffset)
|
||||||
height: Theme.barIconSize(root.barThickness, SettingsData.launcherLogoSizeOffset)
|
height: Theme.barIconSize(root.barThickness, SettingsData.launcherLogoSizeOffset)
|
||||||
@@ -71,6 +71,8 @@ BasePill {
|
|||||||
return "file://" + Theme.shellDir + "/assets/mango.png"
|
return "file://" + Theme.shellDir + "/assets/mango.png"
|
||||||
} else if (CompositorService.isSway) {
|
} else if (CompositorService.isSway) {
|
||||||
return "file://" + Theme.shellDir + "/assets/sway.svg"
|
return "file://" + Theme.shellDir + "/assets/sway.svg"
|
||||||
|
} else if (CompositorService.isLabwc) {
|
||||||
|
return "file://" + Theme.shellDir + "/assets/labwc.png"
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,11 +13,13 @@ Item {
|
|||||||
property bool isNiri: CompositorService.isNiri
|
property bool isNiri: CompositorService.isNiri
|
||||||
property bool isSway: CompositorService.isSway
|
property bool isSway: CompositorService.isSway
|
||||||
property bool isDwl: CompositorService.isDwl
|
property bool isDwl: CompositorService.isDwl
|
||||||
|
property bool isLabwc: CompositorService.isLabwc
|
||||||
|
|
||||||
property string compositorName: {
|
property string compositorName: {
|
||||||
if (isHyprland) return "hyprland"
|
if (isHyprland) return "hyprland"
|
||||||
if (isSway) return "sway"
|
if (isSway) return "sway"
|
||||||
if (isDwl) return "mangowc"
|
if (isDwl) return "mangowc"
|
||||||
|
if (isLabwc) return "labwc"
|
||||||
return "niri"
|
return "niri"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,6 +27,7 @@ Item {
|
|||||||
if (isHyprland) return "/assets/hyprland.svg"
|
if (isHyprland) return "/assets/hyprland.svg"
|
||||||
if (isSway) return "/assets/sway.svg"
|
if (isSway) return "/assets/sway.svg"
|
||||||
if (isDwl) return "/assets/mango.png"
|
if (isDwl) return "/assets/mango.png"
|
||||||
|
if (isLabwc) return "/assets/labwc.png"
|
||||||
return "/assets/niri.svg"
|
return "/assets/niri.svg"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,6 +35,7 @@ Item {
|
|||||||
if (isHyprland) return "https://hypr.land"
|
if (isHyprland) return "https://hypr.land"
|
||||||
if (isSway) return "https://swaywm.org"
|
if (isSway) return "https://swaywm.org"
|
||||||
if (isDwl) return "https://github.com/DreamMaoMao/mangowc"
|
if (isDwl) return "https://github.com/DreamMaoMao/mangowc"
|
||||||
|
if (isLabwc) return "https://labwc.github.io/"
|
||||||
return "https://github.com/YaLTeR/niri"
|
return "https://github.com/YaLTeR/niri"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,6 +43,7 @@ Item {
|
|||||||
if (isHyprland) return "Hyprland Website"
|
if (isHyprland) return "Hyprland Website"
|
||||||
if (isSway) return "Sway Website"
|
if (isSway) return "Sway Website"
|
||||||
if (isDwl) return "mangowc GitHub"
|
if (isDwl) return "mangowc GitHub"
|
||||||
|
if (isLabwc) return "LabWC Website"
|
||||||
return "niri GitHub"
|
return "niri GitHub"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,9 +65,13 @@ Item {
|
|||||||
property string redditUrl: "https://reddit.com/r/niri"
|
property string redditUrl: "https://reddit.com/r/niri"
|
||||||
property string redditTooltip: "r/niri Subreddit"
|
property string redditTooltip: "r/niri Subreddit"
|
||||||
|
|
||||||
property bool showMatrix: isNiri && !isHyprland && !isSway && !isDwl
|
property string ircUrl: "https://web.libera.chat/gamja/?channels=#labwc"
|
||||||
|
property string ircTooltip: "LabWC IRC Channel"
|
||||||
|
|
||||||
|
property bool showMatrix: isNiri && !isHyprland && !isSway && !isDwl && !isLabwc
|
||||||
property bool showCompositorDiscord: isHyprland || isDwl
|
property bool showCompositorDiscord: isHyprland || isDwl
|
||||||
property bool showReddit: isNiri && !isHyprland && !isSway && !isDwl
|
property bool showReddit: isNiri && !isHyprland && !isSway && !isDwl && !isLabwc
|
||||||
|
property bool showIrc: isLabwc
|
||||||
|
|
||||||
DankFlickable {
|
DankFlickable {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -153,6 +162,9 @@ Item {
|
|||||||
if (showMatrix) {
|
if (showMatrix) {
|
||||||
baseWidth += matrixButton.width + 4
|
baseWidth += matrixButton.width + 4
|
||||||
}
|
}
|
||||||
|
if (showIrc) {
|
||||||
|
baseWidth += ircButton.width + Theme.spacingM
|
||||||
|
}
|
||||||
if (showCompositorDiscord) {
|
if (showCompositorDiscord) {
|
||||||
baseWidth += compositorDiscordButton.width + Theme.spacingM
|
baseWidth += compositorDiscordButton.width + Theme.spacingM
|
||||||
}
|
}
|
||||||
@@ -232,11 +244,43 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: ircButton
|
||||||
|
width: 24
|
||||||
|
height: 24
|
||||||
|
x: compositorButton.x + compositorButton.width + Theme.spacingM
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
visible: showIrc
|
||||||
|
|
||||||
|
property bool hovered: false
|
||||||
|
property string tooltipText: ircTooltip
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
name: "forum"
|
||||||
|
size: 20
|
||||||
|
color: Theme.surfaceText
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
hoverEnabled: true
|
||||||
|
onEntered: parent.hovered = true
|
||||||
|
onExited: parent.hovered = false
|
||||||
|
onClicked: Qt.openUrlExternally(ircUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: dmsDiscordButton
|
id: dmsDiscordButton
|
||||||
width: 20
|
width: 20
|
||||||
height: 20
|
height: 20
|
||||||
x: showMatrix ? matrixButton.x + matrixButton.width + Theme.spacingM : compositorButton.x + compositorButton.width + Theme.spacingM
|
x: {
|
||||||
|
if (showMatrix) return matrixButton.x + matrixButton.width + Theme.spacingM
|
||||||
|
if (showIrc) return ircButton.x + ircButton.width + Theme.spacingM
|
||||||
|
return compositorButton.x + compositorButton.width + Theme.spacingM
|
||||||
|
}
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
property bool hovered: false
|
property bool hovered: false
|
||||||
@@ -618,6 +662,7 @@ Item {
|
|||||||
property var hoveredButton: {
|
property var hoveredButton: {
|
||||||
if (compositorButton.hovered) return compositorButton
|
if (compositorButton.hovered) return compositorButton
|
||||||
if (matrixButton.visible && matrixButton.hovered) return matrixButton
|
if (matrixButton.visible && matrixButton.hovered) return matrixButton
|
||||||
|
if (ircButton.visible && ircButton.hovered) return ircButton
|
||||||
if (dmsDiscordButton.hovered) return dmsDiscordButton
|
if (dmsDiscordButton.hovered) return dmsDiscordButton
|
||||||
if (compositorDiscordButton.visible && compositorDiscordButton.hovered) return compositorDiscordButton
|
if (compositorDiscordButton.visible && compositorDiscordButton.hovered) return compositorDiscordButton
|
||||||
if (redditButton.visible && redditButton.hovered) return redditButton
|
if (redditButton.visible && redditButton.hovered) return redditButton
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
DankMaterialShell is a complete desktop shell for [niri](https://github.com/YaLTeR/niri), [Hyprland](https://hypr.land), [MangoWC](https://github.com/DreamMaoMao/mangowc), [Sway](https://swaywm.org), and other Wayland compositors. It replaces waybar, swaylock, swayidle, mako, fuzzel, polkit, and everything else you'd normally stitch together to make a desktop - all in one cohesive package with a gorgeous interface.
|
DankMaterialShell is a complete desktop shell for [niri](https://github.com/YaLTeR/niri), [Hyprland](https://hypr.land), [MangoWC](https://github.com/DreamMaoMao/mangowc), [Sway](https://swaywm.org), [labwc](https://labwc.github.io/), and other Wayland compositors. It replaces waybar, swaylock, swayidle, mako, fuzzel, polkit, and everything else you'd normally stitch together to make a desktop - all in one cohesive package with a gorgeous interface.
|
||||||
|
|
||||||
## Components
|
## Components
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ Endless customization with the [plugin registry](https://plugins.danklinux.com).
|
|||||||
|
|
||||||
## Supported Compositors
|
## Supported Compositors
|
||||||
|
|
||||||
DankMaterialShell works best with **[niri](https://github.com/YaLTeR/niri)**, **[Hyprland](https://hyprland.org/)**, **[sway](https://swaywm.org/)**, and **[dwl/MangoWC](https://github.com/DreamMaoMao/mangowc)** - with full workspace switching, overview integration, and monitor management.
|
DankMaterialShell works best with **[niri](https://github.com/YaLTeR/niri)**, **[Hyprland](https://hyprland.org/)**, **[sway](https://swaywm.org/)**, **[dwl/MangoWC](https://github.com/DreamMaoMao/mangowc)**, and **[labwc](https://labwc.github.io/)** - with full workspace switching, overview integration, and monitor management.
|
||||||
|
|
||||||
Other Wayland compositors work too, just with a reduced feature set.
|
Other Wayland compositors work too, just with a reduced feature set.
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,13 @@ Singleton {
|
|||||||
property bool isNiri: false
|
property bool isNiri: false
|
||||||
property bool isDwl: false
|
property bool isDwl: false
|
||||||
property bool isSway: false
|
property bool isSway: false
|
||||||
|
property bool isLabwc: false
|
||||||
property string compositor: "unknown"
|
property string compositor: "unknown"
|
||||||
|
|
||||||
readonly property string hyprlandSignature: Quickshell.env("HYPRLAND_INSTANCE_SIGNATURE")
|
readonly property string hyprlandSignature: Quickshell.env("HYPRLAND_INSTANCE_SIGNATURE")
|
||||||
readonly property string niriSocket: Quickshell.env("NIRI_SOCKET")
|
readonly property string niriSocket: Quickshell.env("NIRI_SOCKET")
|
||||||
readonly property string swaySocket: Quickshell.env("SWAYSOCK")
|
readonly property string swaySocket: Quickshell.env("SWAYSOCK")
|
||||||
|
readonly property string labwcPid: Quickshell.env("LABWC_PID")
|
||||||
property bool useNiriSorting: isNiri && NiriService
|
property bool useNiriSorting: isNiri && NiriService
|
||||||
|
|
||||||
property var sortedToplevels: []
|
property var sortedToplevels: []
|
||||||
@@ -33,6 +35,13 @@ Singleton {
|
|||||||
return screen.devicePixelRatio || 1
|
return screen.devicePixelRatio || 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (WlrOutputService.wlrOutputAvailable && screen) {
|
||||||
|
const wlrOutput = WlrOutputService.getOutput(screen.name)
|
||||||
|
if (wlrOutput?.enabled && wlrOutput.scale !== undefined && wlrOutput.scale > 0) {
|
||||||
|
return wlrOutput.scale
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isNiri && screen) {
|
if (isNiri && screen) {
|
||||||
const niriScale = NiriService.displayScales[screen.name]
|
const niriScale = NiriService.displayScales[screen.name]
|
||||||
if (niriScale !== undefined) return niriScale
|
if (niriScale !== undefined) return niriScale
|
||||||
@@ -343,6 +352,7 @@ Singleton {
|
|||||||
isNiri = false
|
isNiri = false
|
||||||
isDwl = false
|
isDwl = false
|
||||||
isSway = false
|
isSway = false
|
||||||
|
isLabwc = false
|
||||||
compositor = "hyprland"
|
compositor = "hyprland"
|
||||||
console.info("CompositorService: Detected Hyprland")
|
console.info("CompositorService: Detected Hyprland")
|
||||||
return
|
return
|
||||||
@@ -355,6 +365,7 @@ Singleton {
|
|||||||
isHyprland = false
|
isHyprland = false
|
||||||
isDwl = false
|
isDwl = false
|
||||||
isSway = false
|
isSway = false
|
||||||
|
isLabwc = false
|
||||||
compositor = "niri"
|
compositor = "niri"
|
||||||
console.info("CompositorService: Detected Niri with socket:", niriSocket)
|
console.info("CompositorService: Detected Niri with socket:", niriSocket)
|
||||||
NiriService.generateNiriBinds()
|
NiriService.generateNiriBinds()
|
||||||
@@ -371,13 +382,25 @@ Singleton {
|
|||||||
isHyprland = false
|
isHyprland = false
|
||||||
isDwl = false
|
isDwl = false
|
||||||
isSway = true
|
isSway = true
|
||||||
|
isLabwc = false
|
||||||
compositor = "sway"
|
compositor = "sway"
|
||||||
console.info("CompositorService: Detected Sway with socket:", swaySocket)
|
console.info("CompositorService: Detected Sway with socket:", swaySocket)
|
||||||
}
|
}
|
||||||
}, 0)
|
}, 0)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (labwcPid && labwcPid.length > 0) {
|
||||||
|
isHyprland = false
|
||||||
|
isNiri = false
|
||||||
|
isDwl = false
|
||||||
|
isSway = false
|
||||||
|
isLabwc = true
|
||||||
|
compositor = "labwc"
|
||||||
|
console.info("CompositorService: Detected LabWC with PID:", labwcPid)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (DMSService.dmsAvailable) {
|
if (DMSService.dmsAvailable) {
|
||||||
Qt.callLater(checkForDwl)
|
Qt.callLater(checkForDwl)
|
||||||
} else {
|
} else {
|
||||||
@@ -385,6 +408,7 @@ Singleton {
|
|||||||
isNiri = false
|
isNiri = false
|
||||||
isDwl = false
|
isDwl = false
|
||||||
isSway = false
|
isSway = false
|
||||||
|
isLabwc = false
|
||||||
compositor = "unknown"
|
compositor = "unknown"
|
||||||
console.warn("CompositorService: No compositor detected")
|
console.warn("CompositorService: No compositor detected")
|
||||||
}
|
}
|
||||||
@@ -393,7 +417,7 @@ Singleton {
|
|||||||
Connections {
|
Connections {
|
||||||
target: DMSService
|
target: DMSService
|
||||||
function onCapabilitiesReceived() {
|
function onCapabilitiesReceived() {
|
||||||
if (!isHyprland && !isNiri && !isDwl) {
|
if (!isHyprland && !isNiri && !isDwl && !isLabwc) {
|
||||||
checkForDwl()
|
checkForDwl()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -404,6 +428,8 @@ Singleton {
|
|||||||
isHyprland = false
|
isHyprland = false
|
||||||
isNiri = false
|
isNiri = false
|
||||||
isDwl = true
|
isDwl = true
|
||||||
|
isSway = false
|
||||||
|
isLabwc = false
|
||||||
compositor = "dwl"
|
compositor = "dwl"
|
||||||
console.info("CompositorService: Detected DWL via DMS capability")
|
console.info("CompositorService: Detected DWL via DMS capability")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
|
||||||
pragma ComponentBehavior
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
|
|||||||
@@ -48,8 +48,9 @@ Singleton {
|
|||||||
signal brightnessStateUpdate(var data)
|
signal brightnessStateUpdate(var data)
|
||||||
signal brightnessDeviceUpdate(var device)
|
signal brightnessDeviceUpdate(var device)
|
||||||
signal extWorkspaceStateUpdate(var data)
|
signal extWorkspaceStateUpdate(var data)
|
||||||
|
signal wlrOutputStateUpdate(var data)
|
||||||
|
|
||||||
property var activeSubscriptions: ["network", "network.credentials", "loginctl", "freedesktop", "gamma", "bluetooth", "bluetooth.pairing", "dwl", "brightness"]
|
property var activeSubscriptions: ["network", "network.credentials", "loginctl", "freedesktop", "gamma", "bluetooth", "bluetooth.pairing", "dwl", "brightness", "wlroutput"]
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (socketPath && socketPath.length > 0) {
|
if (socketPath && socketPath.length > 0) {
|
||||||
@@ -346,6 +347,8 @@ Singleton {
|
|||||||
}
|
}
|
||||||
} else if (service === "extworkspace") {
|
} else if (service === "extworkspace") {
|
||||||
extWorkspaceStateUpdate(data)
|
extWorkspaceStateUpdate(data)
|
||||||
|
} else if (service === "wlroutput") {
|
||||||
|
wlrOutputStateUpdate(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
275
Services/WlrOutputService.qml
Normal file
275
Services/WlrOutputService.qml
Normal file
@@ -0,0 +1,275 @@
|
|||||||
|
pragma Singleton
|
||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property bool wlrOutputAvailable: false
|
||||||
|
property var outputs: []
|
||||||
|
property int serial: 0
|
||||||
|
|
||||||
|
signal stateChanged
|
||||||
|
signal configurationApplied(bool success, string message)
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: DMSService
|
||||||
|
|
||||||
|
function onCapabilitiesReceived() {
|
||||||
|
checkCapabilities()
|
||||||
|
}
|
||||||
|
|
||||||
|
function onConnectionStateChanged() {
|
||||||
|
if (DMSService.isConnected) {
|
||||||
|
checkCapabilities()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
wlrOutputAvailable = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function onWlrOutputStateUpdate(data) {
|
||||||
|
if (!wlrOutputAvailable) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
handleStateUpdate(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (!DMSService.dmsAvailable) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
checkCapabilities()
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCapabilities() {
|
||||||
|
if (!DMSService.capabilities || !Array.isArray(DMSService.capabilities)) {
|
||||||
|
wlrOutputAvailable = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasWlrOutput = DMSService.capabilities.includes("wlroutput")
|
||||||
|
if (hasWlrOutput && !wlrOutputAvailable) {
|
||||||
|
wlrOutputAvailable = true
|
||||||
|
console.info("WlrOutputService: wlr-output-management capability detected")
|
||||||
|
requestState()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasWlrOutput) {
|
||||||
|
wlrOutputAvailable = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestState() {
|
||||||
|
if (!DMSService.isConnected || !wlrOutputAvailable) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
DMSService.sendRequest("wlroutput.getState", null, response => {
|
||||||
|
if (!response.result) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
handleStateUpdate(response.result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleStateUpdate(state) {
|
||||||
|
outputs = state.outputs || []
|
||||||
|
serial = state.serial || 0
|
||||||
|
|
||||||
|
if (outputs.length === 0) {
|
||||||
|
console.warn("WlrOutputService: Received empty outputs list")
|
||||||
|
} else {
|
||||||
|
console.log("WlrOutputService: Updated with", outputs.length, "outputs, serial:", serial)
|
||||||
|
outputs.forEach((output, index) => {
|
||||||
|
console.log("WlrOutputService: Output", index, "-", output.name,
|
||||||
|
"enabled:", output.enabled,
|
||||||
|
"mode:", output.currentMode ?
|
||||||
|
output.currentMode.width + "x" + output.currentMode.height + "@" +
|
||||||
|
(output.currentMode.refresh / 1000) + "Hz" : "none")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
stateChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOutput(name) {
|
||||||
|
for (const output of outputs) {
|
||||||
|
if (output.name === name) {
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEnabledOutputs() {
|
||||||
|
return outputs.filter(output => output.enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyConfiguration(heads, callback) {
|
||||||
|
if (!DMSService.isConnected || !wlrOutputAvailable) {
|
||||||
|
if (callback) {
|
||||||
|
callback(false, "Not connected")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("WlrOutputService: Applying configuration for", heads.length, "outputs")
|
||||||
|
heads.forEach((head, index) => {
|
||||||
|
console.log("WlrOutputService: Head", index, "- name:", head.name,
|
||||||
|
"enabled:", head.enabled,
|
||||||
|
"modeId:", head.modeId,
|
||||||
|
"customMode:", JSON.stringify(head.customMode),
|
||||||
|
"position:", JSON.stringify(head.position),
|
||||||
|
"scale:", head.scale,
|
||||||
|
"transform:", head.transform,
|
||||||
|
"adaptiveSync:", head.adaptiveSync)
|
||||||
|
})
|
||||||
|
|
||||||
|
DMSService.sendRequest("wlroutput.applyConfiguration", {
|
||||||
|
"heads": heads
|
||||||
|
}, response => {
|
||||||
|
const success = !response.error
|
||||||
|
const message = response.error || response.result?.message || ""
|
||||||
|
|
||||||
|
if (response.error) {
|
||||||
|
console.warn("WlrOutputService: applyConfiguration error:", response.error)
|
||||||
|
} else {
|
||||||
|
console.log("WlrOutputService: Configuration applied successfully")
|
||||||
|
}
|
||||||
|
|
||||||
|
configurationApplied(success, message)
|
||||||
|
if (callback) {
|
||||||
|
callback(success, message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function testConfiguration(heads, callback) {
|
||||||
|
if (!DMSService.isConnected || !wlrOutputAvailable) {
|
||||||
|
if (callback) {
|
||||||
|
callback(false, "Not connected")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("WlrOutputService: Testing configuration for", heads.length, "outputs")
|
||||||
|
|
||||||
|
DMSService.sendRequest("wlroutput.testConfiguration", {
|
||||||
|
"heads": heads
|
||||||
|
}, response => {
|
||||||
|
const success = !response.error
|
||||||
|
const message = response.error || response.result?.message || ""
|
||||||
|
|
||||||
|
if (response.error) {
|
||||||
|
console.warn("WlrOutputService: testConfiguration error:", response.error)
|
||||||
|
} else {
|
||||||
|
console.log("WlrOutputService: Configuration test passed")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callback) {
|
||||||
|
callback(success, message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function setOutputEnabled(outputName, enabled, callback) {
|
||||||
|
const output = getOutput(outputName)
|
||||||
|
if (!output) {
|
||||||
|
console.warn("WlrOutputService: Output not found:", outputName)
|
||||||
|
if (callback) {
|
||||||
|
callback(false, "Output not found")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const heads = [{
|
||||||
|
"name": outputName,
|
||||||
|
"enabled": enabled
|
||||||
|
}]
|
||||||
|
|
||||||
|
if (enabled && output.currentMode) {
|
||||||
|
heads[0].modeId = output.currentMode.id
|
||||||
|
}
|
||||||
|
|
||||||
|
applyConfiguration(heads, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
function setOutputMode(outputName, modeId, callback) {
|
||||||
|
const heads = [{
|
||||||
|
"name": outputName,
|
||||||
|
"enabled": true,
|
||||||
|
"modeId": modeId
|
||||||
|
}]
|
||||||
|
|
||||||
|
applyConfiguration(heads, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
function setOutputCustomMode(outputName, width, height, refresh, callback) {
|
||||||
|
const heads = [{
|
||||||
|
"name": outputName,
|
||||||
|
"enabled": true,
|
||||||
|
"customMode": {
|
||||||
|
"width": width,
|
||||||
|
"height": height,
|
||||||
|
"refresh": refresh
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
applyConfiguration(heads, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
function setOutputPosition(outputName, x, y, callback) {
|
||||||
|
const heads = [{
|
||||||
|
"name": outputName,
|
||||||
|
"enabled": true,
|
||||||
|
"position": {
|
||||||
|
"x": x,
|
||||||
|
"y": y
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
applyConfiguration(heads, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
function setOutputScale(outputName, scale, callback) {
|
||||||
|
const heads = [{
|
||||||
|
"name": outputName,
|
||||||
|
"enabled": true,
|
||||||
|
"scale": scale
|
||||||
|
}]
|
||||||
|
|
||||||
|
applyConfiguration(heads, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
function setOutputTransform(outputName, transform, callback) {
|
||||||
|
const heads = [{
|
||||||
|
"name": outputName,
|
||||||
|
"enabled": true,
|
||||||
|
"transform": transform
|
||||||
|
}]
|
||||||
|
|
||||||
|
applyConfiguration(heads, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
function setOutputAdaptiveSync(outputName, state, callback) {
|
||||||
|
const heads = [{
|
||||||
|
"name": outputName,
|
||||||
|
"enabled": true,
|
||||||
|
"adaptiveSync": state
|
||||||
|
}]
|
||||||
|
|
||||||
|
applyConfiguration(heads, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureOutput(config, callback) {
|
||||||
|
const heads = [config]
|
||||||
|
applyConfiguration(heads, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureMultipleOutputs(configs, callback) {
|
||||||
|
applyConfiguration(configs, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
assets/labwc.png
Normal file
BIN
assets/labwc.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
@@ -14,13 +14,13 @@
|
|||||||
{
|
{
|
||||||
"term": "- Stateless System Monitoring",
|
"term": "- Stateless System Monitoring",
|
||||||
"context": "- Stateless System Monitoring",
|
"context": "- Stateless System Monitoring",
|
||||||
"reference": "Modules/Settings/AboutTab.qml:544",
|
"reference": "Modules/Settings/AboutTab.qml:588",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"term": "- Support Us With a Star ⭐",
|
"term": "- Support Us With a Star ⭐",
|
||||||
"context": "- Support Us With a Star ⭐",
|
"context": "- Support Us With a Star ⭐",
|
||||||
"reference": "Modules/Settings/AboutTab.qml:509",
|
"reference": "Modules/Settings/AboutTab.qml:553",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
{
|
{
|
||||||
"term": "About",
|
"term": "About",
|
||||||
"context": "About",
|
"context": "About",
|
||||||
"reference": "Modals/Settings/SettingsSidebar.qml:44, Modules/Settings/AboutTab.qml:363",
|
"reference": "Modals/Settings/SettingsSidebar.qml:44, Modules/Settings/AboutTab.qml:407",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1010,7 +1010,7 @@
|
|||||||
{
|
{
|
||||||
"term": "DMS out of date",
|
"term": "DMS out of date",
|
||||||
"context": "DMS out of date",
|
"context": "DMS out of date",
|
||||||
"reference": "Services/DMSService.qml:300",
|
"reference": "Services/DMSService.qml:301",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1262,7 +1262,7 @@
|
|||||||
{
|
{
|
||||||
"term": "Donate on Ko-fi",
|
"term": "Donate on Ko-fi",
|
||||||
"context": "Donate on Ko-fi",
|
"context": "Donate on Ko-fi",
|
||||||
"reference": "Modules/Settings/AboutTab.qml:598",
|
"reference": "Modules/Settings/AboutTab.qml:642",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1688,7 +1688,7 @@
|
|||||||
{
|
{
|
||||||
"term": "Github:",
|
"term": "Github:",
|
||||||
"context": "Github:",
|
"context": "Github:",
|
||||||
"reference": "Modules/Settings/AboutTab.qml:482",
|
"reference": "Modules/Settings/AboutTab.qml:526",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2798,7 +2798,7 @@
|
|||||||
{
|
{
|
||||||
"term": "Plugins:",
|
"term": "Plugins:",
|
||||||
"context": "Plugins:",
|
"context": "Plugins:",
|
||||||
"reference": "Modules/Settings/AboutTab.qml:459",
|
"reference": "Modules/Settings/AboutTab.qml:503",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -3026,7 +3026,7 @@
|
|||||||
{
|
{
|
||||||
"term": "Resources",
|
"term": "Resources",
|
||||||
"context": "Resources",
|
"context": "Resources",
|
||||||
"reference": "Modules/Settings/AboutTab.qml:421",
|
"reference": "Modules/Settings/AboutTab.qml:465",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -3500,7 +3500,7 @@
|
|||||||
{
|
{
|
||||||
"term": "Support Development",
|
"term": "Support Development",
|
||||||
"context": "Support Development",
|
"context": "Support Development",
|
||||||
"reference": "Modules/Settings/AboutTab.qml:583",
|
"reference": "Modules/Settings/AboutTab.qml:627",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -3578,7 +3578,7 @@
|
|||||||
{
|
{
|
||||||
"term": "System Monitoring:",
|
"term": "System Monitoring:",
|
||||||
"context": "System Monitoring:",
|
"context": "System Monitoring:",
|
||||||
"reference": "Modules/Settings/AboutTab.qml:517",
|
"reference": "Modules/Settings/AboutTab.qml:561",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -3728,7 +3728,7 @@
|
|||||||
{
|
{
|
||||||
"term": "To update, run the following command:",
|
"term": "To update, run the following command:",
|
||||||
"context": "To update, run the following command:",
|
"context": "To update, run the following command:",
|
||||||
"reference": "Services/DMSService.qml:300",
|
"reference": "Services/DMSService.qml:301",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -4052,7 +4052,7 @@
|
|||||||
{
|
{
|
||||||
"term": "Website:",
|
"term": "Website:",
|
||||||
"context": "Website:",
|
"context": "Website:",
|
||||||
"reference": "Modules/Settings/AboutTab.qml:436",
|
"reference": "Modules/Settings/AboutTab.qml:480",
|
||||||
"comment": ""
|
"comment": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user