domferr / domferr/tilingshell

Tiled windows visually drift after screen lock/unlock (Wayland), snap back on click

Open
#543 3 comments 2 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
2k
Forks
116
PR merge metrics
No merged PRs in 30d

Description

## Environment

- GNOME Shell 49 (Fedora 43, Wayland)
- Tiling Shell 17.3
- Chrome windows (Wayland native)
- Multi-monitor: single logical display 5120x1440

## Problem

After locking and unlocking the screen, all tiled windows appear visually shifted down and to the right (approximately 8-16 pixels) from where they should be. Clicking any titlebar causes the window to immediately snap back to the correct position.

It also happens occasionally after a Chrome window exits fullscreen video playback.

## Investigation

I've spent some time debugging this and confirmed the following:

- The extension IS disabled on lock and re-enabled on unlock (confirmed via journalctl).
- `Meta.Window.get_frame_rect()` reports the correct position after unlock (e.g. `3994,32 1125x703` for a top-right tile, which matches the expected tiled position).
- `MetaWindowActor.x` / `.y` also match the frame rect — Clutter sees the actor in the correct place.
- `actor.translation_x/y` are both 0 (no leftover transform).
- `actor.scale_x/y` are both 1.

So at every level the extension can observe, the window is in the correct position. But the compositor is visually rendering it elsewhere, and only a user interaction resolves it.

## Attempted fixes (none worked)

To try to correct the drift, I added a `repositionTiledWindows()` method on `TilingManager` that runs after `enable()` and iterates over windows with `assignedTile`, calling `_easeWindowRectFromTile(tile, window, true)` on each.

Additional attempts on top of that:

1. Reset `actor.translation` to `(0,0,0)` and `actor.scale` to `(1,1)` — no visible change.
2. Nudge the window by 1px via `move_resize_frame` then move back — no change; `get_frame_rect()` reports the same values before/during/after the call, suggesting Mutter short-circuits the configure.
3. Force a size change (`width-1, height-1`) with `user_op=true` — same result, Mutter short-circuits.
4. `actor.queue_redraw()` + `actor.queue_relayout()` + `global.stage.queue_redraw()` — no change.
5. Briefly modify `actor.opacity` to invalidate the actor's texture cache — no change.

The only thing that fixes the visual drift is a real state change on the client side (click, focus, resize), which causes applications to commit a new buffer.

## Hypothesis

This looks like a Mutter/Wayland/Application interaction: Any application's last-committed buffer has stale positioning info (possibly because an animation set up via `Main.wm._prepareAnimationInfo` was interrupted by the lock transition), and the application doesn't re-commit a buffer because Mutter's configure events aren't materially different from its current state. The extension can't force the client to re-commit.

## Question

Do you know of a way to force a compositor resync for a Wayland client from within a GNOME Shell extension, short of unmaximize/remaximize cycles or other user-visible state changes? Or is this a known upstream Mutter issue?

Happy to provide full logs or test other approaches.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.