mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-05 21:15:38 -05:00
dankbar: support multiple bars and per-display bars
- Migrate settings to v2 - Up to 4 bars - Per-bar settings instead of global
This commit is contained in:
@@ -26,38 +26,42 @@ Singleton {
|
||||
property var sortedToplevels: []
|
||||
property bool _sortScheduled: false
|
||||
|
||||
signal toplevelsChanged()
|
||||
signal toplevelsChanged
|
||||
|
||||
function getScreenScale(screen) {
|
||||
if (!screen) return 1
|
||||
if (!screen)
|
||||
return 1;
|
||||
|
||||
if (Quickshell.env("QT_WAYLAND_FORCE_DPI") || Quickshell.env("QT_SCALE_FACTOR")) {
|
||||
return screen.devicePixelRatio || 1
|
||||
return screen.devicePixelRatio || 1;
|
||||
}
|
||||
|
||||
if (WlrOutputService.wlrOutputAvailable && screen) {
|
||||
const wlrOutput = WlrOutputService.getOutput(screen.name)
|
||||
const wlrOutput = WlrOutputService.getOutput(screen.name);
|
||||
if (wlrOutput?.enabled && wlrOutput.scale !== undefined && wlrOutput.scale > 0) {
|
||||
return Math.round(wlrOutput.scale * 20) / 20
|
||||
return Math.round(wlrOutput.scale * 20) / 20;
|
||||
}
|
||||
}
|
||||
|
||||
if (isNiri && screen) {
|
||||
const niriScale = NiriService.displayScales[screen.name]
|
||||
if (niriScale !== undefined) return niriScale
|
||||
const niriScale = NiriService.displayScales[screen.name];
|
||||
if (niriScale !== undefined)
|
||||
return niriScale;
|
||||
}
|
||||
|
||||
if (isHyprland && screen) {
|
||||
const hyprlandMonitor = Hyprland.monitors.values.find(m => m.name === screen.name)
|
||||
if (hyprlandMonitor?.scale !== undefined) return hyprlandMonitor.scale
|
||||
const hyprlandMonitor = Hyprland.monitors.values.find(m => m.name === screen.name);
|
||||
if (hyprlandMonitor?.scale !== undefined)
|
||||
return hyprlandMonitor.scale;
|
||||
}
|
||||
|
||||
if (isDwl && screen) {
|
||||
const dwlScale = DwlService.getOutputScale(screen.name)
|
||||
if (dwlScale !== undefined && dwlScale > 0) return dwlScale
|
||||
const dwlScale = DwlService.getOutputScale(screen.name);
|
||||
if (dwlScale !== undefined && dwlScale > 0)
|
||||
return dwlScale;
|
||||
}
|
||||
|
||||
return screen?.devicePixelRatio || 1
|
||||
return screen?.devicePixelRatio || 1;
|
||||
}
|
||||
|
||||
Timer {
|
||||
@@ -65,127 +69,129 @@ Singleton {
|
||||
interval: 100
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
_sortScheduled = false
|
||||
sortedToplevels = computeSortedToplevels()
|
||||
toplevelsChanged()
|
||||
_sortScheduled = false;
|
||||
sortedToplevels = computeSortedToplevels();
|
||||
toplevelsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
function scheduleSort() {
|
||||
if (_sortScheduled) return
|
||||
_sortScheduled = true
|
||||
sortDebounceTimer.restart()
|
||||
if (_sortScheduled)
|
||||
return;
|
||||
_sortScheduled = true;
|
||||
sortDebounceTimer.restart();
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: ToplevelManager.toplevels
|
||||
function onValuesChanged() { root.scheduleSort() }
|
||||
function onValuesChanged() {
|
||||
root.scheduleSort();
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: isHyprland ? Hyprland : null
|
||||
enabled: isHyprland
|
||||
|
||||
function onRawEvent(event) {
|
||||
if (event.name === "openwindow" ||
|
||||
event.name === "closewindow" ||
|
||||
event.name === "movewindow" ||
|
||||
event.name === "movewindowv2" ||
|
||||
event.name === "workspace" ||
|
||||
event.name === "workspacev2" ||
|
||||
event.name === "focusedmon" ||
|
||||
event.name === "focusedmonv2" ||
|
||||
event.name === "activewindow" ||
|
||||
event.name === "activewindowv2" ||
|
||||
event.name === "changefloatingmode" ||
|
||||
event.name === "fullscreen" ||
|
||||
event.name === "moveintogroup" ||
|
||||
event.name === "moveoutofgroup") {
|
||||
if (event.name === "openwindow" || event.name === "closewindow" || event.name === "movewindow" || event.name === "movewindowv2" || event.name === "workspace" || event.name === "workspacev2" || event.name === "focusedmon" || event.name === "focusedmonv2" || event.name === "activewindow" || event.name === "activewindowv2" || event.name === "changefloatingmode" || event.name === "fullscreen" || event.name === "moveintogroup" || event.name === "moveoutofgroup") {
|
||||
try {
|
||||
Hyprland.refreshToplevels()
|
||||
} catch(e) {}
|
||||
root.scheduleSort()
|
||||
Hyprland.refreshToplevels();
|
||||
} catch (e) {}
|
||||
root.scheduleSort();
|
||||
}
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: NiriService
|
||||
function onWindowsChanged() { root.scheduleSort() }
|
||||
function onWindowsChanged() {
|
||||
root.scheduleSort();
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
detectCompositor()
|
||||
scheduleSort()
|
||||
Qt.callLater(() => NiriService.generateNiriLayoutConfig())
|
||||
detectCompositor();
|
||||
scheduleSort();
|
||||
Qt.callLater(() => NiriService.generateNiriLayoutConfig());
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: DwlService
|
||||
function onStateChanged() {
|
||||
if (isDwl && !isHyprland && !isNiri) {
|
||||
scheduleSort()
|
||||
scheduleSort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function computeSortedToplevels() {
|
||||
if (!ToplevelManager.toplevels || !ToplevelManager.toplevels.values)
|
||||
return []
|
||||
return [];
|
||||
|
||||
if (useNiriSorting)
|
||||
return NiriService.sortToplevels(ToplevelManager.toplevels.values)
|
||||
return NiriService.sortToplevels(ToplevelManager.toplevels.values);
|
||||
|
||||
if (isHyprland)
|
||||
return sortHyprlandToplevelsSafe()
|
||||
return sortHyprlandToplevelsSafe();
|
||||
|
||||
return Array.from(ToplevelManager.toplevels.values)
|
||||
return Array.from(ToplevelManager.toplevels.values);
|
||||
}
|
||||
|
||||
function _get(o, path, fallback) {
|
||||
try {
|
||||
let v = o
|
||||
let v = o;
|
||||
for (let i = 0; i < path.length; i++) {
|
||||
if (v === null || v === undefined) return fallback
|
||||
v = v[path[i]]
|
||||
if (v === null || v === undefined)
|
||||
return fallback;
|
||||
v = v[path[i]];
|
||||
}
|
||||
return (v === undefined || v === null) ? fallback : v
|
||||
} catch (e) { return fallback }
|
||||
return (v === undefined || v === null) ? fallback : v;
|
||||
} catch (e) {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
function sortHyprlandToplevelsSafe() {
|
||||
if (!Hyprland.toplevels || !Hyprland.toplevels.values) return []
|
||||
if (!Hyprland.toplevels || !Hyprland.toplevels.values)
|
||||
return [];
|
||||
|
||||
const items = Array.from(Hyprland.toplevels.values)
|
||||
const items = Array.from(Hyprland.toplevels.values);
|
||||
|
||||
function _get(o, path, fb) {
|
||||
try {
|
||||
let v = o
|
||||
for (let k of path) { if (v == null) return fb; v = v[k] }
|
||||
return (v == null) ? fb : v
|
||||
} catch(e) { return fb }
|
||||
let v = o;
|
||||
for (let k of path) {
|
||||
if (v == null)
|
||||
return fb;
|
||||
v = v[k];
|
||||
}
|
||||
return (v == null) ? fb : v;
|
||||
} catch (e) {
|
||||
return fb;
|
||||
}
|
||||
}
|
||||
|
||||
let snap = []
|
||||
let snap = [];
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const t = items[i]
|
||||
if (!t) continue
|
||||
const t = items[i];
|
||||
if (!t)
|
||||
continue;
|
||||
const addr = t.address || "";
|
||||
if (!addr)
|
||||
continue;
|
||||
const li = t.lastIpcObject || null;
|
||||
|
||||
const addr = t.address || ""
|
||||
if (!addr) continue
|
||||
const monName = _get(li, ["monitor"], null) ?? _get(t, ["monitor", "name"], "");
|
||||
const monX = _get(t, ["monitor", "x"], Number.MAX_SAFE_INTEGER);
|
||||
const monY = _get(t, ["monitor", "y"], Number.MAX_SAFE_INTEGER);
|
||||
|
||||
const li = t.lastIpcObject || null
|
||||
const wsId = _get(li, ["workspace", "id"], null) ?? _get(t, ["workspace", "id"], Number.MAX_SAFE_INTEGER);
|
||||
|
||||
const monName = _get(li, ["monitor"], null) ?? _get(t, ["monitor", "name"], "")
|
||||
const monX = _get(t, ["monitor", "x"], Number.MAX_SAFE_INTEGER)
|
||||
const monY = _get(t, ["monitor", "y"], Number.MAX_SAFE_INTEGER)
|
||||
const at = _get(li, ["at"], null);
|
||||
let atX = (at !== null && at !== undefined && typeof at[0] === "number") ? at[0] : 1e9;
|
||||
let atY = (at !== null && at !== undefined && typeof at[1] === "number") ? at[1] : 1e9;
|
||||
|
||||
const wsId = _get(li, ["workspace", "id"], null) ?? _get(t, ["workspace", "id"], Number.MAX_SAFE_INTEGER)
|
||||
|
||||
const at = _get(li, ["at"], null)
|
||||
let atX = (at !== null && at !== undefined && typeof at[0] === "number") ? at[0] : 1e9
|
||||
let atY = (at !== null && at !== undefined && typeof at[1] === "number") ? at[1] : 1e9
|
||||
|
||||
const relX = Number.isFinite(monX) ? (atX - monX) : atX
|
||||
const relY = Number.isFinite(monY) ? (atY - monY) : atY
|
||||
const relX = Number.isFinite(monX) ? (atX - monX) : atX;
|
||||
const relY = Number.isFinite(monY) ? (atY - monY) : atY;
|
||||
|
||||
snap.push({
|
||||
monKey: String(monName),
|
||||
@@ -197,19 +203,20 @@ Singleton {
|
||||
title: t.title || "",
|
||||
address: addr,
|
||||
wayland: t.wayland
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
const groups = new Map()
|
||||
const groups = new Map();
|
||||
for (const it of snap) {
|
||||
const key = it.monKey + "::" + it.wsId
|
||||
if (!groups.has(key)) groups.set(key, [])
|
||||
groups.get(key).push(it)
|
||||
const key = it.monKey + "::" + it.wsId;
|
||||
if (!groups.has(key))
|
||||
groups.set(key, []);
|
||||
groups.get(key).push(it);
|
||||
}
|
||||
|
||||
let groupList = []
|
||||
let groupList = [];
|
||||
for (const [key, arr] of groups) {
|
||||
const repr = arr[0]
|
||||
const repr = arr[0];
|
||||
groupList.push({
|
||||
key,
|
||||
monKey: repr.monKey,
|
||||
@@ -217,122 +224,143 @@ Singleton {
|
||||
monOrderY: repr.monOrderY,
|
||||
wsId: repr.wsId,
|
||||
items: arr
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
groupList.sort((a, b) => {
|
||||
if (a.monOrderX !== b.monOrderX) return a.monOrderX - b.monOrderX
|
||||
if (a.monOrderY !== b.monOrderY) return a.monOrderY - b.monOrderY
|
||||
if (a.monKey !== b.monKey) return a.monKey.localeCompare(b.monKey)
|
||||
if (a.wsId !== b.wsId) return a.wsId - b.wsId
|
||||
return 0
|
||||
})
|
||||
if (a.monOrderX !== b.monOrderX)
|
||||
return a.monOrderX - b.monOrderX;
|
||||
if (a.monOrderY !== b.monOrderY)
|
||||
return a.monOrderY - b.monOrderY;
|
||||
if (a.monKey !== b.monKey)
|
||||
return a.monKey.localeCompare(b.monKey);
|
||||
if (a.wsId !== b.wsId)
|
||||
return a.wsId - b.wsId;
|
||||
return 0;
|
||||
});
|
||||
|
||||
const COLUMN_THRESHOLD = 48
|
||||
const JITTER_Y = 6
|
||||
const COLUMN_THRESHOLD = 48;
|
||||
const JITTER_Y = 6;
|
||||
|
||||
let ordered = []
|
||||
let ordered = [];
|
||||
for (const g of groupList) {
|
||||
const arr = g.items
|
||||
const arr = g.items;
|
||||
|
||||
const xs = arr.map(it => it.x).filter(x => Number.isFinite(x)).sort((a, b) => a - b)
|
||||
let colCenters = []
|
||||
const xs = arr.map(it => it.x).filter(x => Number.isFinite(x)).sort((a, b) => a - b);
|
||||
let colCenters = [];
|
||||
if (xs.length > 0) {
|
||||
for (const x of xs) {
|
||||
if (colCenters.length === 0) {
|
||||
colCenters.push(x)
|
||||
colCenters.push(x);
|
||||
} else {
|
||||
const last = colCenters[colCenters.length - 1]
|
||||
const last = colCenters[colCenters.length - 1];
|
||||
if (x - last >= COLUMN_THRESHOLD) {
|
||||
colCenters.push(x)
|
||||
colCenters.push(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
colCenters = [0]
|
||||
colCenters = [0];
|
||||
}
|
||||
|
||||
for (const it of arr) {
|
||||
let bestCol = 0
|
||||
let bestDist = Number.POSITIVE_INFINITY
|
||||
let bestCol = 0;
|
||||
let bestDist = Number.POSITIVE_INFINITY;
|
||||
for (let ci = 0; ci < colCenters.length; ci++) {
|
||||
const d = Math.abs(it.x - colCenters[ci])
|
||||
const d = Math.abs(it.x - colCenters[ci]);
|
||||
if (d < bestDist) {
|
||||
bestDist = d
|
||||
bestCol = ci
|
||||
bestDist = d;
|
||||
bestCol = ci;
|
||||
}
|
||||
}
|
||||
it._col = bestCol
|
||||
it._col = bestCol;
|
||||
}
|
||||
|
||||
arr.sort((a, b) => {
|
||||
if (a._col !== b._col) return a._col - b._col
|
||||
if (a._col !== b._col)
|
||||
return a._col - b._col;
|
||||
|
||||
const dy = a.y - b.y
|
||||
if (Math.abs(dy) > JITTER_Y) return dy
|
||||
const dy = a.y - b.y;
|
||||
if (Math.abs(dy) > JITTER_Y)
|
||||
return dy;
|
||||
|
||||
if (a.title !== b.title) return a.title.localeCompare(b.title)
|
||||
if (a.address !== b.address) return a.address.localeCompare(b.address)
|
||||
return 0
|
||||
})
|
||||
if (a.title !== b.title)
|
||||
return a.title.localeCompare(b.title);
|
||||
if (a.address !== b.address)
|
||||
return a.address.localeCompare(b.address);
|
||||
return 0;
|
||||
});
|
||||
|
||||
ordered.push.apply(ordered, arr)
|
||||
ordered.push.apply(ordered, arr);
|
||||
}
|
||||
|
||||
return ordered.map(x => x.wayland).filter(w => w !== null && w !== undefined)
|
||||
return ordered.map(x => x.wayland).filter(w => w !== null && w !== undefined);
|
||||
}
|
||||
|
||||
function filterCurrentWorkspace(toplevels, screen) {
|
||||
if (useNiriSorting) return NiriService.filterCurrentWorkspace(toplevels, screen)
|
||||
if (isHyprland) return filterHyprlandCurrentWorkspaceSafe(toplevels, screen)
|
||||
return toplevels
|
||||
if (useNiriSorting)
|
||||
return NiriService.filterCurrentWorkspace(toplevels, screen);
|
||||
if (isHyprland)
|
||||
return filterHyprlandCurrentWorkspaceSafe(toplevels, screen);
|
||||
return toplevels;
|
||||
}
|
||||
|
||||
function filterHyprlandCurrentWorkspaceSafe(toplevels, screenName) {
|
||||
if (!toplevels || toplevels.length === 0 || !Hyprland.toplevels) return toplevels
|
||||
if (!toplevels || toplevels.length === 0 || !Hyprland.toplevels)
|
||||
return toplevels;
|
||||
|
||||
let currentWorkspaceId = null
|
||||
let currentWorkspaceId = null;
|
||||
try {
|
||||
const hy = Array.from(Hyprland.toplevels.values)
|
||||
const hy = Array.from(Hyprland.toplevels.values);
|
||||
for (const t of hy) {
|
||||
const mon = _get(t, ["monitor", "name"], "")
|
||||
const wsId = _get(t, ["workspace", "id"], null)
|
||||
const active = !!_get(t, ["activated"], false)
|
||||
const mon = _get(t, ["monitor", "name"], "");
|
||||
const wsId = _get(t, ["workspace", "id"], null);
|
||||
const active = !!_get(t, ["activated"], false);
|
||||
if (mon === screenName && wsId !== null) {
|
||||
if (active) { currentWorkspaceId = wsId; break }
|
||||
if (currentWorkspaceId === null) currentWorkspaceId = wsId
|
||||
if (active) {
|
||||
currentWorkspaceId = wsId;
|
||||
break;
|
||||
}
|
||||
if (currentWorkspaceId === null)
|
||||
currentWorkspaceId = wsId;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentWorkspaceId === null && Hyprland.workspaces) {
|
||||
const wss = Array.from(Hyprland.workspaces.values)
|
||||
const focusedId = _get(Hyprland, ["focusedWorkspace", "id"], null)
|
||||
const wss = Array.from(Hyprland.workspaces.values);
|
||||
const focusedId = _get(Hyprland, ["focusedWorkspace", "id"], null);
|
||||
for (const ws of wss) {
|
||||
const monName = _get(ws, ["monitor"], "")
|
||||
const wsId = _get(ws, ["id"], null)
|
||||
const monName = _get(ws, ["monitor"], "");
|
||||
const wsId = _get(ws, ["id"], null);
|
||||
if (monName === screenName && wsId !== null) {
|
||||
if (focusedId !== null && wsId === focusedId) { currentWorkspaceId = wsId; break }
|
||||
if (currentWorkspaceId === null) currentWorkspaceId = wsId
|
||||
if (focusedId !== null && wsId === focusedId) {
|
||||
currentWorkspaceId = wsId;
|
||||
break;
|
||||
}
|
||||
if (currentWorkspaceId === null)
|
||||
currentWorkspaceId = wsId;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("CompositorService: workspace snapshot failed:", e)
|
||||
console.warn("CompositorService: workspace snapshot failed:", e);
|
||||
}
|
||||
|
||||
if (currentWorkspaceId === null) return toplevels
|
||||
if (currentWorkspaceId === null)
|
||||
return toplevels;
|
||||
|
||||
// Map wayland → wsId snapshot
|
||||
let map = new Map()
|
||||
let map = new Map();
|
||||
try {
|
||||
const hy = Array.from(Hyprland.toplevels.values)
|
||||
const hy = Array.from(Hyprland.toplevels.values);
|
||||
for (const t of hy) {
|
||||
const wsId = _get(t, ["workspace", "id"], null)
|
||||
if (t && t.wayland && wsId !== null) map.set(t.wayland, wsId)
|
||||
const wsId = _get(t, ["workspace", "id"], null);
|
||||
if (t && t.wayland && wsId !== null)
|
||||
map.set(t.wayland, wsId);
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
return toplevels.filter(w => map.get(w) === currentWorkspaceId)
|
||||
return toplevels.filter(w => map.get(w) === currentWorkspaceId);
|
||||
}
|
||||
|
||||
Timer {
|
||||
@@ -341,77 +369,76 @@ Singleton {
|
||||
running: true
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
detectCompositor()
|
||||
Qt.callLater(() => NiriService.generateNiriLayoutConfig())
|
||||
detectCompositor();
|
||||
Qt.callLater(() => NiriService.generateNiriLayoutConfig());
|
||||
}
|
||||
}
|
||||
|
||||
function detectCompositor() {
|
||||
if (hyprlandSignature && hyprlandSignature.length > 0 &&
|
||||
!niriSocket && !swaySocket && !labwcPid) {
|
||||
isHyprland = true
|
||||
isNiri = false
|
||||
isDwl = false
|
||||
isSway = false
|
||||
isLabwc = false
|
||||
compositor = "hyprland"
|
||||
console.info("CompositorService: Detected Hyprland")
|
||||
return
|
||||
if (hyprlandSignature && hyprlandSignature.length > 0 && !niriSocket && !swaySocket && !labwcPid) {
|
||||
isHyprland = true;
|
||||
isNiri = false;
|
||||
isDwl = false;
|
||||
isSway = false;
|
||||
isLabwc = false;
|
||||
compositor = "hyprland";
|
||||
console.info("CompositorService: Detected Hyprland");
|
||||
return;
|
||||
}
|
||||
|
||||
if (niriSocket && niriSocket.length > 0) {
|
||||
Proc.runCommand("niriSocketCheck", ["test", "-S", niriSocket], (output, exitCode) => {
|
||||
if (exitCode === 0) {
|
||||
isNiri = true
|
||||
isHyprland = false
|
||||
isDwl = false
|
||||
isSway = false
|
||||
isLabwc = false
|
||||
compositor = "niri"
|
||||
console.info("CompositorService: Detected Niri with socket:", niriSocket)
|
||||
NiriService.generateNiriBinds()
|
||||
NiriService.generateNiriBlurrule()
|
||||
isNiri = true;
|
||||
isHyprland = false;
|
||||
isDwl = false;
|
||||
isSway = false;
|
||||
isLabwc = false;
|
||||
compositor = "niri";
|
||||
console.info("CompositorService: Detected Niri with socket:", niriSocket);
|
||||
NiriService.generateNiriBinds();
|
||||
NiriService.generateNiriBlurrule();
|
||||
}
|
||||
}, 0)
|
||||
return
|
||||
}, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (swaySocket && swaySocket.length > 0) {
|
||||
Proc.runCommand("swaySocketCheck", ["test", "-S", swaySocket], (output, exitCode) => {
|
||||
if (exitCode === 0) {
|
||||
isNiri = false
|
||||
isHyprland = false
|
||||
isDwl = false
|
||||
isSway = true
|
||||
isLabwc = false
|
||||
compositor = "sway"
|
||||
console.info("CompositorService: Detected Sway with socket:", swaySocket)
|
||||
isNiri = false;
|
||||
isHyprland = false;
|
||||
isDwl = false;
|
||||
isSway = true;
|
||||
isLabwc = false;
|
||||
compositor = "sway";
|
||||
console.info("CompositorService: Detected Sway with socket:", swaySocket);
|
||||
}
|
||||
}, 0)
|
||||
return
|
||||
}, 0);
|
||||
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
|
||||
isHyprland = false;
|
||||
isNiri = false;
|
||||
isDwl = false;
|
||||
isSway = false;
|
||||
isLabwc = true;
|
||||
compositor = "labwc";
|
||||
console.info("CompositorService: Detected LabWC with PID:", labwcPid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (DMSService.dmsAvailable) {
|
||||
Qt.callLater(checkForDwl)
|
||||
Qt.callLater(checkForDwl);
|
||||
} else {
|
||||
isHyprland = false
|
||||
isNiri = false
|
||||
isDwl = false
|
||||
isSway = false
|
||||
isLabwc = false
|
||||
compositor = "unknown"
|
||||
console.warn("CompositorService: No compositor detected")
|
||||
isHyprland = false;
|
||||
isNiri = false;
|
||||
isDwl = false;
|
||||
isSway = false;
|
||||
isLabwc = false;
|
||||
compositor = "unknown";
|
||||
console.warn("CompositorService: No compositor detected");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,65 +446,85 @@ Singleton {
|
||||
target: DMSService
|
||||
function onCapabilitiesReceived() {
|
||||
if (!isHyprland && !isNiri && !isDwl && !isLabwc) {
|
||||
checkForDwl()
|
||||
checkForDwl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkForDwl() {
|
||||
if (DMSService.apiVersion >= 12 && DMSService.capabilities.includes("dwl")) {
|
||||
isHyprland = false
|
||||
isNiri = false
|
||||
isDwl = true
|
||||
isSway = false
|
||||
isLabwc = false
|
||||
compositor = "dwl"
|
||||
console.info("CompositorService: Detected DWL via DMS capability")
|
||||
isHyprland = false;
|
||||
isNiri = false;
|
||||
isDwl = true;
|
||||
isSway = false;
|
||||
isLabwc = false;
|
||||
compositor = "dwl";
|
||||
console.info("CompositorService: Detected DWL via DMS capability");
|
||||
}
|
||||
}
|
||||
|
||||
function powerOffMonitors() {
|
||||
if (isNiri) return NiriService.powerOffMonitors()
|
||||
if (isHyprland) return Hyprland.dispatch("dpms off")
|
||||
if (isDwl) return _dwlPowerOffMonitors()
|
||||
if (isSway) { try { I3.dispatch("output * dpms off") } catch(_){} return }
|
||||
if (isLabwc) { Quickshell.execDetached(["dms", "dpms", "off"]) }
|
||||
console.warn("CompositorService: Cannot power off monitors, unknown compositor")
|
||||
if (isNiri)
|
||||
return NiriService.powerOffMonitors();
|
||||
if (isHyprland)
|
||||
return Hyprland.dispatch("dpms off");
|
||||
if (isDwl)
|
||||
return _dwlPowerOffMonitors();
|
||||
if (isSway) {
|
||||
try {
|
||||
I3.dispatch("output * dpms off");
|
||||
} catch (_) {}
|
||||
return;
|
||||
}
|
||||
if (isLabwc) {
|
||||
Quickshell.execDetached(["dms", "dpms", "off"]);
|
||||
}
|
||||
console.warn("CompositorService: Cannot power off monitors, unknown compositor");
|
||||
}
|
||||
|
||||
function powerOnMonitors() {
|
||||
if (isNiri) return NiriService.powerOnMonitors()
|
||||
if (isHyprland) return Hyprland.dispatch("dpms on")
|
||||
if (isDwl) return _dwlPowerOnMonitors()
|
||||
if (isSway) { try { I3.dispatch("output * dpms on") } catch(_){} return }
|
||||
if (isLabwc) { Quickshell.execDetached(["dms", "dpms", "on"]) }
|
||||
console.warn("CompositorService: Cannot power on monitors, unknown compositor")
|
||||
if (isNiri)
|
||||
return NiriService.powerOnMonitors();
|
||||
if (isHyprland)
|
||||
return Hyprland.dispatch("dpms on");
|
||||
if (isDwl)
|
||||
return _dwlPowerOnMonitors();
|
||||
if (isSway) {
|
||||
try {
|
||||
I3.dispatch("output * dpms on");
|
||||
} catch (_) {}
|
||||
return;
|
||||
}
|
||||
if (isLabwc) {
|
||||
Quickshell.execDetached(["dms", "dpms", "on"]);
|
||||
}
|
||||
console.warn("CompositorService: Cannot power on monitors, unknown compositor");
|
||||
}
|
||||
|
||||
function _dwlPowerOffMonitors() {
|
||||
if (!Quickshell.screens || Quickshell.screens.length === 0) {
|
||||
console.warn("CompositorService: No screens available for DWL power off")
|
||||
return
|
||||
console.warn("CompositorService: No screens available for DWL power off");
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < Quickshell.screens.length; i++) {
|
||||
const screen = Quickshell.screens[i]
|
||||
const screen = Quickshell.screens[i];
|
||||
if (screen && screen.name) {
|
||||
Quickshell.execDetached(["mmsg", "-d", "disable_monitor," + screen.name])
|
||||
Quickshell.execDetached(["mmsg", "-d", "disable_monitor," + screen.name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _dwlPowerOnMonitors() {
|
||||
if (!Quickshell.screens || Quickshell.screens.length === 0) {
|
||||
console.warn("CompositorService: No screens available for DWL power on")
|
||||
return
|
||||
console.warn("CompositorService: No screens available for DWL power on");
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < Quickshell.screens.length; i++) {
|
||||
const screen = Quickshell.screens[i]
|
||||
const screen = Quickshell.screens[i];
|
||||
if (screen && screen.name) {
|
||||
Quickshell.execDetached(["mmsg", "-d", "enable_monitor," + screen.name])
|
||||
Quickshell.execDetached(["mmsg", "-d", "enable_monitor," + screen.name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -962,7 +962,7 @@ Singleton {
|
||||
console.log("NiriService: Generating layout config...")
|
||||
|
||||
const cornerRadius = typeof SettingsData !== "undefined" ? SettingsData.cornerRadius : 12
|
||||
const gaps = typeof SettingsData !== "undefined" ? Math.max(4, SettingsData.dankBarSpacing) : 4
|
||||
const gaps = typeof SettingsData !== "undefined" ? Math.max(4, (SettingsData.barConfigs[0]?.spacing ?? 4)) : 4
|
||||
|
||||
const configContent = `layout {
|
||||
gaps ${gaps}
|
||||
|
||||
@@ -411,6 +411,16 @@ Singleton {
|
||||
NotifWrapper {}
|
||||
}
|
||||
|
||||
function clearAllPopups() {
|
||||
for (const w of visibleNotifications) {
|
||||
if (w) {
|
||||
w.popup = false
|
||||
}
|
||||
}
|
||||
visibleNotifications = []
|
||||
notificationQueue = []
|
||||
}
|
||||
|
||||
function clearAllNotifications() {
|
||||
bulkDismissing = true
|
||||
popupsDisabled = true
|
||||
|
||||
@@ -428,9 +428,12 @@ Singleton {
|
||||
return id !== widgetId
|
||||
}
|
||||
|
||||
const leftWidgets = SettingsData.dankBarLeftWidgets
|
||||
const centerWidgets = SettingsData.dankBarCenterWidgets
|
||||
const rightWidgets = SettingsData.dankBarRightWidgets
|
||||
const defaultBar = SettingsData.barConfigs[0] || SettingsData.getBarConfig("default")
|
||||
if (!defaultBar) return
|
||||
|
||||
const leftWidgets = defaultBar.leftWidgets || []
|
||||
const centerWidgets = defaultBar.centerWidgets || []
|
||||
const rightWidgets = defaultBar.rightWidgets || []
|
||||
|
||||
const newLeft = leftWidgets.filter(filterWidget)
|
||||
const newCenter = centerWidgets.filter(filterWidget)
|
||||
|
||||
Reference in New Issue
Block a user