fix(xwayland): sync cursor global position to X server - #1430
Conversation
Reviewer's GuideHooks each WXWayland instance to the seat cursor’s positionChanged signal and uses xcb_warp_pointer on the Xwayland root window to keep XQueryPointer and similar clients up to date while the cursor is over native Wayland surfaces. Sequence diagram for synchronizing the cursor position with XwaylandsequenceDiagram
participant Cursor as WCursor
participant Shell as ShellHandler
participant XWayland as WXWayland
participant XServer as XServer
participant Client as XClient
Cursor->>Shell: positionChanged
Shell->>XWayland: xcbConnection()
Shell->>XWayland: xcbScreen()
Shell->>XServer: xcb_warp_pointer(root, qRound(pos.x()), qRound(pos.y()))
Shell->>XServer: xcb_flush()
Client->>XServer: XQueryPointer()
XServer-->>Client: Current global cursor position
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="src/core/shellhandler.cpp" line_range="549-563" />
<code_context>
return xwayland;
}
+void ShellHandler::syncXWaylandCursorPosition(WXWayland *xwayland, const QPointF &pos)
+{
+ auto *connection = xwayland->xcbConnection();
+ auto *screen = xwayland->xcbScreen();
+ if (!connection || !screen)
+ return;
+
+ // Warp the X pointer to the real cursor position. This only changes the
+ // X server's pointer state, not the real cursor. Warping to the current
+ // position is a no-op, so it is also safe while the pointer is over an
+ // Xwayland surface (Xwayland already tracks the position in that case).
+ xcb_warp_pointer(connection, XCB_NONE, screen->root,
+ 0, 0, 0, 0, qRound(pos.x()), qRound(pos.y()));
+ xcb_flush(connection);
+}
+
void ShellHandler::removeXWayland(WXWayland *xwayland)
</code_context>
<issue_to_address>
**issue (bug_risk):** The function passes the compositor cursor's layout coordinates directly to `xcb_warp_pointer`, although the Xwayland desktop geometry can use scaled output coordinates. When an output has a scale or scale override different from 1, X clients receive a pointer position that is offset/scaled incorrectly instead of the real global position.
**Triggers:** When the Xwayland output geometry is scaled relative to the compositor output geometry, as indicated by the existing `outputGeometry`/`treelandGeometry` scaling in `updateXWaylandDesktopProperties`.
**Suggested fix:** Transform the cursor position from the compositor layout coordinate space into Xwayland's global coordinate space, applying the relevant output scale and offset before warping.
</issue_to_address>7c5ad68 to
f846e32
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
空 seat 和服务重启路径仍会导致崩溃或同步失效 / Null-seat and server-restart paths can still crash or disable synchronization.
Review effort: Balanced
Findings: 1
Open (1)
What changed in this PR
该 PR 在现有 WXWayland wrapper 中同步 Wayland 光标位置到 Xwayland;wlroots 提供原生实现,Treeland 通过 ShellHandler 接入。
This PR synchronizes the Wayland cursor position to Xwayland within the existing WXWayland wrapper.
Changes:
- 监听
WCursor::positionChanged并通过 XCB 更新坐标 / Watches cursor movement and updates X coordinates through XCB. - seat 切换及 Xwayland ready 时重新绑定和同步 / Rebinds and synchronizes on seat changes and Xwayland readiness.
| File | Description |
|---|---|
waylib/src/server/protocols/wxwayland.cpp |
添加 Xwayland 光标坐标同步 / Adds Xwayland cursor-coordinate synchronization. |
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
f846e32 to
92587c0
Compare
92587c0 to
1583d90
Compare
Xwayland only learns the pointer position from wl_pointer events while the pointer is over an X window. When the cursor moves over a native Wayland surface, X clients querying the global cursor position (e.g. via XQueryPointer) keep seeing stale coordinates, which breaks X windows that rely on them. Follow the same approach as the keyboard modifiers sync: do it inside WXWayland. Watch the seat cursor's positionChanged, rebind on setSeat(), and warp the X pointer through the existing xwm connection on every cursor move. When the pointer is over an Xwayland surface the position already matches, so the warp is a no-op. Log: 同步光标全局坐标到 Xwayland,使依赖光标全局坐标的 X window 表现正常
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: deepin-wm, zccrs 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 |

参照 #1426 的做法,直接在 WXWayland(waylib)里实现,无需 compositor 层介入。
问题
Xwayland 只在指针位于 X 窗口上时通过
wl_pointer事件获知指针位置。当光标移动到原生 Wayland 窗口上时,X 侧的全局指针坐标停留在离开 X 窗口时的旧值,依赖全局坐标的 X window(如XQueryPointer的调用方)表现异常。修复
waylib/src/server/protocols/wxwayland.cpp(+71):positionChanged,光标移动时通过现有 xwm 连接xcb_warp_pointer将 X 指针同步到真实光标位置;setSeat()切换 seat 时重新绑定;events.ready后同步一次初始位置(seat 可能先于 Xwayland 启动设置);Log: 同步光标全局坐标到 Xwayland,使依赖光标全局坐标的 X window 表现正常
Summary by Sourcery
Keep Xwayland pointer coordinates synchronized with the actual cursor position.
Bug Fixes:
Enhancements: