@@ -491,8 +491,10 @@ void MainWindow::initAttributes()
491491 m_connectionThreadObject->initConnection ();
492492 #endif
493493 } else {
494- // x11自动识别窗口
495- Utils::getAllWindowInfo (static_cast <quint32>(this ->winId ()), m_screenWidth, m_screenHeight, windowRects, windowNames);
494+ // x11: 窗口列表延迟到 showFullScreen 之后通过 refetchWindowInfo() 获取
495+ // 避免右键菜单等弹出窗口残留在 windowRects 中
496+ windowRects.clear ();
497+ windowNames.clear ();
496498 }
497499 // 构建截屏工具栏按钮 by zyg
498500 m_toolBar = new ToolBar (this );
@@ -599,18 +601,38 @@ void MainWindow::initAttributes()
599601 this ,
600602 SLOT (onLockScreenEvent (QDBusMessage)));
601603
602- if (!isFirstMove && !Utils::isWaylandMode) {
603- qCDebug (dsrApp) << " 发送鼠标事件!" ;
604- QMouseEvent *mouseMove =
605- new QMouseEvent (QEvent::MouseMove, this ->cursor ().pos (), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
606- QApplication::sendEvent (this , mouseMove);
607- delete mouseMove;
608- }
604+ // 模拟鼠标事件延迟到 refetchWindowInfo() 中,与窗口列表获取同步
609605
610606 qCInfo (dsrApp) << __LINE__ << __FUNCTION__ << " 属性初始化已完成" ;
611607 }
612608}
613609
610+ void MainWindow::refetchWindowInfo ()
611+ {
612+ qCDebug (dsrApp) << " refetchWindowInfo() called." ;
613+ if (Utils::isWaylandMode || Utils::isTreelandMode) {
614+ // Wayland 下窗口列表通过异步回调 waylandwindowinfo() 获取,无需在此处理
615+ return ;
616+ }
617+
618+ windowRects.clear ();
619+ windowNames.clear ();
620+ Utils::getAllWindowInfo (static_cast <quint32>(this ->winId ()), m_screenWidth, m_screenHeight, windowRects, windowNames);
621+ qCDebug (dsrApp) << " refetchWindowInfo: got" << windowRects.size () << " windows" ;
622+
623+ if (!isFirstMove) {
624+ qCDebug (dsrApp) << " 发送鼠标事件!" ;
625+ sendSimulatedMouseEvent (QEvent::MouseMove, this ->cursor ().pos (), Qt::NoButton, Qt::NoButton);
626+ }
627+ }
628+
629+ void MainWindow::sendSimulatedMouseEvent (QEvent::Type type, const QPoint &pos,
630+ Qt::MouseButton button, Qt::MouseButtons buttons)
631+ {
632+ QScopedPointer<QMouseEvent> event (new QMouseEvent (type, pos, button, buttons, Qt::NoModifier));
633+ QApplication::sendEvent (this , event.data ());
634+ }
635+
614636void MainWindow::forceX11WindowPosition ()
615637{
616638#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
@@ -2268,6 +2290,7 @@ void MainWindow::topWindow()
22682290 this ->initLaunchMode (" screenShot" );
22692291 this ->showFullScreen ();
22702292 this ->initResource ();
2293+ refetchWindowInfo ();
22712294
22722295 // wayland 模式下不进入以下步骤
22732296 if (Utils::isWaylandMode) {
@@ -2486,7 +2509,8 @@ void MainWindow::savePath(const QString &path)
24862509 this ->initLaunchMode (" screenShot" );
24872510 this ->showFullScreen ();
24882511 this ->initResource ();
2489-
2512+ refetchWindowInfo ();
2513+
24902514 qCDebug (dsrApp) << " savePath end" ;
24912515}
24922516
@@ -2512,6 +2536,7 @@ void MainWindow::startScreenshotFor3rd(const QString &path)
25122536 this ->initLaunchMode (" screenShot" );
25132537 this ->showFullScreen ();
25142538 this ->initResource ();
2539+ refetchWindowInfo ();
25152540 m_shotWithPath = true ; // 自带路径
25162541 m_noNotify = true ; // 关闭通知
25172542 qCDebug (dsrApp) << " startScreenshotFor3rd end" ;
@@ -2525,6 +2550,7 @@ void MainWindow::noNotify()
25252550 this ->initLaunchMode (" screenShot" );
25262551 this ->showFullScreen ();
25272552 this ->initResource ();
2553+ refetchWindowInfo ();
25282554}
25292555
25302556void MainWindow::initBackground ()
@@ -6010,6 +6036,16 @@ void MainWindow::onMouseDrag(int x, int y)
60106036 if (status::record == m_functionType) {
60116037 showDragFeedback (x, y);
60126038 }
6039+
6040+ // 截图模式:拖拽阶段(按下左键后移动)XRecord 发出 mouseDrag 而非 mouseMove。
6041+ // Dock Grab 存在时 Qt event filter 收不到拖拽移动事件,框选区域无法更新。
6042+ // 同样用坐标去重避免正常情况下双重触发。
6043+ 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);
6047+ }
6048+ }
60136049}
60146050
60156051// 通过x11从底层获取鼠标按压事件
@@ -6023,6 +6059,15 @@ void MainWindow::onMousePress(int x, int y)
60236059 } else if (m_initScroll && status::scrollshot == m_functionType) {
60246060 scrollShotMouseClickEvent (x, y);
60256061 }
6062+
6063+ // 截图模式:Dock 右键菜单持有 X11 Pointer Grab 时,按下事件会被路由到
6064+ // Dock 而非截图工具,Qt event filter 收不到。通过 XRecord 补发,确保截图
6065+ // 工具能正确进入拖拽状态(isFirstPressButton = true)。
6066+ // 利用 QueuedConnection 的时序:Qt 同步处理已在前,此处排队到后——若 Qt
6067+ // 已处理(isFirstPressButton == true),条件不成立,不重复触发。
6068+ if (status::shot == m_functionType && !isFirstPressButton) {
6069+ sendSimulatedMouseEvent (QEvent::MouseButtonPress, QPoint (x, y), Qt::LeftButton, Qt::LeftButton);
6070+ }
60266071}
60276072
60286073// 通过x11从底层获取鼠标释放事件
@@ -6034,6 +6079,14 @@ void MainWindow::onMouseRelease(int x, int y)
60346079 if (status::record == m_functionType) {
60356080 showReleaseFeedback (x, y);
60366081 }
6082+
6083+ // 截图模式:与 onMousePress 对应——Dock Grab 导致释放事件也路由到 Dock,
6084+ // Qt event filter 收不到,工具栏无法显示。通过 XRecord 补发释放事件。
6085+ // 同样利用 QueuedConnection 时序避免重复:Qt 已处理则 isFirstReleaseButton
6086+ // 为 true,条件不成立;isFirstPressButton 为 true 确保有匹配的按下事件。
6087+ if (status::shot == m_functionType && isFirstPressButton && !isFirstReleaseButton) {
6088+ sendSimulatedMouseEvent (QEvent::MouseButtonRelease, QPoint (x, y), Qt::LeftButton, Qt::LeftButton);
6089+ }
60376090}
60386091
60396092// 通过x11从底层获取鼠标移动事件
@@ -6050,11 +6103,18 @@ void MainWindow::onMouseMove(int x, int y)
60506103 }
60516104 }
60526105
6053- // 启动截图或者录屏后第一次鼠标移动时需要通过此方法,后面都不会在进入此方法
6054- if (!isFirstMove) {
6055- QMouseEvent *mouseMove;
6056- mouseMove = new QMouseEvent (QEvent::MouseMove, QPoint (x, y), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
6057- QApplication::sendEvent (QWidget::focusWidget (), mouseMove);
6106+ // 截图悬停阶段(未开始框选)通过 XRecord 持续补发鼠标移动事件。
6107+ // Dock Grab 存在时 Qt 正常事件通路被阻断,XRecord 在协议层拦截不受影响。
6108+ // 拖拽阶段由 onMouseDrag 负责补发,此处只覆盖悬停阶段(!isFirstPressButton)。
6109+ // 非截图模式保持原有逻辑:仅补发第一次(!isFirstMove)。
6110+ // m_currentCursor 在 mouseMoveEF 开头被更新:坐标已匹配说明 Qt 正常处理过,
6111+ // 无需重复补发,避免正常情况下双重触发。
6112+ bool inShotHoverPhase = status::shot == m_functionType && !isFirstPressButton;
6113+ if (!isFirstMove || inShotHoverPhase) {
6114+ QPoint pos (x, y);
6115+ if (m_currentCursor != pos) {
6116+ sendSimulatedMouseEvent (QEvent::MouseMove, pos, Qt::NoButton, Qt::NoButton);
6117+ }
60586118 }
60596119}
60606120
0 commit comments