From cc0e4cd4fab50d21115e1e2d70fb8d382fac288f Mon Sep 17 00:00:00 2001 From: Ivy233 Date: Mon, 26 Jan 2026 15:48:14 +0800 Subject: [PATCH] fix: improve dock position change animation and auto-hide behavior MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add beforePositionChanged signal to coordinate position change animations. Implement two-phase position change: hide at old position, show at new position. Add commitPositionChange mechanism to ensure position is updated after animations. Fix auto-hide trigger logic for KeepHidden and SmartHide modes after animations. Add fallback timer to ensure position change completes even if animation fails. 修复:改进任务栏位置切换动画和自动隐藏行为 添加 beforePositionChanged 信号以协调位置切换动画。 实现两阶段位置切换:在旧位置隐藏,在新位置显示。 添加 commitPositionChange 机制确保动画后位置正确更新。 修复动画结束后 KeepHidden 和 SmartHide 模式的自动隐藏触发逻辑。 添加后备定时器确保即使动画失败也能完成位置切换。 PMS: BUG-346777 --- panels/dock/dockpanel.cpp | 21 ++++++- panels/dock/dockpanel.h | 5 ++ panels/dock/docksettings.h | 1 + panels/dock/package/main.qml | 108 +++++++++++++++++++++++++++-------- 4 files changed, 109 insertions(+), 26 deletions(-) diff --git a/panels/dock/dockpanel.cpp b/panels/dock/dockpanel.cpp index 6b41822de..5b18e7fa1 100644 --- a/panels/dock/dockpanel.cpp +++ b/panels/dock/dockpanel.cpp @@ -40,6 +40,8 @@ DockPanel::DockPanel(QObject *parent) , m_launcherShown(false) , m_contextDragging(false) , m_isResizing(false) + , m_pendingPosition(Bottom) + , m_hasPendingPosition(false) { connect(this, &DockPanel::compositorReadyChanged, this, [this] { if (!m_compositorReady) return; @@ -262,7 +264,14 @@ Position DockPanel::position() void DockPanel::setPosition(const Position& position) { - SETTINGS->setPosition(position); + if (position == SETTINGS->position()) return; + + m_pendingPosition = position; + m_hasPendingPosition = true; + + // Emit beforePositionChanged to let QML play hide animation + Position oldPosition = SETTINGS->position(); + Q_EMIT beforePositionChanged(oldPosition, position); } ItemAlignment DockPanel::itemAlignment() @@ -350,6 +359,16 @@ void DockPanel::notifyDockPositionChanged(int offsetX, int offsetY) Q_EMIT frontendWindowRectChanged(frontendWindowRect(offsetX, offsetY)); } +void DockPanel::commitPositionChange() +{ + if (!m_hasPendingPosition) { + return; + } + + m_hasPendingPosition = false; + SETTINGS->setPosition(m_pendingPosition); +} + void DockPanel::launcherVisibleChanged(bool visible) { if (visible == m_launcherShown) return; diff --git a/panels/dock/dockpanel.h b/panels/dock/dockpanel.h index 0b3318ca9..f05e7450f 100644 --- a/panels/dock/dockpanel.h +++ b/panels/dock/dockpanel.h @@ -83,6 +83,8 @@ class DockPanel : public DS_NAMESPACE::DPanel, public QDBusContext Q_INVOKABLE void notifyDockPositionChanged(int offsetX, int offsetY); + Q_INVOKABLE void commitPositionChange(); + bool showInPrimary() const; void setShowInPrimary(bool newShowInPrimary); @@ -119,6 +121,7 @@ private Q_SLOTS: void dockSizeChanged(uint size); void hideModeChanged(HideMode mode); + void beforePositionChanged(Position oldPosition, Position newPosition); void positionChanged(Position position); void itemAlignmentChanged(ItemAlignment alignment); void indicatorStyleChanged(IndicatorStyle style); @@ -142,6 +145,8 @@ private Q_SLOTS: bool m_launcherShown; bool m_contextDragging; bool m_isResizing; + Position m_pendingPosition; + bool m_hasPendingPosition; }; } diff --git a/panels/dock/docksettings.h b/panels/dock/docksettings.h index 8635a81e1..47e353bbd 100644 --- a/panels/dock/docksettings.h +++ b/panels/dock/docksettings.h @@ -67,6 +67,7 @@ class DockSettings : public QObject Q_SIGNALS: void dockSizeChanged(uint size); void hideModeChanged(HideMode mode); + void beforePositionChanged(Position oldPosition, Position newPosition); void positionChanged(Position position); void itemAlignmentChanged(ItemAlignment alignment); void indicatorStyleChanged(IndicatorStyle style); diff --git a/panels/dock/package/main.qml b/panels/dock/package/main.qml index 32932da40..afaf1b713 100644 --- a/panels/dock/package/main.qml +++ b/panels/dock/package/main.qml @@ -164,10 +164,22 @@ Window { } } + Timer { + id: positionChangeFallbackTimer + interval: 1000 + running: false + repeat: false + onTriggered: { + Panel.commitPositionChange(); + } + } + SequentialAnimation { id: dockAnimation property bool useTransformBasedAnimation: Qt.platform.pluginName === "xcb" property bool isShowing: false + property bool isPositionChanging: false + property int positionForAnimation: Panel.position property var target: useTransformBasedAnimation ? dockTransform : dock property string animProperty: { if (useTransformBasedAnimation) return dock.useColumnLayout ? "x" : "y"; @@ -185,7 +197,7 @@ Window { from: { if (dockAnimation.isShowing) { if (dockAnimation.useTransformBasedAnimation) { - return (Panel.position === Dock.Left || Panel.position === Dock.Top) ? -Panel.dockSize : Panel.dockSize; + return (dockAnimation.positionForAnimation === Dock.Left || dockAnimation.positionForAnimation === Dock.Top) ? -Panel.dockSize : Panel.dockSize; } return 1; } @@ -196,7 +208,7 @@ Window { return 0; } else { if (dockAnimation.useTransformBasedAnimation) { - return (Panel.position === Dock.Left || Panel.position === Dock.Top) ? -Panel.dockSize : Panel.dockSize; + return (dockAnimation.positionForAnimation === Dock.Left || dockAnimation.positionForAnimation === Dock.Top) ? -Panel.dockSize : Panel.dockSize; } return 1; } @@ -215,6 +227,21 @@ Window { } else { dock.visible = ((dock.useColumnLayout ? dock.width : dock.height) !== 1); } + + // If this was a hide animation during position change, commit the position change + if (isPositionChanging && !isShowing) { + isPositionChanging = false; + Panel.commitPositionChange(); + } else if (isShowing) { + // After show animation completes, check if we need to auto-hide + // For KeepHidden and SmartHide modes, trigger hide check immediately + if (Panel.hideMode === Dock.KeepHidden || Panel.hideMode === Dock.SmartHide) { + hideTimer.running = true; + } else if (Panel.hideState === Dock.Hide) { + // For other cases, if hideState is already Hide, trigger hide animation + hideTimer.running = true; + } + } } } @@ -224,31 +251,9 @@ Window { required property int value text: name - property var positionChangeCallback: function() { - // Disconnect any existing callback first - dockAnimation.onStopped.disconnect(positionChangeCallback); - // Stop any running animations first --fix bug with do not show dock - dockAnimation.stop(); - // Reset transform before starting new animation--fix bug with change position,will have a blank area - dockTransform.x = 0; - dockTransform.y = 0; - - Applet[prop] = value; - checked = Qt.binding(function() { - return Applet[prop] === value; - }); - dockAnimation.startAnimation(true); - } onTriggered: { - if (prop === "position") { - // Connect the callback and start the hide animation - dockAnimation.onStopped.connect(positionChangeCallback); - dockAnimation.startAnimation(false); - } else { + if (Applet[prop] !== value) { Applet[prop] = value - checked = Qt.binding(function() { - return Applet[prop] === value - }) } } checked: Applet[prop] === value @@ -669,9 +674,62 @@ Window { } Connections { + function onBeforePositionChanged(oldPosition, newPosition) { + // Stop any running animations first + dockAnimation.stop(); + hideShowAnimation.stop(); + + // Set the position for animation to old position for hide animation + dockAnimation.positionForAnimation = oldPosition; + + // Mark that we're changing position + dockAnimation.isPositionChanging = true; + + // Check if dock is currently hidden + if (Panel.hideState === Dock.Hide && !dock.visible) { + // Dock is already hidden, no need for hide animation + dockAnimation.isPositionChanging = false; + Panel.commitPositionChange(); + // No need for fallback timer since we committed immediately + } else { + // Start hide animation at old position + dockAnimation.startAnimation(false); + // Start fallback timer to ensure position change is committed + positionChangeFallbackTimer.restart(); + } + } + function onPositionChanged() { + // Stop fallback timer since position has been committed + positionChangeFallbackTimer.stop(); + changeDragAreaAnchor() Panel.requestClosePopup() + + // Start show animation at new position + handlePositionChangeAfterHide(); + } + + function handlePositionChangeAfterHide() { + // Update position for animation to new position for show animation + dockAnimation.positionForAnimation = Panel.position; + + // Set transform to hidden position before showing + if (dockAnimation.useTransformBasedAnimation) { + var hideOffset = (Applet.position === Dock.Left || Applet.position === Dock.Top) ? -Panel.dockSize : Panel.dockSize; + if (dock.useColumnLayout) { + dockTransform.x = hideOffset; + dockTransform.y = 0; + } else { + dockTransform.x = 0; + dockTransform.y = hideOffset; + } + } else { + dockTransform.x = 0; + dockTransform.y = 0; + } + + dockAnimation.startAnimation(true); } function onDockSizeChanged() { dock.dockSize = Panel.dockSize