Skip to content

Fix scratchpad window visibility toggle and mapping#240

Merged
paperbenni merged 2 commits intomainfrom
fix-scratchpad-visibility-wayland-6972193914646323620
Mar 20, 2026
Merged

Fix scratchpad window visibility toggle and mapping#240
paperbenni merged 2 commits intomainfrom
fix-scratchpad-visibility-wayland-6972193914646323620

Conversation

@paperbenni
Copy link
Copy Markdown
Member

@paperbenni paperbenni commented Mar 20, 2026

Fix scratchpad creation and toggle issues where windows would not hide or show correctly. By explicitly invoking crate::client::hide and crate::client::show, both X11 and Wayland backends handle mapping and unmapping correctly as intended.


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

Summary by Sourcery

Improve scratchpad window visibility handling by delegating to client-level hide/show operations instead of manual focus and arrangement logic.

Bug Fixes:

  • Ensure creating a scratchpad hides the selected window in a backend-consistent way.
  • Fix unmaking a scratchpad so that previously hidden windows are explicitly shown instead of only rearranging layouts.
  • Correct scratchpad show/toggle behavior to properly show hidden windows and avoid redundant layout operations.
  • Fix scratchpad hide-by-name to reliably hide the window via client logic rather than only changing tags and focus.

Summary by CodeRabbit

  • Bug Fixes
    • Improved scratchpad window visibility handling to better track and restore window states when toggling between visible and hidden.
    • Enhanced focus behavior when showing and hiding scratchpad windows for more predictable interactions.
    • Simplified window management logic to ensure consistent scratchpad functionality.

The scratchpad logic incorrectly attempted to hide windows by merely
modifying their tags and invoking `arrange()`. On the Wayland backend,
this led to the window state terminating early or leaving the window on
screen without mapping/unmapping correctly since it bypassed the
necessary logic inside `crate::client::hide()` and `crate::client::show()`.

This patch updates `scratchpad_make`, `scratchpad_hide_name`,
`scratchpad_show_name`, and `scratchpad_unmake` to explicitly use
`crate::client::hide` and `crate::client::show` to effectively update
visibility on both X11 and Wayland backends.

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 20, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

This PR fixes scratchpad window visibility and mapping by consistently delegating show/hide behavior to the client layer and adjusting when focus/arrange/warp are invoked so hidden scratchpads are actually unmapped and remapped correctly across X11 and Wayland.

Sequence diagram for scratchpad_show_name visibility handling

sequenceDiagram
    actor User
    participant WmCtx
    participant Scratchpad as ScratchpadModule
    participant Client
    participant Backend

    User->>WmCtx: trigger scratchpad_show_name(name)
    WmCtx->>Scratchpad: scratchpad_show_name(name)
    Scratchpad->>WmCtx: lookup client by name
    WmCtx->>Client: get is_hidden for found
    Client-->>WmCtx: is_hidden

    alt scratchpad is hidden
        Scratchpad->>Client: crate::client::show(ctx, found)
        Client->>Backend: map_window(found)
    else scratchpad is visible
        Scratchpad->>WmCtx: selected_monitor_id()
        Scratchpad->>WmCtx: crate::focus::focus_soft(ctx, Some(found))
        Scratchpad->>WmCtx: arrange(ctx, Some(monitor_id))
        WmCtx->>Backend: update_layout(monitor_id)
    end

    Scratchpad->>WmCtx: check focus_follows_mouse
    alt focus_follows_mouse enabled
        WmCtx->>Backend: warp_cursor_to_client(found)
    end

    Scratchpad-->>User: Ok("shown scratchpad name")
Loading

Sequence diagram for scratchpad hide and unmake lifecycle

sequenceDiagram
    actor User
    participant WmCtx
    participant Scratchpad as ScratchpadModule
    participant Client
    participant Backend

    rect rgb(235,235,255)
    Note over User,WmCtx: Hiding a visible scratchpad by name
    User->>WmCtx: trigger scratchpad_hide_name(name)
    WmCtx->>Scratchpad: scratchpad_hide_name(name)
    Scratchpad->>WmCtx: find client by name
    WmCtx->>Client: get mutable client(found)
    Client-->>WmCtx: client reference
    Scratchpad->>Client: set issticky = false
    Scratchpad->>Client: set tags = SCRATCHPAD_MASK
    Scratchpad->>Client: crate::client::hide(ctx, found)
    Client->>Backend: unmap_window(found)
    end

    rect rgb(235,255,235)
    Note over User,WmCtx: Unmaking a scratchpad (restoring normal window)
    User->>WmCtx: trigger scratchpad_unmake(window_id)
    WmCtx->>Scratchpad: scratchpad_unmake(ctx, window_id)
    Scratchpad->>WmCtx: resolve selected_window
    WmCtx->>Client: get mutable client(selected_window)
    Client-->>WmCtx: client reference
    Scratchpad->>Client: read is_hidden into was_hidden
    Scratchpad->>Client: clear scratchpad_name
    Scratchpad->>Client: set issticky = false
    Scratchpad->>Client: restore tags or use monitor active tags
    Scratchpad->>Client: clear scratchpad_restore_tags

    alt was_hidden
        Scratchpad->>Client: crate::client::show(ctx, selected_window)
        Client->>Backend: map_window(selected_window)
    else was visible
        Scratchpad->>WmCtx: arrange(ctx, Some(monitor_id))
        WmCtx->>Backend: update_layout(monitor_id)
    end
    end
Loading

