GNOME Bugzilla – Bug 144030
Gdk invalidates obscured windows
Last modified: 2014-03-24 03:07:20 UTC
gdkgeometry-x11.c invalidates the newly exposed portion of a window when the clip region changes (for example, during a resize of the window). Since this is an internal invalidation, expose events are sent to the GdkWindow even if it is obscured. This can cause a lot of work to happen unnecessarily. In Eclipse, we often have GdkWindow objects which can be obscured. See this bug: http://bugs.eclipse.org/bugs/show_bug.cgi?id=65269 Our workaround in eclipse is to listen for VisibilityNotify events on each GdkWindow for our own widgets, and avoid redrawing if they are not visible. Is there something which can be done better in Gdk to handle this case? The following patch saved a lot of work in Eclipse, so I am curious about why Gdk is invalidating this region itself. Index: gdk/x11/gdkgeometry-x11.c =================================================================== RCS file: /cvs/gnome/gtk+/gdk/x11/gdkgeometry-x11.c,v retrieving revision 1.22 diff -p -u -r1.22 gdkgeometry-x11.c --- a/gdk/x11/gdkgeometry-x11.c 10 May 2004 20:51:19 -0000 1.22 +++ b/gdk/x11/gdkgeometry-x11.c 8 Jun 2004 18:13:31 -0000 @@ -1146,7 +1146,10 @@ gdk_window_clip_changed (GdkWindow *wind if (!gdk_region_empty (new_clip_region)) { gdk_window_tmp_unset_bg (window); - gdk_window_invalidate_region (window, new_clip_region, FALSE); + /* + * Is this invalidate unnecessary? + * gdk_window_invalidate_region (window, new_clip_region, FALSE); + */ } gdk_region_destroy (new_clip_region);
We do the invalidate because it means that we can repaint without a round trip to the server, which greatly improves appearance for scrolling and similar. Having lots of obscured windows seems rather odd to me ... is the problem that not-front-notebook tabs are just lowered, not unmapped in SWT? (No expose events should be generated for windows where some ancestor is unmapped.)
For SWT notebooks, child widgets are unmapped like normal. However, in Eclipse we do have notebooks which just play z-order games. Our notebooks may be changed to use unmapping in the future, but right now it's apparently easier to play focus games and other tricks when the widgets are not unmapped. There are other places in Eclipse where we obscure windows, for example we have resizable views which pop up over part the eclipse window and obscure what's underneath. However, I can't think of a good use case right now where what's below would be resized.
Created attachment 28741 [details] C example Here is a C program which demonstrates the effect. The application shows a label and below the label is a drawing area which is filled on expose. It prints information about exposes and visibility events. It can be used to demonstrate ways in which obscured windows are told to draw, sometimes when they don't have to. Examples: 1. Move the window so that its title bar is visible, but the drawing area is below your screen. Resizing the window causes the drawing area to get exposes. 2. An effect of guffaw scrolling: position the window as in step 1, and resize it larger. The window becomes visible, is told to draw, but on layout jumps back to being obscured (but still redraws). 3. Similarly, set the window to be STATE_BELOW. The drawing area gets exposes even when it is not visible. 4. Resize the window so you have to scroll to the drawing area, we no longer get exposes (nice!). :) 5. Resize the window large and small rapidly, notice how many of the exposes came at times when the last state the widget saw was that it was obscured.
I don't think we should lose the paint-without-roundtrip optimization. We could track visibility notifies; there is even a thread about that here: http://mail.gnome.org/archives/gtk-devel-list/2003-April/msg00026.html To make it work in the presence of backing store on the X server we would have to maintain the invalid region for the window while the window is obscured, then paint it when the window becomes partially or completely unobscured. A simple way to do this might be to call gdk_window_freeze_updates() when the window becomes fully obscured and gdk_window_thaw_updates() when the window becomes unobscured. But see bug 144272.
In SWT, we currently listen to visibility events on all widgets and windows we create and block expose events if they are not visible. While it clearly improves some benchmarks, a lot of events are generated and so it hurts in other ways (as well, this technique is scary and has had a few bugs). Personally, I'm not convinced that the paint-without-roundtrip optimization is worth it, especially in this particular case of resizing a window. I don't think this affects scrolling, and since layout is deferred and menus use a background of None, painting in this case seems especially unnecessary.
closing out ancient bugs