linuxmint / linuxmint/muffin

WM_TRANSIENT_FOR resolved only once at manage time — transient never follows its parent to another workspace if it was mapped first

Open
#846 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
245
Forks
127
PR merge metrics
No merged PRs in 30d

Description

Distribution: Linux Mint 22.3 (Zena)
Package version: muffin 6.6.3+zena, cinnamon 6.6.7+zena, X11
Graphics hardware: NVIDIA GeForce RTX 4090 (AD102), proprietary driver
Frequency: Always

Bug description

If a transient window is adopted by the WM before its parent, it never follows that parent to another workspace.

The behaviour is consistent with reload_transient_for() (src/x11/window-props.c) resolving WM_TRANSIENT_FOR only once, via meta_x11_display_lookup_x_window(): when the parent is not managed yet the lookup fails and transient_for becomes NULL, and the early return

if (transient_for == window->xtransient_for)
    return;

would prevent any later retry, since the property itself never changes again. meta_window_change_workspace() then walks a transient list that does not contain the child. I have not instrumented muffin to confirm that specific line — the reproducer below establishes the ordering-dependent behaviour, not the exact code path.

The hint stays correct on the client throughout; only the window manager's resolution of it appears to be lost.

Real-world case: the Android emulator's floating control toolbar is a separate top-level window (_NET_WM_WINDOW_TYPE_UTILITY, WM_TRANSIENT_FOR the device window) and is stranded on the old workspace every time.

Steps to reproduce
#!/usr/bin/env python3
# needs python3-xlib
import time
from Xlib import X, Xatom, display

d = display.Display(); s = d.screen(); root = s.root

def win(name, x, w):
    o = root.create_window(x, 60, w, 160, 1, s.root_depth, X.InputOutput,
                           X.CopyFromParent, background_pixel=s.black_pixel)
    o.set_wm_name(name); o.set_wm_class("repro", "Repro"); return o

parent, child = win("repro-parent", 60, 260), win("repro-child", 340, 60)
child.set_wm_transient_for(parent)
child.change_property(d.intern_atom("_NET_WM_WINDOW_TYPE"), Xatom.ATOM, 32,
                      [d.intern_atom("_NET_WM_WINDOW_TYPE_UTILITY")])

child.map(); d.sync(); time.sleep(0.5)   # child first -> bug
parent.map(); d.sync()                   # swap these two lines -> works

print(f"parent 0x{parent.id:08x}  child 0x{child.id:08x}", flush=True)
time.sleep(300)
  1. Run it, note the two window IDs.
  2. wmctrl -i -r <parent> -t 2
  3. The child stays on the original workspace, while xprop -id <child> WM_TRANSIENT_FOR still reports the correct parent.
  4. Swap the two map() lines so the parent is mapped first — the child now follows correctly.

Deterministic here, 3/3 runs. Mapping both back to back without synchronisation also works; only child-before-parent fails.

Expected behavior

The child follows its parent, as meta_window_change_workspace() intends via meta_window_foreach_transient().

Additional information

Affects any application that maps a utility/tool window before its main window. GNOME Bugzilla 645853 and 692976 described the symptom in 2011/2013 but were mass-closed RESOLVED OBSOLETE in the 2021 GitLab migration without a fix. The same code is present in mutter.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the child-before-parent ordering with the provided Python script, then inspect reload_transient_for() in src/x11/window-props.c and the workspace path through meta_window_change_workspace() and meta_window_foreach_transient(). Done means a transient mapped before its parent follows that parent after a workspace change, while the parent-first case continues to work.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
desktop-dev, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.