Reverting the use of WS_EX_COMPOSITED in wxMSW

104 views
Skip to first unread message

Vadim Zeitlin

unread,
Nov 23, 2022, 1:55:07 PM11/23/22
to wx-dev
Hello,

I'm afraid I don't know how to fix all the different problems that
appeared after enabling the use of WS_EX_COMPOSITED in wxMSW, so I'm
probably going to revert the commit turning it on and several related ones,
as problems like https://github.com/wxWidgets/wxWidgets/issues/22982 are
just too nasty and I couldn't find any way to avoid this endless stream of
WM_PAINT messages when using this style.

It's really unfortunate because using double buffering is both more
visually appealing and makes wxMSW behaviour more consistent with wxGTK and
wxOSX, but I just don't know how to use it correctly. If anybody here has
more experience with/knowledge of using WS_EX_COMPOSITED, please let me
know, otherwise I'll revert the change enabling it soon.

Thanks in advance,
VZ

turk...@gmail.com

unread,
Nov 23, 2022, 4:44:51 PM11/23/22
to wx-dev
Maybe you shouldn't be so radical. Using  WS_EX_COMPOSITED, is really good idea. If you cannot yet find a universal solution for such problems, you can prohibit this style for some specific problematic cases. Most likely a solution will be found in the future.

Vadim Zeitlin

unread,
Nov 23, 2022, 5:23:03 PM11/23/22
to wx-...@googlegroups.com
On Wed, 23 Nov 2022 13:37:38 -0800 (PST) turk...@gmail.com wrote:

t> Maybe you shouldn't be so radical. Using WS_EX_COMPOSITED, is really good
t> idea.

Yes, I agree. But actually the really good part is double buffering and
not the style on its own and I wonder if we could achieve most (all?) of
the same benefits by using "buffered paint" functions available since
Vista, i.e. which we can use unconditionally now. Does anybody have any
experience with using these functions, i.e. BeginBufferedPaint() and
friends? They should at least help with painting custom windows, although
probably not the standard controls.

t> If you cannot yet find a universal solution for such problems, you
t> can prohibit this style for some specific problematic cases. Most likely a
t> solution will be found in the future.

I'm not so sure about this, and more time passes, more difficult it will
become to revert it. Of course, if someone does find a solution, we could
always revert the commit reverting it, restoring this feature.

Regards,
VZ

Vadim Zeitlin

unread,
Nov 23, 2022, 5:48:13 PM11/23/22
to wx-...@googlegroups.com
On Wed, 23 Nov 2022 13:37:38 -0800 (PST) turk...@gmail.com wrote:

t> Maybe you shouldn't be so radical. Using WS_EX_COMPOSITED, is really good
t> idea. If you cannot yet find a universal solution for such problems, you
t> can prohibit this style for some specific problematic cases. Most likely a
t> solution will be found in the future.

Well, I hate to contradict myself, but it looks like I did at least find a
solution to this particular problem: it seems that WS_EX_COMPOSITED must be
set on the top level window itself and not just its descendants.

Also, creating a wxPanel in the collpane sample and creating all the other
controls as its children works too (even without setting WS_EX_COMPOSITED
for the TLW), so what really doesn't seem to work is creating windows using
WS_EX_COMPOSITED as children of a window not using it. I think we can
probably live with this limitation and I'll try to implement a fix based on
this soon.

Sorry for a premature false alarm,
VZ

Vadim Zeitlin

unread,
Nov 28, 2022, 2:15:28 PM11/28/22
to wx-...@googlegroups.com
On Wed, 23 Nov 2022 23:48:10 +0100 I wrote:

Me> Well, I hate to contradict myself, but it looks like I did at least find a
Me> solution to this particular problem: it seems that WS_EX_COMPOSITED must be
Me> set on the top level window itself and not just its descendants.

I hate it even more now, but I have to re-contradict myself, or at least
point out a big problem with doing the above: setting WS_EX_COMPOSITED on
the TLW itself does fix the problem with window positioning/repainting, but
it doesn't work under Windows 7 because there it completely breaks the
whole point of using WS_EX_COMPOSITED in the first place, i.e. drawing the
children of a TLW with WS_EX_COMPOSITED is not double buffered any more:
WS_EX_COMPOSITED is not taken into account when creating them (and attempts
to set it later are ignored as well, because I've even tried this in
desperation) and everything drawn in their WM_PAINT handler appears on the
screen immediately instead of going to an off-screen bitmap.

