mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-06-07 19:59:14 -04:00
fix(display): unify compositor output profiles
This commit is contained in:
@@ -445,7 +445,7 @@ Singleton {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Extract niri settings map from neutral config entry for generateNiriOutputsKdl
|
||||
// Extract niri settings map from a neutral config entry.
|
||||
function getNiriSettingsFromConfig(configEntry) {
|
||||
const result = {};
|
||||
for (const outputId in (configEntry.outputs || {})) {
|
||||
@@ -473,6 +473,28 @@ Singleton {
|
||||
return result;
|
||||
}
|
||||
|
||||
function backendSettingsFromConfig(configEntry) {
|
||||
switch (CompositorService.compositor) {
|
||||
case "niri":
|
||||
return getNiriSettingsFromConfig(configEntry);
|
||||
case "hyprland":
|
||||
return getHyprlandSettingsFromConfig(configEntry);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function backendMergedSettings() {
|
||||
switch (CompositorService.compositor) {
|
||||
case "niri":
|
||||
return buildMergedNiriSettings();
|
||||
case "hyprland":
|
||||
return buildMergedHyprlandSettings();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function ensureEnabledOutput(configEntry) {
|
||||
const outputKeys = Object.keys(configEntry.outputs || {});
|
||||
if (outputKeys.length === 0)
|
||||
@@ -518,51 +540,12 @@ Singleton {
|
||||
WlrOutputService.requestState();
|
||||
};
|
||||
|
||||
switch (CompositorService.compositor) {
|
||||
case "niri":
|
||||
{
|
||||
const paths = getConfigPaths();
|
||||
if (!paths) {
|
||||
onWriteFailed();
|
||||
return;
|
||||
}
|
||||
const configContent = generateNiriOutputsKdl(outputsData, getNiriSettingsFromConfig(configEntry));
|
||||
Proc.runCommand("apply-config-write", ["sh", "-c", `mkdir -p "$(dirname "${paths.outputsFile}")" && cat > "${paths.outputsFile}" << 'EOF'\n${configContent}EOF`], (output, exitCode) => {
|
||||
if (exitCode !== 0) {
|
||||
onWriteFailed();
|
||||
return;
|
||||
}
|
||||
onWriteSuccess();
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "hyprland":
|
||||
HyprlandService.generateOutputsConfig(outputsData, getHyprlandSettingsFromConfig(configEntry), success => {
|
||||
if (success)
|
||||
onWriteSuccess();
|
||||
else
|
||||
onWriteFailed();
|
||||
});
|
||||
break;
|
||||
case "mango":
|
||||
MangoService.generateOutputsConfig(outputsData, success => {
|
||||
if (success)
|
||||
onWriteSuccess();
|
||||
else
|
||||
onWriteFailed();
|
||||
});
|
||||
break;
|
||||
case "dwl":
|
||||
DwlService.generateOutputsConfig(outputsData, success => {
|
||||
if (success)
|
||||
onWriteSuccess();
|
||||
else
|
||||
onWriteFailed();
|
||||
});
|
||||
break;
|
||||
default:
|
||||
onWriteFailed();
|
||||
}
|
||||
backendWriteOutputsConfig(outputsData, backendSettingsFromConfig(configEntry), success => {
|
||||
if (success)
|
||||
onWriteSuccess();
|
||||
else
|
||||
onWriteFailed();
|
||||
});
|
||||
}
|
||||
|
||||
// ── Profile management ─────────────────────────────────────────────────
|
||||
@@ -867,8 +850,7 @@ Singleton {
|
||||
Component.onCompleted: {
|
||||
outputs = buildOutputsMap();
|
||||
reloadSavedOutputs();
|
||||
if (CompositorService.isHyprland)
|
||||
checkIncludeStatus();
|
||||
checkIncludeStatus();
|
||||
}
|
||||
|
||||
function reloadSavedOutputs() {
|
||||
@@ -1466,12 +1448,12 @@ Singleton {
|
||||
}
|
||||
|
||||
const liveOutputs = buildOutputsMap();
|
||||
if (CompositorService.isHyprland && Object.keys(liveOutputs).length > 0) {
|
||||
if (Object.keys(liveOutputs).length > 0) {
|
||||
outputs = liveOutputs;
|
||||
HyprlandService.generateOutputsConfig(liveOutputs, SettingsData.hyprlandOutputSettings, success => {
|
||||
backendWriteOutputsConfig(liveOutputs, backendMergedSettings(), success => {
|
||||
fixingInclude = false;
|
||||
if (!success)
|
||||
ToastService.showError(I18n.tr("Display setup failed"), I18n.tr("Failed to write Hyprland outputs config."), "", "display-config");
|
||||
ToastService.showError(I18n.tr("Display setup failed"), I18n.tr("Failed to write outputs config."), "", "display-config");
|
||||
checkIncludeStatus();
|
||||
WlrOutputService.requestState();
|
||||
});
|
||||
@@ -1570,31 +1552,153 @@ Singleton {
|
||||
WlrOutputService.requestState();
|
||||
}
|
||||
|
||||
function backendWriteOutputsConfig(outputsData) {
|
||||
function backendWriteOutputsConfig(outputsData, settingsOrCallback, maybeCallback) {
|
||||
const settings = typeof settingsOrCallback === "function" ? null : settingsOrCallback;
|
||||
const callback = typeof settingsOrCallback === "function" ? settingsOrCallback : maybeCallback;
|
||||
const hasExplicitSettings = settings !== null && settings !== undefined;
|
||||
|
||||
function finish(success) {
|
||||
if (callback)
|
||||
callback(success);
|
||||
}
|
||||
|
||||
switch (CompositorService.compositor) {
|
||||
case "niri":
|
||||
NiriService.generateOutputsConfig(outputsData);
|
||||
break;
|
||||
case "hyprland":
|
||||
if (readOnly) {
|
||||
showHyprlandReadOnlyWarning();
|
||||
return false;
|
||||
{
|
||||
const niriSettings = hasExplicitSettings ? settings : buildMergedNiriSettings();
|
||||
NiriService.generateOutputsConfig(outputsData, niriSettings, success => {
|
||||
if (!success) {
|
||||
finish(false);
|
||||
return;
|
||||
}
|
||||
reloadAndApplyNiriLiveOutputsConfig(outputsData, niriSettings, finish);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "hyprland":
|
||||
{
|
||||
if (readOnly) {
|
||||
showHyprlandReadOnlyWarning();
|
||||
finish(false);
|
||||
return false;
|
||||
}
|
||||
const hyprlandSettings = hasExplicitSettings ? settings : buildMergedHyprlandSettings();
|
||||
HyprlandService.generateOutputsConfig(outputsData, hyprlandSettings, finish);
|
||||
break;
|
||||
}
|
||||
HyprlandService.generateOutputsConfig(outputsData, buildMergedHyprlandSettings());
|
||||
break;
|
||||
case "mango":
|
||||
MangoService.generateOutputsConfig(outputsData);
|
||||
MangoService.generateOutputsConfig(outputsData, finish);
|
||||
break;
|
||||
case "dwl":
|
||||
DwlService.generateOutputsConfig(outputsData);
|
||||
DwlService.generateOutputsConfig(outputsData, finish);
|
||||
break;
|
||||
default:
|
||||
WlrOutputService.applyOutputsConfig(outputsData, outputs);
|
||||
finish(true);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function niriTransformArg(transform) {
|
||||
switch (transform) {
|
||||
case "90":
|
||||
return "90";
|
||||
case "180":
|
||||
return "180";
|
||||
case "270":
|
||||
return "270";
|
||||
case "Flipped":
|
||||
return "flipped";
|
||||
case "Flipped90":
|
||||
return "flipped-90";
|
||||
case "Flipped180":
|
||||
return "flipped-180";
|
||||
case "Flipped270":
|
||||
return "flipped-270";
|
||||
default:
|
||||
return "normal";
|
||||
}
|
||||
}
|
||||
|
||||
function getLiveNiriOutputName(outputName, outputData) {
|
||||
if (outputs[outputName])
|
||||
return outputName;
|
||||
const targetId = getNiriOutputIdentifier(outputData, outputName);
|
||||
for (const liveName in outputs) {
|
||||
if (getNiriOutputIdentifier(outputs[liveName], liveName) === targetId)
|
||||
return liveName;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function applyNiriLiveOutputsConfig(outputsData, niriSettings, callback) {
|
||||
const names = Object.keys(outputsData || {});
|
||||
let pending = 0;
|
||||
let failed = false;
|
||||
|
||||
function done(success) {
|
||||
if (callback)
|
||||
callback(success);
|
||||
}
|
||||
|
||||
for (const outputName of names) {
|
||||
const output = outputsData[outputName];
|
||||
if (!output)
|
||||
continue;
|
||||
const liveName = getLiveNiriOutputName(outputName, output);
|
||||
if (!liveName)
|
||||
continue;
|
||||
|
||||
const identifier = getNiriOutputIdentifier(output, outputName);
|
||||
const settings = niriSettings?.[outputName] || niriSettings?.[identifier] || {};
|
||||
const config = {};
|
||||
|
||||
if (settings.disabled === true)
|
||||
config.disabled = true;
|
||||
else if (settings.disabled === false)
|
||||
config.disabled = false;
|
||||
|
||||
if (!config.disabled) {
|
||||
if (output.current_mode !== undefined && output.modes && output.modes[output.current_mode]) {
|
||||
const mode = output.modes[output.current_mode];
|
||||
config.mode = mode.width + "x" + mode.height + "@" + (mode.refresh_rate / 1000).toFixed(3);
|
||||
}
|
||||
if (output.logical) {
|
||||
config.scale = output.logical.scale ?? 1.0;
|
||||
config.position = {
|
||||
"x": output.logical.x ?? 0,
|
||||
"y": output.logical.y ?? 0
|
||||
};
|
||||
config.transform = niriTransformArg(output.logical.transform);
|
||||
}
|
||||
if (settings.vrrOnDemand !== undefined)
|
||||
config.vrrOnDemand = settings.vrrOnDemand;
|
||||
else if (output.vrr_enabled !== undefined)
|
||||
config.vrr = output.vrr_enabled;
|
||||
}
|
||||
|
||||
pending++;
|
||||
NiriService.applyOutputConfig(liveName, config, success => {
|
||||
failed = failed || !success;
|
||||
pending--;
|
||||
if (pending === 0) {
|
||||
WlrOutputService.requestState();
|
||||
done(!failed);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (pending === 0)
|
||||
done(true);
|
||||
}
|
||||
|
||||
function reloadAndApplyNiriLiveOutputsConfig(outputsData, niriSettings, callback) {
|
||||
Proc.runCommand("niri-reload-output-config", ["niri", "msg", "action", "load-config-file"], () => {
|
||||
applyNiriLiveOutputsConfig(outputsData, niriSettings, callback);
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeOutputPositions(outputsData) {
|
||||
const names = Object.keys(outputsData);
|
||||
if (names.length === 0)
|
||||
@@ -1982,7 +2086,7 @@ Singleton {
|
||||
|
||||
const mergedOutputs = buildOutputsWithPendingChanges();
|
||||
const mergedNiriSettings = buildMergedNiriSettings();
|
||||
const configContent = generateNiriOutputsKdl(mergedOutputs, mergedNiriSettings);
|
||||
const configContent = NiriService.buildOutputsConfig(mergedOutputs, mergedNiriSettings);
|
||||
|
||||
const configDir = Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation));
|
||||
const tempFile = configDir + "/niri/dms/.outputs-validate-tmp.kdl";
|
||||
@@ -2006,7 +2110,7 @@ Singleton {
|
||||
if (formatChanged)
|
||||
SettingsData.saveSettings();
|
||||
commitNiriSettingsChanges();
|
||||
backendWriteOutputsConfig(mergedOutputs);
|
||||
backendWriteOutputsConfig(mergedOutputs, mergedNiriSettings);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -2083,108 +2187,6 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function generateNiriOutputsKdl(outputsData, niriSettings) {
|
||||
let kdlContent = `// Auto-generated by DMS - do not edit manually\n\n`;
|
||||
const sortedNames = Object.keys(outputsData).sort((a, b) => {
|
||||
const la = outputsData[a].logical || {};
|
||||
const lb = outputsData[b].logical || {};
|
||||
return (la.x ?? 0) - (lb.x ?? 0) || (la.y ?? 0) - (lb.y ?? 0);
|
||||
});
|
||||
for (const outputName of sortedNames) {
|
||||
const output = outputsData[outputName];
|
||||
const identifier = getNiriOutputIdentifier(output, outputName);
|
||||
const settings = niriSettings[identifier] || {};
|
||||
kdlContent += `output "${identifier}" {\n`;
|
||||
if (settings.disabled) {
|
||||
kdlContent += ` off\n}\n\n`;
|
||||
continue;
|
||||
}
|
||||
if (output.current_mode !== undefined && output.modes && output.modes[output.current_mode]) {
|
||||
const mode = output.modes[output.current_mode];
|
||||
kdlContent += ` mode "${mode.width}x${mode.height}@${(mode.refresh_rate / 1000).toFixed(3)}"\n`;
|
||||
}
|
||||
if (output.logical) {
|
||||
kdlContent += ` scale ${output.logical.scale ?? 1.0}\n`;
|
||||
if (output.logical.transform && output.logical.transform !== "Normal") {
|
||||
const transformMap = {
|
||||
"Normal": "normal",
|
||||
"90": "90",
|
||||
"180": "180",
|
||||
"270": "270",
|
||||
"Flipped": "flipped",
|
||||
"Flipped90": "flipped-90",
|
||||
"Flipped180": "flipped-180",
|
||||
"Flipped270": "flipped-270"
|
||||
};
|
||||
kdlContent += ` transform "${transformMap[output.logical.transform] || "normal"}"\n`;
|
||||
}
|
||||
if (output.logical.x !== undefined && output.logical.y !== undefined)
|
||||
kdlContent += ` position x=${output.logical.x} y=${output.logical.y}\n`;
|
||||
}
|
||||
if (settings.vrrOnDemand) {
|
||||
kdlContent += ` variable-refresh-rate on-demand=true\n`;
|
||||
} else if (output.vrr_enabled) {
|
||||
kdlContent += ` variable-refresh-rate\n`;
|
||||
}
|
||||
if (settings.focusAtStartup)
|
||||
kdlContent += ` focus-at-startup\n`;
|
||||
if (settings.backdropColor)
|
||||
kdlContent += ` backdrop-color "${settings.backdropColor}"\n`;
|
||||
kdlContent += generateHotCornersBlock(settings);
|
||||
kdlContent += generateLayoutBlock(settings);
|
||||
kdlContent += `}\n\n`;
|
||||
}
|
||||
return kdlContent;
|
||||
}
|
||||
|
||||
function generateHotCornersBlock(settings) {
|
||||
if (!settings.hotCorners)
|
||||
return "";
|
||||
const hc = settings.hotCorners;
|
||||
if (hc.off)
|
||||
return ` hot-corners {\n off\n }\n`;
|
||||
const corners = hc.corners || [];
|
||||
if (corners.length === 0)
|
||||
return "";
|
||||
let block = ` hot-corners {\n`;
|
||||
for (const corner of corners)
|
||||
block += ` ${corner}\n`;
|
||||
block += ` }\n`;
|
||||
return block;
|
||||
}
|
||||
|
||||
function generateLayoutBlock(settings) {
|
||||
if (!settings.layout)
|
||||
return "";
|
||||
const layout = settings.layout;
|
||||
const hasSettings = layout.gaps !== undefined || layout.defaultColumnWidth || layout.presetColumnWidths || layout.alwaysCenterSingleColumn !== undefined;
|
||||
if (!hasSettings)
|
||||
return "";
|
||||
let block = ` layout {\n`;
|
||||
if (layout.gaps !== undefined)
|
||||
block += ` gaps ${layout.gaps}\n`;
|
||||
if (layout.defaultColumnWidth?.type === "proportion") {
|
||||
const val = layout.defaultColumnWidth.value;
|
||||
const formatted = Number.isInteger(val) ? val.toFixed(1) : val.toString();
|
||||
block += ` default-column-width { proportion ${formatted}; }\n`;
|
||||
}
|
||||
if (layout.presetColumnWidths && layout.presetColumnWidths.length > 0) {
|
||||
block += ` preset-column-widths {\n`;
|
||||
for (const preset of layout.presetColumnWidths) {
|
||||
if (preset.type === "proportion") {
|
||||
const val = preset.value;
|
||||
const formatted = Number.isInteger(val) ? val.toFixed(1) : val.toString();
|
||||
block += ` proportion ${formatted}\n`;
|
||||
}
|
||||
}
|
||||
block += ` }\n`;
|
||||
}
|
||||
if (layout.alwaysCenterSingleColumn !== undefined)
|
||||
block += layout.alwaysCenterSingleColumn ? ` always-center-single-column\n` : ` always-center-single-column false\n`;
|
||||
block += ` }\n`;
|
||||
return block;
|
||||
}
|
||||
|
||||
function confirmChanges(profileId) {
|
||||
const outputConfigs = buildCurrentOutputConfigs();
|
||||
lastAppliedEntry = {
|
||||
|
||||
@@ -1248,15 +1248,36 @@ Singleton {
|
||||
|
||||
const commands = [];
|
||||
|
||||
if (config.disabled !== undefined) {
|
||||
commands.push(`niri msg output "${outputName}" ${config.disabled ? "off" : "on"}`);
|
||||
if (config.disabled) {
|
||||
const fullDisableCommand = "{ " + commands.join(" && ") + "; } 2>&1";
|
||||
Proc.runCommand("niri-output-config", ["sh", "-c", fullDisableCommand], (output, exitCode) => {
|
||||
if (exitCode !== 0) {
|
||||
log.warn("Failed to apply output config:", outputName, "exit:", exitCode, output);
|
||||
if (callback)
|
||||
callback(false, output);
|
||||
return;
|
||||
}
|
||||
fetchOutputs();
|
||||
if (callback)
|
||||
callback(true, "Success");
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.position !== undefined) {
|
||||
commands.push(`niri msg output "${outputName}" position ${config.position.x} ${config.position.y}`);
|
||||
commands.push(`niri msg output "${outputName}" position set ${config.position.x} ${config.position.y}`);
|
||||
}
|
||||
|
||||
if (config.mode !== undefined) {
|
||||
commands.push(`niri msg output "${outputName}" mode ${config.mode}`);
|
||||
}
|
||||
|
||||
if (config.vrr !== undefined) {
|
||||
if (config.vrrOnDemand !== undefined) {
|
||||
commands.push(`niri msg output "${outputName}" vrr --on-demand ${config.vrrOnDemand ? "on" : "off"}`);
|
||||
} else if (config.vrr !== undefined) {
|
||||
commands.push(`niri msg output "${outputName}" vrr ${config.vrr ? "on" : "off"}`);
|
||||
}
|
||||
|
||||
@@ -1274,10 +1295,10 @@ Singleton {
|
||||
return;
|
||||
}
|
||||
|
||||
const fullCommand = commands.join(" && ");
|
||||
const fullCommand = "{ " + commands.join(" && ") + "; } 2>&1";
|
||||
Proc.runCommand("niri-output-config", ["sh", "-c", fullCommand], (output, exitCode) => {
|
||||
if (exitCode !== 0) {
|
||||
log.warn("Failed to apply output config:", output);
|
||||
log.warn("Failed to apply output config:", outputName, "exit:", exitCode, output);
|
||||
if (callback)
|
||||
callback(false, output);
|
||||
return;
|
||||
@@ -1297,10 +1318,32 @@ Singleton {
|
||||
return outputName;
|
||||
}
|
||||
|
||||
function generateOutputsConfig(outputsData) {
|
||||
function outputSettingsFor(output, outputName, niriSettings) {
|
||||
const identifier = getOutputIdentifier(output, outputName);
|
||||
if (niriSettings)
|
||||
return niriSettings[identifier] || niriSettings[outputName] || {};
|
||||
return SettingsData.getNiriOutputSettings(identifier);
|
||||
}
|
||||
|
||||
function transformToNiri(transform) {
|
||||
const transformMap = {
|
||||
"Normal": "normal",
|
||||
"90": "90",
|
||||
"180": "180",
|
||||
"270": "270",
|
||||
"Flipped": "flipped",
|
||||
"Flipped90": "flipped-90",
|
||||
"Flipped180": "flipped-180",
|
||||
"Flipped270": "flipped-270"
|
||||
};
|
||||
return transformMap[transform] || "normal";
|
||||
}
|
||||
|
||||
function buildOutputsConfig(outputsData, niriSettings) {
|
||||
const data = outputsData || outputs;
|
||||
if (!data || Object.keys(data).length === 0)
|
||||
return;
|
||||
return "";
|
||||
|
||||
let kdlContent = `// Auto-generated by DMS - do not edit manually\n\n`;
|
||||
|
||||
const sortedNames = Object.keys(data).sort((a, b) => {
|
||||
@@ -1311,11 +1354,11 @@ Singleton {
|
||||
for (const outputName of sortedNames) {
|
||||
const output = data[outputName];
|
||||
const identifier = getOutputIdentifier(output, outputName);
|
||||
const niriSettings = SettingsData.getNiriOutputSettings(identifier);
|
||||
const outputSettings = outputSettingsFor(output, outputName, niriSettings);
|
||||
|
||||
kdlContent += `output "${identifier}" {\n`;
|
||||
|
||||
if (niriSettings.disabled) {
|
||||
if (outputSettings.disabled) {
|
||||
kdlContent += ` off\n`;
|
||||
kdlContent += `}\n\n`;
|
||||
continue;
|
||||
@@ -1330,17 +1373,7 @@ Singleton {
|
||||
kdlContent += ` scale ${output.logical.scale || 1.0}\n`;
|
||||
|
||||
if (output.logical.transform && output.logical.transform !== "Normal") {
|
||||
const transformMap = {
|
||||
"Normal": "normal",
|
||||
"90": "90",
|
||||
"180": "180",
|
||||
"270": "270",
|
||||
"Flipped": "flipped",
|
||||
"Flipped90": "flipped-90",
|
||||
"Flipped180": "flipped-180",
|
||||
"Flipped270": "flipped-270"
|
||||
};
|
||||
kdlContent += ` transform "${transformMap[output.logical.transform] || "normal"}"\n`;
|
||||
kdlContent += ` transform "${transformToNiri(output.logical.transform)}"\n`;
|
||||
}
|
||||
|
||||
if (output.logical.x !== undefined && output.logical.y !== undefined) {
|
||||
@@ -1348,25 +1381,38 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
if (output.vrr_enabled || niriSettings.vrrOnDemand) {
|
||||
const vrrOnDemand = niriSettings.vrrOnDemand ?? false;
|
||||
if (output.vrr_enabled || outputSettings.vrrOnDemand) {
|
||||
const vrrOnDemand = outputSettings.vrrOnDemand ?? false;
|
||||
kdlContent += vrrOnDemand ? ` variable-refresh-rate on-demand=true\n` : ` variable-refresh-rate\n`;
|
||||
}
|
||||
|
||||
if (niriSettings.focusAtStartup) {
|
||||
if (outputSettings.focusAtStartup) {
|
||||
kdlContent += ` focus-at-startup\n`;
|
||||
}
|
||||
|
||||
if (niriSettings.backdropColor) {
|
||||
kdlContent += ` backdrop-color "${niriSettings.backdropColor}"\n`;
|
||||
if (outputSettings.backdropColor) {
|
||||
kdlContent += ` backdrop-color "${outputSettings.backdropColor}"\n`;
|
||||
}
|
||||
|
||||
kdlContent += generateHotCornersBlock(niriSettings);
|
||||
kdlContent += generateLayoutBlock(niriSettings);
|
||||
kdlContent += generateHotCornersBlock(outputSettings);
|
||||
kdlContent += generateLayoutBlock(outputSettings);
|
||||
|
||||
kdlContent += `}\n\n`;
|
||||
}
|
||||
|
||||
return kdlContent;
|
||||
}
|
||||
|
||||
function generateOutputsConfig(outputsData, settingsOrCallback, maybeCallback) {
|
||||
const niriSettings = typeof settingsOrCallback === "function" ? null : settingsOrCallback;
|
||||
const callback = typeof settingsOrCallback === "function" ? settingsOrCallback : maybeCallback;
|
||||
const kdlContent = buildOutputsConfig(outputsData, niriSettings);
|
||||
if (!kdlContent) {
|
||||
if (callback)
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const configDir = Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation));
|
||||
const niriDmsDir = configDir + "/niri/dms";
|
||||
const outputsPath = niriDmsDir + "/outputs.kdl";
|
||||
@@ -1374,9 +1420,13 @@ Singleton {
|
||||
Proc.runCommand("niri-write-outputs", ["sh", "-c", `mkdir -p "${niriDmsDir}" && cat > "${outputsPath}" << 'EOF'\n${kdlContent}EOF`], (output, exitCode) => {
|
||||
if (exitCode !== 0) {
|
||||
log.warn("Failed to write outputs config:", output);
|
||||
if (callback)
|
||||
callback(false, output);
|
||||
return;
|
||||
}
|
||||
log.info("Generated outputs config at", outputsPath);
|
||||
if (callback)
|
||||
callback(true, "");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user