fix(shot): relay XRecord events when Dock grab blocks Qt input on X11#845
Conversation
When a Dock right-click menu is open, Qt's XGrabPointer routes all pointer events to the Dock process. The screenshot overlay never receives them via the normal Qt event path. Fix by relaying XRecord events (which intercept at the protocol level, unaffected by grabs) through QApplication::sendEvent in four handlers: - onMouseMove: continuously relay during hover phase so window auto-highlight updates as the mouse moves - onMouseDrag: relay during drag phase so the selection rectangle tracks the mouse - onMousePress: relay the initial click so the drag state is entered - onMouseRelease: relay the release so the toolbar appears State flags (isFirstPressButton, isFirstReleaseButton, m_currentCursor) are used as dedup guards: QueuedConnection ensures XRecord signals arrive after Qt's synchronous event filter, so if Qt already handled the event the guard condition is already true and the relay is skipped. Log: 修复Dock右键菜单存在时截图工具鼠标事件被X11 Grab拦截的问题 PMS: BUG-330895 Influence: 修复后在Dock右键菜单打开状态下触发截图,窗口悬停检测、 框选拖拽、工具栏显示均可正常工作
ff901e0 to
69838ee
Compare
deepin pr auto review你好!我是CodeGeeX,很高兴为你审查这份代码。 这份 diff 的核心目的是修复 X11 环境下截屏工具的两大痛点:
整体思路非常清晰,逻辑严密,对 X11 事件机制的理解很透彻。以下是我从语法逻辑、代码质量、性能和安全四个维度提出的详细审查意见和改进建议: 一、 语法与逻辑1. 2. 鼠标事件补发的状态机时序风险
3.
二、 代码质量1.
2. 魔法条件提取为语义化变量
3. 注释质量 三、 代码性能1.
2. XRecord 回调中的对象构造
四、 代码安全1. X11 环境变量与权限检查
2. 模拟事件的无限循环风险
综合改进代码示例结合上述建议,以下是优化后的核心代码片段: void MainWindow::refetchWindowInfo()
{
qCDebug(dsrApp) << "refetchWindowInfo() called.";
// 统一判断逻辑,与 initAttributes 对齐
if (Utils::isWaylandMode || Utils::isTreelandMode) {
return;
}
windowRects.clear();
windowNames.clear();
Utils::getAllWindowInfo(static_cast<quint32>(this->winId()), m_screenWidth, m_screenHeight, windowRects, windowNames);
qCDebug(dsrApp) << "refetchWindowInfo: got" << windowRects.size() << "windows";
if (!isFirstMove) {
qCDebug(dsrApp) << "发送鼠标事件!";
sendSimulatedMouseEvent(QEvent::MouseMove, this->cursor().pos(), Qt::NoButton, Qt::NoButton);
}
}
void MainWindow::sendSimulatedMouseEvent(QEvent::Type type, const QPoint &pos,
Qt::MouseButton button, Qt::MouseButtons buttons)
{
// 使用栈对象避免堆分配,提升高频事件性能(sendEvent 不会 delete 事件对象)
// 同时补全 localPos 和 globalPos,兼容 Qt5/Qt6
QMouseEvent event(type, pos, pos, button, buttons, Qt::NoModifier);
event.setTimestamp(QDateTime::currentMSecsSinceEpoch());
QApplication::sendEvent(this, &event);
// 同步更新光标位置,防止后续 Move 去重逻辑误判
m_currentCursor = pos;
}
// onMouseDrag 优化示例
void MainWindow::onMouseDrag(int x, int y)
{
if (status::record == m_functionType) {
showDragFeedback(x, y);
}
bool isInShotDragging = (status::shot == m_functionType) && isFirstPressButton && !isFirstReleaseButton;
if (isInShotDragging) {
QPoint pos(x, y);
// 统一应用去重逻辑
if (m_currentCursor != pos) {
sendSimulatedMouseEvent(QEvent::MouseMove, pos, Qt::NoButton, Qt::LeftButton);
}
}
}总结:这是一份高质量的 Bugfix PR,对 X11 事件机制和 Qt 事件循环的交互理解很深。主要建议集中在防重复触发的健壮性增强、高频事件的堆分配优化以及状态变量的同步更新上。采纳上述建议后,代码将更加健壮和高效。 |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: dengzhongyuan365-dev, lzwind 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 |
|
/forcemerge |
|
This pr force merged! (status: unstable) |
When a Dock right-click menu is open, Qt's XGrabPointer routes all pointer events to the Dock process. The screenshot overlay never receives them via the normal Qt event path.
Fix by relaying XRecord events (which intercept at the protocol level, unaffected by grabs) through QApplication::sendEvent in four handlers:
State flags (isFirstPressButton, isFirstReleaseButton, m_currentCursor) are used as dedup guards: QueuedConnection ensures XRecord signals arrive after Qt's synchronous event filter, so if Qt already handled the event the guard condition is already true and the relay is skipped.
Log: 修复Dock右键菜单存在时截图工具鼠标事件被X11 Grab拦截的问题
PMS: BUG-330895
Influence: 修复后在Dock右键菜单打开状态下触发截图,窗口悬停检测、
框选拖拽、工具栏显示均可正常工作