Skip to content

Commit 049b702

Browse files
fix(shot): suppress XRecord relay on normal path to fix selection flicker on HiDPI
The XRecord relay introduced in BUG-330895 uses coordinate comparison (m_currentCursor vs rootX/rootY) to deduplicate events when Qt already handled them via the native path. However on HiDPI screens the two coordinates live in different spaces — mouseEvent->pos() is a widget-local logical coordinate scaled by pixelRatio, while rootX/rootY are physical screen pixels — so the comparison always evaluates to unequal. Every mouse move during drag triggers two repaint() calls (one from Qt native, one from XRecord relay), causing the dashed selection border to flicker. Replace the coordinate-based dedup with a timestamp approach: - mouseMoveEF records m_lastNativeMouseMoveMs on every native MouseMove (relayed events are gated by m_isRelayedEvent flag to avoid polluting) - onMouseDrag/onMouseMove only relay when no native event arrived in >50ms At ~60fps, native events land every ~16ms, so the 50ms threshold completely suppresses relay under normal operation. When a Dock Grab blocks Qt input, the gap exceeds 50ms and relay kicks in automatically. Log: 修复高分屏截图框选虚线闪烁问题 PMS: BUG-330895 Influence: 高分屏拖拽框选不再闪烁;Dock Grab 场景下 XRecord 补发仍正常工作
1 parent 42627c1 commit 049b702

2 files changed

Lines changed: 18 additions & 14 deletions

File tree

src/main_window.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -629,8 +629,10 @@ void MainWindow::refetchWindowInfo()
629629
void MainWindow::sendSimulatedMouseEvent(QEvent::Type type, const QPoint &pos,
630630
Qt::MouseButton button, Qt::MouseButtons buttons)
631631
{
632+
m_isRelayedEvent = true;
632633
QScopedPointer<QMouseEvent> event(new QMouseEvent(type, pos, button, buttons, Qt::NoModifier));
633634
QApplication::sendEvent(this, event.data());
635+
m_isRelayedEvent = false;
634636
}
635637

636638
void MainWindow::forceX11WindowPosition()
@@ -5297,6 +5299,10 @@ int MainWindow::mouseMoveEF(QMouseEvent *mouseEvent, bool &needRepaint)
52975299
// qCDebug(dsrApp) << "mouseEvent->pos()" << mouseEvent->pos() << " , isFirsMove: " << isFirstMove;
52985300
// 当前光标的位置
52995301
m_currentCursor = mouseEvent->pos();
5302+
// 仅原生事件更新时间戳,转发事件不更新(避免污染判断)
5303+
if (!m_isRelayedEvent) {
5304+
m_lastNativeMouseMoveMs = QDateTime::currentMSecsSinceEpoch();
5305+
}
53005306
// 没打开截图的编辑模式
53015307
if (!m_isShapesWidgetExist) {
53025308
if (m_toolBar && m_toolBar->isVisible()) {
@@ -6037,13 +6043,12 @@ void MainWindow::onMouseDrag(int x, int y)
60376043
showDragFeedback(x, y);
60386044
}
60396045

6040-
// 截图模式:拖拽阶段(按下左键后移动)XRecord 发出 mouseDrag 而非 mouseMove
6041-
// Dock Grab 存在时 Qt event filter 收不到拖拽移动事件,框选区域无法更新。
6042-
// 同样用坐标去重避免正常情况下双重触发
6046+
// 截图模式:拖拽阶段 XRecord 补发鼠标移动事件
6047+
// 仅当 Qt 原生事件通路被阻断(Dock Grab)超过 50ms 未收到 MouseMove 时才转发,
6048+
// 正常操作下 Qt 事件每 ~16ms 到达一次,转发被完全抑制,避免双重 repaint
60436049
if (status::shot == m_functionType && isFirstPressButton && !isFirstReleaseButton) {
6044-
QPoint pos(x, y);
6045-
if (m_currentCursor != pos) {
6046-
sendSimulatedMouseEvent(QEvent::MouseMove, pos, Qt::NoButton, Qt::LeftButton);
6050+
if (QDateTime::currentMSecsSinceEpoch() - m_lastNativeMouseMoveMs > 50) {
6051+
sendSimulatedMouseEvent(QEvent::MouseMove, QPoint(x, y), Qt::NoButton, Qt::LeftButton);
60476052
}
60486053
}
60496054
}
@@ -6103,17 +6108,14 @@ void MainWindow::onMouseMove(int x, int y)
61036108
}
61046109
}
61056110

6106-
// 截图悬停阶段(未开始框选)通过 XRecord 持续补发鼠标移动事件。
6107-
// Dock Grab 存在时 Qt 正常事件通路被阻断,XRecord 在协议层拦截不受影响。
6111+
// 截图悬停阶段(未开始框选)通过 XRecord 补发鼠标移动事件。
61086112
// 拖拽阶段由 onMouseDrag 负责补发,此处只覆盖悬停阶段(!isFirstPressButton)。
61096113
// 非截图模式保持原有逻辑:仅补发第一次(!isFirstMove)。
6110-
// m_currentCursor 在 mouseMoveEF 开头被更新:坐标已匹配说明 Qt 正常处理过,
6111-
// 无需重复补发,避免正常情况下双重触发。
6114+
// 仅当 Qt 原生事件通路被阻断超过 50ms 时才转发。
61126115
bool inShotHoverPhase = status::shot == m_functionType && !isFirstPressButton;
61136116
if (!isFirstMove || inShotHoverPhase) {
6114-
QPoint pos(x, y);
6115-
if (m_currentCursor != pos) {
6116-
sendSimulatedMouseEvent(QEvent::MouseMove, pos, Qt::NoButton, Qt::NoButton);
6117+
if (QDateTime::currentMSecsSinceEpoch() - m_lastNativeMouseMoveMs > 50) {
6118+
sendSimulatedMouseEvent(QEvent::MouseMove, QPoint(x, y), Qt::NoButton, Qt::NoButton);
61176119
}
61186120
}
61196121
}

src/main_window.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1438,7 +1438,9 @@ public slots:
14381438
/**
14391439
* @brief 当前光标的位置
14401440
*/
1441-
QPoint m_currentCursor;
1441+
QPoint m_currentCursor;
1442+
bool m_isRelayedEvent = false;
1443+
qint64 m_lastNativeMouseMoveMs = 0;
14421444
// ---------------------- treeland--------------------------------
14431445

14441446
/**

0 commit comments

Comments
 (0)