Skip to content

fix: fix font not updating in windowed launcher popup on system font change#1483

Open
electricface wants to merge 1 commit intolinuxdeepin:masterfrom
electricface:swt/fix-bug335169-way4
Open

fix: fix font not updating in windowed launcher popup on system font change#1483
electricface wants to merge 1 commit intolinuxdeepin:masterfrom
electricface:swt/fix-bug335169-way4

Conversation

@electricface
Copy link
Member

@electricface electricface commented Mar 6, 2026

Rebase PopupWindow on QQuickApplicationWindow instead of
QQuickWindowQmlImpl so that all QQuickControl descendants (including
dynamically created context menus) participate in Qt's standard
font inheritance chain.
Previously, QQuickControlPrivate::resolveFont() fell back to
QGuiApplication::font() for controls inside PopupWindow because
the window was not recognized as a QQuickApplicationWindow.
This meant controls created after a font change (e.g. AppItemMenu
opened via right-click) always got the stale QGuiApplication font
rather than DTK's custom font size.

Log: Fix windowed launcher popup menu font not updating when system font size is changed
PMS: BUG-335169

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: electricface

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sourcery-ai
Copy link

sourcery-ai bot commented Mar 6, 2026

Reviewer's Guide

Adds font propagation support to PopupWindow so that popup-based UIs (panel popups, menus, tooltips) inherit and dynamically react to system font changes, wiring this through a new font Q_PROPERTY and using Qt Quick Templates2 private APIs, plus the necessary build-system updates and QML bindings.

Sequence diagram for font change propagation to popup controls

sequenceDiagram
    participant User
    participant SystemSettings
    participant DDTKFontManager as DDTK_fontManager
    participant PanelPopupQML as PanelPopupWindow_qml
    participant PopupWindow
    participant ContentItem as QQuickItem_contentItem
    participant QQuickControlPrivate

    User->>SystemSettings: changeFontSize(newSize)
    SystemSettings-->>DDTKFontManager: update t6.font(newSize)
    DDTKFontManager-->>PanelPopupQML: t6.family, t6.pixelSize changed
    PanelPopupQML-->>PopupWindow: update font.family, font.pixelSize via binding
    PopupWindow->>PopupWindow: setFont(QFont from QML)
    PopupWindow->>PopupWindow: resolve with QGuiApplication::font()
    PopupWindow->>PopupWindow: propagateFontToContentItem(m_font)
    PopupWindow->>ContentItem: contentItem()
    PopupWindow->>QQuickControlPrivate: updateFontRecur(contentItem, m_font)
    QQuickControlPrivate-->>ContentItem: applyFontToControlsRecursively(m_font)
    ContentItem-->>User: popup menu re-rendered with new font size
Loading

Class diagram for updated PopupWindow font propagation

classDiagram
    class QQuickWindowQmlImpl

    class PopupWindow {
        <<QML_NAMED_ELEMENT_PopupWindow>>
        +PopupWindow(parent: QWindow*)
        +QFont font() const
        +void setFont(font: QFont const&)
        +void resetFont()
        +void mouseReleaseEvent(event: QMouseEvent*)
        +void mousePressEvent(event: QMouseEvent*)
        +void mouseMoveEvent(event: QMouseEvent*)
        +void fontChanged()
        -void propagateFontToContentItem(font: QFont const&)
        -bool m_dragging
        -bool m_pressing
        -QFont m_font
        -bool m_hasExplicitFont
    }

    PopupWindow --|> QQuickWindowQmlImpl
Loading

Architecture/flow diagram for font propagation across components

flowchart LR
    SystemFonts["System font settings"] --> DDTKFontManager["D.DTK.fontManager.t6"]
    DDTKFontManager --> PanelPopupWindowQML["PanelPopupWindow_qml<br/>font.family,font.pixelSize bindings"]
    PanelPopupWindowQML --> PopupWindow["PopupWindow<br/>Q_PROPERTY font"]
    PopupWindow --> QQuickItemContentItem["QQuickItem contentItem()"]
    QQuickItemContentItem --> QQuickControlPrivate["QQuickControlPrivate::updateFontRecur"]
    QQuickControlPrivate --> PopupControls["QQuickControl descendants<br/>(menus, tooltips, panels)"]

    User["User"] --> SystemFonts
    PopupControls --> User
Loading

File-Level Changes

