Skip to content

fix(wm): stop treating ShowWindow's return value as an error - #1833

Merged
eythaann merged 1 commit into
eythaann:masterfrom
z1pp090:fix/wm-skip-failed-window
Sep 21, 2026
Merged

eythaann merged 1 commit into
eythaann:masterfrom
z1pp090:fix/wm-skip-failed-window

Conversation

@z1pp090

@z1pp090 z1pp090 commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

Symptom

Every now and then the tiling overlay draws the borders of the new layout (e.g. three tiles) on top of a window that still fills the whole monitor, even though that window is not maximized. Minimizing anything, or any other tree change, snaps everything back into place. Seen here on 2.8.6 twice (Sep 15 and Sep 19), always logged from the window-manager widget as an unhandled rejection of SetAppWindowsPositions with an unrelated error code: 0x8007006D "The pipe has been ended", 0x80070057 "The parameter is incorrect".

Root cause

WindowsApi::show_window did ShowWindow(...).ok(). ShowWindow's return value is the window's previous visibility, not a success flag (the comment above it already said so): for a window that was hidden it returns FALSE, and .ok() then builds an error from whatever stale value the thread's last-error slot holds — hence the pipe/parameter codes coming from unrelated calls on the same tokio worker. desired_rect_for calls show_window(SW_NORMAL) to un-maximize a window before placing it, and the ? in set_app_windows_positions aborted the whole batch on that phantom error. The tree and the overlay already reflected the new layout, so every window stayed at its old rect; a window that used to be alone on the monitor keeps its full-size rect under the new borders, which is exactly what the user sees.

Fix

  • WindowsApi::show_window / show_window_async: clear the thread error state before the call and only fail when there is a real error after a FALSE return (the documented way to detect an invalid handle).
  • set_app_windows_positions: resolve every window before placing any. Windows that no longer exist are skipped silently (they can be destroyed between the render and this call); any other failure is logged, the remaining windows are still placed, and the first error is returned afterwards so it stays observable.

Tested

Debug build on Windows 11 with two monitors: tiling, maximize → WM pause, restore → re-tile, no errors or warnings from the window manager. The original race (hidden window in a batch) is not reproduced deliberately, but the log evidence and the ShowWindow contract match. cargo test, clippy and rustfmt clean.

🤖 Generated with Claude Code

@greptile-apps

greptile-apps Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

The PR should not merge until skipped errors are restricted to stale windows or failures affecting live windows remain observable.

Summary

This PR changes batch window positioning to continue when one window's desired rectangle cannot be resolved.

  • Successfully resolved windows are still submitted for positioning.
  • Failed entries are skipped with a debug log.
  • The error handling is currently broader than the destroyed-window race it intends to tolerate.

Reviews (1) · Last reviewed commit: "fix(wm): don't abort a layout render whe..."

@z1pp090 z1pp090 changed the title fix(wm): don't abort a layout render when one window fails to resolve fix(wm): stop treating ShowWindow's return value as an error Sep 19, 2026

@eythaann eythaann left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

remove changes done at src/background/widgets/window_manager/handler.rs the other fix is fine.

@eythaann eythaann Sep 20, 2026 •

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

remove this file changes, on windows destroy the layout set positions will be triggered again (the issue u are trying to solve will still move the windows to the old layout before the window destroyed event) so is completely unnecessary, also doesn't matter having a really rare log error for this, is expected behavior.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done, thanks for the explanation. Dropped the handler.rs changes entirely and squashed the branch into a single commit that only touches show_window / show_window_async in windows_api/mod.rs (2321f04).

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

this is fine, LOL, this issue is here since who knows.

Root cause of the aborted layout renders: `ShowWindow` returns the
window's *previous* visibility, not a success flag. For a window that
was hidden it returns `FALSE`, and `.ok()` then built an error out of
whatever stale value the thread's last-error slot held (the logged
`0x8007006D` "pipe has been ended" / `0x80070057` "parameter is
incorrect" came from unrelated calls). `desired_rect_for` hit this when
un-maximizing a window and the `?` aborted the whole batch.

`WindowsApi::show_window` / `show_window_async`: clear the thread error
state first and only fail on a real error after a `FALSE` return.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01StkifHpSLWH4J5TvuP56ur
@z1pp090
z1pp090 force-pushed the fix/wm-skip-failed-window branch from 902299d to 2321f04 Compare September 21, 2026 04:31
@eythaann
eythaann merged commit 61cbb06 into eythaann:master Sep 21, 2026
1 check passed
@z1pp090
z1pp090 deleted the fix/wm-skip-failed-window branch September 24, 2026 15:36
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