Skip to content

Fix cursor visibility over windows in winit backend#236

Merged
paperbenni merged 1 commit intomainfrom
fix-winit-cursor-z-order-10457518865414828820
Mar 18, 2026
Merged

Fix cursor visibility over windows in winit backend#236
paperbenni merged 1 commit intomainfrom
fix-winit-cursor-z-order-10457518865414828820

Conversation

@paperbenni
Copy link
Copy Markdown
Member

@paperbenni paperbenni commented Mar 18, 2026

This PR fixes an issue where the mouse cursor becomes invisible when hovering over windows in the winit (nested) Wayland backend.

The root cause was that in src/wayland/render/winit.rs, the cursor elements were being appended to the render_elements array after the window and scene elements were appended. Because Smithay processes these render elements in a front-to-back (top-to-bottom) order, this meant the cursor was being rendered at the bottom of the z-index stack, behind the windows.

By moving the call to render_cursor_overlays to happen before the assemble_scene_elements! macro, the cursor elements are now the first ones in the array, correctly rendering them on top of everything else. The array capacity pre-allocation was also slightly bumped (+2) to account for these extra elements.


PR created automatically by Jules for task 10457518865414828820 started by @paperbenni

Summary by Sourcery

Ensure cursors render above windows in the winit Wayland backend by adjusting render element ordering and capacity preallocation.

Bug Fixes:

  • Fix invisible mouse cursor when hovering over windows in the nested winit Wayland backend.

Enhancements:

  • Increase preallocated render element capacity to account for cursor overlay elements.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed cursor overlay rendering order to ensure proper visual layering and presentation consistency.

Move `render_cursor_overlays` before `assemble_scene_elements!` in the winit backend renderer so that the cursor elements are pushed into the render elements vector first. Smithay processes these front-to-back, so appending them first ensures the cursor is drawn on top of windows instead of being hidden behind them. Also slightly increased the vector capacity pre-allocation to account for the cursor elements.

Co-authored-by: paperbenni <15818888+paperbenni@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Mar 18, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adjusts the winit Wayland backend’s render ordering so cursor overlays are pushed into the render_elements list before scene/window elements, ensuring cursors are drawn on top, and slightly increases the pre-allocation capacity to account for the extra elements.

Sequence diagram for updated winit render_frame cursor ordering

sequenceDiagram
    participant RenderFrame
    participant Renderer
    participant CursorPresentation
    participant SceneAssembler
    participant DamageTracker

    RenderFrame->>RenderFrame: get_render_element_counts(scene, space_render_elements_len, num_upper)
    RenderFrame->>RenderFrame: render_elements = Vec_with_capacity(counts_total_plus_2)

    RenderFrame->>Renderer: render_cursor_overlays(renderer, cursor_presentation, pointer_current_location, render_elements_mut)
    Renderer->>CursorPresentation: read_cursor_and_dnd_surfaces
    CursorPresentation-->>Renderer: cursor_overlay_elements
    Renderer-->>RenderFrame: append_cursor_overlays_to_render_elements

    RenderFrame->>SceneAssembler: assemble_scene_elements(scene, space_render_elements, num_upper, render_elements_mut)
    SceneAssembler-->>RenderFrame: append_window_and_scene_elements

    RenderFrame->>DamageTracker: render_output(renderer, render_elements, output, age)
    DamageTracker-->>RenderFrame: render_result
Loading

File-Level Changes

Change Details Files
Ensure cursor overlays render above windows by changing render_elements construction order in the winit Wayland backend.
  • Increase render_elements vector capacity from counts.total() to counts.total() + 2 to account for cursor elements that are now added earlier
  • Invoke render_cursor_overlays immediately after computing counts and before assembling scene elements, so cursor-related render elements come first in the list
  • Remove the previous call to render_cursor_overlays that occurred after assemble_scene_elements, preventing cursors from being placed behind windows in front-to-back rendering
src/wayland/render/winit.rs

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

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 18, 2026

📝 Walkthrough

Walkthrough

Reorders cursor overlay rendering in Wayland window management to execute before scene assembly instead of after. Increases render_elements pre-allocation capacity by 2 and repositions the explicit backend-specific overlay rendering call, modifying control flow for z-order handling.

Changes

