Conversation
Reviewer's GuideThe application-tray X11 event path now avoids shape-update feedback loops by handling LEAVE_NOTIFY only for active, plugin-owned windows and skipping redundant input-shape requests. Cached shape state is explicitly invalidated when tray windows are destroyed or deregistered, preventing stale state from affecting recycled X11 IDs. Sequence diagram for preventing the X11 input-shape event stormsequenceDiagram
participant X11 as X11EventSource
participant Filter as XembedProtocol
participant Handler as XembedProtocolHandler
participant Util as Util
participant Xwayland
X11->>Filter: nativeEventFilter(LEAVE_NOTIFY)
Filter->>Handler: ownsX11Window(eventWindow)
alt unmanaged window
Handler-->>Filter: false
Filter-->>X11: return false
else owned window
Handler-->>Filter: true
Filter->>Util: setX11WindowInputShape(eventWindow, QSize)
alt shape unchanged
Util-->>Filter: return early
else shape changed
Util->>Util: m_inputShapes.insert(window, size)
Util->>Xwayland: xcb_shape_rectangles / xcb_shape_mask / xcb_configure_window
end
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="plugins/application-tray/xembedprotocolhandler.cpp" line_range="184" />
<code_context>
{
if (m_containerWid) {
xcb_destroy_window(Util::instance()->getX11Connection(), m_containerWid);
+ Util::instance()->removeX11WindowInputShapeRecord(m_containerWid);
}
UTIL->removeUniqueId(m_id);
</code_context>
<issue_to_address>
**issue (bug_risk):** The cleanup removes the cached shape only for `m_containerWid`, but `nativeEventFilter` also calls `setX11WindowInputShape` for the managed icon window `m_windowId`, so its cache entry survives handler destruction. If that X11 ID is later reused, the idempotency guard treats the new window as already having a 0x0 shape and skips the shape requests; `ownsX11Window` also treats the reused ID as managed.
**Triggers:** When an embedded tray icon is destroyed and its X11 window ID is reused before the handler is removed.
**Suggested fix:** Remove the shape record for `m_windowId` as well, and invalidate the handler's ownership state when the embedded icon is destroyed.
</issue_to_address>There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Address the critical stale-ownership/XID-reuse issue and track stacking state separately from shape state.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
Open (2)
What changed in this PR
Fixes X11 input-shape event storms in the application tray by filtering unmanaged windows and caching shape updates.
Changes:
- Adds X11 window ownership checks.
- Adds idempotent input-shape tracking.
- Cleans cached state during tray lifecycle changes.
| File | Summary | Findings |
|---|---|---|
plugins/application-tray/xembedprotocolhandler.h |
Declares ownership and invalidation state. | — |
plugins/application-tray/xembedprotocolhandler.cpp |
Filters events and manages cleanup. | Critical (2 votes): Ownership can remain stale during delayed cleanup, allowing XID reuse to affect unrelated windows. |
plugins/application-tray/util.h |
Declares shape-cache storage and cleanup. | — |
plugins/application-tray/util.cpp |
Implements idempotent shape updates. | Moderate (2 votes): Shape-only caching can skip required stacking-order updates. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
1. Filter LEAVE_NOTIFY to only windows managed by the handler 2. Add idempotency guard to setX11WindowInputShape 3. Clean up shape records when container window is destroyed Log: Fix high CPU usage of Xwayland and tray plugin Influence: 1. Open wine WeCom and hover tray icons to verify CPU stays normal 2. Trigger nm-applet leave events and confirm no Xwayland CPU spike 3. Verify tray icon hover/click still works after the fix fix: 防止应用托盘的 X11 输入形状事件风暴 1. 只处理 handler 所管理窗口的 LEAVE_NOTIFY 事件 2. 为 setX11WindowInputShape 增加幂等保护 3. 容器窗口销毁时清理形状记录 Log: 修复 Xwayland 与托盘插件 CPU 占用过高的问题 Influence: 1. 打开 wine 企业微信并悬停托盘图标,确认 CPU 保持正常 2. 触发 nm-applet 离开事件,确认 Xwayland 无 CPU 飙升 3. 验证托盘图标悬停/点击功能仍然正常 PMS: BUG-378231
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: BLumia, wineee 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 |
deepin pr auto review🤖 AI 代码审查报告📊 总体评价
🔍 详细分析1. 语法逻辑 ✅评分: 25/25 分 ✓ 通过 评价: 语法正确,逻辑清晰 分析要点:
潜在问题: 2. 代码质量 ✅评分: 25/25 分 ✓ 通过 评价: 代码结构清晰,注释完整 分析要点:
潜在问题: 3. 代码性能 ✅评分: 20/20 分 ✓ 通过 评价: 性能良好,资源使用合理 分析要点:
潜在问题: 4. 代码安全 🔒评分: 30/30 分 ✓ 通过
分析要点:
漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个 安全漏洞详情: 📋 审查结论本次提交旨在修复 X11 输入形状事件风暴导致的 Xwayland 和托盘插件 CPU 占用过高问题(PMS: BUG-378231)。代码通过三个核心机制实现修复:
代码逻辑正确,注释详尽,性能优化有效,无安全风险。建议合入。 本报告由 AI 代码审查工具自动生成 |


X11 Input Shape 事件风暴导致 CPU 占用过高技术报告
摘要
在 Treeland(Wayland 合成器)环境下,打开 wine 版企业微信后出现
XwaylandCPU 占用飙升至 98% 的问题。经过系统化排查,定位根因为dde-tray-loader的application-tray插件在处理 X11LEAVE_NOTIFY事件时缺少窗口归属过滤与幂等保护,任何 X11 客户端(wine 企业微信、nm-applet 等)的离开事件都会触发一次setX11WindowInputShape,而该调用又会引发 Xwayland 的 enter/leave 重算并广播新事件,形成每秒十几万次的事件风暴死循环。问题现象
Xwayland :1wineserverexplorer.exe /desktoptrayplugin-loadnm-applet排查过程
1. 定位高 CPU 进程
发现多个进程异常高 CPU,其中 Xwayland 主线程占 99%。
2. Xwayland 主线程栈采样
通过
gdb多次采样 Xwayland 主线程,反复命中同一调用链:关键证据:每次 shape 请求都会触发
WindowsRestructured对全窗口树做 enter/leave 事件重算,这是极昂贵的操作。3. 反查 shape 请求的发送方
在 Xwayland 进程内通过 gdb 读取 client 结构体:
通过
ss反查该 inode 的对端:确认元凶是
trayplugin-load(dde-dock 托盘插件)。4. 抓取请求内容
strace 抓
trayplugin-load的写操作:解码 X11 请求字节流:
与源码
Util::setX11WindowInputShape逐字节对应。5. 定位代码
grep -rn "setX11WindowInputShape" plugins/application-tray/命中:
xembedprotocolhandler.cpp:72—nativeEventFilter处理LEAVE_NOTIFYutil.cpp:270—setX11WindowInputShape实现根因分析
死循环触发链
三个缺陷
缺少窗口归属过滤:
nativeEventFilter对所有 X11 客户端的LEAVE_NOTIFY都响应,包括 wine 企业微信、nm-applet 等无关窗口。缺少幂等保护:
setX11WindowInputShape每次调用都无条件发送 3 条 X11 请求,即使目标窗口的 input shape 已经是目标值。缺少防重入机制:事件处理路径中没有任何去抖 / 防重入保护,导致事件风暴正反馈。
触发条件
XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_ENTER_WINDOW事件掩码LEAVE_NOTIFY事件即可点燃风暴补充发现
nm-applet是独立问题:启动仅 14 分钟即内存泄漏至 20 GB(RSS),其 CPU 高占用与 shape 循环无关,是自身 GTK 事件循环空转 + 内存泄漏导致的。修复方案
修改文件
util.hremoveX11WindowInputShapeRecord()声明、m_inputShapes记录表、#include <QSize>util.cppsetX11WindowInputShape增加幂等保护;新增记录清理函数xembedprotocolhandler.hownsX11Window()声明xembedprotocolhandler.cppnativeEventFilter增加窗口归属过滤;析构时清理记录三层防护
验证结果
编译验证
application-tray目标编译通过,无错误,产物生成libapplication-tray.so。运行时验证(待部署后执行)
遗留风险与后续建议
部署验证未完成:补丁已提交但未部署到系统(
/usr/lib/dde-dock/plugins/),需替换.so后重新登录验证。更彻底的优化方向(超出本次修复范围):
setX11WindowInputShape连发 3 条请求(rectangles + mask + configure)可考虑合并configure_window(STACK_MODE_BELOW)改变堆叠顺序是引发新事件的元凶之一,纯 input shape 场景可能不需要nm-applet 内存泄漏:这是独立问题,需要单独排查(可能是 GTK 版本或特定场景触发)。
监控建议:可考虑添加 Xwayland CPU 超阈值告警,快速发现类似事件风暴问题。
附录:关键命令
Summary by Sourcery
Prevent application-tray X11 leave-event feedback loops from driving excessive Xwayland CPU usage.
Bug Fixes:
Enhancements: