Skip to content

Conversation

@calsys456
Copy link
Collaborator

@calsys456 calsys456 commented Jan 7, 2026

For the requirement of DDE.

Summary by Sourcery

Expose a compositor helper and DDE shell protocol request to move an XWayland window relative to a given Wayland surface.

New Features:

  • Add Helper::moveXWaylandSurface API to reposition an XWayland window based on an anchor WSurface and offset.
  • Extend treeland_dde_shell_manager_v1 with a move_xwayland_surface request that invokes the helper and returns completion status via a wl_callback.

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: calsys456

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sourcery-ai
Copy link

sourcery-ai bot commented Jan 7, 2026

Reviewer's Guide

Adds a Helper API and Wayland DDE shell protocol entry point to move an XWayland window to a position relative to a given wl_surface, and wires it to return a completion callback to the client.

Sequence diagram for moving an XWayland surface relative to a wl_surface

sequenceDiagram
    actor DDEClient
    participant WlClient as wl_client
    participant DDEShellMgr as DDEShellManagerInterfaceV1Private
    participant Helper as Helper
    participant RootContainer as RootSurfaceContainer
    participant Wrapper as SurfaceWrapper
    participant XWaylandSurf as qw_xwayland_surface

    DDEClient->>WlClient: treeland_dde_shell_manager_v1_move_xwayland_surface(callback_id, wid, anchor, dx, dy)
    WlClient->>DDEShellMgr: treeland_dde_shell_manager_v1_move_xwayland_surface(resource, callback, wid, anchor, dx, dy)

    DDEShellMgr->>DDEShellMgr: WSurface::fromHandle(qw_surface::from_resource(anchor))
    DDEShellMgr->>Helper: moveXWaylandSurface(wid, wsurface, dx, dy)
    activate Helper
    Helper->>RootContainer: rootSurfaceContainer()->getSurface(anchor)
    RootContainer-->>Helper: SurfaceWrapper for anchor
    Helper->>Helper: pos = wrapper->position().toPoint()

    loop iterate_root_surfaces
        Helper->>RootContainer: rootSurfaceContainer()->surfaces()
        RootContainer-->>Helper: SurfaceWrapper list
        Helper->>Wrapper: type()
        alt wrapper_is_XWayland
            Helper->>Wrapper: surface()->handle()->handle()
            Helper->>XWaylandSurf: try_from_wlr_surface(wlr_surface)
            alt window_id_matches_wid
                Helper-->>Helper: select surface
                Helper-->>Helper: break
            end
        end
    end

    alt surface_found
        Helper->>XWaylandSurf: configure(clamped_x, clamped_y, width, height)
        Helper-->>DDEShellMgr: true
    else surface_not_found
        Helper-->>DDEShellMgr: false
    end
    deactivate Helper

    DDEShellMgr->>DDEShellMgr: wl_resource_create(callback)
    DDEShellMgr->>DDEClient: wl_callback_send_done(ok)
    DDEShellMgr->>DDEShellMgr: wl_resource_destroy(callback)
Loading

Updated class diagram for Helper XWayland movement and DDE shell manager

classDiagram
    class Helper {
        +static Helper* instance()
        +bool moveXWaylandSurface(uint wid, WSurface* anchor, int dx, int dy)
        -RootSurfaceContainer* m_rootSurfaceContainer
    }

    class RootSurfaceContainer {
        +SurfaceWrapper* getSurface(WSurface* surface)
        +QList~SurfaceWrapper*~ surfaces()
    }

    class SurfaceWrapper {
        <<enumeration>> Type
        +Type type()
        +WSurface* surface()
        +QPointF position()
        Type XWayland
    }

    class qw_xwayland_surface {
        +static qw_xwayland_surface* try_from_wlr_surface(wlr_surface* surface)
        +void configure(int x, int y, int width, int height)
        +qw_xwayland_surface_handle* handle()
    }

    class qw_xwayland_surface_handle {
        +int16_t width
        +int16_t height
        +xcb_window_t window_id
    }

    class DDEShellManagerInterfaceV1Private {
        +void treeland_dde_shell_manager_v1_move_xwayland_surface(Resource* resource, uint32_t callback, uint32_t wid, wl_resource* anchor, int32_t dx, int32_t dy)
    }

    class WSurface {
        +static WSurface* fromHandle(qw_surface* surface)
    }

    class qw_surface {
        +static qw_surface* from_resource(wl_resource* resource)
    }

    Helper --> RootSurfaceContainer : uses
    RootSurfaceContainer --> SurfaceWrapper : returns
    SurfaceWrapper --> qw_xwayland_surface : converted via wlr_surface
    qw_xwayland_surface --> qw_xwayland_surface_handle : has
    DDEShellManagerInterfaceV1Private --> Helper : calls_moveXWaylandSurface
    DDEShellManagerInterfaceV1Private --> WSurface : uses_fromHandle
    WSurface --> qw_surface : constructed_from
    qw_surface --> wl_resource : wraps
Loading

File-Level Changes

Change Details Files
Expose a Helper method to move an XWayland surface relative to an anchor WSurface and implement the movement logic.
  • Add moveXWaylandSurface signature to Helper and declare parameters for X window id, anchor surface, and offsets.
  • Implement moveXWaylandSurface to resolve the anchor surface position, iterate over root surfaces to find the matching XWayland surface by window id, and log and fail if not found.
  • Configure the found XWayland surface to the new position using dx/dy offsets relative to the anchor and clamp coordinates to int16 bounds while preserving size.
