mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-06-08 04:09:15 -04:00
refactor(fullscreen): Refine fullscreen layering and frame overlay behavior
- Replaced fullscreen hide/reveal toggles with Show Over Fullscreen layer toggles - Added Launcher opt to Show Over Fullscreen setting - Kept fullscreen stacking compositor-owned via top/overlay layer choices - Fixed Hyrland Special Workspaces - Updated DMS Advanced Configuration docs
This commit is contained in:
@@ -36,6 +36,7 @@ Singleton {
|
||||
signal randrDataReady
|
||||
|
||||
property var sortedToplevels: []
|
||||
property var hyprlandVisibleSpecialWorkspaces: ({})
|
||||
property bool _sortScheduled: false
|
||||
|
||||
signal toplevelsChanged
|
||||
@@ -153,10 +154,14 @@ Singleton {
|
||||
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" || event.name === "activespecial") {
|
||||
try {
|
||||
Hyprland.refreshToplevels();
|
||||
if (event.name === "workspace" || event.name === "workspacev2" || event.name === "focusedmon" || event.name === "focusedmonv2" || event.name === "activespecial")
|
||||
Hyprland.refreshMonitors();
|
||||
} catch (e) {}
|
||||
if (event.name === "activespecial")
|
||||
root.updateHyprlandVisibleSpecialWorkspaces(event);
|
||||
root.scheduleSort();
|
||||
}
|
||||
}
|
||||
@@ -171,6 +176,7 @@ Singleton {
|
||||
Component.onCompleted: {
|
||||
fetchRandrData();
|
||||
detectCompositor();
|
||||
updateHyprlandVisibleSpecialWorkspaces(null);
|
||||
scheduleSort();
|
||||
Qt.callLater(() => {
|
||||
NiriService.generateNiriLayoutConfig();
|
||||
@@ -215,6 +221,81 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function _normalizeSpecialWorkspaceName(name) {
|
||||
const raw = String(name ?? "").trim();
|
||||
if (raw.length === 0)
|
||||
return "";
|
||||
if (raw === "special")
|
||||
return "special:special";
|
||||
return raw.startsWith("special:") ? raw : `special:${raw}`;
|
||||
}
|
||||
|
||||
function _hyprlandRawEventParts(event, argumentCount) {
|
||||
if (!event)
|
||||
return [];
|
||||
try {
|
||||
const parsed = event.parse(argumentCount);
|
||||
if (parsed && parsed.length !== undefined)
|
||||
return parsed;
|
||||
} catch (e) {}
|
||||
const data = String(event.data ?? "");
|
||||
return data.length > 0 ? data.split(",") : [];
|
||||
}
|
||||
|
||||
function _specialWorkspaceNameFromMonitor(monitor) {
|
||||
if (!monitor)
|
||||
return "";
|
||||
const candidates = [
|
||||
monitor.activeSpecialWorkspace?.name,
|
||||
monitor.specialWorkspace?.name,
|
||||
monitor.lastIpcObject?.specialWorkspace?.name,
|
||||
monitor.lastIpcObject?.specialWorkspace,
|
||||
monitor.lastIpcObject?.activeSpecialWorkspace?.name
|
||||
];
|
||||
for (let i = 0; i < candidates.length; i++) {
|
||||
const normalized = _normalizeSpecialWorkspaceName(candidates[i]);
|
||||
if (normalized)
|
||||
return normalized;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function updateHyprlandVisibleSpecialWorkspaces(event) {
|
||||
if (!isHyprland) {
|
||||
hyprlandVisibleSpecialWorkspaces = ({});
|
||||
return;
|
||||
}
|
||||
|
||||
const next = {};
|
||||
try {
|
||||
const monitors = Hyprland.monitors?.values || [];
|
||||
for (const monitor of monitors) {
|
||||
const monitorName = monitor?.name ?? monitor?.lastIpcObject?.name ?? "";
|
||||
if (!monitorName)
|
||||
continue;
|
||||
const specialName = _specialWorkspaceNameFromMonitor(monitor);
|
||||
if (specialName)
|
||||
next[monitorName] = specialName;
|
||||
}
|
||||
} catch (e) {
|
||||
log.warn("updateHyprlandVisibleSpecialWorkspaces monitor snapshot failed:", e);
|
||||
}
|
||||
|
||||
if (event?.name === "activespecial") {
|
||||
const parts = _hyprlandRawEventParts(event, 2);
|
||||
const specialName = _normalizeSpecialWorkspaceName(parts[0]);
|
||||
const monitorName = String(parts[1] ?? Hyprland.focusedMonitor?.name ?? Hyprland.focusedWorkspace?.monitor?.name ?? "");
|
||||
if (monitorName) {
|
||||
if (specialName)
|
||||
next[monitorName] = specialName;
|
||||
else
|
||||
delete next[monitorName];
|
||||
}
|
||||
}
|
||||
|
||||
hyprlandVisibleSpecialWorkspaces = next;
|
||||
}
|
||||
|
||||
function sortHyprlandToplevelsSafe() {
|
||||
if (!Hyprland.toplevels || !Hyprland.toplevels.values)
|
||||
return [];
|
||||
@@ -451,6 +532,171 @@ Singleton {
|
||||
return false;
|
||||
}
|
||||
|
||||
function _hyprlandToplevelMapped(hyprToplevel) {
|
||||
if (!hyprToplevel)
|
||||
return false;
|
||||
if (hyprToplevel.mapped === false)
|
||||
return false;
|
||||
const ipcMapped = hyprToplevel.lastIpcObject?.mapped;
|
||||
if (ipcMapped === false)
|
||||
return false;
|
||||
if (hyprToplevel.hidden === true)
|
||||
return false;
|
||||
const ipcHidden = hyprToplevel.lastIpcObject?.hidden;
|
||||
if (ipcHidden === true)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function hyprlandVisibleSpecialWorkspaceOnScreen(screenOrName) {
|
||||
const screenName = _screenName(screenOrName);
|
||||
if (!isHyprland || !screenName)
|
||||
return "";
|
||||
hyprlandVisibleSpecialWorkspaces;
|
||||
const trackedName = hyprlandVisibleSpecialWorkspaces[screenName] ?? "";
|
||||
if (trackedName)
|
||||
return trackedName;
|
||||
try {
|
||||
const monitor = Hyprland.monitors?.values?.find(m => m.name === screenName);
|
||||
return _specialWorkspaceNameFromMonitor(monitor);
|
||||
} catch (e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function hyprlandSpecialWorkspaceBlocksConnectedFrame(screenOrName) {
|
||||
const screenName = _screenName(screenOrName);
|
||||
if (!isHyprland || !screenName || !Hyprland.toplevels?.values)
|
||||
return false;
|
||||
const visibleSpecialWorkspace = hyprlandVisibleSpecialWorkspaceOnScreen(screenName);
|
||||
if (!visibleSpecialWorkspace)
|
||||
return false;
|
||||
|
||||
try {
|
||||
for (const t of Hyprland.toplevels.values) {
|
||||
const monName = t.monitor?.name ?? t.lastIpcObject?.monitor ?? "";
|
||||
if (monName !== screenName)
|
||||
continue;
|
||||
const wsName = _normalizeSpecialWorkspaceName(t.workspace?.name ?? t.lastIpcObject?.workspace?.name ?? "");
|
||||
if (!wsName || wsName !== visibleSpecialWorkspace)
|
||||
continue;
|
||||
if (_hyprlandToplevelMapped(t))
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
log.warn("hyprlandSpecialWorkspaceBlocksConnectedFrame failed:", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function connectedFrameBlockedOnScreen(screenOrName) {
|
||||
if (hasFullscreenToplevelOnScreen(screenOrName))
|
||||
return true;
|
||||
return hyprlandSpecialWorkspaceBlocksConnectedFrame(screenOrName);
|
||||
}
|
||||
|
||||
function _screenForName(screenOrName) {
|
||||
if (screenOrName && typeof screenOrName !== "string")
|
||||
return screenOrName;
|
||||
const screenName = _screenName(screenOrName);
|
||||
if (!screenName)
|
||||
return null;
|
||||
const screens = Quickshell.screens || [];
|
||||
for (let i = 0; i < screens.length; i++) {
|
||||
if (screens[i]?.name === screenName)
|
||||
return screens[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function frameConfiguredForScreen(screenOrName) {
|
||||
if (!SettingsData.frameEnabled)
|
||||
return false;
|
||||
const screen = _screenForName(screenOrName);
|
||||
if (!screen || !SettingsData.isScreenInPreferences(screen, SettingsData.frameScreenPreferences))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function frameWindowVisibleForScreen(screenOrName) {
|
||||
if (!frameConfiguredForScreen(screenOrName))
|
||||
return false;
|
||||
return !connectedFrameBlockedOnScreen(screenOrName);
|
||||
}
|
||||
|
||||
function usesConnectedFrameChromeForScreen(screenOrName) {
|
||||
return SettingsData.connectedFrameModeActive && frameWindowVisibleForScreen(screenOrName);
|
||||
}
|
||||
|
||||
function framePeerSurfacesUseOverlayForScreen(screenOrName) {
|
||||
return frameWindowVisibleForScreen(screenOrName);
|
||||
}
|
||||
|
||||
function hyprlandToplevelOverlapsDockEdge(hyprToplevel, screenName, dockPosition, dockThickness, screenWidth, screenHeight) {
|
||||
if (!hyprToplevel?.lastIpcObject || !screenName)
|
||||
return false;
|
||||
const monName = hyprToplevel.monitor?.name ?? hyprToplevel.lastIpcObject?.monitor ?? "";
|
||||
if (monName && monName !== screenName)
|
||||
return false;
|
||||
const ipc = hyprToplevel.lastIpcObject;
|
||||
const at = ipc.at;
|
||||
const size = ipc.size;
|
||||
if (!at || !size)
|
||||
return false;
|
||||
const monX = hyprToplevel.monitor?.x ?? 0;
|
||||
const monY = hyprToplevel.monitor?.y ?? 0;
|
||||
const winX = at[0] - monX;
|
||||
const winY = at[1] - monY;
|
||||
const winW = size[0];
|
||||
const winH = size[1];
|
||||
switch (dockPosition) {
|
||||
case SettingsData.Position.Top:
|
||||
return winY < dockThickness;
|
||||
case SettingsData.Position.Bottom:
|
||||
return winY + winH > screenHeight - dockThickness;
|
||||
case SettingsData.Position.Left:
|
||||
return winX < dockThickness;
|
||||
case SettingsData.Position.Right:
|
||||
return winX + winW > screenWidth - dockThickness;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function hyprlandDockOverlapForSmartAutoHide(screenName, dockPosition, dockThickness, screenWidth, screenHeight) {
|
||||
if (!isHyprland || !screenName || !Hyprland.toplevels?.values)
|
||||
return false;
|
||||
|
||||
const filtered = filterCurrentWorkspace(sortedToplevels, screenName);
|
||||
for (let i = 0; i < filtered.length; i++) {
|
||||
const toplevel = filtered[i];
|
||||
let hyprToplevel = null;
|
||||
for (const t of Hyprland.toplevels.values) {
|
||||
if (t.wayland === toplevel) {
|
||||
hyprToplevel = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hyprlandToplevelOverlapsDockEdge(hyprToplevel, screenName, dockPosition, dockThickness, screenWidth, screenHeight))
|
||||
return true;
|
||||
}
|
||||
|
||||
const visibleSpecialWorkspace = hyprlandVisibleSpecialWorkspaceOnScreen(screenName);
|
||||
if (!visibleSpecialWorkspace)
|
||||
return false;
|
||||
|
||||
for (const hyprToplevel of Hyprland.toplevels.values) {
|
||||
const wsName = _normalizeSpecialWorkspaceName(hyprToplevel.workspace?.name ?? hyprToplevel.lastIpcObject?.workspace?.name ?? "");
|
||||
if (wsName !== visibleSpecialWorkspace)
|
||||
continue;
|
||||
if (!_hyprlandToplevelMapped(hyprToplevel))
|
||||
continue;
|
||||
if (hyprlandToplevelOverlapsDockEdge(hyprToplevel, screenName, dockPosition, dockThickness, screenWidth, screenHeight))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function filterHyprlandCurrentDisplaySafe(toplevels, screenName) {
|
||||
if (!toplevels || toplevels.length === 0 || !Hyprland.toplevels)
|
||||
return toplevels;
|
||||
|
||||
@@ -500,8 +500,16 @@ Singleton {
|
||||
property bool _dankLauncherV2WantsToggle: false
|
||||
property string _dankLauncherV2PendingQuery: ""
|
||||
property string _dankLauncherV2PendingMode: ""
|
||||
property bool _dankLauncherV2TriggerUsesOverlayLayer: false
|
||||
|
||||
function openDankLauncherV2() {
|
||||
function _setDankLauncherV2TriggerUsesOverlayLayer(value) {
|
||||
_dankLauncherV2TriggerUsesOverlayLayer = value === true;
|
||||
if (dankLauncherV2Modal)
|
||||
dankLauncherV2Modal.triggerUsesOverlayLayer = _dankLauncherV2TriggerUsesOverlayLayer;
|
||||
}
|
||||
|
||||
function openDankLauncherV2(triggerUsesOverlayLayer) {
|
||||
_setDankLauncherV2TriggerUsesOverlayLayer(triggerUsesOverlayLayer);
|
||||
if (dankLauncherV2Modal) {
|
||||
dankLauncherV2Modal.show();
|
||||
} else if (dankLauncherV2ModalLoader) {
|
||||
@@ -511,7 +519,8 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function openDankLauncherV2WithQuery(query: string) {
|
||||
function openDankLauncherV2WithQuery(query: string, triggerUsesOverlayLayer) {
|
||||
_setDankLauncherV2TriggerUsesOverlayLayer(triggerUsesOverlayLayer);
|
||||
if (dankLauncherV2Modal) {
|
||||
dankLauncherV2Modal.showWithQuery(query);
|
||||
} else if (dankLauncherV2ModalLoader) {
|
||||
@@ -522,7 +531,8 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function openDankLauncherV2WithMode(mode: string) {
|
||||
function openDankLauncherV2WithMode(mode: string, triggerUsesOverlayLayer) {
|
||||
_setDankLauncherV2TriggerUsesOverlayLayer(triggerUsesOverlayLayer);
|
||||
if (dankLauncherV2Modal) {
|
||||
dankLauncherV2Modal.showWithMode(mode);
|
||||
} else if (dankLauncherV2ModalLoader) {
|
||||
@@ -544,7 +554,8 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function toggleDankLauncherV2() {
|
||||
function toggleDankLauncherV2(triggerUsesOverlayLayer) {
|
||||
_setDankLauncherV2TriggerUsesOverlayLayer(triggerUsesOverlayLayer);
|
||||
if (dankLauncherV2Modal) {
|
||||
dankLauncherV2Modal.toggle();
|
||||
} else if (dankLauncherV2ModalLoader) {
|
||||
@@ -554,7 +565,8 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function toggleDankLauncherV2WithMode(mode: string) {
|
||||
function toggleDankLauncherV2WithMode(mode: string, triggerUsesOverlayLayer) {
|
||||
_setDankLauncherV2TriggerUsesOverlayLayer(triggerUsesOverlayLayer);
|
||||
if (dankLauncherV2Modal) {
|
||||
dankLauncherV2Modal.toggleWithMode(mode);
|
||||
} else if (dankLauncherV2ModalLoader) {
|
||||
@@ -565,7 +577,8 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function toggleDankLauncherV2WithQuery(query: string) {
|
||||
function toggleDankLauncherV2WithQuery(query: string, triggerUsesOverlayLayer) {
|
||||
_setDankLauncherV2TriggerUsesOverlayLayer(triggerUsesOverlayLayer);
|
||||
if (dankLauncherV2Modal) {
|
||||
dankLauncherV2Modal.toggleWithQuery(query);
|
||||
} else if (dankLauncherV2ModalLoader) {
|
||||
@@ -577,6 +590,8 @@ Singleton {
|
||||
}
|
||||
|
||||
function _onDankLauncherV2ModalLoaded() {
|
||||
if (dankLauncherV2Modal)
|
||||
dankLauncherV2Modal.triggerUsesOverlayLayer = _dankLauncherV2TriggerUsesOverlayLayer;
|
||||
if (_dankLauncherV2WantsOpen) {
|
||||
_dankLauncherV2WantsOpen = false;
|
||||
if (_dankLauncherV2PendingQuery) {
|
||||
|
||||
Reference in New Issue
Block a user