I have been using a video player recently that uses full-screen windows, the kind that get promoted all the way to the top as long as they have focus.
I have also seen lots of the asserts from $SUBJECT recently, while I was
interacting with such a window.
I think I finally found out what's wrong, while running ctwm from a
debugger.
First, the stack trace (transcribed by hand since I didn't run the
debugger in an xterm, of course). Most recent call at the bottom.
HandleEnterNotify() event_handlers.c line 3301
SetFocus() win_ops.c line 168
OtpRestackWindow() otp.c line 1578
OtpCheckConsistency() otp.c line 200
OtpCheckConsistencyVS() otp.c line 248
assert()
The code in SetFocus() around the call site looks like
(do stuff with SetFocusVisualAttributes() and AutoSqueeze())
163 Scr->Focus = tmp_win;
164
165 #ifdef EWMH
166 /* Priority may change when focus does */
167 if(old_focus && OtpIsFocusDependent(old_focus)) {
168 OtpRestackWindow(old_focus);
169 }
170 if(tmp_win && OtpIsFocusDependent(tmp_win)) {
171 OtpRestackWindow(tmp_win);
172 }
173 #endif
174 }
and otp.c:
1571 void
1572 OtpRestackWindow(TwmWindow *twm_win)
1573 {
1574 OtpWinList *owl = twm_win->otp;
1575
1576 RemoveOwl(owl);
1577 InsertOwl(owl, Above);
1578 OtpCheckConsistency();
1579 }
1
The first call to OtpRestackWindow() would eventually call the failing
assert(PRI(owl) >= priority) in OtpCheckConsistency() but after it has
already fixed its target.
Now PRI here looks innocent, but in reality it is defined as
#define PRI(owl) OwlEffectivePriority(owl)
In other words, it calls a function that dynamically determines window
priority, possibly depending on which window has focus.
But which window that is, is just changing. Suddenly there may be one or
two windows in the stacking order which are in the wrong place. When we
check consistency after adjusting the first candidate (old_focus), the
second candidate (tmp_win) may still be wrongly stacked, causing the
assertion failure.
Now I'm trying to convince myself that the following code change is
necessary and sufficient:
163
164 #ifdef EWMH
165 /*
166 * Priority may change when focus does: do PRI calculation
167 * on old_focus and tmp_win while it doesn't have focus.
168 */
169 Scr->Focus = NULL;
170
171 if(old_focus && OtpIsFocusDependent(old_focus)) {
172 OtpRestackWindow(old_focus);
173 }
174
175 Scr->Focus = tmp_win;
176
177 if(tmp_win && OtpIsFocusDependent(tmp_win)) {
178 OtpRestackWindow(tmp_win);
179 }
180 #else
181 Scr->Focus = tmp_win;
182 #endif
Does anybody has ideas about that?
I'm running with this now, and I'll see if I have more of these
problems.
-Olaf.
--
___ Olaf 'Rhialto' Seibert -- "What good is a Ring of Power
\X/ rhialto/at/falu.nl -- if you're unable...to Speak." - Agent Elrond
signature.asc
Description: PGP signature
