Dock: improvements, new animations, always float, better look.

This commit is contained in:
LemmyCook 2025-09-06 15:18:53 -04:00
parent 7860c41959
commit 809f16c27e
2 changed files with 77 additions and 54 deletions

View file

@ -60,6 +60,7 @@ Singleton {
property int animationFast: Math.round(150 * Settings.data.general.animationSpeed) property int animationFast: Math.round(150 * Settings.data.general.animationSpeed)
property int animationNormal: Math.round(300 * Settings.data.general.animationSpeed) property int animationNormal: Math.round(300 * Settings.data.general.animationSpeed)
property int animationSlow: Math.round(450 * Settings.data.general.animationSpeed) property int animationSlow: Math.round(450 * Settings.data.general.animationSpeed)
property int animationSlowest: Math.round(750 * Settings.data.general.animationSpeed)
// Dimensions // Dimensions
property int barHeight: 36 property int barHeight: 36

View file

@ -34,24 +34,28 @@ Variants {
WlrLayershell.namespace: "noctalia-dock" WlrLayershell.namespace: "noctalia-dock"
property bool autoHide: Settings.data.dock.autoHide readonly property bool autoHide: Settings.data.dock.autoHide
property bool hidden: autoHide readonly property int hideDelay: 500
property int hideDelay: 500 readonly property int showDelay: 100
property int showDelay: 100 readonly property int hideAnimationDuration: Style.animationFast
property int hideAnimationDuration: Style.animationFast readonly property int showAnimationDuration: Style.animationFast
property int showAnimationDuration: Style.animationFast readonly property int peekHeight: 7 * scaling
property int peekHeight: 7 * scaling readonly property int fullHeight: dockContainer.height
property int fullHeight: dockContainer.height readonly property int iconSize: 36 * scaling
property int iconSize: 36 readonly property int floatingMargin: 12 * scaling // Margin to make dock float
// Bar positioning properties // Bar detection and positioning properties
property bool barAtBottom: Settings.data.bar.position === "bottom" readonly property bool hasBar: modelData.name ? (Settings.data.bar.monitors.includes(modelData.name)
property int barHeight: barAtBottom ? (Settings.data.bar.height || 30) * scaling : 0 || (Settings.data.bar.monitors.length === 0)) : false
property int dockSpacing: 4 * scaling // Space between dock and bar readonly property bool barAtBottom: hasBar && Settings.data.bar.position === "bottom"
readonly property bool barAtTop: hasBar && Settings.data.bar.position === "top"
readonly property int barHeight: (barAtBottom || barAtTop) ? (Settings.data.bar.height || 30) * scaling : 0
readonly property int dockSpacing: 8 * scaling // Space between dock and bar/edge
// Track hover state // Track hover state
property bool dockHovered: false property bool dockHovered: false
property bool anyAppHovered: false property bool anyAppHovered: false
property bool hidden: autoHide
// Dock is positioned at the bottom // Dock is positioned at the bottom
anchors.bottom: true anchors.bottom: true
@ -63,11 +67,11 @@ Variants {
// Make the window transparent // Make the window transparent
color: Color.transparent color: Color.transparent
// Set the window size - always include space for peek area when auto-hide is enabled // Set the window size - include extra height only if bar is at bottom
implicitWidth: dockContainer.width implicitWidth: dockContainer.width + (floatingMargin * 2)
implicitHeight: fullHeight + (barAtBottom ? barHeight + dockSpacing : 0) implicitHeight: fullHeight + floatingMargin + (barAtBottom ? barHeight + dockSpacing : 0)
// Position the entire window above the bar when bar is at bottom // Position the entire window above the bar only when bar is at bottom
margins.bottom: barAtBottom ? barHeight : 0 margins.bottom: barAtBottom ? barHeight : 0
// Watch for autoHide setting changes // Watch for autoHide setting changes
@ -111,7 +115,7 @@ Variants {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
height: peekHeight + dockSpacing height: peekHeight + floatingMargin + (barAtBottom ? dockSpacing : 0)
hoverEnabled: autoHide hoverEnabled: autoHide
visible: autoHide visible: autoHide
@ -130,24 +134,32 @@ Variants {
Rectangle { Rectangle {
id: dockContainer id: dockContainer
width: dockLayout.implicitWidth + 48 * scaling width: dockLayout.implicitWidth + Style.marginL * scaling * 2
height: iconSize * 1.4 * scaling height: Math.round(iconSize * 1.6)
color: Qt.alpha(Color.mSurface, Settings.data.dock.backgroundOpacity) color: Qt.alpha(Color.mSurface, Settings.data.dock.backgroundOpacity)
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: dockSpacing anchors.bottomMargin: floatingMargin + (barAtBottom ? dockSpacing : 0)
topLeftRadius: Style.radiusL * scaling radius: Style.radiusL * scaling
topRightRadius: Style.radiusL * scaling border.width: Math.max(1, Style.borderS * scaling)
border.color: Color.mOutline
// Animate the dock sliding up and down // Fade and zoom animation properties
transform: Translate { opacity: hidden ? 0 : 1
y: hidden ? (fullHeight - peekHeight) : 0 scale: hidden ? 0.85 : 1
Behavior on y { Behavior on opacity {
NumberAnimation { NumberAnimation {
duration: hidden ? hideAnimationDuration : showAnimationDuration duration: hidden ? hideAnimationDuration : showAnimationDuration
easing.type: Easing.InOutQuad easing.type: Easing.InOutQuad
} }
}
Behavior on scale {
NumberAnimation {
duration: hidden ? hideAnimationDuration : showAnimationDuration
easing.type: hidden ? Easing.InQuad : Easing.OutBack
easing.overshoot: hidden ? 0 : 1.05
} }
} }
@ -179,7 +191,7 @@ Variants {
Item { Item {
id: dock id: dock
width: dockLayout.implicitWidth width: dockLayout.implicitWidth
height: parent.height - (20 * scaling) height: parent.height - (Style.marginM * 2 * scaling)
anchors.centerIn: parent anchors.centerIn: parent
NTooltip { NTooltip {
@ -203,39 +215,40 @@ Variants {
Repeater { Repeater {
model: ToplevelManager ? ToplevelManager.toplevels : null model: ToplevelManager ? ToplevelManager.toplevels : null
delegate: Rectangle { delegate: Item {
id: appButton id: appButton
Layout.preferredWidth: iconSize * scaling Layout.preferredWidth: iconSize
Layout.preferredHeight: iconSize * scaling Layout.preferredHeight: iconSize
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
color: Color.transparent
radius: Style.radiusM * scaling
property bool isActive: ToplevelManager.activeToplevel && ToplevelManager.activeToplevel === modelData property bool isActive: ToplevelManager.activeToplevel && ToplevelManager.activeToplevel === modelData
property bool hovered: appMouseArea.containsMouse property bool hovered: appMouseArea.containsMouse
property string appId: modelData ? modelData.appId : "" property string appId: modelData ? modelData.appId : ""
property string appTitle: modelData ? modelData.title : "" property string appTitle: modelData ? modelData.title : ""
// The icon // The icon with better quality settings
Image { Image {
id: appIcon id: appIcon
width: iconSize * scaling width: iconSize
height: iconSize * scaling height: iconSize
anchors.centerIn: parent anchors.centerIn: parent
source: dock.getAppIcon(modelData) source: dock.getAppIcon(modelData)
visible: source.toString() !== "" visible: source.toString() !== ""
sourceSize.width: iconSize * 2
sourceSize.height: iconSize * 2
smooth: true smooth: true
mipmap: false mipmap: true
antialiasing: false antialiasing: true
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
cache: true
scale: appButton.hovered ? 1.1 : 1.0 scale: appButton.hovered ? 1.15 : 1.0
Behavior on scale { Behavior on scale {
NumberAnimation { NumberAnimation {
duration: Style.animationFast duration: Style.animationNormal
easing.type: Easing.OutBack easing.type: Easing.OutBack
easing.overshoot: 1.2
} }
} }
} }
@ -246,15 +259,15 @@ Variants {
visible: !appIcon.visible visible: !appIcon.visible
text: "question_mark" text: "question_mark"
font.family: "Material Symbols Rounded" font.family: "Material Symbols Rounded"
font.pointSize: iconSize * 0.7 * scaling font.pointSize: iconSize * 0.7
color: appButton.isActive ? Color.mPrimary : Color.mOnSurfaceVariant color: appButton.isActive ? Color.mPrimary : Color.mOnSurfaceVariant
scale: appButton.hovered ? 1.15 : 1.0
scale: appButton.hovered ? 1.1 : 1.0
Behavior on scale { Behavior on scale {
NumberAnimation { NumberAnimation {
duration: Style.animationFast duration: Style.animationFast
easing.type: Easing.OutBack easing.type: Easing.OutBack
easing.overshoot: 1.2
} }
} }
} }
@ -269,8 +282,8 @@ Variants {
onEntered: { onEntered: {
anyAppHovered = true anyAppHovered = true
const appName = appButton.appTitle || appButton.appId || "Unknown" const appName = appButton.appTitle || appButton.appId || "Unknown"
appTooltip.text = appName.length > 40 ? appName.substring(0, 37) + "..." : appName
appTooltip.target = appButton appTooltip.target = appButton
appTooltip.text = appName.length > 40 ? appName.substring(0, 37) + "..." : appName
appTooltip.isVisible = true appTooltip.isVisible = true
if (autoHide) { if (autoHide) {
showTimer.stop() showTimer.stop()
@ -300,15 +313,24 @@ Variants {
} }
} }
// Active indicator
Rectangle { Rectangle {
visible: isActive visible: isActive
width: iconSize * 0.25 width: iconSize * 0.2
height: 4 * scaling height: iconSize * 0.1
color: Color.mPrimary color: Color.mPrimary
radius: Style.radiusXS radius: Style.radiusXS * scaling
anchors.top: parent.bottom anchors.top: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: Style.marginXXS * scaling anchors.topMargin: Style.marginXXS * 1.5 * scaling
// Pulse animation for active indicator
SequentialAnimation on opacity {
running: isActive
loops: Animation.Infinite
NumberAnimation { to: 0.6; duration: Style.animationSlowest; easing.type: Easing.InOutQuad }
NumberAnimation { to: 1.0; duration: Style.animationSlowest; easing.type: Easing.InOutQuad }
}
} }
} }
} }
@ -317,4 +339,4 @@ Variants {
} }
} }
} }
} }