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
23 changes: 23 additions & 0 deletions panels/dock/AppletItemButton.qml
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,27 @@ IconButton {
Component.onCompleted: {
contentItem.smooth = false
}

property var contentGlobalPoint: {
var a = contentItem
if (!a) return Qt.point(0, 0)
var x = 0, y = 0
while (a && a.parent) {
x += a.x
y += a.y
a = a.parent
}

return Qt.point(x, y)
}

PositionFixer {
id: positionFixer
item: control
container: control
}

onContentGlobalPointChanged: {
positionFixer.fix()
}
}
2 changes: 2 additions & 0 deletions panels/dock/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ file(
pluginmanagerintegration.cpp
dockpositioner.h
dockpositioner.cpp
positionfixer.h
positionfixer.cpp
)

set_source_files_properties(DockCompositor.qml PROPERTIES
Expand Down
79 changes: 79 additions & 0 deletions panels/dock/positionfixer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "positionfixer.h"
#include <QQuickWindow>

Check warning on line 6 in panels/dock/positionfixer.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QQuickWindow> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <cmath>

Check warning on line 7 in panels/dock/positionfixer.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <cmath> not found. Please note: Cppcheck does not need standard library headers to get proper results.

namespace dock {

PositionFixer::PositionFixer(QQuickItem *parent)
: QQuickItem(parent)
{
m_timer = new QTimer(this);
m_timer->setInterval(100);
m_timer->setSingleShot(true);
connect(m_timer, &QTimer::timeout, this, &PositionFixer::forceFix);
}

QQuickItem *PositionFixer::item() const
{
return m_item;
}

void PositionFixer::setItem(QQuickItem *newItem)

Check warning on line 25 in panels/dock/positionfixer.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'setItem' is never used.
{
if (m_item == newItem)
return;
m_item = newItem;
if (m_item && !m_container) {
setContainer(m_item->parentItem());
}
emit itemChanged();
}

QQuickItem *PositionFixer::container() const

Check warning on line 36 in panels/dock/positionfixer.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'container' is never used.
{
return m_container;
}

void PositionFixer::setContainer(QQuickItem *newContainer)
{
if (m_container == newContainer)
return;
m_container = newContainer;
emit containerChanged();
}

void PositionFixer::fix()
{
m_timer->start();
}

void PositionFixer::forceFix()
{
if (!m_item || !m_container || !m_container->window()) {
return;
}

QQuickItem *contentItem = m_container->window()->contentItem();
if (!contentItem) {
return;
}

QPointF scenePos = m_container->mapToItem(contentItem, QPointF(0, 0));

qreal dpr = m_container->window()->devicePixelRatio();
qreal physicalX = std::round(scenePos.x() * dpr);
qreal physicalY = std::round(scenePos.y() * dpr);

QQuickItem *itemParent = m_item->parentItem() ? m_item->parentItem() : m_container;

QPointF localPosX = itemParent->mapFromItem(contentItem, QPointF(physicalX / dpr, scenePos.y()));
QPointF localPosY = itemParent->mapFromItem(contentItem, QPointF(scenePos.x(), physicalY / dpr));
m_item->setX(localPosX.x());
m_item->setY(localPosY.y());
}

}
44 changes: 44 additions & 0 deletions panels/dock/positionfixer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#pragma once

#include <QQuickItem>

Check warning on line 7 in panels/dock/positionfixer.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QQuickItem> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QTimer>

Check warning on line 8 in panels/dock/positionfixer.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QTimer> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QtQml/qqml.h>

Check warning on line 9 in panels/dock/positionfixer.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QtQml/qqml.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

namespace dock {

class PositionFixer : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(QQuickItem *item READ item WRITE setItem NOTIFY itemChanged)
Q_PROPERTY(QQuickItem *container READ container WRITE setContainer NOTIFY containerChanged)

QML_NAMED_ELEMENT(PositionFixer)

public:
explicit PositionFixer(QQuickItem *parent = nullptr);

QQuickItem *item() const;
void setItem(QQuickItem *newItem);

QQuickItem *container() const;
void setContainer(QQuickItem *newContainer);

Q_INVOKABLE void fix();
Q_INVOKABLE void forceFix();

signals:
void itemChanged();
void containerChanged();
void useZeroTargetChanged();

private:
QQuickItem *m_item = nullptr;
QQuickItem *m_container = nullptr;
QTimer *m_timer = nullptr;
};

}
121 changes: 48 additions & 73 deletions panels/dock/taskmanager/package/AppItem.qml
Original file line number Diff line number Diff line change
Expand Up @@ -140,88 +140,63 @@ Item {
}
target: Panel
}

D.DciIcon {
id: icon
name: root.iconName
height: iconSize
width: iconSize
sourceSize: Qt.size(iconSize, iconSize)
//加一层Item为了实现图标centerIn,不受到icon中fixposition的影响
Item {
width: root.iconSize
height: root.iconSize
anchors.centerIn: parent
retainWhileLoading: true
smooth: false

function mapToScene(px, py) {
return parent.mapToItem(Window.window.contentItem, Qt.point(px, py))
}

function mapFromScene(px, py) {
return parent.mapFromItem(Window.window.contentItem, Qt.point(px, py))
}

function fixPosition() {
if (root.Drag.active || !parent || launchAnimation.running) {
return
D.DciIcon {
id: icon
name: root.iconName
anchors.fill: parent
sourceSize: Qt.size(iconSize, iconSize)
retainWhileLoading: true
smooth: false

PositionFixer {
id: positionFixer
item: icon
}
anchors.centerIn = undefined
var targetX = (parent.width - width) / 2
var targetY = (parent.height - height) / 2

var scenePos = mapToScene(targetX, targetY)

var physicalX = Math.round(scenePos.x * Panel.devicePixelRatio)
var physicalY = Math.round(scenePos.y * Panel.devicePixelRatio)

var localPos = mapFromScene(physicalX / Panel.devicePixelRatio, physicalY / Panel.devicePixelRatio)

x = localPos.x
y = localPos.y
}

Timer {
id: fixPositionTimer
interval: 100
repeat: false
running: false
onTriggered: {
icon.fixPosition()
}
}

Connections {
target: root
function onIconGlobalPointChanged() {
fixPositionTimer.start()
}
}
LaunchAnimation {
id: launchAnimation
launchSpace: {
switch (Panel.position) {
case Dock.Top:
case Dock.Bottom:
return (root.height - icon.height) / 2
case Dock.Left:
case Dock.Right:
return (root.width - icon.width) / 2
Connections {
target: root
function onIconGlobalPointChanged() {
if (root.Drag.active || !parent || launchAnimation.running) {
return
}
positionFixer.fix()
}
}
LaunchAnimation {
id: launchAnimation
launchSpace: {
switch (Panel.position) {
case Dock.Top:
case Dock.Bottom:
return (root.height - icon.height) / 2
case Dock.Left:
case Dock.Right:
return (root.width - icon.width) / 2
}
}

direction: {
switch (Panel.position) {
case Dock.Top:
return LaunchAnimation.Direction.Down
case Dock.Bottom:
return LaunchAnimation.Direction.Up
case Dock.Left:
return LaunchAnimation.Direction.Right
case Dock.Right:
return LaunchAnimation.Direction.Left
direction: {
switch (Panel.position) {
case Dock.Top:
return LaunchAnimation.Direction.Down
case Dock.Bottom:
return LaunchAnimation.Direction.Up
case Dock.Left:
return LaunchAnimation.Direction.Right
case Dock.Right:
return LaunchAnimation.Direction.Left
}
}
target: icon
loops: 1
running: false
}
target: icon
loops: 1
running: false
}
}
}
Expand Down
41 changes: 8 additions & 33 deletions panels/dock/tray/ShellSurfaceItemProxy.qml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ Item {
}

function fixPosition() {
fixPositionTimer.start()
positionFixer.fix()
}

PositionFixer {
id: positionFixer
item: impl
}

ShellSurfaceItem {
Expand Down Expand Up @@ -56,11 +61,10 @@ Item {

onVisibleChanged: function () {
if (visible) {
fixPositionTimer.start()
positionFixer.fix()
}

if (autoClose && !visible) {
// surface is valid but client's shellSurface maybe invalid.
Qt.callLater(closeShellSurface)
}
}
Expand All @@ -71,37 +75,8 @@ Item {
}
}

function mapToScene(x, y) {
const point = Qt.point(x, y)
// Must use parent.mapFoo, because the impl's position is relative to the parent Item
const mappedPoint = parent.mapToItem(Window.window.contentItem, point)
return mappedPoint
}

function mapFromScene(x, y) {
const point = Qt.point(x, y)
// Must use parent.mapFoo, because the impl's position is relative to the parent Item
const mappedPoint = parent.mapFromItem(Window.window.contentItem, point)
return mappedPoint
}

function fixPosition() {
// See QTBUG: https://bugreports.qt.io/browse/QTBUG-135833
// TODO: should get the devicePixelRatio from the Window
x = mapFromScene(Math.ceil(mapToScene(0, 0).x * Panel.devicePixelRatio) / Panel.devicePixelRatio, 0).x
y = mapFromScene(0, Math.ceil(mapToScene(0, 0).y * Panel.devicePixelRatio) / Panel.devicePixelRatio).y
}

Timer {
id: fixPositionTimer
interval: 100
repeat: false
running: false
onTriggered: {
impl.fixPosition()
}
}
}

Component.onCompleted: function () {
impl.surfaceDestroyed.connect(root.surfaceDestroyed)
}
Expand Down
Loading