After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 108926 - Bad tearing during resize
Bad tearing during resize
Status: RESOLVED FIXED
Product: metacity
Classification: Other
Component: general
2.4.x
Other Linux
: Normal normal
: METACITY2.6.x
Assigned To: Metacity maintainers list
Metacity maintainers list
Depends on:
Blocks:
 
 
Reported: 2003-03-21 22:26 UTC by Soren Sandmann Pedersen
Modified: 2004-12-22 21:47 UTC
See Also:
GNOME target: ---
GNOME version: 2.3/2.4


Attachments
bad tearing (3.80 KB, image/png)
2003-03-21 22:28 UTC, Soren Sandmann Pedersen
  Details
patch that makes metacity wait for a configure event (1.31 KB, patch)
2003-03-21 22:28 UTC, Soren Sandmann Pedersen
none Details | Review
patch (12.81 KB, patch)
2003-08-15 23:04 UTC, Soren Sandmann Pedersen
none Details | Review
new patch (13.35 KB, patch)
2003-08-16 11:06 UTC, Soren Sandmann Pedersen
none Details | Review
64-bit fixes (2.31 KB, patch)
2003-09-25 09:27 UTC, Gwenole Beauchesne
none Details | Review

Description Soren Sandmann Pedersen 2003-03-21 22:26:48 UTC
The frame tears badly during resize as the soon-to-be-attached screenshot
shows. 

What happens is this:

        - in meta_frame_sync_to_window, the frame window is resized.
          Then in meta_ui_repaint_frame() the corresponding foreign
          GdkWindow has process_updates called on it. But since the
          window was never invalidated, nothing happens. 

          Instead since the window has a bg=None, an expose is sent and
          the window is redrawn. Since the bg=None, this doesn't flicker,
          but until the expose arrives, there is bad tearing.

        - adding a gdk_window_invalidate(window, NULL) makes most of the
          window actually be redrawn. However, since the window was resized
          with X{Move,Resize}Window, Gdk doesn't know the new coordinates
          before a configure event arrives. This means gdk will not
          invalidate the newly uncovered area of the window, so this
          doesn't actually solve anything.

        - calling gdk_window_move_resize() will not help since the window
          is not a child window. Gdk always waits for configure events
          for windows that aren't child windows. 

        - as long as gdk has the wrong idea about what the window
          dimensions are, this tearing will go on, because gdk clips any
          drawing to what it thinks is the visible area.

I don't know what the solution is. Maybe add a
"gdk_window_i_AM_the_window_manager_dammit()" that would make 
resizing of gdk windows update the cache immediately. 

Another solution would be to bypass gdk entirely in metacity.

A non-solution is to make the frame window a regular gdk toplevel, 
because resizing such windows will also not update the cached dimensions.

I am attaching a patch that makes resizing prettier by making metacity
wait for the configure event, but this is a bad hack, and the extra
roundtrip here should not be necessary.
Comment 1 Soren Sandmann Pedersen 2003-03-21 22:28:07 UTC
Created attachment 15158 [details]
bad tearing
Comment 2 Soren Sandmann Pedersen 2003-03-21 22:28:47 UTC
Created attachment 15159 [details] [review]
patch that makes metacity wait for a configure event
Comment 3 Havoc Pennington 2003-03-21 23:34:39 UTC
hey owen, can we add a function called that? ;-)
Comment 4 Owen Taylor 2003-03-21 23:51:42 UTC
Hmmm ... can you create your "toplevels" as child window?
GTK+ assumes child windows resize immediately. They 
certainly shouldn't get all the extra properties, focus
windows, etc, that GTK+ puts on toplevels.
Comment 5 Havoc Pennington 2003-03-22 00:16:05 UTC
they're created with XCreateWindow(), then wrapped with 
gdk_window_foreign_new()... 
I guess we could try creating them with gdk_window_new instead, 
but I don't know what side effects it might have.
Comment 6 Havoc Pennington 2003-08-13 19:26:57 UTC
How about gdk_window_foreign_set_is_toplevel ()?
something like that?
Comment 7 Soren Sandmann Pedersen 2003-08-15 23:04:23 UTC
Created attachment 19252 [details] [review]
patch
Comment 8 Soren Sandmann Pedersen 2003-08-15 23:07:45 UTC
This patch seems to work, but I haven't tested it very thoroughly.

There are some events that GDK doesn't provide for the 
event mask, so I'm setting it twice, both in ui.c and in
frame.c
Comment 9 Havoc Pennington 2003-08-16 02:12:17 UTC
The patch looks good. 