This seems completely crazy to me, especially combined with the fact that
setting WS_EX_COMPOSITED for a child window also prevents its children from
having WS_EX_COMPOSITED, but they still are effectively double buffered.
But I've confirmed it with a pretty simple program using Win32 API directly
and this seems to indeed be the case, i.e. it's not just something wx does
wrongly. It also looks like a Windows bug that was fixed in Windows 10
because there setting WS_EX_COMPOSITED on the TLW works as expected

However even if we were ready to live with flicker under Windows 7 and use
this approach, there is still another problem left: wxListCtrl (in report
mode, with a header) just can't be used with a parent that has
WS_EX_COMPOSITED style (even under Windows 10 -- I haven't tried 11, but we
can't ignore the problem under Windows 10 anyhow). I have no idea why is
this so, but I can also reproduce this in a non-wx example and I found
other people complaining about this problem (but unfortunately without ever
proposing any solution to it), so we just have to live with this. So far
I've worked around the problem by resetting WS_EX_COMPOSITED on its parent
when wxListCtrl is created, which meant that it disabled double buffering
for its siblings, but at least not for its cousins, while now it would
disable it for the entire TLW which is unacceptable. Moreover, if the
native list view control is broken by having a parent with WS_EX_COMPOSITED
it means there could be other windows that don't support it neither, e.g.
I've seen some complaints about using WS_EX_COMPOSITED with Edge ActiveX
control too, even though I haven't reproduced them myself yet.

So, to summarize, we just can't set WS_EX_COMPOSITED on the TLW.


Me> Also, creating a wxPanel in the collpane sample and creating all the other
Me> controls as its children works too (even without setting WS_EX_COMPOSITED
Me> for the TLW),

This does work and, of course, it was always recommended to use wxPanel
for the children instead of creating them directly as children of the
frame, but it doesn't really help with the existing code and I don't think
totally breaking it is a good idea. So the only real solution I see is, as
I've mentioned in https://github.com/wxWidgets/wxWidgets/issues/22982, to
revert 616586f301 (Remove wxStaticBox custom drawing code entirely,
2022-11-08) and stop using WS_EX_TRANSPARENT for it again. I dislike it
because all the custom drawing code was a source of many problems in the
past, but I guess we can live with this.


However it turns out that this is not the end of the problems with using
WS_EX_COMPOSITED because I've also discovered that it's incompatible with
using wxNO_FULL_REPAINT_ON_RESIZE style -- which is the default since a
very long time. I.e. without explicitly using wxFULL_REPAINT_ON_RESIZE we
get very noticeable redrawing artifacts when simply creating 2 windows not
doing anything at all inside a frame: when resizing the frame, parts of the
rightmost of them (the leftmost one is fine, probably because its position
doesn't change) don't get redrawn correctly. It makes sense that we need to
repaint the window entirely with WS_EX_COMPOSITED, of course, as otherwise
the system can't draw it on screen by blitting the off-screen buffer
because it doesn't contain the full window representation, but it means
that there can also be a non-trivial cost of using WS_EX_COMPOSITED when
redrawing the window takes time.

And, of course, there are also the problems that had been already fixed:
the already mentioned wxListCtrl one and we also need to reset
WS_EX_COMPOSITED when using wxDragImage as it just doesn't work with it.
And I'm afraid we might discover other ones later, see e.g. the one
mentioned in https://groups.google.com/g/wx-users/c/iSeDwkai0Es


So while I've created https://github.com/wxWidgets/wxWidgets/pull/23002
which fixes/avoids the known issues above, I'm still not sure at all if we
want to keep using WS_EX_COMPOSITED or not. It doesn't seem like many
people use it, actually, at least I can't find any mention of it in a
couple of open source projects I've looked at. And I start having a nagging
suspicion that it's just not a good idea to use it...

And if anybody reading this knows more (or knows somebody who knows) about
WS_EX_COMPOSITED, its limitations and its implementation (I really wish I
had Windows sources, at least with GTK you can always check how is
something implemented), I'd really appreciate any help because even though
I can work around some of the problems, I still don't fully understand what
causes them and, of course, others -- like list view header drawing --
can't be worked around at all.

Thanks in advance,
VZ
Reply all
Reply to author
Forward
0 new messages