src/seat/helper.h
src/seat/helper.cpp
Extend the DDE shell manager v1 protocol implementation with a request to move XWayland surfaces and respond via wl_callback.
  • Include Helper and Wayland server headers in the DDEShellManagerInterfaceV1 implementation.
  • Add treeland_dde_shell_manager_v1_move_xwayland_surface virtual override to the private interface class to handle the new protocol request.
  • Implement the handler to convert the wl_resource anchor to WSurface, invoke Helper::moveXWaylandSurface, and reply to the client with a wl_callback containing a success/failure code.
  • Wire the callback id from the request into wl_resource_create and ensure the callback resource is destroyed after sending done.
src/modules/dde-shell/ddeshellmanagerinterfacev1.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@calsys456
Copy link
Collaborator Author

Related with linuxdeepin/treeland-protocols#36

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues, and left some high level feedback:

  • In Helper::moveXWaylandSurface, several pointer dereferences assume non-null (e.g., m_rootSurfaceContainer->getSurface(anchor), wrapper->surface()->handle()->handle(), xwaylandSurface->handle()); consider adding null checks so that a missing or mismatched surface can’t cause a crash.
  • treeland_dde_shell_manager_v1_move_xwayland_surface assumes the passed wl_resource* anchor is valid and corresponds to a WSurface; adding validation (including handling a null/invalid resource and fromHandle() failures) would make the protocol handler more robust against misbehaving clients.
  • The wl_callback used to return the status sends the raw ok value as the done timestamp; if the protocol intends this as a status code rather than a time, consider documenting this or using a more conventional success/error signaling mechanism to avoid confusion with standard wl_callback semantics.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In Helper::moveXWaylandSurface, several pointer dereferences assume non-null (e.g., m_rootSurfaceContainer->getSurface(anchor), wrapper->surface()->handle()->handle(), xwaylandSurface->handle()); consider adding null checks so that a missing or mismatched surface can’t cause a crash.
- treeland_dde_shell_manager_v1_move_xwayland_surface assumes the passed wl_resource* anchor is valid and corresponds to a WSurface; adding validation (including handling a null/invalid resource and fromHandle() failures) would make the protocol handler more robust against misbehaving clients.
- The wl_callback used to return the status sends the raw ok value as the done timestamp; if the protocol intends this as a status code rather than a time, consider documenting this or using a more conventional success/error signaling mechanism to avoid confusion with standard wl_callback semantics.

## Individual Comments

### Comment 1
<location> `src/seat/helper.cpp:2902` </location>
<code_context>
+ */
+bool Helper::moveXWaylandSurface(uint wid, WSurface *anchor, int dx, int dy)
+{
+    QPoint pos = m_rootSurfaceContainer->getSurface(anchor)->position().toPoint();
+    qw_xwayland_surface *surface = nullptr;
+    for (SurfaceWrapper *wrapper : std::as_const(rootSurfaceContainer()->surfaces())) {
</code_context>

<issue_to_address>
**issue (bug_risk):** Guard against a missing surface for the given anchor to avoid potential null dereference.

If `getSurface(anchor)` can return `nullptr` (e.g. when the anchor is destroyed or not in `m_rootSurfaceContainer`), this will dereference a null pointer and crash. Store the result of `getSurface(anchor)` in a local variable, check it for null, and return early or log instead of calling `position()` unconditionally.
</issue_to_address>

### Comment 2
<location> `src/seat/helper.cpp:2907-2908` </location>
<code_context>
+    for (SurfaceWrapper *wrapper : std::as_const(rootSurfaceContainer()->surfaces())) {
+        if (wrapper->type() == SurfaceWrapper::Type::XWayland) {
+            wlr_surface *wlrSurface = wrapper->surface()->handle()->handle();
+            qw_xwayland_surface *xwaylandSurface = qw_xwayland_surface::try_from_wlr_surface(wlrSurface);
+            if (xwaylandSurface->handle()->window_id == static_cast<xcb_window_t>(wid)) {
+                surface = xwaylandSurface;
+                break;
</code_context>

<issue_to_address>
**issue (bug_risk):** Check the result of `try_from_wlr_surface` before dereferencing its handle.

If `try_from_wlr_surface` returns `nullptr`, dereferencing `xwaylandSurface->handle()` will crash. Add a null check (e.g. `if (!xwaylandSurface) continue;`) before accessing `window_id`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

*/
bool Helper::moveXWaylandSurface(uint wid, WSurface *anchor, int dx, int dy)
{
QPoint pos = m_rootSurfaceContainer->getSurface(anchor)->position().toPoint();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Guard against a missing surface for the given anchor to avoid potential null dereference.

If getSurface(anchor) can return nullptr (e.g. when the anchor is destroyed or not in m_rootSurfaceContainer), this will dereference a null pointer and crash. Store the result of getSurface(anchor) in a local variable, check it for null, and return early or log instead of calling position() unconditionally.

Comment on lines +2907 to +2908
qw_xwayland_surface *xwaylandSurface = qw_xwayland_surface::try_from_wlr_surface(wlrSurface);
if (xwaylandSurface->handle()->window_id == static_cast<xcb_window_t>(wid)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Check the result of try_from_wlr_surface before dereferencing its handle.

If try_from_wlr_surface returns nullptr, dereferencing xwaylandSurface->handle() will crash. Add a null check (e.g. if (!xwaylandSurface) continue;) before accessing window_id.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants