Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
why do wxMac and wxGTK always erase window background?
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  4 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Kevin Ollivier  
View profile  
 More options Nov 20 2008, 1:28 pm
From: Kevin Ollivier <kevin-li...@theolliviers.com>
Date: Thu, 20 Nov 2008 10:28:56 -0800
Local: Thurs, Nov 20 2008 1:28 pm
Subject: Re: Re[2]: [wx-dev] Re: why do wxMac and wxGTK always erase window background?
Hi Vadim,

On Nov 20, 2008, at 8:36 AM, Vadim Zeitlin wrote:

There isn't anything wrong with the double-buffering - it's simply  
that on Mac and likely GTK there is no way to retain the drawing done  
during previous paints except to NOT invalidate the area you don't  
want repainted. (Which I'm almost certain will give correct results on  
Win, too, BTW.) Once you invalidate an area by calling Refresh on it,  
it is redrawn from scratch on Mac/GTK regardless of what  
eraseBackground says.

The reason things are designed this way is probably due to compositing  
- when any pixel drawn on screen could be a composition of 2 or more  
windows, a real mess could be caused if you draw on an area that  
wasn't invalidated first. For example, the area of the screen you're  
drawing could have a semi-transparent window floating above it, which  
you would happily be drawing over with your (opaque) drawing calls,  
and since that screen area wasn't invalidated, the window manager  
doesn't realize it needs to tell the semi-transparent window to redraw  
itself and composite the results of both drawings into a final result.  
So, rather than risk all sorts of weird messes like this, Apple just  
decided to not make this sort of thing possible, and IMHO I'm glad  
they did. :-)

In short, on Mac at least, you HAVE to let the window manager know  
that you want to repaint any area of the screen before you draw there,  
so that it can check if it needs to tell other windows above or below  
to repaint as well and then merge the results.

The Windows WM was written in simpler times and avoids this problem by  
not completely supporting compositing (with Win32 at least, AFAIK, you  
have to do special hacks to get true compositing), but on Mac/GTK  
programmers can't take the easy way out. ;-) (Of course, on the flip  
side, they can do lots of cool stuff without hacks too.)

> RD> As a side note, I don't think anybody has mentioned yet that the
> RD> eraseBackground parameter to wxWindow::Refresh is totally  
> ignored on Mac
> RD> and GTK.

> Yes, Andrew did write this. But this doesn't make it less of a  
> problem...

AFAICT, there's not much we can do about it, this is just how the OS  
works. However, as long as you use Refresh efficiently, the same code  
should work fine on Win, Mac and Linux. It's just that the usefulness  
of EVT_ERASE_BACKGROUND is limited to Windows, and unfortunately  
people who use it will just run into troubles when they port to GTK/
Mac because of the reasons mentioned above.

To be honest, I wonder if we ought not either put some serious  
warnings about this or even outright deprecate it. It's only really of  
use on Windows, and while I know some people stick to Windows,  
unexpectedly having to refactor your whole drawing model when you  
decide to port to any other platform would I think be an unpleasant  
surprise, to say the least. And once you get used to calling Refresh  
with the area you want repainted, it's really not that much more code.  
It's more just moving code from your paint method into a  
CalculateDirtyRegion type of function.

Regards,

Kevin


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Andrew Trevorrow  
View profile  
 More options Nov 20 2008, 7:04 pm
From: Andrew Trevorrow <and...@trevorrow.com>
Date: Fri, 21 Nov 2008 11:04:56 +1100
Local: Thurs, Nov 20 2008 7:04 pm
Subject: [wx-dev] Re: why do wxMac and wxGTK always erase window background?

Kevin Ollivier wrote:
> There isn't anything wrong with the double-buffering ...

Agreed -- double-buffering has nothing to do with this issue.

> - it's simply  
> that on Mac and likely GTK there is no way to retain the drawing done  
> during previous paints except to NOT invalidate the area you don't  
> want repainted. (Which I'm almost certain will give correct results on  
> Win, too, BTW.) Once you invalidate an area by calling Refresh on it,  
> it is redrawn from scratch on Mac/GTK regardless of what  
> eraseBackground says.

This is simply not correct, as my changes to the minimal app show.
By replacing the frame's default erase and paint event handlers
with handlers that draw nothing, you *can* retain the drawing done by
previous paints.  Run the app and select the About item and you'll see
100 random overlapping squares appear in a child window as a result
of this code in MyFrame::OnAbout():

   for (int i=0; i<100; i++) {
      mywin->Refresh(false);    // invalidate ALL of child window
      mywin->Update();          // draw ONE square at random location
   }

If your paragraph above was correct then we'd only see one square at
the end of this loop, but we see 100.  So it *is* possible to retain
drawing done by previous paints, but wxMac makes it more difficult
than it should be.

> AFAICT, there's not much we can do about it, this is just how the OS  
> works. ...

It's not the Mac OS that is painting the background, it's a bit of
wxMac code.  Theoretically, it should be possible to set an internal
flag if Refresh(false) is called and then use that flag in the next
Update() call to avoid painting the background.

I've no idea how difficult that would be to implement -- my tests
show there are some wxMac controls (eg. wxStatusBar) that assume the
background has already been painted, but it should be possible to
add a dc.Clear() call in the paint event handler for those controls.

Andrew


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Kevin Ollivier  
View profile  
 More options Nov 19 2008, 2:39 am
From: Kevin Ollivier <kevin-li...@theolliviers.com>
Date: Tue, 18 Nov 2008 23:39:28 -0800
Local: Wed, Nov 19 2008 2:39 am
Subject: Re: [wx-dev] Re: why do wxMac and wxGTK always erase window background?

On Nov 18, 2008, at 7:14 PM, Andrew Trevorrow wrote:

> Kevin Ollivier wrote:

>>> That's not what my tests show -- wxMac and wxGTK *do* erase the
>>> background.  ...

>> No, that's incorrect. They do not erase the background, instead, they
>> repaint the entire control, which is exactly what you tell them to do
>> when you call Refresh() rather than using RefreshRect().

> I'm not calling Refresh(), I'm calling Refresh(false).  According to
> the wx docs, passing false for the eraseBackground parameter should
> prevent the background being erased, but wxMac/wxGTK seem to ignore
> that parameter.  That's either a bug, or else the docs should mention
> that fact so other people don't waste their time.

Looking closer at it, on Mac, there is a bug in certain cases (i.e.  
when you don't have an empty EVT_ERASE_BACKGROUND handler and don't  
use a transparent background style), but it's not what's causing your  
problem. I'll agree though that the docs could probably be more clear  
about the fact that wxMac and wxGTK synthesize the  
EVT_ERASE_BACKGROUND event and that Refresh(false) doesn't always work  
as expected.

I think what you're missing is that on Mac at least, controls are  
transparent by default. So, if you invalidate your entire control's  
area (i.e. call Refresh) and then don't paint part of your control,  
that doesn't mean that no painting occurs in that area. Instead,  
because the control is transparent, the areas that the control doesn't  
paint itself will be painted by the parent control (in this example,  
the wxFrame). This is why to completely stop "background" painting,  
you need to add an empty EVT_PAINT handler to your wxFrame - in  
essence, you need to completely turn off all parent control drawing.  
However, this is not a solution, just a workaround that could cause  
weird graphical glitches as you noticed.

Bottom line - don't invalidate any areas of the control where you  
don't want any painting to occur. This is a simple and straightforward  
way of avoiding unnecessary painting. That is what RefreshRect and  
GetUpdateRegion are there for.

Kevin


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Robin Dunn  
View profile  
 More options Nov 20 2008, 11:32 am
From: Robin Dunn <ro...@alldunn.com>
Date: Thu, 20 Nov 2008 08:32:53 -0800
Local: Thurs, Nov 20 2008 11:32 am
Subject: Re: [wx-dev] Re: why do wxMac and wxGTK always erase window background?

Maybe another way to look at it would help people understand what Andrew
is asking about.  If you turn it around and look at it from a different
perspective you can say that on Windows when Refresh(false) is called it
causes the current content of the window to be preserved and that
whatever is drawn in the next EVT_PAINT handler will be drawn on top of
that current content.  On Mac and GTK the current content is not
preserved, and Andrew is wondering how to make it behave that way.

As a side note, I don't think anybody has mentioned yet that the
eraseBackground parameter to wxWindow::Refresh is totally ignored on Mac
and GTK.  It there anything that it could be used for to give us the
ability to preserve the current window content?

--
Robin Dunn
Software Craftsman
http://wxPython.org  Java give you jitters?  Relax with wxPython!


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »