Window flickering problem in XWin multiwindow mode

S.J. Luo sjaluo@gmail.com
Sat May 7 02:01:32 GMT 2022


Hi,

> > > I have some EDA tools running on a Linux machine and display on my Windows
> > > PC using xorg-server-21.1.3 XWin multiwindow mode
> > > Sometimes the application window flickers forever for an unknown reason.
> > > The problem became more severe after my PC upgrade to Windows10.
> > >
> > > Knowing the root cause, I am now able to demonstrate the issue with a small
> > > test case as well as a patch that works for me. Both are attached below.
> >
> > Thanks very much for taking the time to look into this, and writing a patch.
> > But I'd like to add a bit more commentary, which perhaps you can supply,
> > about the analysis you did to determine:
> >
> > 1. how the code is misbehaving
> > 2. how this change remedies that
> > 3. how this change doesn't effect anything else
> >
> > What your fix does is examine the queue of pending WM messages to
> > determine if there are any more pending for the window receiving a
> > WM_WM_CHANGE_STATE message, and if there are, ignore it.
> >
> > It seems to me that is error prone, in a couple of ways:
> >
> > 1. it should check the message type as well, as e.g. a pending message
> > of a different type could cause a WM_WM_CHANGE_STATE message to be ignored.
> >
> > 2. even then, assuming that successive WM_WM_CHANGE_STATE messages
> > cancel out each other isn't always true e.g. consider a sequence of
> > _NET_WM_STATE_ADD _NET_WM_STATE_MAXIMIZED_VERT followed by
> > _NET_WM_STATE_ADD _NET_WM_STATE_MAXIMIZED_HORZ.
> >

> Here I have some details on the problem:
> In following, WWCS means WM_WM_CHANGE_STATE
> There exists a message self-generating loop
> I.e., a WWCS message may generate another WWCS.
>
> winSendMessageToWM(WWCS) --> MultiWindowWMProc(WWCS)
> --> UpdateState() --> ShowWindow() --> MultiWindowProc(WM_SIZE)
> --> winAdjustXWindowState() --> winSendMessageToWM(WWCS)
>
> In normal case, there is a conditional code inside UpdateState() that
> could break the loop.
>
>             if (current_state == state)
>                 return;
>
> Normally after maximizing the window, the WWCS just
> to be self-generated once. On processing the 2nd WWCS,
> the current window state matches WWCS target state
> and ShowWindow() won't be called and the loop could end.
>
> Initial
>     Window state normal
>     queue : | WWCS(max1) |
> --> process WWCS(max1) :
>     Winow state (norm) != target state (max2)
>     Set Window state to max and generate WWCS(max2)
>     queue : | WWCS(max2) |
> --> Process WWCS(max2) :
>     Winow state (max) == target state (max)
>     break
>
> where WWCS(max1) means WWCS msg with target state max
> and 1 means first generated/inserted WWCS in queue.
>
> However, there is case triggering this loop running forever.
> Assuming intitially there are two WWCS message exists
> where one is to maximize window and one is to normal window
> The condition of state compare in UpdateState() would never match.
> And WWCS(max) and WWCS(norm) is going to self-generate in turn.
>
> Initial
>     Window state normal
>     queue : | WWCS(max1) | WWCS(norm1) |
> --> process WWCS(max1)
>     Winow state (norm) != target state (max)
>     Set window state to max and generate WWCS(max2)
>     queue : | WWCS(norm1) | WWCS(max2) |
> --> Process WWCS(norm1)
>     Winow state (max) != target state (norm)
>     Set window state to norm and generate WWCS(norm2)
>     queue : | WWCS(max2) | WWCS(norm2) |
> --> Process WWCS(max2)
>     Winow state (norm) != target state (max)
>     Set window state to max and generate WWCS(max3)
>     queue : | WWCS(norm2) | WWCS(max3) |
> --> Process WWCS(norm2)
>     Winow state (max) != target state (norm)
>     Set window state to norm and generate WWCS(norm3)
>     queue : | WWCS(max3) | WWCS(norm3) |
> :
> (loop forever)
>

I just did some more study on the code of multiwindow window manager and
X11 Window Properties as well as the questions you brought up.

The first question :

> it should check the message type as well, as e.g.
> a different type mesage could cause WM_WM_CHANGE_STYLE to be ignored.

Not sure what the "type" of a message means.
Do you mean window manager message WM_xxxxx that is processed by
winMultiWindowWMProc() where it is alreadychecked in HaveMessage(),
or do you mean X message XCB_xxxxxx that is processed by
winMultiWindowXMsgProc()?
Maybe you can provide an example of another message type?

The second question:

> Successive WM_WM_CHANGE_STATE messages cancel out each other
> isn't always true ex. _NET_WM_STATE_ADD _NET_WM_STATE_MAXIMIZED_VERT
> followed by _NET_WM_STATE_ADD _NET_WM_STATE_MAXIMIZED_HORZ.

Inspecting the code that deal with XCB_CLIENT_MESSAGE, it seems already
true before the patch: The window goes maximized only if X client do one
_WM_STATE_ADD action with _NET_WM_STATE_MAXIMIZED_VERT and
_NET_WM_STATE_MAXIMIZED_HORZ simultaneously specified. Otherwise,
the WM_WM_CHANGE would not be sent to the queue.
Further, in UpdateWindowState(), the state and related X properties are
either all-overwritten or all-skipped.
There seems to be no state property half-update case if we skip
UpdateWindowState().

In anyway, I just came out somewhat different patch attached.
Where it just skips the Win32 ShowWindow() call instead of
skipping processing WM_WM_CHANGE_STATE. It might be better because
the X properties are still always updated in each in WM_WM_CHANGE_STATE.
Maybe you could provide further comment.

SL
-------------- next part --------------
A non-text attachment was scrubbed...
Name: flicker2b.patch
Type: application/x-patch
Size: 4634 bytes
Desc: not available
URL: <https://cygwin.com/pipermail/cygwin/attachments/20220507/03415656/attachment-0001.bin>


More information about the Cygwin mailing list