feat: support KWin split menus in QML title bars - #688
Conversation
1. Add splitScreenEnabled property to TitleBar and WindowButtonGroup QML components 2. Implement showSplitMenu and hideSplitMenu methods in DQuickWindowAttached using platform functions 3. Add hover timer (700ms) and hold timer (300ms) to trigger split menu on the maximize button 4. Track splitMenuWindowId in DQuickWindowAttachedPrivate to manage menu lifecycle 5. Handle menu hiding on hover exit, release, cancel, visibility change, and enabled change 6. Guard menu operations with button/window visibility and enabled checks Log: Added KWin split screen menu support triggered by hovering or long- pressing the maximize button in QML title bars Influence: 1. Test hovering over the maximize button for 700ms to verify the split menu appears 2. Test long-pressing the maximize button for 300ms to verify the split menu appears 3. Verify normal click still maximizes/restores the window when menu is not triggered 4. Test that moving the mouse away hides the split menu 5. Verify splitScreenEnabled=false disables the split menu entirely 6. Test menu behavior when the window is not visible or the button is disabled 7. Verify the menu positions correctly relative to the button's screen position 8. Test hide delay behavior when releasing outside vs. inside the button feat: 在 QML 标题栏中支持 KWin 分屏菜单 1. 在 TitleBar 和 WindowButtonGroup QML 组件中添加 splitScreenEnabled 属性 2. 通过平台函数在 DQuickWindowAttached 中实现 showSplitMenu 和 hideSplitMenu 方法 3. 添加悬停定时器(700ms)和长按定时器(300ms)以在最大化按钮上触发分屏 菜单 4. 在 DQuickWindowAttachedPrivate 中跟踪 splitMenuWindowId 以管理菜单生 命周期 5. 处理鼠标离开、释放、取消、可见性变化和启用状态变化时的菜单隐藏 6. 使用按钮/窗口可见性和启用状态检查保护菜单操作 Log: 新增 KWin 分屏菜单支持,通过悬停或长按 QML 标题栏中的最大化按钮触发 Influence: 1. 测试将鼠标悬停在最大化按钮上 700ms,验证分屏菜单是否出现 2. 测试长按最大化按钮 300ms,验证分屏菜单是否出现 3. 验证未触发菜单时正常点击仍能最大化/还原窗口 4. 测试鼠标移开后分屏菜单是否正确隐藏 5. 验证 splitScreenEnabled=false 时完全禁用分屏菜单 6. 测试窗口不可见或按钮禁用时的菜单行为 7. 验证菜单相对于按钮屏幕位置的正确定位 8. 测试在按钮外部释放与内部释放时的隐藏延迟行为
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: 18202781743 The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
Reviewer's GuideAdds configurable KWin split-menu support to QML title bars by combining maximize-button hover/long-press interaction with direct platform-function calls, while retaining existing maximize/restore behavior on unsupported platforms and ordinary clicks. Sequence diagram for QML split-menu interactionsequenceDiagram
participant User
participant MaximizeButton
participant DQuickWindowAttached
participant Platform
alt Hover for 700ms or hold for 300ms
User->>MaximizeButton: hover or press
MaximizeButton->>DQuickWindowAttached: showSplitMenu(maxOrWindedBtn)
DQuickWindowAttached->>Platform: _d_supportSplitMenu(wid)
alt Platform supports split menu
DQuickWindowAttached->>Platform: _d_showSplitMenu(wid, rect)
Platform-->>DQuickWindowAttached: menu shown
else Unsupported or invalid window/button
DQuickWindowAttached-->>MaximizeButton: false
end
else Ordinary click
User->>MaximizeButton: click
MaximizeButton->>MaximizeButton: maxOrWinded()
end
alt Menu requested
User->>MaximizeButton: release or leave button
MaximizeButton->>DQuickWindowAttached: hideSplitMenu(delay)
DQuickWindowAttached->>Platform: _d_hideSplitMenu(wid, delay)
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="qt6/src/qml/WindowButtonGroup.qml" line_range="131-136" />
<code_context>
+ control.maxOrWinded()
+ __longPressed = false
+ }
+ onVisibleChanged: {
+ if (!visible) {
+ hoverTimer.stop()
+ holdTimer.stop()
+ __menuRequested = false
+ }
+ }
+ onEnabledChanged: if (!enabled) hideSplitMenu(false)
</code_context>
<issue_to_address>
**issue (bug_risk):** When the maximize button becomes invisible while a split menu is open, this handler stops the timers and clears `__menuRequested` without calling `hideSplitMenu`, so the platform menu remains visible and the client loses the state needed to hide it.
**Triggers:** When the window enters fullscreen or another state that makes `maxOrWindedBtn.visible` false after the split menu has been shown.
**Suggested fix:** Call `hideSplitMenu(false)` (or an appropriate delayed hide) before clearing the request state when the button becomes invisible, and handle window visibility changes explicitly if they do not change the button's `visible` property.
</issue_to_address>| onVisibleChanged: { | ||
| if (!visible) { | ||
| hoverTimer.stop() | ||
| holdTimer.stop() | ||
| __menuRequested = false | ||
| } |
There was a problem hiding this comment.
issue (bug_risk): When the maximize button becomes invisible while a split menu is open, this handler stops the timers and clears __menuRequested without calling hideSplitMenu, so the platform menu remains visible and the client loses the state needed to hide it.
Triggers: When the window enters fullscreen or another state that makes maxOrWindedBtn.visible false after the split menu has been shown.
Suggested fix: Call hideSplitMenu(false) (or an appropriate delayed hide) before clearing the request state when the button becomes invisible, and handle window visibility changes explicitly if they do not change the button's visible property.
deepin pr auto reviewAI 代码审查报告
总体评价
漏洞统计漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
四维度评分
维度1: 语法逻辑 (22/25 ✓)
代码目的: 在 QML 标题栏中支持 KWin 分屏菜单,通过悬停或长按最大化按钮触发。 分析: C++ 层 发现的问题:
建议修复: // dquickwindow.cpp - showSplitMenu() 中添加重入保护
bool DQuickWindowAttached::showSplitMenu(QQuickItem *button)
{
D_D(DQuickWindowAttached);
// 如果已有菜单显示,先隐藏
if (d->splitMenuWindowId)
hideSplitMenu(false);
// ... 原有逻辑
}
// dquickwindow.cpp - hideSplitMenu() 统一清理 splitMenuWindowId
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);
d->splitMenuWindowId = 0; // 始终清理,避免过期状态
}// WindowButtonGroup.qml - onVisibleChanged 添加 hideSplitMenu 调用
onVisibleChanged: {
if (!visible) {
hoverTimer.stop()
holdTimer.stop()
hideSplitMenu(false) // 隐藏平台菜单
__menuRequested = false
}
}维度2: 代码质量 (21/25 ✓)
分析: 代码结构合理,QML 层将分屏菜单逻辑封装在最大化按钮内部,C++ 层通过平台函数指针调用实现平台集成。命名规范一致( 发现的问题:
建议修复: // 为新函数添加 Qt 风格文档注释
/*!
* \~chinese \brief DQuickWindowAttached::showSplitMenu 显示分屏菜单
* \~chinese 通过平台函数在指定按钮位置显示 KWin 分屏菜单
* \~chinese \param button 触发分屏菜单的 QQuickItem 按钮
* \~chinese \return 成功显示返回 true,否则返回 false
*/
// 统一函数指针类型定义,避免重复和不一致
using SplitMenuSupportFunc = bool (*)(WId);
using SplitMenuShowFunc = void (*)(WId, const QRect &);
using SplitMenuHideFunc = void (*)(WId, bool);维度3: 代码性能 (20/20 ✓)
分析: 代码性能表现良好:
无性能问题。 维度4: 代码安全 (30/30 ✓)
安全分析:
安全合规,无安全风险。 改进建议总结
审查结论本次提交实现了 KWin 分屏菜单功能,代码质量整体优秀。功能实现与 commit message 描述一致,包括:
无安全漏洞,建议修复少量边界条件和状态管理问题。 |
为 QML TitleBar/WindowButtonGroup 增加 splitScreenEnabled,并在最大化按钮悬停或长按时请求 KWin 分屏菜单。普通点击保持最大化/还原行为;长按成功后释放不触发最大化;不支持平台接口时正常点击行为不受影响。
DQuickWindowAttached 直接封装平台函数调用,不经过 dtkgui。客户端处理按钮交互和功能禁用时的收起请求,窗口关闭/消失后的菜单清理由窗管负责。
关联平台接口:linuxdeepin/dde-qtplatform-plugins#345
验证:实现工作目录中 Qt5/Qt6 构建通过(最多 6 个核心);QML 无界面测试 8 项通过(包含初始化/清理,覆盖普通点击、长按、悬停离开、功能禁用及不支持的平台)。PR 基于最新 master,差异检查通过;真实 KWin 桌面显示效果尚未实测。
Summary by Sourcery
Enable QML title-bar maximize buttons to invoke and manage KWin split-screen menus while retaining existing window-state interactions.
New Features:
Bug Fixes:
Enhancements: