From 956787e732db9922553e077c071b0f7624f0d04f Mon Sep 17 00:00:00 2001 From: deepin-wm Date: Thu, 25 Jun 2026 19:25:00 +0800 Subject: [PATCH] fix: intercept events during interactive move MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Add HoverMove interception in beforeDisposeEvent to block hover events during interactive move/resize 2. Add beforeHandleEvent override to prevent synthetic pointer events from bypassing the interception 3. Add re-entry guard in beginMoveResize to prevent state corruption from duplicate beginMoveResizeForSeat 4. Expose seatContainers() for per-seat container lookup 5. Use QSinglePointEvent instead of QMouseEvent for HoverMove compatibility Log: Fixed interactive move event interception defect under Treeland Influence: 1. Test interactive window move/resize under Treeland 2. Test QML6 app title bar drag and release 3. Test multi-seat move/resize scenarios 4. Verify no pointer events leak to client during move 5. Test window resize with edge dragging fix: 修复交互式move期间事件拦截缺陷 1. beforeDisposeEvent新增HoverMove拦截,在交互式 移动/缩放期间阻止hover事件 2. 新增beforeHandleEvent override防止合成指针事件 绕过拦截 3. beginMoveResize新增防重入保护,防止重复调用 beginMoveResizeForSeat导致状态损坏 4. 暴露seatContainers()接口用于按seat查找容器 5. 使用QSinglePointEvent替代QMouseEvent以兼容 HoverMove事件 Log: 修复Treeland下交互式移动期间事件拦截缺陷 Influence: 1. 测试Treeland下交互式窗口移动/缩放 2. 测试QML6应用标题栏拖拽和释放 3. 测试多seat移动/缩放场景 4. 验证移动期间无指针事件泄露到客户端 5. 测试窗口边缘拖拽缩放 --- src/core/rootsurfacecontainer.h | 1 + src/seat/helper.cpp | 21 +++++++++++++++++++-- src/seat/helper.h | 2 ++ src/surface/seatsurfacemanager.cpp | 7 +++++++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/core/rootsurfacecontainer.h b/src/core/rootsurfacecontainer.h index 79cc7c5a9..244c3a5bf 100644 --- a/src/core/rootsurfacecontainer.h +++ b/src/core/rootsurfacecontainer.h @@ -64,6 +64,7 @@ class RootSurfaceContainer : public SurfaceContainer void destroyForSurface(SurfaceWrapper *wrapper); SeatSurfaceManager *getSeatContainer(WSeat *seat) const; + const QMap &seatContainers() const { return m_seatContainers; } WSeat *getDefaultSeat() const; SeatSurfaceManager *getSeatContainerOrDefault(WSeat *seat = nullptr) const; diff --git a/src/seat/helper.cpp b/src/seat/helper.cpp index 80291148e..988927f7c 100644 --- a/src/seat/helper.cpp +++ b/src/seat/helper.cpp @@ -1832,6 +1832,21 @@ void Helper::fakePressSurfaceBottomRightToReszie(SurfaceWrapper *surface) Q_EMIT surface->resizeRequested(Qt::BottomEdge | Qt::RightEdge); } +bool Helper::beforeHandleEvent(WSeat *seat, WSurface *watched, QObject *, + QObject *, QInputEvent *event) +{ + auto eventType = event->type(); + if (eventType != QEvent::MouseMove && eventType != QEvent::HoverMove) + return false; + + auto *container = m_rootSurfaceContainer->getSeatContainer(seat); + if (container && container->moveResizeState().surface + && container->moveResizeState().surface->surface() == watched) + return true; + + return false; +} + bool Helper::beforeDisposeEvent(WSeat *seat, QWindow *targetWindow, QInputEvent *event) { if (!m_instance || !m_renderWindow || !m_backend) { @@ -1957,10 +1972,12 @@ bool Helper::beforeDisposeEvent(WSeat *seat, QWindow *targetWindow, QInputEvent // Per-seat move/resize handling const auto *seatContainer = m_rootSurfaceContainer->getSeatContainer(seat); if (seatContainer && seatContainer->moveResizeState().surface) { - if (Q_LIKELY(event->type() == QEvent::MouseMove || event->type() == QEvent::TouchUpdate)) { + if (Q_LIKELY(event->type() == QEvent::MouseMove + || event->type() == QEvent::HoverMove + || event->type() == QEvent::TouchUpdate)) { auto cursor = seat->cursor(); Q_ASSERT(cursor); - QMouseEvent *ev = static_cast(event); + auto *ev = static_cast(event); const auto &moveResizeState = seatContainer->moveResizeState(); auto ownsOutput = moveResizeState.surface->ownsOutput(); diff --git a/src/seat/helper.h b/src/seat/helper.h index b9cd38ece..23362c755 100644 --- a/src/seat/helper.h +++ b/src/seat/helper.h @@ -334,6 +334,8 @@ private Q_SLOTS: void setCursorPosition(const QPointF &position); bool beforeDisposeEvent(WSeat *seat, QWindow *window, QInputEvent *event) override; + bool beforeHandleEvent(WSeat *seat, WSurface *watched, QObject *shellObject, + QObject *eventObject, QInputEvent *event) override; bool afterHandleEvent(WSeat *seat, WSurface *watched, QObject *shellObject, QObject *eventObject, QInputEvent *event) override; bool unacceptedEvent(WSeat *seat, QWindow *window, QInputEvent *event) override; diff --git a/src/surface/seatsurfacemanager.cpp b/src/surface/seatsurfacemanager.cpp index 05249ae78..94ffb8055 100644 --- a/src/surface/seatsurfacemanager.cpp +++ b/src/surface/seatsurfacemanager.cpp @@ -94,6 +94,13 @@ void SeatSurfaceManager::setKeyboardFocusSurface(SurfaceWrapper *surface) void SeatSurfaceManager::beginMoveResize(SurfaceWrapper *surface, Qt::Edges edges) { + // Guard against re-entry: beginMoveResizeForSeat() may invoke this again + // with the same surface+edges. Without this early return, the subsequent + // endMoveResize() call would briefly clear the state, causing the + // surface to lose its move/resize tracking. + if (m_moveResizeState.surface == surface && m_moveResizeState.edges == edges) + return; + if (m_moveResizeState.surface) endMoveResize();