[PATCH] support for group-transient and pathologically-transient windows
Submitted by Justin Blanchard
Please describe the problem: Internally, libwnck has had problems dealing with group-transient windows (which set their WM_TRANSIENT_FOR hint to point to the root) and with pathological cases such as "A is a transient for B and B is a transient for A".
In particular, transiency cycles would lead to infinite loops. Bug 332493 was resolved with a fix for transiency cycles that worked provided no window outside the cycle marked itself transient for one of the windows in the cycle.
Steps to reproduce: [While trying to package a test program a while back I accidentally overwrote the most important source file with a tarball. :-P I can provide an x86 binary version or try to rewrite it upon request.]
Does this happen every time?
Other information: From bug 332493:
This patch amost completely solves the transiency problems in wnck. It's not quite EWMH compliant since setting WM_TRANSIENT_FOR to None will result in a window which isn't transient. (_wnck_atom_get doesn't really provide a way to tell whether the hint is set to None or unset.) There might be one other exception I haven't thought about much: an application closing a transient window's parent without changing the WM_TRANSIENT_FOR hint. I actually haven't coaxed a program into doing that... and I doubt it'd cause a crash.
Central idea of the patch: window.c will do the necessary bookkeeping to ensure that parent-chasing loops behave correctly. Rather than returning whatever nonsense an application reports, wnck_window_get_transient() will return the parent app window if its argument has one and NULL otherwise. The return value is guaranteed not to cycle. If an application sets up a WM_TRANSIENT_FOR cycle, of length one or otherwise, all windows in the cycle will be considered group transient. (A transient for a group-transient window, however, isn't automatically group-transient.)
This patch will change wnck's behavior wrt transients. For completeness (and to help you decide whether the patch is acceptable):
wnck_window_get_transient() will return NULL if argument is group-modal. Reason: it's not actually transient for an app window. In addition, setting TRANSIENT_FOR to root or None should give the same group-modal behavior (even if, as I mentioned, that's not yet true).
wnck_window_or_transient_needs_attention() will stick to the old behavior: if a window in the last_transient chain needs attention, it'll return true. If some other transient needs attention, it will be ignored. IMO this behavior is wrong and /any/ (non-group) transient with the NEEDS_ATTENTION hint should count, but that'd be a different patch anyway.
Reason group transients shouldn't count: the main use I've seen for the function is to ensure that a tasklist/selector makes the right items flash. Since wnck doesn't mark group transient windows as SKIP_TASKBAR, we'd want group transient windows themselves to flash if they need attention.
(Random) wnck_tasklist_activate_task_window() will now call wnck_window_unminimize() instead of wnck_window_activate_transient() if it's activating a minimized window. AFAICT that captures the intent more correctly and ultimately does the same thing. I probably shouldn't have done that, but I was trying to cut down on explicit mentions of transiency anyway.
Overall, it seems that libwnck's best bet when faced with group transiency is to ignore it. However, these code changes should make it good at identifying it. I imagine the corresponding changes in metacity would be more interesting.
Dan: I did not tell wnck to emit a warning, but it's easy to insert one at any point in update_transient_for() when ...->priv->transient_for_cycle is set to TRUE.