From 55696f01d981c58894a7ef0630dd810d36c3367b Mon Sep 17 00:00:00 2001 From: Tian Shilin Date: Tue, 3 Mar 2026 16:54:00 +0800 Subject: [PATCH] Fix: Optimize tooltip positioning logic. Log: The Popup is rendered on the window's Overlay layer and is not part of the content visual tree. As a result, the tooltip does not follow its anchor item during scrolling or window resizing, causing positional drift. To resolve this, AlertToolTip has been changed from a ToolTip (which uses Popup) to a regular Item, making it part of the content visual tree. This ensures it naturally scrolls with its parent, respects container clipping, and maintains correct positioning at all times. PMS: bug-341973 --- qt6/src/qml/AlertToolTip.qml | 52 +++++++++++++++++++++++------------- qt6/src/qml/EditPanel.qml | 5 +++- 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/qt6/src/qml/AlertToolTip.qml b/qt6/src/qml/AlertToolTip.qml index 400e82c4..2f8d0fc2 100644 --- a/qt6/src/qml/AlertToolTip.qml +++ b/qt6/src/qml/AlertToolTip.qml @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2021 - 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2021 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -6,20 +6,47 @@ import QtQuick import org.deepin.dtk 1.0 as D import org.deepin.dtk.style 1.0 as DS -ToolTip { +Control { id: control property Item target + property string text + property int timeout: 0 + property bool _expired: false + readonly property bool _shown: control.visible && !_expired x: 0 - y: target ? target.height + DS.Style.control.spacing : 0 + y: (target ? target.height : 0) + (_shown ? DS.Style.control.spacing : 0) + Behavior on y { + NumberAnimation { duration: 200 } + } + opacity: _shown ? 1 : 0 + enabled: _shown topPadding: DS.Style.alertToolTip.verticalPadding bottomPadding: DS.Style.alertToolTip.verticalPadding leftPadding: DS.Style.alertToolTip.horizontalPadding rightPadding: DS.Style.alertToolTip.horizontalPadding - implicitWidth: Math.min(DS.Style.control.implicitWidth(control), target.width) + implicitWidth: target ? Math.min(DS.Style.control.implicitWidth(control), target.width) : DS.Style.control.implicitWidth(control) implicitHeight: DS.Style.control.implicitHeight(control) - margins: 0 - closePolicy: Popup.NoAutoClose + z: D.DTK.TopOrder + + Timer { + id: autoHideTimer + interval: control.timeout + running: control.timeout > 0 && control.visible && !control._expired + onTriggered: control._expired = true + } + + onVisibleChanged: { + _expired = false + if (visible && timeout > 0) + autoHideTimer.restart() + } + + onTextChanged: { + _expired = false + if (visible && timeout > 0) + autoHideTimer.restart() + } background: FloatingPanel { radius: DS.Style.alertToolTip.radius @@ -40,23 +67,12 @@ ToolTip { wrapMode: Text.Wrap } - enter: Transition { - // TODO: Transparency causes tooltips to appear through the window background - temporarily removed - // NumberAnimation { properties: "opacity"; from: 0.0; to: 1.0; duration: 200 } - NumberAnimation { properties: "y"; from: control.target.height; to: control.target.height + DS.Style.control.spacing; duration: 200 } - } - - exit: Transition { - // NumberAnimation { properties: "opacity"; from: 1.0; to: 0.0 } - NumberAnimation { properties: "y"; from: control.target.height + DS.Style.control.spacing ; to: control.target.height } - } - BoxShadow { id: line property D.Palette dropShadowColor: DS.Style.alertToolTip.connecterdropShadow property D.Palette backgroundColor: DS.Style.alertToolTip.connecterBackground property D.Palette borderColor: DS.Style.control.border - y: - height * (0.75) - control.topMargin - control.topPadding + y: -height * 0.75 width: DS.Style.alertToolTip.connectorWidth height: DS.Style.alertToolTip.connectorHeight shadowBlur: 4 diff --git a/qt6/src/qml/EditPanel.qml b/qt6/src/qml/EditPanel.qml index b32518ab..698a8def 100644 --- a/qt6/src/qml/EditPanel.qml +++ b/qt6/src/qml/EditPanel.qml @@ -31,8 +31,11 @@ Rectangle { } } + // Keep Loader active while there is alert text so we don't destroy/recreate when + // caller toggles showAlert to refresh the message; avoids wrong text (e.g. "systemd journal") + // from binding context during recreation. Loader { - active: showAlert && alertText.length !== 0 + active: alertText.length !== 0 sourceComponent: AlertToolTip { target: control timeout: alertDuration