Cohort / File(s) Summary
Cursor Overlay Rendering Reordering
src/wayland/render/winit.rs
Moves cursor overlay computation and rendering to occur before scene element assembly. Increments render_elements capacity by 2, removes post-assembly overlay rendering, and adds upfront comment documentation for the rendering step.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 minutes

Poem

🐰 Whiskers twitch with rendering glee,
Cursors dance before we see,
Reordered overlays, so bright,
Z-order flows just right,
Hop-hop-hop, the frames take flight!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly addresses the main fix: reordering cursor overlay rendering to ensure visibility over windows in the winit backend.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-winit-cursor-z-order-10457518865414828820
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can validate your CodeRabbit configuration file in your editor.

If your editor has YAML language server, you can enable auto-completion and validation by adding # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json at the top of your CodeRabbit configuration file.

Copy link
Copy Markdown

@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 left some high level feedback:

  • The + 2 in Vec::with_capacity(counts.total() + 2) is a bit of a magic number; consider either deriving this from the number of potential cursor overlays or adding a short comment explaining why 2 is sufficient.
  • Since this change relies on cursor elements being processed first in render_elements for correct z-ordering, consider adding a brief comment near render_cursor_overlays explaining that it must be called before assemble_scene_elements! to keep cursors on top.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `+ 2` in `Vec::with_capacity(counts.total() + 2)` is a bit of a magic number; consider either deriving this from the number of potential cursor overlays or adding a short comment explaining why `2` is sufficient.
- Since this change relies on cursor elements being processed first in `render_elements` for correct z-ordering, consider adding a brief comment near `render_cursor_overlays` explaining that it must be called before `assemble_scene_elements!` to keep cursors on top.

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/wayland/render/winit.rs (1)

62-62: Consider making the cursor capacity hint data-driven.

+ 2 at Line 62 is safe, but surface-tree cursors can produce more than two elements. If you want to avoid avoidable reallocations on hot paths, prebuild overlays into a temporary vec and size render_elements with counts.total() + cursor_elements.len().

♻️ Optional refactor
-    let mut render_elements = Vec::with_capacity(counts.total() + 2);
-
-    // Backend-specific: render cursor overlays (client surface cursors and DnD icons)
-    render_cursor_overlays(
-        renderer,
-        &cursor_presentation,
-        state.pointer.current_location(),
-        &mut render_elements,
-    );
+    let mut cursor_elements = Vec::new();
+    // Backend-specific: render cursor overlays (client surface cursors and DnD icons)
+    render_cursor_overlays(
+        renderer,
+        &cursor_presentation,
+        state.pointer.current_location(),
+        &mut cursor_elements,
+    );
+    let mut render_elements =
+        Vec::with_capacity(counts.total() + cursor_elements.len());
+    render_elements.extend(cursor_elements);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/wayland/render/winit.rs` at line 62, The allocation for render_elements
uses a fixed "+ 2" buffer which can under-estimate surface-tree cursor overlays;
before creating render_elements, prebuild the cursor/overlay elements into a
temporary Vec (e.g., cursor_elements) and then allocate render_elements with
Vec::with_capacity(counts.total() + cursor_elements.len()), then extend or
append cursor_elements into render_elements when populating; update the code
around the render_elements allocation (the render_elements variable and any
cursor/overlay construction logic) to compute cursor_elements first and use its
length for the capacity hint to avoid unnecessary reallocations.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/wayland/render/winit.rs`:
- Line 62: The allocation for render_elements uses a fixed "+ 2" buffer which
can under-estimate surface-tree cursor overlays; before creating
render_elements, prebuild the cursor/overlay elements into a temporary Vec
(e.g., cursor_elements) and then allocate render_elements with
Vec::with_capacity(counts.total() + cursor_elements.len()), then extend or
append cursor_elements into render_elements when populating; update the code
around the render_elements allocation (the render_elements variable and any
cursor/overlay construction logic) to compute cursor_elements first and use its
length for the capacity hint to avoid unnecessary reallocations.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d8da9ae1-e518-4ba2-af80-4234a021718d

📥 Commits

Reviewing files that changed from the base of the PR and between 2a9fcd1 and 6c11548.

📒 Files selected for processing (1)
  • src/wayland/render/winit.rs

@paperbenni paperbenni merged commit 290f16d into main Mar 18, 2026
5 checks passed
@paperbenni paperbenni deleted the fix-winit-cursor-z-order-10457518865414828820 branch March 18, 2026 15:27
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.

1 participant