Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
59f6731
fix: install DLL to bin directory on Windows
kt286 Aug 20, 2026
78051cf
i18n: [dtkdeclarative] Updates for project Deepin Tool Kit (#669)
transifex-integration[bot] Aug 26, 2026
444be1b
fix(slider): align tick labels within slider bounds
mhduiy Aug 27, 2026
d0de769
fix(arrowlistview): fix ArrowListView height oscillation and item cli…
mhduiy Aug 31, 2026
43f8b3b
fix(slider): add NoArrowType case in SliderHandle
52cyb Aug 18, 2026
576f425
fix: compare winId consistently in _q_onWindowMotifHintsChanged
svan71 Jul 11, 2026
2ac5a39
fix(dciicon): restore smooth filtering for mixed-DPI scaling
gugullll Sep 7, 2026
7c97a95
fix(dciicon): restore smooth filtering for mixed-DPI scaling
gugullll Sep 4, 2026
1cb9d79
chore: New release 6.7.49
github-actions[bot] Sep 10, 2026
15d3495
i18n: Translate dtkdeclarative.ts in sv (#674)
transifex-integration[bot] Sep 11, 2026
db82f88
fix(popup): set fixed default implicit size for Window popupType
Ivy233 Aug 25, 2026
6883c5a
fix(popup): restore implicit size bindings on Popup for qt6
Ivy233 Sep 18, 2026
b8ee7b1
fix: correct model reference in ArrowListView
wjyrich Sep 20, 2026
660a12b
feat: add split screen menu to title bar
18202781743 Sep 11, 2026
5b35715
fix: use formal parameter in ThemeMenu signal handler
52cyb Sep 8, 2026
c82227a
chore: New release 6.7.50 (#709)
deepin-bot[bot] Sep 22, 2026
4769ee4
fix(ComboBox): size popup before it is mapped
mhduiy Sep 28, 2026
4d55a74
i18n: Translate dtkdeclarative.ts in mn (#720)
transifex-integration[bot] Oct 15, 2026
4325119
chore: New release 6.7.51
github-actions[bot] Oct 15, 2026
ca271bb
chore: add split screen menu and fix popup sizing
18202781743 Oct 20, 2026
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
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,33 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [6.7.51] - 2026-10-15

### Changed

- I18n: Translate dtkdeclarative.ts in mn (#720)

### Fixed

- Size popup before it is mapped

## [6.7.50] - 2026-09-22

### Added

- Add split screen menu to title bar

### Changed

- I18n: Translate dtkdeclarative.ts in sv (#674)

### Fixed

- Set fixed default implicit size for Window popupType
- Restore implicit size bindings on Popup for qt6
- Correct model reference in ArrowListView
- Use formal parameter in ThemeMenu signal handler

## [6.7.49] - 2026-09-10

### Added
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6.7.49
6.7.51
2 changes: 1 addition & 1 deletion archlinux/PKGBUILD
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Maintainer: zccrs <zhangjide@deepin.org>
pkgname=dtkdeclarative-git
pkgver=6.7.49
pkgver=6.7.51
pkgrel=1
sourcename=dtkdeclarative
sourcetars=("$sourcename"_"$pkgver".tar.xz)
Expand Down
12 changes: 12 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
dtkdeclarative (6.7.51) unstable; urgency=medium

* Release 6.7.51

-- yeshanshan <yeshanshan@uniontech.com> Thu, 15 Oct 2026 20:23:34 +0800

dtkdeclarative (6.7.50) unstable; urgency=medium

* Release 6.7.50

-- yeshanshan <yeshanshan@uniontech.com> Tue, 22 Sep 2026 16:19:42 +0800

dtkdeclarative (6.7.49) unstable; urgency=medium

* Release 6.7.49
Expand Down
16 changes: 14 additions & 2 deletions qt6/src/qml/ArrowListView.qml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ FocusScope {
property int itemHeight: DS.Style.arrowListView.itemHeight
property alias view: itemsView

// Full height of the list, to size a popup before it is mapped.
readonly property real sizedHeight: {
if (itemsView.count === 0)
return 0
const item = itemsView.itemAtIndex(0)
const measured = itemsView.contentHeight > 0 && item ? (item.height || item.implicitHeight) : 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · Variable-height rows mis-size popups

When a ComboBox uses delegates with different heights, or index 0 is not realized while custom-height delegates are in use, sizedHeight uses one realized row's height for every visible row and falls back to itemHeight when index 0 is not realized, so the popup height is inaccurate and clips rows or leaves excess space.

Calculate the total height of the visible rows, or otherwise account for each delegate's height and unrealized rows.

Also at qt6/src/qml/ArrowListView.qml:26-27.

Prompt for AI agents
In `qt6/src/qml/ArrowListView.qml` at line 23:

**Variable-height rows mis-size popups**

When a ComboBox uses delegates with different heights, or index 0 is not realized while custom-height delegates are in use, `sizedHeight` uses one realized row's height for every visible row and falls back to `itemHeight` when index 0 is not realized, so the popup height is inaccurate and clips rows or leaves excess space.

Calculate the total height of the visible rows, or otherwise account for each delegate's height and unrealized rows.

Also at `qt6/src/qml/ArrowListView.qml:26-27`.

const arrowStrips = itemsView.count > maxVisibleItems
? 2 * (DS.Style.arrowListView.stepButtonIconSize.height + contentLayout.spacing) : 0
return Math.min(itemsView.count, maxVisibleItems) * (measured > 0 ? measured : itemHeight) + arrowStrips
}

implicitWidth: Math.max(DS.Style.arrowListView.width, contentLayout.implicitWidth)
implicitHeight: contentLayout.implicitHeight

Expand All @@ -25,7 +36,7 @@ FocusScope {
visible: itemsView.interactive
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.preferredHeight: implicitHeight

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · Long-list popup clips arrow buttons

When a list has more items than maxVisibleItems and both arrow buttons are shown, the layout and sizedHeight reserve 12 px per arrow, but the loaded ActionButton remains 16 px tall; the popup is 8 px too short when both arrows are shown, so the buttons overlap or are clipped.

Use the button’s actual stepButtonSize.height consistently for the layout reservation and popup-height calculation, or size the loaded button to the reserved height.

Also at qt6/src/qml/ArrowListView.qml:26.

Prompt for AI agents
In `qt6/src/qml/ArrowListView.qml` at line 28:

**Long-list popup clips arrow buttons**

When a list has more items than `maxVisibleItems` and both arrow buttons are shown, the layout and `sizedHeight` reserve 12 px per arrow, but the loaded `ActionButton` remains 16 px tall; the popup is 8 px too short when both arrows are shown, so the buttons overlap or are clipped.

Use the button’s actual `stepButtonSize.height` consistently for the layout reservation and popup-height calculation, or size the loaded button to the reserved height.

Also at `qt6/src/qml/ArrowListView.qml:26`.

Layout.preferredHeight: DS.Style.arrowListView.stepButtonIconSize.height
view: itemsView
stepSize: control.itemHeight
direction: P.ArrowListViewButton.UpButton
Expand All @@ -36,6 +47,7 @@ FocusScope {
clip: true
Layout.fillWidth: true
Layout.fillHeight: true
onHeightChanged: if (height > 0 && contentHeight === 0) forceLayout()
implicitHeight: itemsView.count > 0 ? Math.min(contentHeight, maxVisibleItems * contentHeight / itemsView.count) : 0
implicitWidth:{
var maxWidth = DS.Style.arrowListView.width
Expand Down Expand Up @@ -81,7 +93,7 @@ FocusScope {
visible: itemsView.interactive
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.preferredHeight: implicitHeight
Layout.preferredHeight: DS.Style.arrowListView.stepButtonIconSize.height
view: itemsView
stepSize: control.itemHeight
direction: P.ArrowListViewButton.DownButton
Expand Down
3 changes: 3 additions & 0 deletions qt6/src/qml/ComboBox.qml
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@ T.ComboBox {
rightMargin: DS.Style.popup.margin
palette: control.palette
implicitWidth: control.flat ? Math.max(contentItem.implicitWidth, control.width) : control.width
// 60 is a temporary viewport so the list can realize one row and be measured.
implicitHeight: (contentItem.sizedHeight > 0 ? contentItem.sizedHeight : 2 * DS.Style.arrowListView.itemHeight)
+ topPadding + bottomPadding
Comment on lines +198 to +199

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · Empty models show blank popups

When the ComboBox model is empty and its popup is opened, including while the model is loading, contentItem.sizedHeight is zero, so the two-row fallback gives the popup a nonzero height and it displays a blank panel.

Return zero popup content height for an empty model rather than applying the two-row fallback.

Prompt for AI agents
In `qt6/src/qml/ComboBox.qml` at lines 198-199:

**Empty models show blank popups**

When the ComboBox model is empty and its popup is opened, including while the model is loading, `contentItem.sizedHeight` is zero, so the two-row fallback gives the popup a nonzero height and it displays a blank panel.

Return zero popup content height for an empty model rather than applying the two-row fallback.

onClosed: control.isInteractingWithContent = false
Connections {
target: control
Expand Down
2 changes: 1 addition & 1 deletion qt6/src/qml/PasswordEdit.qml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2020 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

Expand Down
4 changes: 2 additions & 2 deletions qt6/src/qml/ThemeMenu.qml
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -14,7 +14,7 @@ Menu {
ActionGroup {
id: themeEG
exclusive: true
onTriggered: {
onTriggered: function(action) {
D.ApplicationHelper.setPaletteType(action.themeType)
}
}
Expand Down
2 changes: 2 additions & 0 deletions qt6/src/qml/TitleBar.qml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Item {

// visibility access
property bool fullScreenButtonVisible: true
property bool splitScreenEnabled: true
signal toggleWindowState()
property alias windowButtonGroup: windowButtonsLoader.sourceComponent

Expand Down Expand Up @@ -179,6 +180,7 @@ Item {
embedMode: control.embedMode
textColor: control.textColor
fullScreenButtonVisible: control.fullScreenButtonVisible
splitScreenEnabled: control.splitScreenEnabled
Component.onCompleted: {
control.toggleWindowState.connect(maxOrWinded)
}
Expand Down
79 changes: 78 additions & 1 deletion qt6/src/qml/WindowButtonGroup.qml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ RowLayout {

property D.Palette textColor: DS.Style.button.text
property bool fullScreenButtonVisible: true
property bool splitScreenEnabled: true
property bool embedMode: false
signal maxOrWinded()

Expand Down Expand Up @@ -76,6 +77,7 @@ RowLayout {

WindowButton {
id: maxOrWindedBtn; objectName: "maxOrWindedBtn"
hoverEnabled: true
property bool hasWindowFlag/*: (Window.window.flags & Qt.WindowMaximizeButtonHint)*/
Component.onCompleted: hasWindowFlag = (Window.window.flags & Qt.WindowMaximizeButtonHint)

Expand All @@ -86,7 +88,82 @@ RowLayout {
property bool isMaximized: Window.window.visibility === Window.Maximized
icon.name: isMaximized ? "window_restore" : "window_maximize"
textColor: control.textColor
onClicked: maxOrWinded()
property bool __longPressed: false
property bool __menuRequested: false

function showSplitMenu() {
if (!control.splitScreenEnabled || !visible || !enabled)
return false
if (!__menuRequested)
__menuRequested = control.__dwindow.showSplitMenu(maxOrWindedBtn)
return __menuRequested
}

function hideSplitMenu(delay) {
hoverTimer.stop()
holdTimer.stop()
control.__dwindow.hideSplitMenu(delay)
__menuRequested = false
}

onHoveredChanged: {
if (hovered && !pressed)
hoverTimer.restart()
else if (!hovered) {
hoverTimer.stop()
if (pressed)
holdTimer.stop()
else
hideSplitMenu(true)
}
}
onPressed: {
__longPressed = false
hoverTimer.stop()
holdTimer.restart()
}
onReleased: {
holdTimer.stop()
if (!__longPressed)
hideSplitMenu(false)
else
__menuRequested = false
}
onCanceled: {
hideSplitMenu(true)
__longPressed = false
}
onClicked: {
if (!__longPressed)
control.maxOrWinded()
__longPressed = false
}
onVisibleChanged: {
if (!visible) {
hoverTimer.stop()
holdTimer.stop()
__menuRequested = false
}
}
onEnabledChanged: if (!enabled) hideSplitMenu(false)

Timer {
id: hoverTimer
interval: 700
onTriggered: maxOrWindedBtn.showSplitMenu()
}
Timer {
id: holdTimer
interval: 300
onTriggered: maxOrWindedBtn.__longPressed = maxOrWindedBtn.showSplitMenu()
}
Connections {
target: control
function onSplitScreenEnabledChanged() {
if (!control.splitScreenEnabled)
maxOrWindedBtn.hideSplitMenu(false)
}
}

visible: (hasWindowFlag && !__forceHind && __canResize && __sizeResizable)
enabled: (__canMaximize && __canResize)
Expand Down
41 changes: 41 additions & 0 deletions src/dquickwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
#include <private/qquickpath_p.h>
#include <private/qquickpath_p_p.h>
#include <private/qquicktransition_p.h>
#include <private/qquickwindow_p.h>

Check warning on line 15 in src/dquickwindow.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

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

#include <QPlatformSurfaceEvent>

Check warning on line 17 in src/dquickwindow.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

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

Check warning on line 18 in src/dquickwindow.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

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

Check warning on line 19 in src/dquickwindow.cpp

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.

DQUICK_BEGIN_NAMESPACE

Expand Down Expand Up @@ -1010,6 +1012,45 @@
DWindowManagerHelper::popupSystemWindowMenu(window());
}

// Platform split-menu functions take a Qt window id and a global logical rectangle.
bool DQuickWindowAttached::showSplitMenu(QQuickItem *button)
{
D_D(DQuickWindowAttached);
auto *w = window();
if (!w || !w->isVisible() || !w->handle() || !button || button->window() != w
|| !button->isVisible() || !button->isEnabled())
return false;

const auto support = reinterpret_cast<bool (*)(WId)>(
QGuiApplication::platformFunction("_d_supportSplitMenu"));
const auto show = reinterpret_cast<void (*)(WId, const QRect &)>(
QGuiApplication::platformFunction("_d_showSplitMenu"));
const auto hide = QGuiApplication::platformFunction("_d_hideSplitMenu");
const WId wid = w->winId();
if (!support || !show || !hide || !support(wid))
return false;

const QRect rect = button->mapRectToScene(button->boundingRect()).toAlignedRect();
if (!rect.isValid())
return false;
show(wid, QRect(w->mapToGlobal(rect.topLeft()), rect.size()));
d->splitMenuWindowId = wid;
return true;
}

void DQuickWindowAttached::hideSplitMenu(bool delay)
{
D_D(DQuickWindowAttached);
if (!d->splitMenuWindowId)
return;
const auto hide = reinterpret_cast<void (*)(WId, bool)>(
QGuiApplication::platformFunction("_d_hideSplitMenu"));
if (hide)
hide(d->splitMenuWindowId, delay);
if (!delay)
d->splitMenuWindowId = 0;
}

bool DQuickWindowAttached::setWindowBlurAreaByWM(const QVector<DPlatformHandle::WMBlurArea> &area)
{
D_D(DQuickWindowAttached);
Expand Down
3 changes: 3 additions & 0 deletions src/dquickwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ public Q_SLOTS:

void popupSystemWindowMenu();

bool showSplitMenu(QQuickItem *button);
void hideSplitMenu(bool delay = true);

bool setWindowBlurAreaByWM(const QVector<DPlatformHandle::WMBlurArea> &area);
bool setWindowBlurAreaByWM(const QList<QPainterPath> &area);

Expand Down
1 change: 1 addition & 0 deletions src/private/dquickwindow_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class DQuickWindowAttachedPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate
#endif

QPointer<QWindow> window = nullptr;
WId splitMenuWindowId = 0;
DPlatformHandle *handle = nullptr;
BoolOptional explicitEnable {Invalid};
BoolOptional explicitTranslucentBackground {Invalid};
Expand Down
Loading
Loading