mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 13:32:50 -05:00
feat: Intelligent Dock Auto-hide
This commit is contained in:
@@ -366,6 +366,7 @@ Singleton {
|
||||
|
||||
property bool showDock: false
|
||||
property bool dockAutoHide: false
|
||||
property bool dockSmartAutoHide: false
|
||||
property bool dockGroupByApp: false
|
||||
property bool dockOpenOnOverview: false
|
||||
property int dockPosition: SettingsData.Position.Bottom
|
||||
|
||||
@@ -231,6 +231,7 @@ var SPEC = {
|
||||
|
||||
showDock: { def: false },
|
||||
dockAutoHide: { def: false },
|
||||
dockSmartAutoHide: { def: false },
|
||||
dockGroupByApp: { def: false },
|
||||
dockOpenOnOverview: { def: false },
|
||||
dockPosition: { def: 1 },
|
||||
|
||||
@@ -2,6 +2,7 @@ pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Shapes
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import Quickshell.Wayland
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
@@ -28,7 +29,7 @@ Variants {
|
||||
}
|
||||
|
||||
property var modelData: item
|
||||
property bool autoHide: SettingsData.dockAutoHide
|
||||
property bool autoHide: SettingsData.dockAutoHide || SettingsData.dockSmartAutoHide
|
||||
property real backgroundTransparency: SettingsData.dockTransparency
|
||||
property bool groupByApp: SettingsData.dockGroupByApp
|
||||
readonly property int borderThickness: SettingsData.dockBorderEnabled ? SettingsData.dockBorderThickness : 0
|
||||
@@ -111,6 +112,133 @@ Variants {
|
||||
property bool contextMenuOpen: (dockVariants.contextMenu && dockVariants.contextMenu.visible && dockVariants.contextMenu.screen === modelData)
|
||||
property bool revealSticky: false
|
||||
|
||||
readonly property bool shouldHideForWindows: {
|
||||
if (!SettingsData.dockSmartAutoHide)
|
||||
return false;
|
||||
if (!CompositorService.isNiri && !CompositorService.isHyprland)
|
||||
return false;
|
||||
|
||||
const screenName = dock.modelData?.name ?? "";
|
||||
const dockThickness = effectiveBarHeight + SettingsData.dockSpacing + SettingsData.dockBottomGap + SettingsData.dockMargin;
|
||||
const screenWidth = dock.screen?.width ?? 0;
|
||||
const screenHeight = dock.screen?.height ?? 0;
|
||||
|
||||
if (CompositorService.isNiri) {
|
||||
NiriService.windows;
|
||||
|
||||
let currentWorkspaceId = null;
|
||||
for (let i = 0; i < NiriService.allWorkspaces.length; i++) {
|
||||
const ws = NiriService.allWorkspaces[i];
|
||||
if (ws.output === screenName && ws.is_active) {
|
||||
currentWorkspaceId = ws.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentWorkspaceId === null)
|
||||
return false;
|
||||
|
||||
for (let i = 0; i < NiriService.windows.length; i++) {
|
||||
const win = NiriService.windows[i];
|
||||
if (win.workspace_id !== currentWorkspaceId)
|
||||
continue;
|
||||
|
||||
// Get window position and size from layout data
|
||||
const tilePos = win.layout?.tile_pos_in_workspace_view;
|
||||
const winSize = win.layout?.window_size || win.layout?.tile_size;
|
||||
|
||||
if (tilePos && winSize) {
|
||||
const winX = tilePos[0];
|
||||
const winY = tilePos[1];
|
||||
const winW = winSize[0];
|
||||
const winH = winSize[1];
|
||||
|
||||
switch (SettingsData.dockPosition) {
|
||||
case SettingsData.Position.Top:
|
||||
if (winY < dockThickness)
|
||||
return true;
|
||||
break;
|
||||
case SettingsData.Position.Bottom:
|
||||
if (winY + winH > screenHeight - dockThickness)
|
||||
return true;
|
||||
break;
|
||||
case SettingsData.Position.Left:
|
||||
if (winX < dockThickness)
|
||||
return true;
|
||||
break;
|
||||
case SettingsData.Position.Right:
|
||||
if (winX + winW > screenWidth - dockThickness)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
} else if (!win.is_floating) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hyprland implementation
|
||||
const filtered = CompositorService.filterCurrentWorkspace(CompositorService.sortedToplevels, screenName);
|
||||
|
||||
if (filtered.length === 0)
|
||||
return false;
|
||||
|
||||
for (let i = 0; i < filtered.length; i++) {
|
||||
const toplevel = filtered[i];
|
||||
|
||||
let hyprToplevel = null;
|
||||
if (Hyprland.toplevels) {
|
||||
const hyprToplevels = Array.from(Hyprland.toplevels.values);
|
||||
for (let j = 0; j < hyprToplevels.length; j++) {
|
||||
if (hyprToplevels[j].wayland === toplevel) {
|
||||
hyprToplevel = hyprToplevels[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hyprToplevel?.lastIpcObject)
|
||||
continue;
|
||||
|
||||
const ipc = hyprToplevel.lastIpcObject;
|
||||
const at = ipc.at;
|
||||
const size = ipc.size;
|
||||
if (!at || !size)
|
||||
continue;
|
||||
|
||||
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 (SettingsData.dockPosition) {
|
||||
case SettingsData.Position.Top:
|
||||
if (winY < dockThickness)
|
||||
return true;
|
||||
break;
|
||||
case SettingsData.Position.Bottom:
|
||||
if (winY + winH > screenHeight - dockThickness)
|
||||
return true;
|
||||
break;
|
||||
case SettingsData.Position.Left:
|
||||
if (winX < dockThickness)
|
||||
return true;
|
||||
break;
|
||||
case SettingsData.Position.Right:
|
||||
if (winX + winW > screenWidth - dockThickness)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: revealHold
|
||||
interval: 250
|
||||
@@ -122,6 +250,15 @@ Variants {
|
||||
if (CompositorService.isNiri && NiriService.inOverview && SettingsData.dockOpenOnOverview) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Smart auto-hide: show dock when no windows overlap, hide when they do
|
||||
if (SettingsData.dockSmartAutoHide) {
|
||||
if (shouldHideForWindows)
|
||||
return dockMouseArea.containsMouse || dockApps.requestDockShow || contextMenuOpen || revealSticky;
|
||||
return true; // No overlapping windows - show dock
|
||||
}
|
||||
|
||||
// Regular auto-hide: always hide unless hovering
|
||||
return !autoHide || dockMouseArea.containsMouse || dockApps.requestDockShow || contextMenuOpen || revealSticky;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,10 +86,30 @@ Item {
|
||||
settingKey: "dockAutoHide"
|
||||
tags: ["dock", "autohide", "hide", "hover"]
|
||||
text: I18n.tr("Auto-hide Dock")
|
||||
description: I18n.tr("Hide the dock when not in use and reveal it when hovering near the dock area")
|
||||
description: I18n.tr("Always hide the dock and reveal it when hovering near the dock area")
|
||||
checked: SettingsData.dockAutoHide
|
||||
visible: SettingsData.showDock
|
||||
onToggled: checked => SettingsData.set("dockAutoHide", checked)
|
||||
onToggled: checked => {
|
||||
if (checked && SettingsData.dockSmartAutoHide) {
|
||||
SettingsData.set("dockSmartAutoHide", false);
|
||||
}
|
||||
SettingsData.set("dockAutoHide", checked);
|
||||
}
|
||||
}
|
||||
|
||||
SettingsToggleRow {
|
||||
settingKey: "dockSmartAutoHide"
|
||||
tags: ["dock", "smart", "autohide", "windows", "overlap", "intelligent"]
|
||||
text: I18n.tr("Intelligent Auto-hide")
|
||||
description: I18n.tr("Show dock when floating windows don't overlap its area")
|
||||
checked: SettingsData.dockSmartAutoHide
|
||||
visible: SettingsData.showDock && (CompositorService.isNiri || CompositorService.isHyprland)
|
||||
onToggled: checked => {
|
||||
if (checked && SettingsData.dockAutoHide) {
|
||||
SettingsData.set("dockAutoHide", false);
|
||||
}
|
||||
SettingsData.set("dockSmartAutoHide", checked);
|
||||
}
|
||||
}
|
||||
|
||||
SettingsToggleRow {
|
||||
|
||||
@@ -4265,6 +4265,12 @@
|
||||
"reference": "Modules/Settings/DankBarTab.qml:1068",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Intelligent Auto-hide",
|
||||
"context": "Intelligent Auto-hide",
|
||||
"reference": "Modules/Settings/DockTab.qml:103",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Interface:",
|
||||
"context": "Interface:",
|
||||
@@ -7415,6 +7421,12 @@
|
||||
"reference": "Modules/Settings/ThemeColorsTab.qml:1375",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Show dock when windows don't overlap its area, hide when they do",
|
||||
"context": "Show dock when windows don't overlap its area, hide when they do",
|
||||
"reference": "Modules/Settings/DockTab.qml:104",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Show launcher overlay when typing in Niri overview. Disable to use another launcher.",
|
||||
"context": "Show launcher overlay when typing in Niri overview. Disable to use another launcher.",
|
||||
|
||||
@@ -4976,6 +4976,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Intelligent Auto-hide",
|
||||
"translation": "",
|
||||
"context": "Intelligent Auto-hide",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Interface:",
|
||||
"translation": "",
|
||||
@@ -8651,6 +8658,13 @@
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Show dock when windows don't overlap its area, hide when they do",
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
},
|
||||
{
|
||||
"term": "Show launcher overlay when typing in Niri overview. Disable to use another launcher.",
|
||||
"translation": "",
|
||||
|
||||
Reference in New Issue
Block a user