Change Details Files
Add a font Q_PROPERTY to PopupWindow and propagate its value to all QQuickControl descendants so popup content follows system font changes.
  • Introduce a QFont-backed font Q_PROPERTY on PopupWindow with getter, setter, resetter, and fontChanged signal.
  • Track explicit font vs default state via m_hasExplicitFont and resolve the assigned font against QGuiApplication::font() to avoid redundant updates.
  • Implement propagateFontToContentItem() that calls QQuickControlPrivate::updateFontRecur() starting from the window contentItem().
  • Include QQuickItem and qquickcontrol_p_p headers to support font propagation logic.
frame/popupwindow.h
frame/popupwindow.cpp
Bind PanelPopupWindow’s font to the global DTK font manager and wire up Qt Quick Templates2 private linkage in the build system.
  • Bind PanelPopupWindow.font.family and font.pixelSize to D.DTK.fontManager.t6 so popup UIs respond dynamically to system font changes without per-applet overrides.
  • Add Qt QuickTemplates2 to the top-level Qt find_package call and link QtQuickTemplates2Private in frame/CMakeLists.txt to access QQuickControlPrivate APIs used by PopupWindow.
frame/qml/PanelPopupWindow.qml
CMakeLists.txt
frame/CMakeLists.txt

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • In resetFont() you reset to a default-constructed QFont, which breaks the symmetry with setFont() (which resolves against QGuiApplication::font()); consider resetting to QGuiApplication::font() (or clearing the resolve mask appropriately) so that reset restores the effective system font rather than an uninitialized default.
  • The m_hasExplicitFont flag is set but never read; either remove it to simplify the implementation or make use of it (for example to distinguish between explicit and inherited fonts when reacting to external font changes).
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `resetFont()` you reset to a default-constructed `QFont`, which breaks the symmetry with `setFont()` (which resolves against `QGuiApplication::font()`); consider resetting to `QGuiApplication::font()` (or clearing the resolve mask appropriately) so that reset restores the effective system font rather than an uninitialized default.
- The `m_hasExplicitFont` flag is set but never read; either remove it to simplify the implementation or make use of it (for example to distinguish between explicit and inherited fonts when reacting to external font changes).

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

system font change

Rebase PopupWindow on QQuickApplicationWindow instead of
QQuickWindowQmlImpl so that all QQuickControl descendants (including
dynamically created context menus) participate in Qt's standard
font inheritance chain.
Previously, QQuickControlPrivate::resolveFont() fell back to
QGuiApplication::font() for controls inside PopupWindow because
the window was not recognized as a QQuickApplicationWindow.
This meant controls created after a font change (e.g. AppItemMenu
opened via right-click) always got the stale QGuiApplication font
rather than DTK's custom font size.

Log: Fix windowed launcher popup menu font not updating when system font size is changed
PMS: BUG-335169
@electricface electricface force-pushed the swt/fix-bug335169-way4 branch from d829f56 to 573168c Compare March 8, 2026 03:33
@deepin-ci-robot
Copy link

deepin pr auto review

这份代码审查主要针对将 PopupWindow 类从继承 QQuickWindowQmlImpl 改为继承 QQuickApplicationWindow 的改动。以下是关于语法逻辑、代码质量、代码性能和代码安全的详细审查意见:

1. 语法逻辑

  • CMakeLists.txt 依赖项变更

    • 问题:在主 CMakeLists.txt 中,添加了 QuickTemplates2 到公共组件列表,这是正确的。但在 frame/CMakeLists.txt 中,链接库添加的是 Qt${QT_VERSION_MAJOR}::QuickTemplates2Private
    • 分析:代码中 popupwindow.h 引用了 #include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>,这表明使用了 Qt 的私有 API (_p.h)。虽然 CMake 写法正确,但逻辑上意味着该模块现在依赖于 Qt Quick Templates 2 的私有实现细节。
    • 风险:私有 API 在不同 Qt 版本间可能发生二进制或源代码不兼容的变更,未来升级 Qt 版本时可能需要修改代码。
  • 类继承变更

    • 问题PopupWindowQQuickWindowQmlImpl 变更为 QQuickApplicationWindow
    • 分析QQuickWindowQmlImpl 是 Qt Quick 内部用于实现 Window QML 类型的类,而 QQuickApplicationWindow 是用于 ApplicationWindow 的类。
    • 逻辑影响QQuickApplicationWindow 继承自 QQuickWindow,但它增加了对菜单栏、工具栏等 Application Window 特有属性的支持。如果 PopupWindow 的初衷仅仅是一个简单的弹出窗口,继承 QQuickApplicationWindow 可能引入了不必要的功能(尽管它也是一个 Window)。更轻量级的做法通常是继承 QQuickWindowQQuickPopup(如果是纯 QML 组件)。但如果是为了复用 ApplicationWindow 的某些特定行为(如布局管理器或特定的窗口属性),这个改动是合理的。
    • 头文件引用popupwindow.h 中引用了私有头文件 qquickapplicationwindow_p.h。这是合法的 C++ 语法,但如前所述,这依赖于私有 API。

