From 21f24983ed5cab704985dc72becf4f2ba501ec8f Mon Sep 17 00:00:00 2001 From: wjyrich Date: Thu, 2 Apr 2026 21:31:37 +0800 Subject: [PATCH] feat: add split window background support for dock app items MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Created new AppBackground.qml component to handle split window background rendering 2. Added splitBackgroundVisible property to control split background display 3. Enhanced AppletItemBackground.qml with drawDefaultBackground property for conditional rendering 4. Modified AppItem.qml to use AppBackground instead of AppletItemBackground 5. Updated text calculation logic to remove extra spacing between icon and title 6. Added windowSplit property propagation through components 7. Improved title text color handling based on active state and theme Log: Added split window background visualization for dock app items Influence: 1. Test dock app items with multiple windows open in split mode 2. Verify background colors change correctly in light and dark themes 3. Check hover and active states for split window backgrounds 4. Test title text color changes when app is active 5. Verify spacing between icon and title in split mode 6. Test transition animations when switching between split and non- split modes feat: 为任务栏应用项添加分屏窗口背景支持 1. 创建新的 AppBackground.qml 组件处理分屏窗口背景渲染 2. 添加 splitBackgroundVisible 属性控制分屏背景显示 3. 增强 AppletItemBackground.qml 添加 drawDefaultBackground 属性用于条件 渲染 4. 修改 AppItem.qml 使用 AppBackground 替代 AppletItemBackground 5. 更新文本计算逻辑,移除图标和标题之间的额外间距 6. 添加 windowSplit 属性在组件间传递 7. 改进标题文本颜色处理,基于激活状态和主题 Log: 新增任务栏应用项分屏窗口背景可视化功能 Influence: 1. 测试分屏模式下打开多个窗口的任务栏应用项 2. 验证浅色和深色主题下背景颜色正确变化 3. 检查分屏窗口背景的悬停和激活状态 4. 测试应用激活时标题文本颜色变化 5. 验证分屏模式下图标和标题之间的间距 6. 测试分屏和非分屏模式切换时的过渡动画 --- panels/dock/taskmanager/package/AppItem.qml | 51 +++---- .../taskmanager/package/AppItemBackground.qml | 143 ++++++++++++++++++ .../dock/taskmanager/package/AppItemTitle.qml | 3 +- .../taskmanager/package/StatusIndicator.qml | 12 -- .../dock/taskmanager/package/TaskManager.qml | 5 +- panels/dock/taskmanager/textcalculator.cpp | 3 +- 6 files changed, 172 insertions(+), 45 deletions(-) create mode 100644 panels/dock/taskmanager/package/AppItemBackground.qml delete mode 100644 panels/dock/taskmanager/package/StatusIndicator.qml diff --git a/panels/dock/taskmanager/package/AppItem.qml b/panels/dock/taskmanager/package/AppItem.qml index 000956d2b..94e332aae 100644 --- a/panels/dock/taskmanager/package/AppItem.qml +++ b/panels/dock/taskmanager/package/AppItem.qml @@ -38,11 +38,9 @@ Item { Drag.mimeData: { "text/x-dde-dock-dnd-appid": itemId, "text/x-dde-dock-dnd-source": "taskbar", "text/x-dde-dock-dnd-winid": windows.length > 0 ? windows[0] : ""} property bool useColumnLayout: Panel.rootObject.useColumnLayout - property int statusIndicatorSize: useColumnLayout ? root.width * 0.72 : root.height * 0.72 property int iconSize: Panel.rootObject.dockItemMaxSize * 9 / 14 property bool enableTitle: false property bool titleActive: enableTitle && titleLoader.active - property int appTitleSpacing: 0 property var iconGlobalPoint: { var a = icon var x = 0, y = 0 @@ -79,16 +77,15 @@ Item { Control { anchors.fill: parent id: appItem - implicitWidth: root.titleActive ? (iconContainer.width + 4 + titleLoader.width + root.appTitleSpacing) : iconContainer.width + root.appTitleSpacing + implicitWidth: root.titleActive ? (root.iconSize + hoverBackground.horizontalSpacing + titleLoader.width) : iconContainer.width visible: !root.Drag.active // When in dragging, hide app item - background: AppletItemBackground { + background: AppItemBackground { id: hoverBackground readonly property int verticalSpacing: Math.round(root.iconSize / 8) + 1 readonly property int horizontalSpacing: Math.round(root.iconSize / 8) readonly property int nonSplitHeight: root.iconSize + verticalSpacing * 2 - readonly property int hoverPadding: Math.round((Panel.rootObject.dockItemMaxSize * 0.8 - root.iconSize) / 2) - readonly property int splitWidth: Math.round(icon.width + titleLoader.width + hoverPadding * 2) + readonly property int splitWidth: Math.round(root.iconSize + titleLoader.width + horizontalSpacing * 3) readonly property int nonSplitWidth: Math.round(root.iconSize + horizontalSpacing * 2) enabled: false @@ -98,10 +95,8 @@ Item { radius: height / 5 anchors.centerIn: parent isActive: root.active - opacity: (hoverHandler.hovered || (root.active && root.windows.length > 0)) ? 1.0 : 0.0 - Behavior on opacity { - NumberAnimation { duration: 150 } - } + windowCount: root.windows.length + displayMode: root.displayMode } Item { id: iconContainer @@ -118,10 +113,6 @@ Item { anchors.left: parent.left anchors.horizontalCenter: undefined } - PropertyChanges { - target: iconContainer - anchors.leftMargin: hoverBackground.horizontalSpacing - } }, State { name: "nonTitleActive" @@ -134,13 +125,12 @@ Item { } } ] - StatusIndicator { - id: statusIndicator - palette: itemPalette - width: root.statusIndicatorSize - height: root.statusIndicatorSize - anchors.centerIn: iconContainer - visible: root.displayMode === Dock.Efficient && root.windows.length > 0 + + Connections { + function onDisplayModeChanged() { + windowIndicator.updateIndicatorAnchors() + } + target: root } Connections { @@ -258,28 +248,30 @@ Item { windowIndicator.anchors.horizontalCenter = undefined windowIndicator.anchors.verticalCenter = undefined + const anchorTarget = root.displayMode === Dock.Efficient ? appItem : hoverBackground + switch(Panel.position) { case Dock.Top: { windowIndicator.anchors.horizontalCenter = iconContainer.horizontalCenter - windowIndicator.anchors.top = hoverBackground.top + windowIndicator.anchors.top = anchorTarget.top windowIndicator.anchors.topMargin = 1 return } case Dock.Bottom: { windowIndicator.anchors.horizontalCenter = iconContainer.horizontalCenter - windowIndicator.anchors.bottom = hoverBackground.bottom + windowIndicator.anchors.bottom = anchorTarget.bottom windowIndicator.anchors.bottomMargin = 1 return } case Dock.Left: { windowIndicator.anchors.verticalCenter = parent.verticalCenter - windowIndicator.anchors.left = hoverBackground.left + windowIndicator.anchors.left = anchorTarget.left windowIndicator.anchors.leftMargin = 1 return } case Dock.Right:{ windowIndicator.anchors.verticalCenter = parent.verticalCenter - windowIndicator.anchors.right = hoverBackground.right + windowIndicator.anchors.right = anchorTarget.right windowIndicator.anchors.rightMargin = 1 return } @@ -294,13 +286,18 @@ Item { AppItemTitle { id: titleLoader anchors.left: iconContainer.right - anchors.leftMargin: 4 + anchors.leftMargin: Math.round(root.iconSize / 8) anchors.verticalCenter: parent.verticalCenter enabled: root.enableTitle && root.windows.length > 0 text: root.title + textColor: { + if (root.displayMode === Dock.Efficient && root.active) { + return "#000000" + } + return D.DTK.themeType === D.ApplicationHelper.DarkType ? "#FFFFFF" : "#000000" + } } - // TODO: value can set during debugPanel Loader { id: animationRoot anchors.fill: parent diff --git a/panels/dock/taskmanager/package/AppItemBackground.qml b/panels/dock/taskmanager/package/AppItemBackground.qml new file mode 100644 index 000000000..35ded3ad6 --- /dev/null +++ b/panels/dock/taskmanager/package/AppItemBackground.qml @@ -0,0 +1,143 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +import QtQuick +import QtQuick.Controls + +import org.deepin.ds.dock 1.0 +import org.deepin.dtk + +AppletItemBackground { + id: control + property int windowCount: 0 + property int displayMode: Dock.Efficient + property Palette minDockEffectActive: Palette { + normal { + crystal: Qt.rgba(1.0, 1.0, 1.0, 0.8) + } + normalDark { + crystal: Qt.rgba(1.0, 1.0, 1.0, 0.6) + } + hovered { + crystal: Qt.rgba(1.0, 1.0, 1.0, 0.9) + } + hoveredDark { + crystal: Qt.rgba(1.0, 1.0, 1.0, 0.7) + } + } + property Palette normalDockEffectActive: Palette { + normal { + crystal: ("transparent") + } + normalDark: normal + hovered { + crystal: Qt.rgba(1.0, 1.0, 1.0, 0.15) + } + hoveredDark: hovered + } + backgroundColor: Palette { + normal { + crystal: if (displayMode === Dock.Efficient && control.windowCount > 0) { + return Qt.rgba(1.0, 1.0, 1.0, 0.35) + } else { + return ("transparent") + } + } + normalDark: { + crystal: if (displayMode === Dock.Efficient && control.windowCount > 0) { + return Qt.rgba(1.0, 1.0, 1.0, 0.1) + } else { + return ("transparent") + } + } + hovered { + crystal: Qt.rgba(1.0, 1.0, 1.0, 0.15) + } + hoveredDark { + crystal: Qt.rgba(1.0, 1.0, 1.0, 0.15) + } + pressed { + crystal: Qt.rgba(1.0, 1.0, 1.0, 0.25) + } + pressedDark { + crystal: Qt.rgba(1.0, 1.0, 1.0, 0.25) + } + } + activeBackgroundColor: displayMode === Dock.Efficient ? minDockEffectActive : normalDockEffectActive + insideBorderColor: Palette { + normal { + crystal: if (displayMode === Dock.Efficient && control.windowCount > 0) { + return Qt.rgba(1.0, 1.0, 1.0, 0.05) + } else { + return ("transparent") + } + } + normalDark: normal + hovered { + crystal: Qt.rgba(0, 0, 0, 0.05) + } + hoveredDark: hovered + pressed: hovered + pressedDark: pressed + } + + activeInsideBorderColor: Palette { + normal { + crystal: if (displayMode === Dock.Efficient) { + return Qt.rgba(0, 0, 0, 0.1) + } else { + return ("transparent") + } + } + normalDark: { + crystal: if (displayMode === Dock.Efficient) { + return Qt.rgba(1.0, 1.0, 1.0, 0.1) + } else { + return ("transparent") + } + } + hovered { + crystal: Qt.rgba(1.0, 1.0, 1.0, 0.1) + } + hoveredDark: hovered + pressed: hovered + pressedDark: pressed + } + outsideBorderColor: Palette { + normal: { + crystal: ("transparent") + } + normalDark: normal + hovered : normal + hoveredDark: hovered + pressed: hovered + pressedDark: pressed + } + activeOutsideBorderColor: Palette { + normal { + crystal: if (displayMode === Dock.Efficient) { + return Qt.rgba(0, 0, 0, 0.1) + } else { + return ("transparent") + } + } + normalDark { + crystal: if (displayMode === Dock.Efficient) { + return Qt.rgba(0, 0, 0, 0.05) + } else { + return ("transparent") + } + } + hovered { + crystal: Qt.rgba(0.0, 0.0, 0.0, 0.10) + } + hoveredDark: hovered + pressed { + crystal: Qt.rgba(0.0, 0.0, 0.0, 0.10) + } + pressedDark { + crystal: Qt.rgba(0.0, 0.0, 0.0, 0.05) + } + } +} diff --git a/panels/dock/taskmanager/package/AppItemTitle.qml b/panels/dock/taskmanager/package/AppItemTitle.qml index 6d14b6ad4..06c6806e9 100644 --- a/panels/dock/taskmanager/package/AppItemTitle.qml +++ b/panels/dock/taskmanager/package/AppItemTitle.qml @@ -14,6 +14,7 @@ Item { property bool active: titleLoader.active property string text: "" + property color textColor: D.DTK.themeType === D.ApplicationHelper.DarkType ? "#FFFFFF" : "#000000" implicitWidth: titleLoader.width implicitHeight: titleLoader.height @@ -28,7 +29,7 @@ Item { text: root.TextCalculator.elidedText - color: D.DTK.themeType === D.ApplicationHelper.DarkType ? "#FFFFFF" : "#000000" + color: root.textColor font: root.TextCalculator.calculator.font verticalAlignment: Text.AlignVCenter diff --git a/panels/dock/taskmanager/package/StatusIndicator.qml b/panels/dock/taskmanager/package/StatusIndicator.qml deleted file mode 100644 index 5478265f6..000000000 --- a/panels/dock/taskmanager/package/StatusIndicator.qml +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: GPL-3.0-or-later - -import QtQuick 2.15 -import QtQuick.Controls 2.15 - -Rectangle { - required property AppItemPalette palette - radius: width * 0.2 - color: palette.rectIndicator -} diff --git a/panels/dock/taskmanager/package/TaskManager.qml b/panels/dock/taskmanager/package/TaskManager.qml index dbf7a7b5a..8827750bb 100644 --- a/panels/dock/taskmanager/package/TaskManager.qml +++ b/panels/dock/taskmanager/package/TaskManager.qml @@ -64,7 +64,7 @@ ContainmentItem { iconSize: Panel.rootObject.dockItemMaxSize * 9 / 14 spacing: appContainer.spacing cellSize: visualModel.cellWidth - itemPadding: 4 + itemPadding: taskmanager.appTitleSpacing remainingSpace: taskmanager.remainingSpacesForSplitWindow font.family: D.DTK.fontManager.t6.family font.pixelSize: Math.max(10, Math.min(20, Math.round(textCalculator.iconSize * 0.35))) @@ -74,7 +74,7 @@ ContainmentItem { id: appContainer anchors.fill: parent useColumnLayout: taskmanager.useColumnLayout - spacing: 0 + spacing: taskmanager.appTitleSpacing remove: Transition { NumberAnimation { properties: "scale,opacity" @@ -191,7 +191,6 @@ ContainmentItem { blendOpacity: taskmanager.blendOpacity title: delegateRoot.title enableTitle: textCalculator.enabled - appTitleSpacing: taskmanager.appTitleSpacing ListView.delayRemove: Drag.active Component.onCompleted: { dropFilesOnItem.connect(taskmanager.Applet.dropFilesOnItem) diff --git a/panels/dock/taskmanager/textcalculator.cpp b/panels/dock/taskmanager/textcalculator.cpp index c47e9db3b..0151311e9 100644 --- a/panels/dock/taskmanager/textcalculator.cpp +++ b/panels/dock/taskmanager/textcalculator.cpp @@ -277,8 +277,7 @@ void TextCalculator::calculateOptimalTextWidth() qreal textWidth = calculateElidedTextWidth(title, baselineWidth); // Only add spacing between icon and text when text is present if (textWidth > 0.0) { - qreal appTitleSpacing = qMax(10.0, m_iconSize / 3.0); - itemWidth = m_iconSize + m_itemPadding + textWidth + appTitleSpacing; + itemWidth = m_iconSize + m_itemPadding + textWidth; } else { itemWidth = m_cellSize; }