@@ -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,34 @@ 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+ QMouseEvent *mouseMove =
626+ new QMouseEvent (QEvent::MouseMove, this ->cursor ().pos (), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
627+ QApplication::sendEvent (this , mouseMove);
628+ delete mouseMove;
629+ }
630+ }
631+
614632void MainWindow::forceX11WindowPosition ()
615633{
616634#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
@@ -2268,6 +2286,7 @@ void MainWindow::topWindow()
22682286 this ->initLaunchMode (" screenShot" );
22692287 this ->showFullScreen ();
22702288 this ->initResource ();
2289+ refetchWindowInfo ();
22712290
22722291 // wayland 模式下不进入以下步骤
22732292 if (Utils::isWaylandMode) {
@@ -2486,7 +2505,8 @@ void MainWindow::savePath(const QString &path)
24862505 this ->initLaunchMode (" screenShot" );
24872506 this ->showFullScreen ();
24882507 this ->initResource ();
2489-
2508+ refetchWindowInfo ();
2509+
24902510 qCDebug (dsrApp) << " savePath end" ;
24912511}
24922512
@@ -2512,6 +2532,7 @@ void MainWindow::startScreenshotFor3rd(const QString &path)
25122532 this ->initLaunchMode (" screenShot" );
25132533 this ->showFullScreen ();
25142534 this ->initResource ();
2535+ refetchWindowInfo ();
25152536 m_shotWithPath = true ; // 自带路径
25162537 m_noNotify = true ; // 关闭通知
25172538 qCDebug (dsrApp) << " startScreenshotFor3rd end" ;
@@ -2525,6 +2546,7 @@ void MainWindow::noNotify()
25252546 this ->initLaunchMode (" screenShot" );
25262547 this ->showFullScreen ();
25272548 this ->initResource ();
2549+ refetchWindowInfo ();
25282550}
25292551
25302552void MainWindow::initBackground ()
@@ -6010,6 +6032,18 @@ void MainWindow::onMouseDrag(int x, int y)
60106032 if (status::record == m_functionType) {
60116033 showDragFeedback (x, y);
60126034 }
6035+
6036+ // 截图模式:拖拽阶段(按下左键后移动)XRecord 发出 mouseDrag 而非 mouseMove。
6037+ // Dock Grab 存在时 Qt event filter 收不到拖拽移动事件,框选区域无法更新。
6038+ // 同样用坐标去重避免正常情况下双重触发。
6039+ if (status::shot == m_functionType && isFirstPressButton && !isFirstReleaseButton) {
6040+ QPoint pos (x, y);
6041+ if (m_currentCursor != pos) {
6042+ QMouseEvent *mouseDrag = new QMouseEvent (QEvent::MouseMove, pos, Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
6043+ QApplication::sendEvent (this , mouseDrag);
6044+ delete mouseDrag;
6045+ }
6046+ }
60136047}
60146048
60156049// 通过x11从底层获取鼠标按压事件
@@ -6023,6 +6057,18 @@ void MainWindow::onMousePress(int x, int y)
60236057 } else if (m_initScroll && status::scrollshot == m_functionType) {
60246058 scrollShotMouseClickEvent (x, y);
60256059 }
6060+
6061+ // 截图模式:Dock 右键菜单持有 X11 Pointer Grab 时,按下事件会被路由到
6062+ // Dock 而非截图工具,Qt event filter 收不到。通过 XRecord 补发,确保截图
6063+ // 工具能正确进入拖拽状态(isFirstPressButton = true)。
6064+ // 利用 QueuedConnection 的时序:Qt 同步处理已在前,此处排队到后——若 Qt
6065+ // 已处理(isFirstPressButton == true),条件不成立,不重复触发。
6066+ if (status::shot == m_functionType && !isFirstPressButton) {
6067+ QMouseEvent *mousePress = new QMouseEvent (QEvent::MouseButtonPress, QPoint (x, y),
6068+ Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
6069+ QApplication::sendEvent (this , mousePress);
6070+ delete mousePress;
6071+ }
60266072}
60276073
60286074// 通过x11从底层获取鼠标释放事件
@@ -6034,6 +6080,17 @@ void MainWindow::onMouseRelease(int x, int y)
60346080 if (status::record == m_functionType) {
60356081 showReleaseFeedback (x, y);
60366082 }
6083+
6084+ // 截图模式:与 onMousePress 对应——Dock Grab 导致释放事件也路由到 Dock,
6085+ // Qt event filter 收不到,工具栏无法显示。通过 XRecord 补发释放事件。
6086+ // 同样利用 QueuedConnection 时序避免重复:Qt 已处理则 isFirstReleaseButton
6087+ // 为 true,条件不成立;isFirstPressButton 为 true 确保有匹配的按下事件。
6088+ if (status::shot == m_functionType && isFirstPressButton && !isFirstReleaseButton) {
6089+ QMouseEvent *mouseRelease = new QMouseEvent (QEvent::MouseButtonRelease, QPoint (x, y),
6090+ Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
6091+ QApplication::sendEvent (this , mouseRelease);
6092+ delete mouseRelease;
6093+ }
60376094}
60386095
60396096// 通过x11从底层获取鼠标移动事件
@@ -6050,11 +6107,20 @@ void MainWindow::onMouseMove(int x, int y)
60506107 }
60516108 }
60526109
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);
6110+ // 截图悬停阶段(未开始框选)通过 XRecord 持续补发鼠标移动事件。
6111+ // Dock Grab 存在时 Qt 正常事件通路被阻断,XRecord 在协议层拦截不受影响。
6112+ // 拖拽阶段由 onMouseDrag 负责补发,此处只覆盖悬停阶段(!isFirstPressButton)。
6113+ // 非截图模式保持原有逻辑:仅补发第一次(!isFirstMove)。
6114+ // m_currentCursor 在 mouseMoveEF 开头被更新:坐标已匹配说明 Qt 正常处理过,
6115+ // 无需重复补发,避免正常情况下双重触发。
6116+ bool inShotHoverPhase = status::shot == m_functionType && !isFirstPressButton;
6117+ if (!isFirstMove || inShotHoverPhase) {
6118+ QPoint pos (x, y);
6119+ if (m_currentCursor != pos) {
6120+ QMouseEvent *mouseMove = new QMouseEvent (QEvent::MouseMove, pos, Qt::NoButton, Qt::NoButton, Qt::NoModifier);
6121+ QApplication::sendEvent (this , mouseMove);
6122+ delete mouseMove;
6123+ }
60586124 }
60596125}
60606126
0 commit comments