2. 代码质量

  • 私有 API 的使用

    • 意见:直接继承 QQuickApplicationWindow 并包含其私有头文件 qquickapplicationwindow_p.h 是一种"黑客"做法,除非这是为了实现某些只有私有 API 才能提供的特定功能。
    • 改进建议:如果可能,考虑使用公共 API。例如,在 QML 中使用 ApplicationWindow 并通过 setParenttransientParent 关联,或者在 C++ 中继承 QQuickWindow 并手动添加所需的功能。如果必须使用私有 API,建议添加详细的注释说明原因,并做好版本兼容性检查。
  • QML 属性设置

    • 改动:在 PanelPopupWindow.qml 中添加了 font.familyfont.pixelSize
    • 意见:这看起来是为了统一字体样式。直接在根元素设置字体属性是合理的做法,可以确保子组件继承这些设置。

3. 代码性能

  • 继承开销
    • 分析QQuickApplicationWindow 相比 QQuickWindowQQuickWindowQmlImpl 可能会有轻微的额外内存开销,因为它包含了更多的附加属性(如 menuBar, toolBar 等)。如果 PopupWindow 实例创建非常频繁,这可能会有微小影响。但对于面板弹出窗口这种通常数量较少、生命周期较长的组件,性能影响可以忽略不计。

4. 代码安全

  • Wayland 兼容性

    • 分析:代码中包含 if(Qt${QT_VERSION_MAJOR}_VERSION VERSION_GREATER_EQUAL 6.10) 以及对 WaylandClientPrivate 的查找。这表明项目正在适配新的 Qt/Wayland 特性。
    • 意见PopupWindow 构造函数中设置了 setMinimumSize(QSize(1, 1)) 并注释说明是为了防止 Wayland 协议错误,这是很好的实践。
    • 潜在风险:切换基类可能会影响 Wayland 下的窗口类型行为。QQuickApplicationWindow 默认的窗口类型或 surface 处理可能与 QQuickWindowQmlImpl 不同。建议在 Wayland 环境下重点测试该弹窗的显示、隐藏以及焦点管理,确保没有引入回归问题。
  • 鼠标事件处理

    • 分析mouseReleaseEvent 中的逻辑检查点击位置是否在窗口外部,如果是则关闭窗口。
    • 意见:逻辑看起来是安全的。使用了 QMetaObject::invokeMethod(..., Qt::QueuedConnection) 来关闭窗口,这是一种安全的做法,可以避免在事件处理过程中直接销毁对象导致崩溃。

总结与改进建议

  1. 确认继承必要性:请确认将 PopupWindow 改为继承 QQuickApplicationWindow 是功能必须的(例如需要其特定的布局或属性支持),还是仅仅为了解决某个特定 Bug。如果只是为了获取窗口行为,继承 QQuickWindow 通常更轻量且不依赖私有 API。
  2. 私有头文件依赖:如果必须继承 QQuickApplicationWindow,请确保在 CI/CD 流程中针对不同 Qt 版本(尤其是 minor 版本更新)进行编译测试,因为私有 API 容易变动。
  3. Wayland 测试:鉴于改动涉及窗口基类和 Wayland 相关的 CMake 配置,务必在 Wayland 会话下进行完整的回归测试,特别是关于窗口弹出、层级和输入焦点的测试。
  4. 字体设置:QML 中字体的硬编码(D.DTK.fontManager.t6)建议确认是否符合设计规范,并确保 D.DTK 对象在加载时已完全初始化。

总体而言,代码改动在语法上是正确的,但引入了对 Qt 私有 API 的依赖,这增加了维护成本和潜在的兼容性风险。建议在合并前充分测试,特别是跨 Qt 版本的兼容性测试。

@electricface electricface changed the title fix(dock): Launcher popup menu in small window mode fails to update with system font size changes fix: fix font not updating in windowed launcher popup on system font change Mar 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants