Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions panels/dock/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ ds_install_package(PACKAGE org.deepin.ds.dock TARGET dockpanel)
ds_handle_package_translation(PACKAGE org.deepin.ds.dock)

# sub plugins
add_subdirectory(cardleft)
add_subdirectory(showdesktop)
add_subdirectory(taskmanager)
add_subdirectory(tray)
Expand Down
6 changes: 6 additions & 0 deletions panels/dock/DockCompositor.qml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Item {
property ListModel trayPluginSurfaces: ListModel {}
property ListModel quickPluginSurfaces: ListModel {}
property ListModel fixedPluginSurfaces: ListModel {}
property ListModel cardPluginSurfaces: ListModel {}

property var compositor: waylandCompositor
property var panelScale: 1.0
Expand Down Expand Up @@ -62,6 +63,7 @@ Item {
let ret = findSurfaceFromModel(trayPluginSurfaces, surfaceId)
if (ret === null) ret = findSurfaceFromModel(quickPluginSurfaces, surfaceId)
if (ret === null) ret = findSurfaceFromModel(fixedPluginSurfaces, surfaceId)
if (ret === null) ret = findSurfaceFromModel(cardPluginSurfaces, surfaceId)
return ret
}

Expand Down Expand Up @@ -92,6 +94,8 @@ Item {
quickPluginSurfaces.append({shellSurface: dockPluginSurface})
} else if (dockPluginSurface.pluginType === Dock.Fixed) {
fixedPluginSurfaces.append({shellSurface: dockPluginSurface})
} else if (dockPluginSurface.pluginType === Dock.Card) {
cardPluginSurfaces.append({shellSurface: dockPluginSurface})
}
dockCompositor.pluginSurfacesUpdated()
}
Expand All @@ -104,6 +108,8 @@ Item {
removeDockPluginSurface(quickPluginSurfaces, dockPluginSurface)
} else if (dockPluginSurface.pluginType === Dock.Fixed) {
removeDockPluginSurface(fixedPluginSurfaces, dockPluginSurface)
} else if (dockPluginSurface.pluginType === Dock.Card) {
removeDockPluginSurface(cardPluginSurfaces, dockPluginSurface)
}
dockCompositor.pluginSurfacesUpdated()
}
Expand Down
5 changes: 5 additions & 0 deletions panels/dock/cardleft/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
#
# SPDX-License-Identifier: GPL-3.0-or-later

ds_install_package(PACKAGE org.deepin.ds.dock.cardleft)
254 changes: 254 additions & 0 deletions panels/dock/cardleft/package/CardLeftDockArea.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

import QtQuick 2.15
import QtQuick.Window 2.15

import org.deepin.ds 1.0
import org.deepin.ds.dock 1.0
import org.deepin.ds.dock.tray 1.0 as DDT
import org.deepin.dtk 1.0 as D

AppletItem {
id: root

readonly property bool fashionMode: Panel.rootObject.fashionDock.enabled
readonly property int dockSize: Panel.rootObject.dockSize
readonly property int hoverInset: 5
readonly property real taskbarRadius: Panel.rootObject.fashionDock.backgroundRadius
readonly property real hoverBackgroundRadius: Math.max(0, taskbarRadius - hoverInset)
readonly property int hoverFadeDuration: 150
readonly property int taskbarWidth: Panel.rootObject.adaptiveCardLeftWidth
readonly property int rightContentPadding: Math.max(10, Math.round(taskbarWidth * 0.07))
readonly property int verticalInset: Math.max(5, Math.round(dockSize * 0.16))
readonly property int pageContentHeight: Math.max(24, dockSize - verticalInset * 2)
readonly property int pageIndicatorRightInset: Math.max(4, hoverInset + 3)

readonly property color primaryTextColor: Panel.colorTheme === Dock.Dark
? Qt.rgba(1, 1, 1, 0.96)
: Qt.rgba(0, 0, 0, 0.92)

property int dockOrder: 5
property bool shouldVisible: fashionMode && pageCount > 0
property int currentIndex: 0
property int previousIndex: -1
property int switchDirection: 1
property real pageTransitionProgress: 1
readonly property int pageCount: DockCompositor.cardPluginSurfaces.count
property bool contentHovered: false
readonly property bool pageTransitioning: pageTransitionAnimation.running || pageTransitionProgress < 1
readonly property bool effectiveHovered: rootHoverHandler.hovered || contentHovered

visible: shouldVisible
implicitWidth: taskbarWidth
implicitHeight: dockSize
clip: true

function normalizeIndex() {
if (pageCount <= 0) {
previousIndex = -1
pageTransitionProgress = 1
currentIndex = 0
return
}

if (currentIndex >= pageCount) {
previousIndex = -1
pageTransitionProgress = 1
currentIndex = pageCount - 1
} else if (currentIndex < 0) {
previousIndex = -1
pageTransitionProgress = 1
currentIndex = 0
}
}

function step(delta) {
if (pageCount <= 1) {
return
}

const nextIndex = (currentIndex + delta + pageCount) % pageCount
if (nextIndex === currentIndex) {
return
}

pageTransitionAnimation.stop()
previousIndex = currentIndex
switchDirection = delta > 0 ? 1 : -1
pageTransitionProgress = 0
currentIndex = nextIndex
pageTransitionAnimation.restart()
}

function updateContentHovered() {
const item = pluginRepeater.itemAt(currentIndex)
contentHovered = !!item && item.visible && item.surfaceHovered
}

onCurrentIndexChanged: updateContentHovered()
onPageCountChanged: {
normalizeIndex()
updateContentHovered()
}

NumberAnimation {
id: pageTransitionAnimation

target: root
property: "pageTransitionProgress"
from: 0
to: 1
duration: 180
easing.type: Easing.OutCubic
onStopped: {
root.pageTransitionProgress = 1
root.previousIndex = -1
root.updateContentHovered()
}
}

HoverHandler {
id: rootHoverHandler
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad | PointerDevice.Stylus
}

AppletItemBackground {
x: root.hoverInset
y: root.hoverInset
width: Math.max(0, parent.width - root.hoverInset)
height: Math.max(0, parent.height - root.hoverInset * 2)
radius: root.hoverBackgroundRadius
enabled: false
opacity: root.effectiveHovered ? 1 : 0
D.ColorSelector.hovered: root.effectiveHovered

Behavior on opacity {
NumberAnimation {
duration: root.hoverFadeDuration
easing.type: Easing.OutCubic
}
}
}

CardLeftDockSwitcher {
anchors.right: parent.right
anchors.rightMargin: root.pageIndicatorRightInset
anchors.verticalCenter: parent.verticalCenter
visible: root.effectiveHovered && root.pageCount > 1
itemCount: root.pageCount
currentIndex: root.currentIndex
indicatorSize: 2
indicatorSpacing: 4
indicatorColor: root.primaryTextColor
}

Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 13
anchors.rightMargin: root.rightContentPadding
height: root.pageContentHeight
clip: true

Repeater {
id: pluginRepeater
model: DockCompositor.cardPluginSurfaces

delegate: Item {
id: surfaceHost

property var plugin: model.shellSurface
readonly property bool surfaceHovered: visible && surfaceItem.hovered
function itemGlobalPoint() {
var item = surfaceHost
var x = 0
var y = 0
while (item) {
x += item.x
y += item.y
item = item.parent
}
return Qt.point(x, y)
}
function itemGlobalPos() {
var point = itemGlobalPoint()
if (surfaceHost.Window.window) {
point.x += surfaceHost.Window.window.x
point.y += surfaceHost.Window.window.y
}
return point
}

y: {
if (index === root.currentIndex) {
return (1 - root.pageTransitionProgress) * root.switchDirection * height
}

if (index === root.previousIndex && root.pageTransitioning) {
return -root.pageTransitionProgress * root.switchDirection * height
}

return 0
}
width: parent.width
height: parent.height
visible: !!plugin && (index === root.currentIndex || (root.pageTransitioning && index === root.previousIndex))

DDT.ShellSurfaceItemProxy {
id: surfaceItem
anchors.fill: parent
shellSurface: surfaceHost.plugin
}

function updateSurfaceGeometry() {
if (!plugin || !visible) {
return
}

const globalPoint = itemGlobalPoint()
const globalPos = itemGlobalPos()
plugin.updatePluginGeometry(Qt.rect(Math.round(globalPoint.x),
Math.round(globalPoint.y),
Math.round(width),
Math.round(height)))
plugin.setGlobalPos(Qt.point(Math.round(globalPos.x),
Math.round(globalPos.y)))
surfaceItem.fixPosition()
}

Component.onCompleted: updateSurfaceGeometry()
onYChanged: geometryUpdateTimer.restart()
onWidthChanged: geometryUpdateTimer.restart()
onHeightChanged: geometryUpdateTimer.restart()
onVisibleChanged: {
geometryUpdateTimer.restart()
root.updateContentHovered()
}
onSurfaceHoveredChanged: root.updateContentHovered()

Timer {
id: geometryUpdateTimer
interval: 50
repeat: false
onTriggered: surfaceHost.updateSurfaceGeometry()
}
}
}
}

