mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-05-10 06:19:36 -04:00
fix(Dock): Refactor & Fix Dock in FrameModes. Updates to Zone offset in Standalone & Connected modes
- Fixed hairline seam in some connected mode variants - Moved dock-related properties to a new DockGeometry component for a future base
This commit is contained in:
@@ -46,14 +46,10 @@ Variants {
|
||||
property bool groupByApp: SettingsData.dockGroupByApp
|
||||
readonly property int borderThickness: SettingsData.dockBorderEnabled ? SettingsData.dockBorderThickness : 0
|
||||
readonly property string connectedBarSide: SettingsData.dockPosition === SettingsData.Position.Top ? "top" : SettingsData.dockPosition === SettingsData.Position.Bottom ? "bottom" : SettingsData.dockPosition === SettingsData.Position.Left ? "left" : "right"
|
||||
readonly property bool connectedBarActiveOnEdge: Theme.isConnectedEffect && !!(dock.screen || modelData) && SettingsData.getActiveBarEdgesForScreen(dock.screen || modelData).includes(connectedBarSide)
|
||||
readonly property real connectedJoinInset: {
|
||||
if (Theme.isConnectedEffect)
|
||||
return connectedBarActiveOnEdge ? SettingsData.frameBarSize : SettingsData.frameThickness;
|
||||
if (SettingsData.frameEnabled)
|
||||
return SettingsData.frameEdgeInsetForSide(dock.screen || modelData, dock.connectedBarSide);
|
||||
return 0;
|
||||
}
|
||||
readonly property bool frameDockExclusionActive: dockGeometry.frameExclusionActive
|
||||
readonly property bool connectedBarActiveOnEdge: dockGeometry.connectedBarActiveOnEdge
|
||||
readonly property real connectedJoinInset: dockGeometry.connectedJoinInset
|
||||
readonly property real dockFrameInset: dockGeometry.frameInset
|
||||
readonly property real surfaceRadius: Theme.connectedSurfaceRadius
|
||||
readonly property color surfaceColor: Theme.isConnectedEffect ? Theme.connectedSurfaceColor : Theme.withAlpha(Theme.surfaceContainer, backgroundTransparency)
|
||||
readonly property color surfaceBorderColor: Theme.isConnectedEffect ? "transparent" : BlurService.borderColor
|
||||
@@ -68,7 +64,7 @@ Variants {
|
||||
readonly property int hasApps: dockApps.implicitWidth > 0 || dockApps.implicitHeight > 0
|
||||
|
||||
readonly property real widgetHeight: SettingsData.dockIconSize
|
||||
readonly property real effectiveBarHeight: widgetHeight + SettingsData.dockSpacing * 2 + 10 + borderThickness * 2
|
||||
readonly property real effectiveBarHeight: dockGeometry.visualThickness
|
||||
function getBarHeight(barConfig) {
|
||||
if (!barConfig)
|
||||
return 0;
|
||||
@@ -137,15 +133,32 @@ Variants {
|
||||
|
||||
readonly property real dockMargin: SettingsData.dockMargin
|
||||
readonly property bool effectiveBlurEnabled: Theme.connectedSurfaceBlurEnabled
|
||||
readonly property real effectiveDockBottomGap: Theme.isConnectedEffect ? 0 : SettingsData.dockBottomGap
|
||||
readonly property real effectiveDockMargin: Theme.isConnectedEffect ? 0 : SettingsData.dockMargin
|
||||
readonly property real effectiveDockBottomGap: dockGeometry.visualOffset
|
||||
readonly property real effectiveDockMargin: dockGeometry.effectiveMargin
|
||||
readonly property real positionSpacing: barSpacing + effectiveDockBottomGap + effectiveDockMargin
|
||||
readonly property real joinedEdgeMargin: Theme.isConnectedEffect ? 0 : (barSpacing + effectiveDockMargin + 1 + dock.borderThickness)
|
||||
readonly property real joinedEdgeMargin: dockGeometry.joinedEdgeMargin
|
||||
readonly property real _dpr: (dock.screen && dock.screen.devicePixelRatio) ? dock.screen.devicePixelRatio : 1
|
||||
function px(v) {
|
||||
return Math.round(v * _dpr) / _dpr;
|
||||
}
|
||||
|
||||
DockGeometry {
|
||||
id: dockGeometry
|
||||
|
||||
screen: dock.screen || dock.modelData
|
||||
edge: dock.connectedBarSide
|
||||
dockVisible: dock.visible
|
||||
autoHide: dock.autoHide
|
||||
hasFullscreenToplevel: dock.hasFullscreenToplevel
|
||||
iconSize: dock.widgetHeight
|
||||
spacing: SettingsData.dockSpacing
|
||||
borderThickness: dock.borderThickness
|
||||
offset: SettingsData.dockBottomGap
|
||||
margin: SettingsData.dockMargin
|
||||
barSpacing: dock.barSpacing
|
||||
dpr: dock._dpr
|
||||
}
|
||||
|
||||
// Dock window origin in screen-relative coordinates (FrameWindow space).
|
||||
function _dockWindowOriginX() {
|
||||
if (!dock.isVertical)
|
||||
@@ -231,7 +244,7 @@ Variants {
|
||||
return false;
|
||||
|
||||
const screenName = dock.modelData?.name ?? "";
|
||||
const dockThickness = dock.connectedJoinInset + effectiveBarHeight + SettingsData.dockSpacing + dock.effectiveDockBottomGap + dock.effectiveDockMargin;
|
||||
const dockThickness = dockGeometry.motionThickness;
|
||||
const screenWidth = dock.screen?.width ?? 0;
|
||||
const screenHeight = dock.screen?.height ?? 0;
|
||||
|
||||
@@ -434,20 +447,21 @@ Variants {
|
||||
}
|
||||
color: "transparent"
|
||||
|
||||
readonly property real dockReserveZone: dockGeometry.reserveZone
|
||||
readonly property bool shouldReserveDockSpace: dockGeometry.shouldReserveSpace
|
||||
|
||||
exclusiveZone: {
|
||||
if (dock.hasFullscreenToplevel)
|
||||
if (!dock.shouldReserveDockSpace)
|
||||
return -1;
|
||||
if (!SettingsData.showDock || autoHide)
|
||||
if (dock.frameDockExclusionActive)
|
||||
return -1;
|
||||
if (barSpacing > 0)
|
||||
return -1;
|
||||
return px(connectedJoinInset + effectiveBarHeight + SettingsData.dockSpacing + effectiveDockBottomGap + effectiveDockMargin);
|
||||
return dock.dockReserveZone;
|
||||
}
|
||||
|
||||
property real animationHeadroom: Math.ceil(SettingsData.dockIconSize * 0.35)
|
||||
|
||||
implicitWidth: isVertical ? (px(connectedJoinInset + effectiveBarHeight + SettingsData.dockSpacing + effectiveDockMargin + SettingsData.dockIconSize * 0.3) + animationHeadroom) : 0
|
||||
implicitHeight: !isVertical ? (px(connectedJoinInset + effectiveBarHeight + SettingsData.dockSpacing + effectiveDockMargin + SettingsData.dockIconSize * 0.3) + animationHeadroom) : 0
|
||||
implicitWidth: isVertical ? (px(dockGeometry.surfaceThickness + SettingsData.dockIconSize * 0.3) + animationHeadroom) : 0
|
||||
implicitHeight: !isVertical ? (px(dockGeometry.surfaceThickness + SettingsData.dockIconSize * 0.3) + animationHeadroom) : 0
|
||||
|
||||
Item {
|
||||
id: maskItem
|
||||
@@ -474,6 +488,28 @@ Variants {
|
||||
item: maskItem
|
||||
}
|
||||
|
||||
PanelWindow {
|
||||
id: dockExclusion
|
||||
|
||||
screen: dock.screen || dock.modelData
|
||||
visible: dock.frameDockExclusionActive && dock.shouldReserveDockSpace
|
||||
color: "transparent"
|
||||
mask: Region {}
|
||||
implicitWidth: dock.isVertical ? dock.dockReserveZone : 1
|
||||
implicitHeight: dock.isVertical ? 1 : dock.dockReserveZone
|
||||
exclusiveZone: visible ? dock.dockReserveZone : -1
|
||||
|
||||
WlrLayershell.namespace: "dms:dock-exclusion"
|
||||
WlrLayershell.layer: WlrLayer.Top
|
||||
|
||||
anchors {
|
||||
top: !dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Top) : true
|
||||
bottom: !dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Bottom) : true
|
||||
left: !dock.isVertical ? true : (SettingsData.dockPosition === SettingsData.Position.Left)
|
||||
right: !dock.isVertical ? true : (SettingsData.dockPosition === SettingsData.Position.Right)
|
||||
}
|
||||
}
|
||||
|
||||
property var hoveredButton: {
|
||||
if (!dockApps.children[0]) {
|
||||
return null;
|
||||
@@ -527,7 +563,7 @@ Variants {
|
||||
const screenHeight = dock.screen ? dock.screen.height : 0;
|
||||
|
||||
const gap = Theme.spacingS;
|
||||
const bgMargin = dock.joinedEdgeMargin + dock.connectedJoinInset;
|
||||
const bgMargin = dockGeometry.bodyEdgeMargin;
|
||||
const btnW = dock.hoveredButton.width;
|
||||
const btnH = dock.hoveredButton.height;
|
||||
|
||||
@@ -598,11 +634,11 @@ Variants {
|
||||
// Keep the taller hit area regardless of the reveal state to prevent shrinking loop
|
||||
return Math.min(Math.max(dockBackground.height + 64, 200), maxDockHeight);
|
||||
}
|
||||
return dock.reveal ? px(dock.connectedJoinInset + dock.effectiveBarHeight + SettingsData.dockSpacing + dock.effectiveDockBottomGap + dock.effectiveDockMargin) : 1;
|
||||
return dock.reveal ? px(dockGeometry.motionThickness) : 1;
|
||||
}
|
||||
width: {
|
||||
if (dock.isVertical) {
|
||||
return dock.reveal ? px(dock.connectedJoinInset + dock.effectiveBarHeight + SettingsData.dockSpacing + dock.effectiveDockBottomGap + dock.effectiveDockMargin) : 1;
|
||||
return dock.reveal ? px(dockGeometry.motionThickness) : 1;
|
||||
}
|
||||
// Keep the wider hit area regardless of the reveal state to prevent shrinking loop
|
||||
return Math.min(dockBackground.width + 8 + dock.borderThickness, maxDockWidth);
|
||||
@@ -648,7 +684,7 @@ Variants {
|
||||
const retractDist = dockBackground.width + SettingsData.dockSpacing + 10;
|
||||
return SettingsData.dockPosition === SettingsData.Position.Right ? retractDist : -retractDist;
|
||||
}
|
||||
const hideDistance = dock.connectedJoinInset + dock.effectiveBarHeight + SettingsData.dockSpacing + dock.effectiveDockBottomGap + dock.effectiveDockMargin + 10;
|
||||
const hideDistance = dockGeometry.motionThickness + 10;
|
||||
if (SettingsData.dockPosition === SettingsData.Position.Right) {
|
||||
return hideDistance;
|
||||
} else {
|
||||
@@ -664,7 +700,7 @@ Variants {
|
||||
const retractDist = dockBackground.height + SettingsData.dockSpacing + 10;
|
||||
return SettingsData.dockPosition === SettingsData.Position.Bottom ? retractDist : -retractDist;
|
||||
}
|
||||
const hideDistance = dock.connectedJoinInset + dock.effectiveBarHeight + SettingsData.dockSpacing + dock.effectiveDockBottomGap + dock.effectiveDockMargin + 10;
|
||||
const hideDistance = dockGeometry.motionThickness + 10;
|
||||
if (SettingsData.dockPosition === SettingsData.Position.Bottom) {
|
||||
return hideDistance;
|
||||
} else {
|
||||
@@ -709,10 +745,10 @@ Variants {
|
||||
right: dock.isVertical ? (SettingsData.dockPosition === SettingsData.Position.Right ? parent.right : undefined) : undefined
|
||||
verticalCenter: dock.isVertical ? parent.verticalCenter : undefined
|
||||
}
|
||||
anchors.topMargin: !dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Top ? (dock.connectedJoinInset + dock.joinedEdgeMargin) : 0
|
||||
anchors.bottomMargin: !dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Bottom ? (dock.connectedJoinInset + dock.joinedEdgeMargin) : 0
|
||||
anchors.leftMargin: dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Left ? (dock.connectedJoinInset + dock.joinedEdgeMargin) : 0
|
||||
anchors.rightMargin: dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Right ? (dock.connectedJoinInset + dock.joinedEdgeMargin) : 0
|
||||
anchors.topMargin: !dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Top ? dockGeometry.bodyEdgeMargin : 0
|
||||
anchors.bottomMargin: !dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Bottom ? dockGeometry.bodyEdgeMargin : 0
|
||||
anchors.leftMargin: dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Left ? dockGeometry.bodyEdgeMargin : 0
|
||||
anchors.rightMargin: dock.isVertical && SettingsData.dockPosition === SettingsData.Position.Right ? dockGeometry.bodyEdgeMargin : 0
|
||||
|
||||
implicitWidth: dock.isVertical ? (dockApps.implicitHeight + SettingsData.dockSpacing * 2) : (dockApps.implicitWidth + SettingsData.dockSpacing * 2)
|
||||
implicitHeight: dock.isVertical ? (dockApps.implicitWidth + SettingsData.dockSpacing * 2) : (dockApps.implicitHeight + SettingsData.dockSpacing * 2)
|
||||
|
||||
61
quickshell/Modules/Dock/DockGeometry.qml
Normal file
61
quickshell/Modules/Dock/DockGeometry.qml
Normal file
@@ -0,0 +1,61 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
|
||||
QtObject {
|
||||
id: root
|
||||
|
||||
property var screen: null
|
||||
property string edge: "bottom"
|
||||
property bool dockVisible: false
|
||||
property bool autoHide: false
|
||||
property bool hasFullscreenToplevel: false
|
||||
property real iconSize: 40
|
||||
property real spacing: 4
|
||||
property real borderThickness: 0
|
||||
property real offset: 0
|
||||
property real margin: 0
|
||||
property real barSpacing: 0
|
||||
property real dpr: 1
|
||||
|
||||
function px(value) {
|
||||
return Math.round(value * dpr) / dpr;
|
||||
}
|
||||
|
||||
readonly property bool frameExclusionActive: SettingsData.frameEnabled && !!screen && SettingsData.isScreenInPreferences(screen, SettingsData.frameScreenPreferences)
|
||||
readonly property bool connectedMode: Theme.isConnectedEffect
|
||||
readonly property bool connectedBarActiveOnEdge: connectedMode && !!screen && SettingsData.getActiveBarEdgesForScreen(screen).includes(edge)
|
||||
|
||||
readonly property real connectedJoinInset: {
|
||||
if (connectedMode)
|
||||
return connectedBarActiveOnEdge ? SettingsData.frameBarSize : SettingsData.frameThickness;
|
||||
if (SettingsData.frameEnabled)
|
||||
return SettingsData.frameEdgeInsetForSide(screen, edge);
|
||||
return 0;
|
||||
}
|
||||
|
||||
readonly property real frameInset: {
|
||||
if (!frameExclusionActive)
|
||||
return 0;
|
||||
if (connectedMode)
|
||||
return connectedJoinInset;
|
||||
return SettingsData.frameThickness;
|
||||
}
|
||||
|
||||
readonly property real effectiveMargin: connectedMode ? 0 : margin
|
||||
readonly property real visualOffset: connectedMode ? 0 : offset
|
||||
readonly property real reserveOffset: offset
|
||||
readonly property real joinedEdgeMargin: connectedMode ? 0 : (barSpacing + effectiveMargin + 1 + borderThickness)
|
||||
readonly property real bodyEdgeMargin: frameInset + joinedEdgeMargin
|
||||
|
||||
readonly property real bodyThickness: iconSize + spacing * 2 + borderThickness * 2
|
||||
readonly property real visualThickness: bodyThickness + 10
|
||||
readonly property real surfaceThickness: frameInset + visualThickness + spacing + effectiveMargin
|
||||
readonly property real motionThickness: surfaceThickness + visualOffset
|
||||
|
||||
// Frame/bar edge exclusions already reserve the edge itself, so the dock
|
||||
// reservation covers only the dock body and user offset beyond that edge.
|
||||
readonly property real reserveZone: px(bodyThickness + reserveOffset + effectiveMargin)
|
||||
readonly property bool shouldReserveSpace: dockVisible && !hasFullscreenToplevel && !autoHide && barSpacing <= 0
|
||||
}
|
||||
@@ -91,6 +91,8 @@ PanelWindow {
|
||||
readonly property real _popoutFillOverlapYValue: (ConnectedModeState.popoutBarSide === "left" || ConnectedModeState.popoutBarSide === "right") ? win._seamOverlap : 0
|
||||
readonly property real _dockFillOverlapXValue: win._dockHorizontal ? win._seamOverlap : 0
|
||||
readonly property real _dockFillOverlapYValue: (win._dockState.barSide === "left" || win._dockState.barSide === "right") ? win._seamOverlap : 0
|
||||
readonly property real _dockJoinOverlapXValue: ConnectorGeometry.isVertical(win._dockState.barSide) ? win._seamOverlap : 0
|
||||
readonly property real _dockJoinOverlapYValue: ConnectorGeometry.isHorizontal(win._dockState.barSide) ? win._seamOverlap : 0
|
||||
readonly property real _notifSideUnderlapValue: ConnectorGeometry.isVertical(win._notifState.barSide) ? win._seamOverlap : 0
|
||||
readonly property real _notifStartUnderlapValue: win._notifState.omitStartConnector ? win._seamOverlap : 0
|
||||
readonly property real _notifEndUnderlapValue: win._notifState.omitEndConnector ? win._seamOverlap : 0
|
||||
@@ -1117,6 +1119,14 @@ PanelWindow {
|
||||
return ((win._dockState.barSide === "left" || win._dockState.barSide === "right") ? win._dockConnectorRadiusValue : 0) - win._dockFillOverlapYValue;
|
||||
}
|
||||
|
||||
function _dockJoinOverlapXOffset() {
|
||||
return win._dockState.barSide === "left" ? -win._dockJoinOverlapXValue : 0;
|
||||
}
|
||||
|
||||
function _dockJoinOverlapYOffset() {
|
||||
return win._dockState.barSide === "top" ? -win._dockJoinOverlapYValue : 0;
|
||||
}
|
||||
|
||||
function _farConnectorBarSide(sourceSide, placement) {
|
||||
if (sourceSide === "top" || sourceSide === "bottom")
|
||||
return placement === "left" ? "left" : "right";
|
||||
@@ -1359,10 +1369,10 @@ PanelWindow {
|
||||
|
||||
Rectangle {
|
||||
id: _dockFill
|
||||
x: win._dockBodyXInChrome()
|
||||
y: win._dockBodyYInChrome()
|
||||
width: _dockBodyBlurAnchor.width + win._dockFillOverlapXValue * 2
|
||||
height: _dockBodyBlurAnchor.height + win._dockFillOverlapYValue * 2
|
||||
x: win._dockBodyXInChrome() + win._dockJoinOverlapXOffset()
|
||||
y: win._dockBodyYInChrome() + win._dockJoinOverlapYOffset()
|
||||
width: _dockBodyBlurAnchor.width + win._dockFillOverlapXValue * 2 + win._dockJoinOverlapXValue
|
||||
height: _dockBodyBlurAnchor.height + win._dockFillOverlapYValue * 2 + win._dockJoinOverlapYValue
|
||||
color: win._opaqueSurfaceColor
|
||||
z: 1
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ Item {
|
||||
|
||||
property var parentModal: null
|
||||
readonly property bool connectedFrameModeActive: SettingsData.connectedFrameModeActive
|
||||
readonly property bool connectedPersistentDockActive: connectedFrameModeActive && SettingsData.showDock && !SettingsData.dockAutoHide && !SettingsData.dockSmartAutoHide
|
||||
|
||||
FileBrowserModal {
|
||||
id: dockLogoFileBrowser
|
||||
@@ -611,16 +612,18 @@ Item {
|
||||
value: SettingsData.dockSpacing
|
||||
minimum: 0
|
||||
maximum: 32
|
||||
unit: "px"
|
||||
defaultValue: 8
|
||||
onSliderValueChanged: newValue => SettingsData.set("dockSpacing", newValue)
|
||||
}
|
||||
|
||||
SettingsSliderRow {
|
||||
text: I18n.tr("Exclusive Zone Offset")
|
||||
visible: !root.connectedFrameModeActive
|
||||
visible: !root.connectedFrameModeActive || root.connectedPersistentDockActive
|
||||
value: SettingsData.dockBottomGap
|
||||
minimum: -100
|
||||
maximum: 100
|
||||
unit: "px"
|
||||
defaultValue: 0
|
||||
onSliderValueChanged: newValue => SettingsData.set("dockBottomGap", newValue)
|
||||
}
|
||||
@@ -631,6 +634,7 @@ Item {
|
||||
value: SettingsData.dockMargin
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
unit: "px"
|
||||
defaultValue: 0
|
||||
onSliderValueChanged: newValue => SettingsData.set("dockMargin", newValue)
|
||||
}
|
||||
@@ -639,7 +643,7 @@ Item {
|
||||
SettingsControlledByFrame {
|
||||
visible: root.connectedFrameModeActive
|
||||
parentModal: root.parentModal
|
||||
settingLabel: I18n.tr("Dock spacing, transparency, and border")
|
||||
settingLabel: I18n.tr("Dock margin, transparency, and border")
|
||||
reason: I18n.tr("Managed by Frame in Connected Mode")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user