mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Formatting
This commit is contained in:
@@ -121,7 +121,7 @@ Rectangle {
|
||||
property int indicatorWidth: Style.capsuleHeight
|
||||
property color warningColor: Color.mTertiary
|
||||
property color criticalColor: Color.mError
|
||||
|
||||
|
||||
width: isVertical ? Math.max(0, indicatorWidth - Style.marginS * 2) : Math.max(0, indicatorWidth + Style.marginXS * 2)
|
||||
height: isVertical ? Math.max(0, Style.capsuleHeight + Style.marginXS * 2) : pillHeight
|
||||
radius: Math.min(width, height) / 2
|
||||
@@ -133,15 +133,24 @@ Rectangle {
|
||||
|
||||
// Smooth appearance/disappearance animation
|
||||
Behavior on scale {
|
||||
NumberAnimation { duration: Style.animationNormal; easing.type: Easing.OutCubic }
|
||||
NumberAnimation {
|
||||
duration: Style.animationNormal
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: Style.animationNormal; easing.type: Easing.OutCubic }
|
||||
NumberAnimation {
|
||||
duration: Style.animationNormal
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation { duration: Style.animationNormal; easing.type: Easing.OutCubic }
|
||||
ColorAnimation {
|
||||
duration: Style.animationNormal
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -340,10 +349,8 @@ Rectangle {
|
||||
applyUiScale: false
|
||||
anchors.centerIn: parent
|
||||
// Invert color when memory indicator active
|
||||
color: isVertical ? (memCritical ? criticalColor : (memWarning ? warningColor : Color.mOnSurface)) : ((memWarning || memCritical) ? Color.mSurfaceVariant : Color.mOnSurface)
|
||||
color: isVertical ? (memCritical ? criticalColor : (memWarning ? warningColor : Color.mOnSurface)) : ((memWarning || memCritical) ? Color.mSurfaceVariant : Color.mOnSurface)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
NText {
|
||||
|
||||
@@ -28,8 +28,10 @@ NBox {
|
||||
height: content.widgetHeight
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
// Highlight color based on thresholds
|
||||
fillColor: (SystemStatService.cpuUsage > Settings.data.systemMonitor.cpuCriticalThreshold)? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.criticalColor || Color.mError) : Color.mError): (SystemStatService.cpuUsage > Settings.data.systemMonitor.cpuWarningThreshold)? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.warningColor || Color.mTertiary) : Color.mTertiary): Color.mPrimary
|
||||
textColor: (SystemStatService.cpuUsage > Settings.data.systemMonitor.cpuCriticalThreshold)? Color.mSurfaceVariant: (SystemStatService.cpuUsage > Settings.data.systemMonitor.cpuWarningThreshold)? Color.mSurfaceVariant: Color.mOnSurface
|
||||
fillColor: (SystemStatService.cpuUsage > Settings.data.systemMonitor.cpuCriticalThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.criticalColor
|
||||
|| Color.mError) : Color.mError) : (SystemStatService.cpuUsage > Settings.data.systemMonitor.cpuWarningThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.warningColor
|
||||
|| Color.mTertiary) : Color.mTertiary) : Color.mPrimary
|
||||
textColor: (SystemStatService.cpuUsage > Settings.data.systemMonitor.cpuCriticalThreshold) ? Color.mSurfaceVariant : (SystemStatService.cpuUsage > Settings.data.systemMonitor.cpuWarningThreshold) ? Color.mSurfaceVariant : Color.mOnSurface
|
||||
}
|
||||
NCircleStat {
|
||||
value: SystemStatService.cpuTemp
|
||||
@@ -40,8 +42,10 @@ NBox {
|
||||
height: content.widgetHeight
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
// Highlight color based on thresholds
|
||||
fillColor: (SystemStatService.cpuTemp > Settings.data.systemMonitor.tempCriticalThreshold)? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.criticalColor || Color.mError) : Color.mError): (SystemStatService.cpuTemp > Settings.data.systemMonitor.tempWarningThreshold)? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.warningColor || Color.mTertiary) : Color.mTertiary): Color.mPrimary
|
||||
textColor: (SystemStatService.cpuTemp > Settings.data.systemMonitor.tempCriticalThreshold)? Color.mSurfaceVariant: (SystemStatService.cpuTemp > Settings.data.systemMonitor.tempWarningThreshold)? Color.mSurfaceVariant: Color.mOnSurface
|
||||
fillColor: (SystemStatService.cpuTemp > Settings.data.systemMonitor.tempCriticalThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.criticalColor
|
||||
|| Color.mError) : Color.mError) : (SystemStatService.cpuTemp > Settings.data.systemMonitor.tempWarningThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.warningColor
|
||||
|| Color.mTertiary) : Color.mTertiary) : Color.mPrimary
|
||||
textColor: (SystemStatService.cpuTemp > Settings.data.systemMonitor.tempCriticalThreshold) ? Color.mSurfaceVariant : (SystemStatService.cpuTemp > Settings.data.systemMonitor.tempWarningThreshold) ? Color.mSurfaceVariant : Color.mOnSurface
|
||||
}
|
||||
NCircleStat {
|
||||
value: SystemStatService.memPercent
|
||||
@@ -51,8 +55,10 @@ NBox {
|
||||
height: content.widgetHeight
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
// Highlight color based on thresholds
|
||||
fillColor: (SystemStatService.memPercent > Settings.data.systemMonitor.memCriticalThreshold)? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.criticalColor || Color.mError) : Color.mError): (SystemStatService.memPercent > Settings.data.systemMonitor.memWarningThreshold)? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.warningColor || Color.mTertiary) : Color.mTertiary): Color.mPrimary
|
||||
textColor: (SystemStatService.memPercent > Settings.data.systemMonitor.memCriticalThreshold)? Color.mSurfaceVariant: (SystemStatService.memPercent > Settings.data.systemMonitor.memWarningThreshold)? Color.mSurfaceVariant: Color.mOnSurface
|
||||
fillColor: (SystemStatService.memPercent > Settings.data.systemMonitor.memCriticalThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.criticalColor
|
||||
|| Color.mError) : Color.mError) : (SystemStatService.memPercent > Settings.data.systemMonitor.memWarningThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.warningColor
|
||||
|| Color.mTertiary) : Color.mTertiary) : Color.mPrimary
|
||||
textColor: (SystemStatService.memPercent > Settings.data.systemMonitor.memCriticalThreshold) ? Color.mSurfaceVariant : (SystemStatService.memPercent > Settings.data.systemMonitor.memWarningThreshold) ? Color.mSurfaceVariant : Color.mOnSurface
|
||||
}
|
||||
NCircleStat {
|
||||
value: SystemStatService.diskPercents["/"] ?? 0
|
||||
@@ -62,8 +68,12 @@ NBox {
|
||||
height: content.widgetHeight
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
// Highlight color based on thresholds
|
||||
fillColor: ( (SystemStatService.diskPercents["/"] ?? 0) > Settings.data.systemMonitor.diskCriticalThreshold)? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.criticalColor || Color.mError) : Color.mError): ( (SystemStatService.diskPercents["/"] ?? 0) > Settings.data.systemMonitor.diskWarningThreshold)? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.warningColor || Color.mTertiary) : Color.mTertiary): Color.mPrimary
|
||||
textColor: ((SystemStatService.diskPercents["/"] ?? 0) > Settings.data.systemMonitor.diskCriticalThreshold)? Color.mSurfaceVariant: ((SystemStatService.diskPercents["/"] ?? 0) > Settings.data.systemMonitor.diskWarningThreshold)? Color.mSurfaceVariant: Color.mOnSurface
|
||||
fillColor: ((SystemStatService.diskPercents["/"]
|
||||
?? 0) > Settings.data.systemMonitor.diskCriticalThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.criticalColor
|
||||
|| Color.mError) : Color.mError) : ((SystemStatService.diskPercents["/"]
|
||||
?? 0) > Settings.data.systemMonitor.diskWarningThreshold) ? (Settings.data.systemMonitor.useCustomColors ? (Settings.data.systemMonitor.warningColor
|
||||
|| Color.mTertiary) : Color.mTertiary) : Color.mPrimary
|
||||
textColor: ((SystemStatService.diskPercents["/"] ?? 0) > Settings.data.systemMonitor.diskCriticalThreshold) ? Color.mSurfaceVariant : ((SystemStatService.diskPercents["/"] ?? 0) > Settings.data.systemMonitor.diskWarningThreshold) ? Color.mSurfaceVariant : Color.mOnSurface
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,10 +260,10 @@ SmartPanel {
|
||||
"icon": "settings-screen-recorder",
|
||||
"source": screenRecorderTab
|
||||
}, {
|
||||
"id": SettingsPanel.Tab.SystemMonitor,
|
||||
"label": "settings.system-monitor.title",
|
||||
"icon": "settings-system-monitor",
|
||||
"source": systemMonitorTab
|
||||
"id": SettingsPanel.Tab.SystemMonitor,
|
||||
"label": "settings.system-monitor.title",
|
||||
"icon": "settings-system-monitor",
|
||||
"source": systemMonitorTab
|
||||
}, {
|
||||
"id": SettingsPanel.Tab.Hooks,
|
||||
"label": "settings.hooks.title",
|
||||
|
||||
@@ -22,7 +22,7 @@ ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginM
|
||||
|
||||
NToggle {
|
||||
NToggle {
|
||||
label: I18n.tr("settings.system-monitor.use-custom-highlight-colors.label")
|
||||
description: I18n.tr("settings.system-monitor.use-custom-highlight-colors.description")
|
||||
checked: Settings.data.systemMonitor.useCustomColors
|
||||
@@ -45,7 +45,6 @@ ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginM
|
||||
visible: Settings.data.systemMonitor.useCustomColors
|
||||
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
@@ -61,7 +60,7 @@ ColumnLayout {
|
||||
Layout.preferredHeight: Style.baseWidgetSize
|
||||
enabled: Settings.data.systemMonitor.useCustomColors
|
||||
selectedColor: Settings.data.systemMonitor.warningColor || Color.mTertiary
|
||||
onColorSelected: function(color) {
|
||||
onColorSelected: function (color) {
|
||||
Settings.data.systemMonitor.warningColor = color
|
||||
}
|
||||
}
|
||||
@@ -81,7 +80,7 @@ ColumnLayout {
|
||||
Layout.preferredHeight: Style.baseWidgetSize
|
||||
enabled: Settings.data.systemMonitor.useCustomColors
|
||||
selectedColor: Settings.data.systemMonitor.criticalColor || Color.mError
|
||||
onColorSelected: function(color) {
|
||||
onColorSelected: function (color) {
|
||||
Settings.data.systemMonitor.criticalColor = color
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ Singleton {
|
||||
const niriSocket = Quickshell.env("NIRI_SOCKET")
|
||||
const swaySock = Quickshell.env("SWAYSOCK")
|
||||
const currentDesktop = Quickshell.env("XDG_CURRENT_DESKTOP")
|
||||
|
||||
|
||||
// Check for MangoWC using XDG_CURRENT_DESKTOP environment variable
|
||||
// MangoWC sets XDG_CURRENT_DESKTOP=mango
|
||||
if (currentDesktop && currentDesktop.toLowerCase().includes("mango")) {
|
||||
@@ -61,7 +61,6 @@ Singleton {
|
||||
isSway = false
|
||||
isMango = true
|
||||
backendLoader.sourceComponent = mangoComponent
|
||||
Logger.i("CompositorService", "MangoWC detected via XDG_CURRENT_DESKTOP:", currentDesktop)
|
||||
} else if (niriSocket && niriSocket.length > 0) {
|
||||
isHyprland = false
|
||||
isNiri = true
|
||||
@@ -89,9 +88,6 @@ Singleton {
|
||||
backendLoader.sourceComponent = niriComponent
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loader {
|
||||
id: backendLoader
|
||||
onLoaded: {
|
||||
|
||||
@@ -7,7 +7,6 @@ import qs.Services.Keyboard
|
||||
|
||||
// MangoService integrates with MangoWC compositor using mmsg IPC commands
|
||||
// for real-time window management, workspace control, and state monitoring
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
@@ -22,53 +21,52 @@ Item {
|
||||
signal windowListChanged
|
||||
signal displayScalesChanged
|
||||
|
||||
// MangoWC-specific state
|
||||
property bool initialized: false
|
||||
property bool overviewActive: false
|
||||
property var workspaceCache: ({}) // Cache for workspace data to detect changes
|
||||
property var windowCache: ({}) // Cache for window data to detect changes
|
||||
property var monitorCache: ({}) // Cache for monitor/scale data
|
||||
property string currentLayout: "" // Current layout name
|
||||
property string currentLayoutSymbol: "" // Current layout symbol (e.g., 'S' for scroller)
|
||||
property string currentKeyboardLayout: "" // Current keyboard layout name
|
||||
property string selectedMonitor: "" // Currently selected/focused monitor
|
||||
// MangoWC-specific state
|
||||
property bool initialized: false
|
||||
property bool overviewActive: false
|
||||
property var workspaceCache: ({}) // Cache for workspace data to detect changes
|
||||
property var windowCache: ({}) // Cache for window data to detect changes
|
||||
property var monitorCache: ({}) // Cache for monitor/scale data
|
||||
property string currentLayout: "" // Current layout name
|
||||
property string currentLayoutSymbol: "" // Current layout symbol (e.g., 'S' for scroller)
|
||||
property string currentKeyboardLayout: "" // Current keyboard layout name
|
||||
property string selectedMonitor: "" // Currently selected/focused monitor
|
||||
|
||||
// mmsg command templates for MangoWC IPC (mmsg is the MangoWC message interface)
|
||||
readonly property var mmsgCommands: ({
|
||||
query: {
|
||||
workspaces: ["mmsg", "-g", "-t"],
|
||||
windows: ["mmsg", "-g", "-c"],
|
||||
layout: ["mmsg", "-g", "-l"],
|
||||
keyboard: ["mmsg", "-g", "-k"],
|
||||
outputs: ["mmsg", "-g", "-A"],
|
||||
monitors: ["mmsg", "-g", "-o"],
|
||||
eventStream: ["mmsg", "-w"]
|
||||
},
|
||||
action: {
|
||||
view: ["mmsg", "-s", "-d", "view"],
|
||||
tag: ["mmsg", "-s", "-t"],
|
||||
focusMaster: ["mmsg", "-s", "-d", "focusmaster"],
|
||||
killClient: ["mmsg", "-s", "-d", "killclient"],
|
||||
toggleOverview: ["mmsg", "-s", "-d", "toggleoverview"],
|
||||
setLayout: ["mmsg", "-s", "-d", "setlayout"],
|
||||
quit: ["mmsg", "-s", "-q"]
|
||||
}
|
||||
})
|
||||
// mmsg command templates for MangoWC IPC (mmsg is the MangoWC message interface)
|
||||
readonly property var mmsgCommands: ({
|
||||
"query": {
|
||||
"workspaces": ["mmsg", "-g", "-t"],
|
||||
"windows": ["mmsg", "-g", "-c"],
|
||||
"layout": ["mmsg", "-g", "-l"],
|
||||
"keyboard": ["mmsg", "-g", "-k"],
|
||||
"outputs": ["mmsg", "-g", "-A"],
|
||||
"monitors": ["mmsg", "-g", "-o"],
|
||||
"eventStream": ["mmsg", "-w"]
|
||||
},
|
||||
"action": {
|
||||
"view": ["mmsg", "-s", "-d", "view"],
|
||||
"tag": ["mmsg", "-s", "-t"],
|
||||
"focusMaster": ["mmsg", "-s", "-d", "focusmaster"],
|
||||
"killClient": ["mmsg", "-s", "-d", "killclient"],
|
||||
"toggleOverview": ["mmsg", "-s", "-d", "toggleoverview"],
|
||||
"setLayout": ["mmsg", "-s", "-d", "setlayout"],
|
||||
"quit": ["mmsg", "-s", "-q"]
|
||||
}
|
||||
})
|
||||
|
||||
readonly property string overviewLayoutSymbol: "" // Symbol representing overview layout
|
||||
readonly property int defaultWorkspaceId: 1 // Default workspace ID when none specified
|
||||
readonly property string overviewLayoutSymbol: "" // Symbol representing overview layout
|
||||
readonly property int defaultWorkspaceId: 1 // Default workspace ID when none specified
|
||||
|
||||
// Debounce timer for rapid state changes to avoid excessive updates
|
||||
Timer {
|
||||
id: updateTimer
|
||||
interval: 50
|
||||
repeat: false
|
||||
onTriggered: safeUpdate()
|
||||
}
|
||||
// Debounce timer for rapid state changes to avoid excessive updates
|
||||
Timer {
|
||||
id: updateTimer
|
||||
interval: 50
|
||||
repeat: false
|
||||
onTriggered: safeUpdate()
|
||||
}
|
||||
|
||||
|
||||
// Event stream process for real-time MangoWC state monitoring using mmsg -w
|
||||
// Monitors events: workspace changes, window focus/movement, layout changes, monitor selection
|
||||
// Event stream process for real-time MangoWC state monitoring using mmsg -w
|
||||
// Monitors events: workspace changes, window focus/movement, layout changes, monitor selection
|
||||
Process {
|
||||
id: eventStream
|
||||
running: false
|
||||
@@ -92,24 +90,23 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// Restart timer for event stream recovery on failure
|
||||
Timer {
|
||||
id: restartTimer
|
||||
interval: 1000
|
||||
onTriggered: {
|
||||
if (initialized) {
|
||||
eventStream.running = true
|
||||
}
|
||||
}
|
||||
}
|
||||
// Restart timer for event stream recovery on failure
|
||||
Timer {
|
||||
id: restartTimer
|
||||
interval: 1000
|
||||
onTriggered: {
|
||||
if (initialized) {
|
||||
eventStream.running = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Process to query workspaces using mmsg -g -t
|
||||
Process {
|
||||
id: workspacesProcess
|
||||
running: false
|
||||
command: mmsgCommands.query.workspaces
|
||||
property string accumulatedOutput: ""
|
||||
// Process to query workspaces using mmsg -g -t
|
||||
Process {
|
||||
id: workspacesProcess
|
||||
running: false
|
||||
command: mmsgCommands.query.workspaces
|
||||
property string accumulatedOutput: ""
|
||||
|
||||
stdout: SplitParser {
|
||||
onRead: function (line) {
|
||||
@@ -127,13 +124,13 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// Process to query windows using mmsg -g -c
|
||||
Process {
|
||||
id: windowsProcess
|
||||
running: false
|
||||
command: mmsgCommands.query.windows
|
||||
property string accumulatedOutput: ""
|
||||
property var currentWindow: ({})
|
||||
// Process to query windows using mmsg -g -c
|
||||
Process {
|
||||
id: windowsProcess
|
||||
running: false
|
||||
command: mmsgCommands.query.windows
|
||||
property string accumulatedOutput: ""
|
||||
property var currentWindow: ({})
|
||||
|
||||
onRunningChanged: {
|
||||
if (running) {
|
||||
@@ -144,7 +141,8 @@ Item {
|
||||
stdout: SplitParser {
|
||||
onRead: function (line) {
|
||||
const trimmed = line.trim()
|
||||
if (!trimmed) return
|
||||
if (!trimmed)
|
||||
return
|
||||
|
||||
const parts = trimmed.split(' ')
|
||||
if (parts.length >= 3) {
|
||||
@@ -154,37 +152,37 @@ Item {
|
||||
|
||||
if (!windowsProcess.currentWindow[outputName]) {
|
||||
windowsProcess.currentWindow[outputName] = {
|
||||
id: outputName,
|
||||
output: outputName
|
||||
"id": outputName,
|
||||
"output": outputName
|
||||
}
|
||||
}
|
||||
|
||||
switch (property) {
|
||||
case "title":
|
||||
windowsProcess.currentWindow[outputName].title = value
|
||||
break
|
||||
case "appid":
|
||||
windowsProcess.currentWindow[outputName].appId = value
|
||||
windowsProcess.currentWindow[outputName].class = value
|
||||
break
|
||||
case "fullscreen":
|
||||
windowsProcess.currentWindow[outputName].fullscreen = (value === "1")
|
||||
break
|
||||
case "floating":
|
||||
windowsProcess.currentWindow[outputName].floating = (value === "1")
|
||||
break
|
||||
case "x":
|
||||
windowsProcess.currentWindow[outputName].x = parseInt(value)
|
||||
break
|
||||
case "y":
|
||||
windowsProcess.currentWindow[outputName].y = parseInt(value)
|
||||
break
|
||||
case "width":
|
||||
windowsProcess.currentWindow[outputName].width = parseInt(value)
|
||||
break
|
||||
case "height":
|
||||
windowsProcess.currentWindow[outputName].height = parseInt(value)
|
||||
break
|
||||
case "title":
|
||||
windowsProcess.currentWindow[outputName].title = value
|
||||
break
|
||||
case "appid":
|
||||
windowsProcess.currentWindow[outputName].appId = value
|
||||
windowsProcess.currentWindow[outputName].class = value
|
||||
break
|
||||
case "fullscreen":
|
||||
windowsProcess.currentWindow[outputName].fullscreen = (value === "1")
|
||||
break
|
||||
case "floating":
|
||||
windowsProcess.currentWindow[outputName].floating = (value === "1")
|
||||
break
|
||||
case "x":
|
||||
windowsProcess.currentWindow[outputName].x = parseInt(value)
|
||||
break
|
||||
case "y":
|
||||
windowsProcess.currentWindow[outputName].y = parseInt(value)
|
||||
break
|
||||
case "width":
|
||||
windowsProcess.currentWindow[outputName].width = parseInt(value)
|
||||
break
|
||||
case "height":
|
||||
windowsProcess.currentWindow[outputName].height = parseInt(value)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -201,11 +199,11 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// Process to query current layout using mmsg -g -l
|
||||
Process {
|
||||
id: layoutProcess
|
||||
running: false
|
||||
command: mmsgCommands.query.layout
|
||||
// Process to query current layout using mmsg -g -l
|
||||
Process {
|
||||
id: layoutProcess
|
||||
running: false
|
||||
command: mmsgCommands.query.layout
|
||||
|
||||
stdout: SplitParser {
|
||||
onRead: function (line) {
|
||||
@@ -228,11 +226,11 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// Process to query keyboard layout using mmsg -g -k
|
||||
Process {
|
||||
id: keyboardProcess
|
||||
running: false
|
||||
command: mmsgCommands.query.keyboard
|
||||
// Process to query keyboard layout using mmsg -g -k
|
||||
Process {
|
||||
id: keyboardProcess
|
||||
running: false
|
||||
command: mmsgCommands.query.keyboard
|
||||
|
||||
stdout: SplitParser {
|
||||
onRead: function (line) {
|
||||
@@ -258,11 +256,11 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// Process to query output scales using mmsg -g -A
|
||||
Process {
|
||||
id: outputsProcess
|
||||
running: false
|
||||
command: mmsgCommands.query.outputs
|
||||
// Process to query output scales using mmsg -g -A
|
||||
Process {
|
||||
id: outputsProcess
|
||||
running: false
|
||||
command: mmsgCommands.query.outputs
|
||||
|
||||
stdout: SplitParser {
|
||||
onRead: function (line) {
|
||||
@@ -271,11 +269,11 @@ Item {
|
||||
if (parts.length >= 3 && parts[1] === "scale_factor") {
|
||||
const outputName = parts[0]
|
||||
const scaleFactor = parseFloat(parts[2])
|
||||
|
||||
|
||||
if (!monitorCache[outputName]) {
|
||||
monitorCache[outputName] = {}
|
||||
}
|
||||
|
||||
|
||||
monitorCache[outputName].scale = scaleFactor
|
||||
monitorCache[outputName].name = outputName
|
||||
}
|
||||
@@ -294,11 +292,11 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// Process to query monitor states using mmsg -g -o
|
||||
Process {
|
||||
id: monitorStateProcess
|
||||
running: false
|
||||
command: mmsgCommands.query.monitors
|
||||
// Process to query monitor states using mmsg -g -o
|
||||
Process {
|
||||
id: monitorStateProcess
|
||||
running: false
|
||||
command: mmsgCommands.query.monitors
|
||||
|
||||
stdout: SplitParser {
|
||||
onRead: function (line) {
|
||||
@@ -325,11 +323,11 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// Process to enumerate available outputs using mmsg -g -O
|
||||
Process {
|
||||
id: outputEnumProcess
|
||||
running: false
|
||||
command: ["mmsg", "-g", "-O"]
|
||||
// Process to enumerate available outputs using mmsg -g -O
|
||||
Process {
|
||||
id: outputEnumProcess
|
||||
running: false
|
||||
command: ["mmsg", "-g", "-O"]
|
||||
|
||||
stdout: SplitParser {
|
||||
onRead: function (line) {
|
||||
@@ -339,10 +337,10 @@ Item {
|
||||
const outputName = trimmed.replace(/^\+\s*/, '')
|
||||
if (outputName && !monitorCache[outputName]) {
|
||||
monitorCache[outputName] = {
|
||||
name: outputName,
|
||||
scale: 1.0,
|
||||
active: false,
|
||||
focused: false
|
||||
"name": outputName,
|
||||
"scale": 1.0,
|
||||
"active": false,
|
||||
"focused": false
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -358,7 +356,6 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Initialize MangoService and establish connection to MangoWC
|
||||
function initialize() {
|
||||
if (initialized) {
|
||||
@@ -367,8 +364,8 @@ Item {
|
||||
}
|
||||
|
||||
try {
|
||||
Logger.i("MangoService", "Initializing MangoWC service...")
|
||||
|
||||
Logger.i("MangoService", "Service started")
|
||||
|
||||
queryOutputEnum()
|
||||
queryMonitorState()
|
||||
eventStream.running = true
|
||||
@@ -377,7 +374,7 @@ Item {
|
||||
queryLayout()
|
||||
queryKeyboard()
|
||||
queryOutputs()
|
||||
|
||||
|
||||
initialized = true
|
||||
Logger.i("MangoService", "Service initialized successfully")
|
||||
} catch (e) {
|
||||
@@ -386,49 +383,45 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Switch to a specific workspace/tag
|
||||
function switchToWorkspace(workspace) {
|
||||
try {
|
||||
const tagId = workspace.idx || workspace.id || defaultWorkspaceId
|
||||
const outputName = workspace.output || selectedMonitor || ""
|
||||
let command = [...mmsgCommands.action.tag]
|
||||
|
||||
let command = mmsgCommands.action.tag.slice()
|
||||
|
||||
// Only add -o parameter for multi-monitor setups
|
||||
if (outputName && Object.keys(monitorCache).length > 1) {
|
||||
command.push("-o", outputName)
|
||||
}
|
||||
command.push(tagId.toString())
|
||||
|
||||
|
||||
Quickshell.execDetached(command)
|
||||
} catch (e) {
|
||||
Logger.e("MangoService", "Failed to switch workspace:", e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Focus a specific window on its workspace
|
||||
function focusWindow(window) {
|
||||
try {
|
||||
if (window && window.output) {
|
||||
let command = [...mmsgCommands.action.view]
|
||||
let command = mmsgCommands.action.view.slice()
|
||||
const isMultiMonitor = Object.keys(monitorCache).length > 1
|
||||
|
||||
|
||||
if (isMultiMonitor) {
|
||||
command.push("-o", window.output)
|
||||
}
|
||||
command.push(window.workspaceId.toString())
|
||||
Quickshell.execDetached(command)
|
||||
|
||||
|
||||
Qt.callLater(() => {
|
||||
let focusCommand = [...mmsgCommands.action.focusMaster]
|
||||
if (isMultiMonitor) {
|
||||
focusCommand.push("-o", window.output)
|
||||
}
|
||||
Quickshell.execDetached(focusCommand)
|
||||
})
|
||||
let focusCommand = mmsgCommands.action.focusMaster.slice()
|
||||
if (isMultiMonitor) {
|
||||
focusCommand.push("-o", window.output)
|
||||
}
|
||||
Quickshell.execDetached(focusCommand)
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
Logger.e("MangoService", "Failed to focus window:", e)
|
||||
@@ -437,7 +430,7 @@ Item {
|
||||
|
||||
function closeWindow(window) {
|
||||
try {
|
||||
const command = [...mmsgCommands.action.killClient]
|
||||
const command = mmsgCommands.action.killClient.slice()
|
||||
if (selectedMonitor && Object.keys(monitorCache).length > 1) {
|
||||
command.push("-o", selectedMonitor)
|
||||
}
|
||||
@@ -447,10 +440,9 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function toggleOverview() {
|
||||
try {
|
||||
const command = [...mmsgCommands.action.toggleOverview]
|
||||
const command = mmsgCommands.action.toggleOverview.slice()
|
||||
if (selectedMonitor && Object.keys(monitorCache).length > 1) {
|
||||
command.push("-o", selectedMonitor)
|
||||
}
|
||||
@@ -462,7 +454,7 @@ Item {
|
||||
|
||||
function setLayout(layoutName) {
|
||||
try {
|
||||
const command = [...mmsgCommands.action.setLayout]
|
||||
const command = mmsgCommands.action.setLayout.slice()
|
||||
command.push(layoutName)
|
||||
Quickshell.execDetached(command)
|
||||
} catch (e) {
|
||||
@@ -478,10 +470,9 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Parse workspace data from mmsg -g -t output
|
||||
// Handles formats: tag details, tag masks, and binary states
|
||||
// State bits: bit 0 = active/selected, bit 1 = urgent
|
||||
// Parse workspace data from mmsg -g -t output
|
||||
// Handles formats: tag details, tag masks, and binary states
|
||||
// State bits: bit 0 = active/selected, bit 1 = urgent
|
||||
function parseWorkspaces(output) {
|
||||
const lines = output.trim().split('\n')
|
||||
const workspacesList = []
|
||||
@@ -490,13 +481,18 @@ Item {
|
||||
|
||||
for (const line of lines) {
|
||||
const trimmed = line.trim()
|
||||
if (!trimmed) continue
|
||||
if (!trimmed)
|
||||
continue
|
||||
|
||||
const tagMatch = trimmed.match(/^(\S+)\s+tag\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/)
|
||||
if (tagMatch) {
|
||||
const [, outputName, tagNum, state, clients, focused] = tagMatch
|
||||
const outputName = tagMatch[1]
|
||||
const tagNum = tagMatch[2]
|
||||
const state = tagMatch[3]
|
||||
const clients = tagMatch[4]
|
||||
const focused = tagMatch[5]
|
||||
const tagId = parseInt(tagNum)
|
||||
|
||||
|
||||
const isActive = (parseInt(state) & 1) !== 0
|
||||
const isUrgent = (parseInt(state) & 2) !== 0
|
||||
const isOccupied = parseInt(clients) > 0
|
||||
@@ -507,15 +503,15 @@ Item {
|
||||
}
|
||||
|
||||
const workspaceData = {
|
||||
id: tagId,
|
||||
idx: tagId,
|
||||
name: tagId.toString(),
|
||||
output: outputName,
|
||||
isActive: isActive,
|
||||
isFocused: isFocused || (isActive && (outputName === selectedMonitor)),
|
||||
isUrgent: isUrgent,
|
||||
isOccupied: isOccupied,
|
||||
clients: parseInt(clients)
|
||||
"id": tagId,
|
||||
"idx": tagId,
|
||||
"name": tagId.toString(),
|
||||
"output": outputName,
|
||||
"isActive": isActive,
|
||||
"isFocused": isFocused || (isActive && (outputName === selectedMonitor)),
|
||||
"isUrgent": isUrgent,
|
||||
"isOccupied": isOccupied,
|
||||
"clients": parseInt(clients)
|
||||
}
|
||||
|
||||
newWorkspaceCache[`${outputName}-${tagId}`] = workspaceData
|
||||
@@ -524,36 +520,41 @@ Item {
|
||||
|
||||
const clientsMatch = trimmed.match(/^(\S+)\s+clients\s+(\d+)$/)
|
||||
if (clientsMatch) {
|
||||
const [, outputName, clientCount] = clientsMatch
|
||||
const outputName = clientsMatch[1]
|
||||
const clientCount = clientsMatch[2]
|
||||
outputClients[outputName] = parseInt(clientCount)
|
||||
}
|
||||
|
||||
const tagsMatch = trimmed.match(/^(\S+)\s+tags\s+(\d+)\s+(\d+)\s+(\d+)$/)
|
||||
if (tagsMatch) {
|
||||
const [, outputName, occ, seltags, urg] = tagsMatch
|
||||
const outputName = tagsMatch[1]
|
||||
const occ = tagsMatch[2]
|
||||
const seltags = tagsMatch[3]
|
||||
const urg = tagsMatch[4]
|
||||
|
||||
const occBits = occ.padStart(9, '0')
|
||||
const selBits = seltags.padStart(9, '0')
|
||||
const urgBits = urg.padStart(9, '0')
|
||||
|
||||
for (let i = 0; i < 9; i++) {
|
||||
|
||||
for (var i = 0; i < 9; i++) {
|
||||
const tagId = i + 1
|
||||
const isActive = selBits[8-i] === '1'
|
||||
const isUrgent = urgBits[8-i] === '1'
|
||||
const isOccupied = occBits[8-i] === '1'
|
||||
|
||||
const isActive = selBits[8 - i] === '1'
|
||||
const isUrgent = urgBits[8 - i] === '1'
|
||||
const isOccupied = occBits[8 - i] === '1'
|
||||
|
||||
const workspaceData = {
|
||||
id: tagId,
|
||||
idx: tagId,
|
||||
name: tagId.toString(),
|
||||
output: outputName,
|
||||
isActive: isActive,
|
||||
isFocused: false, // Will be determined by selected monitor
|
||||
isUrgent: isUrgent,
|
||||
isOccupied: isOccupied,
|
||||
clients: 0 // Will be updated by tag-specific data
|
||||
"id": tagId,
|
||||
"idx": tagId,
|
||||
"name": tagId.toString(),
|
||||
"output": outputName,
|
||||
"isActive": isActive,
|
||||
"isFocused": false,
|
||||
"isUrgent"// Will be determined by selected monitor
|
||||
: isUrgent,
|
||||
"isOccupied": isOccupied,
|
||||
"clients": 0 // Will be updated by tag-specific data
|
||||
}
|
||||
|
||||
|
||||
const key = `${outputName}-${tagId}`
|
||||
if (!newWorkspaceCache[key]) {
|
||||
newWorkspaceCache[key] = workspaceData
|
||||
@@ -564,73 +565,79 @@ Item {
|
||||
|
||||
const layoutMatch = trimmed.match(/^(\S+)\s+layout\s+(\S+)$/)
|
||||
if (layoutMatch) {
|
||||
const [, , layoutSymbol] = layoutMatch
|
||||
const layoutSymbol = layoutMatch[2]
|
||||
handleLayoutChange(layoutSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
if (JSON.stringify(newWorkspaceCache) !== JSON.stringify(workspaceCache)) {
|
||||
workspaceCache = newWorkspaceCache
|
||||
|
||||
workspacesList.sort((a, b) => {
|
||||
if (a.id !== b.id) return a.id - b.id
|
||||
return a.output.localeCompare(b.output)
|
||||
})
|
||||
if (JSON.stringify(newWorkspaceCache) !== JSON.stringify(workspaceCache)) {
|
||||
workspaceCache = newWorkspaceCache
|
||||
|
||||
workspaces.clear()
|
||||
for (var i = 0; i < workspacesList.length; i++) {
|
||||
workspaces.append(workspacesList[i])
|
||||
}
|
||||
|
||||
workspaceChanged()
|
||||
workspacesList.sort((a, b) => {
|
||||
if (a.id !== b.id)
|
||||
return a.id - b.id
|
||||
return a.output.localeCompare(b.output)
|
||||
})
|
||||
|
||||
workspaces.clear()
|
||||
for (var i = 0; i < workspacesList.length; i++) {
|
||||
workspaces.append(workspacesList[i])
|
||||
}
|
||||
|
||||
workspaceChanged()
|
||||
}
|
||||
}
|
||||
|
||||
// Parse window data from mmsg -g -c output into window list
|
||||
function parseWindows(windowData) {
|
||||
// Parse window data from mmsg -g -c output into window list
|
||||
function parseWindows(windowData) {
|
||||
const windowsList = []
|
||||
const newWindowCache = {}
|
||||
let newFocusedIndex = -1
|
||||
|
||||
for (const [outputName, data] of Object.entries(windowData)) {
|
||||
const windowEntries = Object.entries(windowData)
|
||||
for (var i = 0; i < windowEntries.length; i++) {
|
||||
const outputName = windowEntries[i][0]
|
||||
const data = windowEntries[i][1]
|
||||
if (data.title || data.appId) {
|
||||
|
||||
const isFocused = (outputName === selectedMonitor)
|
||||
|
||||
|
||||
let activeTagId = defaultWorkspaceId
|
||||
for (const [key, tagData] of Object.entries(workspaceCache)) {
|
||||
const workspaceEntries = Object.entries(workspaceCache)
|
||||
for (var j = 0; j < workspaceEntries.length; j++) {
|
||||
const key = workspaceEntries[j][0]
|
||||
const tagData = workspaceEntries[j][1]
|
||||
if (tagData.output === outputName && tagData.isActive) {
|
||||
activeTagId = tagData.id
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const windowInfo = {
|
||||
id: `${outputName}-${data.appId || 'unknown'}`,
|
||||
title: data.title || "",
|
||||
appId: data.appId || "",
|
||||
class: data.appId || "",
|
||||
workspaceId: activeTagId,
|
||||
isFocused: isFocused,
|
||||
output: outputName,
|
||||
fullscreen: data.fullscreen || false,
|
||||
floating: data.floating || false,
|
||||
x: data.x || 0,
|
||||
y: data.y || 0,
|
||||
width: data.width || 0,
|
||||
height: data.height || 0,
|
||||
geometry: {
|
||||
x: data.x || 0,
|
||||
y: data.y || 0,
|
||||
width: data.width || 0,
|
||||
height: data.height || 0
|
||||
"id": `${outputName}-${data.appId || 'unknown'}`,
|
||||
"title": data.title || "",
|
||||
"appId": data.appId || "",
|
||||
"class": data.appId || "",
|
||||
"workspaceId": activeTagId,
|
||||
"isFocused": isFocused,
|
||||
"output": outputName,
|
||||
"fullscreen": data.fullscreen || false,
|
||||
"floating": data.floating || false,
|
||||
"x": data.x || 0,
|
||||
"y": data.y || 0,
|
||||
"width": data.width || 0,
|
||||
"height": data.height || 0,
|
||||
"geometry": {
|
||||
"x": data.x || 0,
|
||||
"y": data.y || 0,
|
||||
"width": data.width || 0,
|
||||
"height": data.height || 0
|
||||
}
|
||||
}
|
||||
|
||||
windowsList.push(windowInfo)
|
||||
newWindowCache[windowInfo.id] = windowInfo
|
||||
|
||||
|
||||
if (isFocused) {
|
||||
newFocusedIndex = windowsList.length - 1
|
||||
Logger.d("MangoService", `Focused window detected: ${data.title} on ${outputName}`)
|
||||
@@ -641,46 +648,49 @@ Item {
|
||||
if (JSON.stringify(newWindowCache) !== JSON.stringify(windowCache)) {
|
||||
windowCache = newWindowCache
|
||||
windows = windowsList
|
||||
|
||||
|
||||
if (newFocusedIndex !== focusedWindowIndex) {
|
||||
focusedWindowIndex = newFocusedIndex
|
||||
activeWindowChanged()
|
||||
}
|
||||
|
||||
|
||||
windowListChanged()
|
||||
}
|
||||
}
|
||||
|
||||
// Handle layout change events and update overview state
|
||||
function handleLayoutChange(layoutSymbol) {
|
||||
// Handle layout change events and update overview state
|
||||
function handleLayoutChange(layoutSymbol) {
|
||||
const wasOverview = overviewActive
|
||||
const isOverview = (layoutSymbol === overviewLayoutSymbol)
|
||||
|
||||
|
||||
if (wasOverview !== isOverview) {
|
||||
overviewActive = isOverview
|
||||
Logger.d("MangoService", `Overview mode: ${overviewActive}`)
|
||||
}
|
||||
|
||||
|
||||
if (layoutSymbol !== currentLayoutSymbol) {
|
||||
currentLayoutSymbol = layoutSymbol
|
||||
currentLayout = layoutSymbol
|
||||
}
|
||||
}
|
||||
|
||||
// Update display scales and notify CompositorService
|
||||
function updateDisplayScales() {
|
||||
// Update display scales and notify CompositorService
|
||||
function updateDisplayScales() {
|
||||
const scales = {}
|
||||
for (const [outputName, data] of Object.entries(monitorCache)) {
|
||||
const monitorEntries = Object.entries(monitorCache)
|
||||
for (var i = 0; i < monitorEntries.length; i++) {
|
||||
const outputName = monitorEntries[i][0]
|
||||
const data = monitorEntries[i][1]
|
||||
scales[outputName] = {
|
||||
name: data.name || outputName,
|
||||
scale: data.scale || 1.0,
|
||||
width: data.width || 0,
|
||||
height: data.height || 0,
|
||||
refresh_rate: data.refresh_rate || 0,
|
||||
x: data.x || 0,
|
||||
y: data.y || 0,
|
||||
active: data.active || false,
|
||||
focused: data.focused || false
|
||||
"name": data.name || outputName,
|
||||
"scale": data.scale || 1.0,
|
||||
"width": data.width || 0,
|
||||
"height": data.height || 0,
|
||||
"refresh_rate": data.refresh_rate || 0,
|
||||
"x": data.x || 0,
|
||||
"y": data.y || 0,
|
||||
"active": data.active || false,
|
||||
"focused": data.focused || false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -690,106 +700,110 @@ Item {
|
||||
displayScalesChanged()
|
||||
}
|
||||
|
||||
|
||||
// Handle real-time events from mmsg -w event stream and trigger updates
|
||||
function handleEvent(eventLine) {
|
||||
// Handle real-time events from mmsg -w event stream and trigger updates
|
||||
function handleEvent(eventLine) {
|
||||
const parts = eventLine.trim().split(/\s+/)
|
||||
if (parts.length < 2) return
|
||||
if (parts.length < 2)
|
||||
return
|
||||
|
||||
const eventType = parts[1]
|
||||
|
||||
switch (eventType) {
|
||||
case "selmon":
|
||||
if (parts.length >= 3) {
|
||||
const monitorName = parts[0]
|
||||
const isSelected = parts[2] === "1"
|
||||
if (isSelected) {
|
||||
selectedMonitor = monitorName
|
||||
Logger.d("MangoService", `Selected monitor changed to: ${monitorName}`)
|
||||
}
|
||||
case "selmon":
|
||||
if (parts.length >= 3) {
|
||||
const monitorName = parts[0]
|
||||
const isSelected = parts[2] === "1"
|
||||
if (isSelected) {
|
||||
selectedMonitor = monitorName
|
||||
Logger.d("MangoService", `Selected monitor changed to: ${monitorName}`)
|
||||
}
|
||||
updateTimer.restart()
|
||||
break
|
||||
case "tag":
|
||||
case "title":
|
||||
case "appid":
|
||||
case "fullscreen":
|
||||
case "floating":
|
||||
case "layout":
|
||||
case "kb_layout":
|
||||
case "scale_factor":
|
||||
case "toggle":
|
||||
case "last_layer":
|
||||
case "keymode":
|
||||
case "clients":
|
||||
case "tags":
|
||||
updateTimer.restart()
|
||||
break
|
||||
}
|
||||
updateTimer.restart()
|
||||
break
|
||||
case "tag":
|
||||
case "title":
|
||||
case "appid":
|
||||
case "fullscreen":
|
||||
case "floating":
|
||||
case "layout":
|
||||
case "kb_layout":
|
||||
case "scale_factor":
|
||||
case "toggle":
|
||||
case "last_layer":
|
||||
case "keymode":
|
||||
case "clients":
|
||||
case "tags":
|
||||
updateTimer.restart()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Start workspace query process
|
||||
function queryWorkspaces() {
|
||||
workspacesProcess.running = true
|
||||
}
|
||||
|
||||
// Start workspace query process
|
||||
function queryWorkspaces() {
|
||||
workspacesProcess.running = true
|
||||
}
|
||||
// Start window query process
|
||||
function queryWindows() {
|
||||
windowsProcess.running = true
|
||||
}
|
||||
|
||||
// Start window query process
|
||||
function queryWindows() {
|
||||
windowsProcess.running = true
|
||||
}
|
||||
// Start layout query process
|
||||
function queryLayout() {
|
||||
layoutProcess.running = true
|
||||
}
|
||||
|
||||
// Start layout query process
|
||||
function queryLayout() {
|
||||
layoutProcess.running = true
|
||||
}
|
||||
// Start keyboard layout query process
|
||||
function queryKeyboard() {
|
||||
keyboardProcess.running = true
|
||||
}
|
||||
|
||||
// Start keyboard layout query process
|
||||
function queryKeyboard() {
|
||||
keyboardProcess.running = true
|
||||
}
|
||||
// Start output scales query process
|
||||
function queryOutputs() {
|
||||
outputsProcess.running = true
|
||||
}
|
||||
|
||||
// Start output scales query process
|
||||
function queryOutputs() {
|
||||
outputsProcess.running = true
|
||||
}
|
||||
// Query display scales (alias for queryOutputs)
|
||||
function queryDisplayScales() {
|
||||
queryOutputs()
|
||||
}
|
||||
|
||||
// Query display scales (alias for queryOutputs)
|
||||
function queryDisplayScales() {
|
||||
queryOutputs()
|
||||
}
|
||||
// Start output enumeration process
|
||||
function queryOutputEnum() {
|
||||
outputEnumProcess.running = true
|
||||
}
|
||||
|
||||
// Start output enumeration process
|
||||
function queryOutputEnum() {
|
||||
outputEnumProcess.running = true
|
||||
}
|
||||
// Start monitor state query process
|
||||
function queryMonitorState() {
|
||||
monitorStateProcess.running = true
|
||||
}
|
||||
|
||||
// Start monitor state query process
|
||||
function queryMonitorState() {
|
||||
monitorStateProcess.running = true
|
||||
}
|
||||
// Safely update all state by querying workspaces, windows, and monitor state
|
||||
function safeUpdate() {
|
||||
try {
|
||||
queryWorkspaces()
|
||||
queryWindows()
|
||||
queryMonitorState()
|
||||
} catch (e) {
|
||||
Logger.e("MangoService", "Safe update failed:", e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Safely update all state by querying workspaces, windows, and monitor state
|
||||
function safeUpdate() {
|
||||
try {
|
||||
queryWorkspaces()
|
||||
queryWindows()
|
||||
queryMonitorState()
|
||||
} catch (e) {
|
||||
Logger.e("MangoService", "Safe update failed:", e)
|
||||
}
|
||||
}
|
||||
|
||||
// Get the ID of the currently active workspace/tag
|
||||
function getCurrentActiveTagId() {
|
||||
for (const [key, tagData] of Object.entries(workspaceCache)) {
|
||||
// Get the ID of the currently active workspace/tag
|
||||
function getCurrentActiveTagId() {
|
||||
const workspaceEntries1 = Object.entries(workspaceCache)
|
||||
for (var i = 0; i < workspaceEntries1.length; i++) {
|
||||
const key = workspaceEntries1[i][0]
|
||||
const tagData = workspaceEntries1[i][1]
|
||||
if (tagData.isActive && tagData.output === selectedMonitor) {
|
||||
return tagData.id
|
||||
}
|
||||
}
|
||||
|
||||
for (const [key, tagData] of Object.entries(workspaceCache)) {
|
||||
const workspaceEntries2 = Object.entries(workspaceCache)
|
||||
for (var i = 0; i < workspaceEntries2.length; i++) {
|
||||
const key = workspaceEntries2[i][0]
|
||||
const tagData = workspaceEntries2[i][1]
|
||||
if (tagData.isActive) {
|
||||
return tagData.id
|
||||
}
|
||||
|
||||
@@ -21,16 +21,19 @@ Singleton {
|
||||
|
||||
readonly property string displayName: {
|
||||
// Explicit override
|
||||
if (envRealName && envRealName.length > 0)
|
||||
if (envRealName && envRealName.length > 0) {
|
||||
return envRealName
|
||||
}
|
||||
|
||||
// Name from getent
|
||||
if (realName && realName.length > 0)
|
||||
if (realName && realName.length > 0) {
|
||||
return realName
|
||||
}
|
||||
|
||||
// Fallback: capitalized $USER
|
||||
if (username && username.length > 0)
|
||||
if (username && username.length > 0) {
|
||||
return username.charAt(0).toUpperCase() + username.slice(1)
|
||||
}
|
||||
|
||||
// Last resort: placeholder
|
||||
return "User"
|
||||
|
||||
Reference in New Issue
Block a user