MouseArea {
anchors.fill: parent
enabled: root.pageCount > 1
acceptedButtons: Qt.NoButton
onWheel: function(wheel) {
const deltaY = wheel.angleDelta.y !== 0 ? wheel.angleDelta.y : wheel.pixelDelta.y
if (deltaY !== 0) {
root.step(deltaY < 0 ? 1 : -1)
wheel.accepted = true
}
}
}
}
37 changes: 37 additions & 0 deletions panels/dock/cardleft/package/CardLeftDockSwitcher.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

import QtQuick 2.15

Item {
id: root

required property int itemCount
property int currentIndex: 0
property int indicatorSize: 2
property int indicatorSpacing: 4
property color indicatorColor: Qt.rgba(1, 1, 1, 0.96)

visible: itemCount > 1
implicitWidth: indicatorColumn.implicitWidth
implicitHeight: indicatorColumn.implicitHeight

Column {
id: indicatorColumn

spacing: root.indicatorSpacing

Repeater {
model: root.itemCount

Rectangle {
width: root.indicatorSize
height: root.indicatorSize
radius: width / 2
color: root.indicatorColor
opacity: index === root.currentIndex ? 1 : 0.35
}
}
}
}
8 changes: 8 additions & 0 deletions panels/dock/cardleft/package/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Plugin": {
"Version": "1.0",
"Id": "org.deepin.ds.dock.cardleft",
"Url": "CardLeftDockArea.qml",
"Parent": "org.deepin.ds.dock"
}
}
4 changes: 3 additions & 1 deletion panels/dock/constants.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2023 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-License-Identifier: LGPL-3.0-or-later
Expand Down Expand Up @@ -36,6 +36,7 @@ enum IndicatorStyle {
enum ItemAlignment {
CenterAlignment = 0,
LeftAlignment = 1,
FashionAlignment = 2,
};

enum ColorTheme {
Expand Down Expand Up @@ -79,6 +80,7 @@ enum TrayPluginType {
Tray = 1,
Fixed,
Quick,
Card,
};

enum TrayPluginSizePolicy {
Expand Down
4 changes: 4 additions & 0 deletions panels/dock/docksettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ static QString itemAlignment2String(const ItemAlignment& alignment)
return "left";
case ItemAlignment::CenterAlignment:
return "center";
case ItemAlignment::FashionAlignment:
return "fashion";
}

return "center";
Expand All @@ -111,6 +113,8 @@ static ItemAlignment string2ItenAlignment(const QString& alignmentStr)
return ItemAlignment::LeftAlignment;
else if (alignmentStr == "center")
return ItemAlignment::CenterAlignment;
else if (alignmentStr == "fashion")
return ItemAlignment::FashionAlignment;

return ItemAlignment::CenterAlignment;
}
Expand Down
Loading
Loading