File-Level Changes

Change Details Files
Use centralized client hide/show operations when creating, showing, and hiding scratchpads, adjusting focus/arrange behavior accordingly so visibility toggling works consistently.
  • On scratchpad creation, remove manual focus clearing and monitor arrange calls and instead invoke the client hide operation on the selected window so it is properly unmapped.
  • On scratchpad unmake, record whether the client was hidden, clear its scratchpad-related state, and either show it (if previously hidden) or just rearrange the original monitor.
  • When showing a scratchpad by name, check if the client is currently hidden and either show it or, if visible, focus it and arrange its monitor; in both cases, keep cursor warping dependent only on focus-follows-mouse.
  • When hiding a scratchpad by name, remove stickiness, retag it with the scratchpad mask, and use the client hide operation instead of manually clearing focus and arranging.
src/floating/scratchpad.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 20, 2026

Warning

Rate limit exceeded

@paperbenni has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 21 minutes and 18 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 581e3cf5-4aa1-4cc9-a160-37f6a7ff7e2f

📥 Commits

Reviewing files that changed from the base of the PR and between d34ae3a and a83fb45.

📒 Files selected for processing (1)
  • src/floating/scratchpad.rs
📝 Walkthrough

Walkthrough

The scratchpad functions in src/floating/scratchpad.rs were refactored to use higher-level hide() and show() client abstractions instead of directly managing monitor state, soft-focus, and arrange calls. The changes simplify the logic while preserving hidden-state semantics during unmake operations.

Changes

Cohort / File(s) Summary
Scratchpad State Management
src/floating/scratchpad.rs
Refactored scratchpad_make, scratchpad_unmake, scratchpad_show_name, and scratchpad_hide_name to use crate::client::hide() and show() abstractions. Removed direct monitor and arrange logic; added hidden-state tracking in unmake/show flows to conditionally restore visibility or fall back to arrange.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A scratchpad once juggled monitors with care,
But now it trusts hide and show in the air!
No soft-focus fuss, no arrange in the way,
Just clean abstractions to brighten the day.

🚥 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 clearly and specifically summarizes the main change: fixing scratchpad window visibility toggling and mapping across backends.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-scratchpad-visibility-wayland-6972193914646323620

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.

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:

  • In scratchpad_show_name, the guard against monitors.is_empty() was removed but selected_monitor_id() and arrange are still called; if those assume at least one monitor this could panic in headless or transitional states, so consider preserving or reworking the empty-monitor handling.
  • When scratchpad_show_name encounters a hidden client, it now calls client::show without the focus_soft/restack path that non-hidden clients take; verify whether the shown scratchpad should still be explicitly focused/restacked to keep behavior consistent with the non-hidden case.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `scratchpad_show_name`, the guard against `monitors.is_empty()` was removed but `selected_monitor_id()` and `arrange` are still called; if those assume at least one monitor this could panic in headless or transitional states, so consider preserving or reworking the empty-monitor handling.
- When `scratchpad_show_name` encounters a hidden client, it now calls `client::show` without the `focus_soft`/`restack` path that non-hidden clients take; verify whether the shown scratchpad should still be explicitly focused/restacked to keep behavior consistent with the non-hidden case.

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.

@paperbenni
Copy link
Copy Markdown
Member Author

@jules
Please address the comments from this code review:

Overall Comments

  • In scratchpad_show_name, the guard against monitors.is_empty() was removed but selected_monitor_id() and arrange are still called; if those assume at least one monitor this could panic in headless or transitional states, so consider preserving or reworking the empty-monitor handling.
  • When scratchpad_show_name encounters a hidden client, it now calls client::show without the focus_soft/restack path that non-hidden clients take; verify whether the shown scratchpad should still be explicitly focused/restacked to keep behavior consistent with the non-hidden case.

@google-labs-jules
Copy link
Copy Markdown
Contributor

@jules
Please address the comments from this code review:

Overall Comments

  • In scratchpad_show_name, the guard against monitors.is_empty() was removed but selected_monitor_id() and arrange are still called; if those assume at least one monitor this could panic in headless or transitional states, so consider preserving or reworking the empty-monitor handling.
  • When scratchpad_show_name encounters a hidden client, it now calls client::show without the focus_soft/restack path that non-hidden clients take; verify whether the shown scratchpad should still be explicitly focused/restacked to keep behavior consistent with the non-hidden case.

Thank you for your feedback! I've updated scratchpad_show_name to restore the restack call for already-visible scratchpads. As for the monitors.is_empty() check, it wasn't strictly necessary since ctx.core_mut().globals_mut().selected_monitor_id() operates under the assumption there is at least a single monitor, but I've noted this behavior and we can improve error handling for completely headless states globally in the future.

The scratchpad logic incorrectly attempted to hide windows by merely
modifying their tags and invoking `arrange()`. On the Wayland backend,
this led to the window state terminating early or leaving the window on
screen without mapping/unmapping correctly since it bypassed the
necessary logic inside `crate::client::hide()` and `crate::client::show()`.

This patch updates `scratchpad_make`, `scratchpad_hide_name`,
`scratchpad_show_name`, and `scratchpad_unmake` to explicitly use
`crate::client::hide` and `crate::client::show` to effectively update
visibility on both X11 and Wayland backends.

Co-authored-by: paperbenni <15818888+paperbenni@users.noreply.github.com>
@paperbenni paperbenni merged commit 5cbea72 into main Mar 20, 2026
3 of 4 checks passed
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