GNOME Bugzilla – Bug 643416
Composited children of GtkScrolledWindow are drawn incorrectly on scrolling
Last modified: 2011-03-08 22:38:04 UTC
Created attachment 182041 [details] Test case See test case. On expose event of scrolledWindow, treeview is drawn translucently on a red background. On scrolling, the part of treeview which should just move without changing is taken from the composited image instead of the backing pixmap, thus fading out the unchanged treeview part on each scroll repaint, which is, obviously, incorrect. The correct behavior would be to use backing pixmap as a source for drawing the unchanged part.
Created attachment 182043 [details] Screenshot of test case after scrolling
Created attachment 182699 [details] [review] trivial patch
Here's a patch for the issue. But I think the patch is at least inomplete, because the same problem will hit us if we scroll windows with an RGBA colormap and it probably needs work for offscreen windows, too. So more fixage is likely needed. I also do not understand why we copy from the parent instead. The commit that introduced the commit - http://git.gnome.org/browse/gtk+/commit/?id=df4f4c14 - references shaped windows but I dn't understand what exactly the issue is. I'm cc'ing Alex as he wrote that commit and might be able to give an example.
The comment is a bit vague I guess, but the issue is with native subwindows and how they are implemented. Native subwindows can be put wherever you want in the client side window hieararchy. This is implemented by puting the actual X window inside the "nearest" parent that has a native window, and then we use shaped windows to implement the clipping of that native window against non-native parents and overlapping siblings. This results in quite some complexity when scrolling a non-native window, as it could have native children in its subtree. Without the native children we'd just recalculate the new absolute positions of everything, then copy any already existing regions that will be visible in the result to their final place, and expose the rest. However, with native children there is some complexity. First of all, you need to actually move the native children, to get their positioning right in the result. This move then additionally means that things get copied. Additionally you need to make the native children shaped right, which is a two-stage process, first apply calculated shape for the new position, then actually move the window to the new position. The actual shape is done with bg none, so whenever some new area would be exposed with the window content we just keep the old bits. At some point I had such a shaped window covering an area that i had to copy to a new location due to a scroll/move. The actual new data in the reshaped native window had not been written yet, so the right bits were already on the screen. However, the ownership of that onscreen region was wrong, being owned by an overlapping sibling window, so we INCLUDE_INFERIOURS was not enough to copy it, we had to go to the shared parent and then use INCLUDE_INFERIOURS to be able to copy the bits. However, since adding this code in commit df4f4c14c7db72fbe003c3c122efc6ae46001fd5, we have added code in gdk_window_scroll() to not copy stuff from any area covered by native children either before or after the reshape+move, so I'm not sure this stuff is needed anymore. On the other hand, I can't say with 100% certainty that there is no way to end up with a non-rendered shaped window covering the source of a window copy, even though I can't spot any immediate cause. Maybe it can happen for instance when mapping (with bg none) a window and then scrolling before we handle the expose.
Should be fixed in both GTK2 and GTK3.
The fix will get released in 2.24.2 and 3.0.4, right?
Almost, 2.24.2 and 3.0.3.