From 20bc4eb84ebe5be7c8bec8a7b82b3339a8c91f79 Mon Sep 17 00:00:00 2001 From: Fangxun Zhao Date: Mon, 3 Aug 2026 14:13:09 +0800 Subject: [PATCH] fix(dock-tray): prevent stash popup from closing during drag-and-drop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Added contextDragging check to keep the close timer from running during drag 2. Track wasOpenBeforeDrag flag to distinguish user-initiated open from drag open 3. Track stashDropSucceeded flag to prevent closing when drag successfully moves to stash 4. Wired up onStashDropSucceeded callbacks from both StashContainer and TrayContainer Log: Fix stash popup being unexpectedly closed during drag-and-drop operations Influence: Resolves popup close behavior during drag fix(dock-tray): 修复拖拽过程中 stash 面板意外关闭的问题 1. 添加 contextDragging 检查,防止拖拽中关闭计时器运行 2. 记录 wasOpenBeforeDrag 标记,区分用户主动打开和拖拽打开 3. 记录 stashDropSucceeded 标记,防止拖拽成功移入 stash 后关闭面板 4. 连接 StashContainer 和 TrayContainer 的拖拽成功回调 Log: 修复拖拽操作时 stash 面板被意外关闭的问题 PMS: BUG-336185 Influence: 解决拖拽时面板关闭行为异常 --- .../tray/package/ActionShowStashDelegate.qml | 10 ++++-- panels/dock/tray/package/StashContainer.qml | 10 ++++-- panels/dock/tray/package/TrayContainer.qml | 13 +++++++- panels/dock/tray/package/tray.qml | 32 ++++++++++++++++++- 4 files changed, 59 insertions(+), 6 deletions(-) diff --git a/panels/dock/tray/package/ActionShowStashDelegate.qml b/panels/dock/tray/package/ActionShowStashDelegate.qml index fb7639943..6737544f1 100644 --- a/panels/dock/tray/package/ActionShowStashDelegate.qml +++ b/panels/dock/tray/package/ActionShowStashDelegate.qml @@ -81,11 +81,15 @@ AppletItemButton { Timer { id: closeStashPopupTimer - running: !isDropHover && !stashedPopup.dropHover && !stashedPopup.stashItemDragging + running: !isDropHover && !stashedPopup.dropHover && !stashedPopup.stashItemDragging && !Panel.contextDragging interval: 300 repeat: false onTriggered: { - stashedPopup.close() + // 只在“拖拽前面板未打开”且“拖拽未成功移入 stash”时才关闭 + if (!stashedPopup.wasOpenBeforeDrag + && !stashedPopup.stashDropSucceeded) { + stashedPopup.close() + } } } @@ -101,6 +105,8 @@ AppletItemButton { stashedPopup.close() } else { stashedPopup.open() + // 用户主动点击打开:后续拖拽结束不应自动关闭面板 + stashedPopup.wasOpenBeforeDrag = true } if (toolTipShowTimer.running) { toolTipShowTimer.stop() diff --git a/panels/dock/tray/package/StashContainer.qml b/panels/dock/tray/package/StashContainer.qml index 53b6b51f1..171d2fba2 100644 --- a/panels/dock/tray/package/StashContainer.qml +++ b/panels/dock/tray/package/StashContainer.qml @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later @@ -33,6 +33,8 @@ Item { readonly property int rowCount: Math.round(Math.sqrt(model.count)) property bool dropHover: false property bool stashItemDragging: false + // 拖拽成功移入 stash 时的回调,由 tray.qml 传入 + property var onStashDropSucceeded: null function isStashPopup(surfaceId) { @@ -94,6 +96,7 @@ Item { } onExited: function (dragEvent) { dropHover = false + stashItemDragging = false } onPositionChanged: function (dragEvent) { let surfaceId = dragEvent.getDataAsString("text/x-dde-shell-tray-dnd-surfaceId") @@ -101,7 +104,10 @@ Item { } onDropped: function (dropEvent) { let surfaceId = dropEvent.getDataAsString("text/x-dde-shell-tray-dnd-surfaceId") - DDT.TraySortOrderModel.dropToStashTray(surfaceId, 0, false); + let success = DDT.TraySortOrderModel.dropToStashTray(surfaceId, 0, false); + if (success && onStashDropSucceeded) { + onStashDropSucceeded() + } } } diff --git a/panels/dock/tray/package/TrayContainer.qml b/panels/dock/tray/package/TrayContainer.qml index 8c571b982..982f3a098 100644 --- a/panels/dock/tray/package/TrayContainer.qml +++ b/panels/dock/tray/package/TrayContainer.qml @@ -91,6 +91,8 @@ Item { property int dropHoverIndex: -1 required property var surfaceAcceptor readonly property bool isDropping: dropArea.containsDrag + // 拖拽成功移入 stash 时的回调(命中 action-show-stash),由 tray.qml 传入 + property var onStashDropSucceeded: null onIsDraggingChanged: { animationEnable = !isDragging @@ -220,8 +222,17 @@ Item { if (isStash || source === "quickPanel") { DDT.TraySortOrderModel.commitStagedDrop() } else { + // 检查是否放到了展开按钮上(命中 action-show-stash 分支,图标移入 stash) + // 在 dropToDockTray 之前检查,避免模型变更后索引失效 + let modelIndex = DDT.TraySortOrderModel.getModelIndexByVisualIndex(Math.floor(currentItemIndex)) + let dropOnSurfaceId = root.model.data(modelIndex, DDT.TraySortOrderModel.SurfaceIdRole) + let isDroppedOnStashButton = (dropOnSurfaceId === "internal/action-show-stash") + // 托盘内部拖拽直接提交 - DDT.TraySortOrderModel.dropToDockTray(surfaceId, Math.floor(currentItemIndex), isBefore); + let success = DDT.TraySortOrderModel.dropToDockTray(surfaceId, Math.floor(currentItemIndex), isBefore); + if (isDroppedOnStashButton && success && onStashDropSucceeded) { + onStashDropSucceeded() + } } DDT.TraySortOrderModel.actionsAlwaysVisible = false } diff --git a/panels/dock/tray/package/tray.qml b/panels/dock/tray/package/tray.qml index e6c9a0303..4f126fb24 100644 --- a/panels/dock/tray/package/tray.qml +++ b/panels/dock/tray/package/tray.qml @@ -44,6 +44,10 @@ AppletItem { property alias dropHover: stashContainer.dropHover property alias stashItemDragging: stashContainer.stashItemDragging + property bool wasOpenBeforeDrag: false + // 拖拽成功标记(图标是否成功移入 stash),由放下的回调根据返回值设置 + property bool stashDropSucceeded: false + popupX: DockPanelPositioner.x popupY: DockPanelPositioner.y @@ -72,6 +76,10 @@ AppletItem { stashedPopup.close() } } + // 拖拽成功移入 stash 时由 StashContainer 回调 + onStashDropSucceeded: function() { + stashedPopup.stashDropSucceeded = true + } } } @@ -96,12 +104,30 @@ AppletItem { interval: 10 repeat: false onTriggered: { - if (!Panel.contextDragging && !stashedPopup.dropHover) { + // 拖拽仍在进行中时,绝不关闭(可能正要拖入面板) + if (Panel.contextDragging) + return + // 只在“拖拽前面板未打开”且“拖拽未成功移入 stash”时才关闭 + if (!stashedPopup.dropHover + && !stashedPopup.wasOpenBeforeDrag + && !stashedPopup.stashDropSucceeded) { stashedPopup.close() } } } + Connections { + target: Panel + function onContextDraggingChanged() { + // 拖拽开始时记录面板状态,拖拽结束后据此决定是否自动关闭 + if (Panel.contextDragging) { + stashedPopup.wasOpenBeforeDrag = stashedPopup.popupVisible + stashedPopup.stashDropSucceeded = false + } + } + } + + TrayContainer { id: trayContainter isHorizontal: !tray.useColumnLayout @@ -113,6 +139,10 @@ AppletItem { Component.onCompleted: { DDT.TrayItemPositionManager.layoutHealthCheck(1500) } + // 拖拽成功移入 stash 时由 TrayContainer 回调(命中 action-show-stash) + onStashDropSucceeded: function() { + stashedPopup.stashDropSucceeded = true + } } function isTrayPluginPopup(surfaceId) {