In one spot you seem to have reimplemented this:
GdkDisplay * gdk_x11_lookup_xdisplay (Display *xdisplay)
(from gdkx.h)

Also, when creating the GdkWindow for the frame maybe you should 
just set the event mask to 0; otherwise people might think
that event mask matters when in reality we're going to immediately 
replace it.

I wonder if there's some reason I did the "if (move and resize)
MoveResize() else if (move) Move() else if (resize) Resize()" 
thing. Probably not. Conceivably it changes configure events 
somehow?

Anyway I'll apply this patch and try using it for a while and 
if it doesn't break let's put it in.
Comment 10 Soren Sandmann Pedersen 2003-08-16 11:02:29 UTC
I don't think you can set the event mask for the GdkWindow to 0,
because GDK depends on knowing it in some places. So I did it this to
let GDK know as much as possible about the real event mask. But a
comment is probably in order. I'll attach a new patch.
Comment 11 Soren Sandmann Pedersen 2003-08-16 11:06:08 UTC
Created attachment 19262 [details] [review]
new patch
Comment 12 Havoc Pennington 2003-08-16 15:17:16 UTC
This works for me, do you want to commit? I have it applied to my 
tree too if you want me to commit. Thanks
Comment 13 Soren Sandmann Pedersen 2003-08-16 16:24:10 UTC
It's easier for me if you commit as I have some other experiments in
my tree currently.
Comment 14 Havoc Pennington 2003-08-16 16:33:53 UTC
Committed. I removed the change of max resizes per second (20->200) 
since it seemed unrelated; if you think that's a good idea in 
general maybe we can discuss separately.
I wanted to put a cap on CPU usage from opaque resize so people wouldn't
whine about it on timeshare systems.
Comment 15 Soren Sandmann Pedersen 2003-08-16 16:39:25 UTC
Right, the 20->200 was just a leftover from something else.

Comment 16 Gwenole Beauchesne 2003-09-24 10:34:53 UTC
This patch breaks metacity on AMD64, or at least exhibits another
problem more clearly. i.e. Now with 2.6.1, resizing gnome-terminal
windows (or rxvt) makes it inoperant, or at least metacity thinks we
request a 0x0 change.
Comment 17 Havoc Pennington 2003-09-25 03:40:47 UTC
How do you know it was this patch? (If you debugged the problem, can
you tell us what it was? ;-))
Comment 18 Frederic Crozat 2003-09-25 07:59:32 UTC
Problem is not entirely debugged, unfortunately :(

Reverting to metacity just before this patch was checked in (thanks
CVS) so no problem but applying this patch breaks load of width_inc
and height_inc by metacity.. It is not clear yet why metacity doesn't
load these values correctly on AMD64 while xprop does..
Comment 19 Gwenole Beauchesne 2003-09-25 08:12:36 UTC
CVS dichotomy. ;-)

I can only speak about effects of the bug, not the cause since it's
yet to be found:
- Metacity 2.4.1 (the one from MDK 9.0/AMD64) works correctly wrt.
windows resizing.
- Metacity 2.6.1 makes gnome-terminal (and rxvt, aka. resizable
windows under constraints) not resizing correctly.
- It may be that patch triggered a latent bug.
- SizeHints look totally bogus. It may be that due to some gdk use,
those values are nuked somehow.
- I do think of a 32-bit/64-bit arg mismatch either as a vararg or as
an integral constant passed as the >= 7th argument. However, I looked
at longish metacity functions, they seem to be called correctly.

Reading gcc warnings only lead me to another 64-bit bug in delete.c
but that doesn't solve this problem. :-(
Comment 20 Gwenole Beauchesne 2003-09-25 09:27:54 UTC
Created attachment 20272 [details] [review]
64-bit fixes
Comment 21 Gwenole Beauchesne 2003-09-25 09:33:44 UTC
There was a mismatch between the 32-bit values returned through
XGetAsyncData(), and 64-bit (long) that were expected from
xPropSizeHints et al.

You can optimize it further for 32-bit with proper #if SIZEOF_LONG ==
8/#endif, if you check for them in configury scripts of course. Oh, I
think X defines LONG64 too.
Comment 22 Havoc Pennington 2003-09-29 18:20:45 UTC
I think the problem you're patching is bug #114035, which isn't the
same as this original bug report (the reopen was not right I think, 
as the change just happened to expose #114035, it didn't introduce it).

Let's further track this issue on bug #114035