[wmii] Fwd: (pseudo-)transparency bug in rxvt-unicode >= 5.x

From: Anselm R. Garbe <garbeam_AT_wmii.de>
Date: Fri, 19 May 2006 12:49:38 +0200

Just for documentation, I give no shit about it anymore,
because it seems that my mail has been defered by the developer
of rxvt-unicode. However I'm subscribed.


PS: If so, think if you really want to use rxvt-unicode in the
future. I can't recommend it anymore then. Take this report as
reference, I also think real ion3-users might be interested.

----- Forwarded message from "Anselm R. Garbe" <garbeam_AT_wmii.de> -----

Date: Fri, 19 May 2006 12:20:19 +0200
From: "Anselm R. Garbe" <garbeam_AT_wmii.de>
To: rxvt-unicode_AT_lists.schmorp.de
Subject: (pseudo-)transparency bug in rxvt-unicode >= 5.x
User-Agent: Mutt/1.5.9i

Hi there,

I joined the IRC channel to report schmorp about a bug in rxvt-unicode,
yesterday. Because he didn't seemed (http://wmii.de/urxvt.bug) to be
interested in it, I send this report to this list. I digged into the
rxvt-unicode code on my own, and found a semi-solution, which fixes the
bug for me, but not in general, because the overall behavior of
transparency-related refreshes in rxvt-unicode is quite broken.

If rxvt-unicode is run with -tr (Opt_transparent) argument, then it
performs XClearWindow calls on its parent windows, which rxvt-unicode
does not own(!) at all. This results in an undrawed frame in all window
managers, which do not set a background pixmap to frame windows (an
XClearWindow call restores the window's background pixmap for those
window managers who set a pixmap, for ParentRelative frames it simply
clears them and makes their content looking like the root window).
Besides this, a side-effect (which is quite a hack indeed) is used in
rxvt-unicode, because the XClearWindow call is identical to
XClearArea(display, window, 0, 0, 0, 0, False); - the last argument is a
Bool which indicates if exposure events are reported to the window owner
or not, if he selects input for them. Hence an XClearWindow call
suppresses any exposure events, thus the window manager doesn't can't
redraw its frame correctly.

This behavior is simply broken, because it does not conform to the very
fundamental ICCCM conventions
(http://tronche.com/gui/x/icccm/sec-4.html), to not draw (clearing is a
special case of draw) on windows, which an application does not own or
has not created. The only exception is for programs which set the
wallpaper of the root window. Besides this, rxvt-unicode breaks this
convention somwhat more through using the XClearWindow call, which
suppresses any notification that the window's content changed to the

Nearly all window managers redraw their frame windows on exposure events
(only the window owner can draw on a frame window correctly). Because of
the described misbehavior, they cannot draw. This is not a problem in
these window managers, it is a problem in rxvt-unicode.

I rechecked with all releases of rxvt-unicode, the problem occures in
rxvt-unicode 5.x and 7.x, - only 3.x and earlier versions work fine.
There are much more window managers which do not set a background pixmap
of their rendering, than window managers who do. I only found metacity,
fluxbox, fvwm, and kwin who set a background pixmap of their rendering,
most others do not. Anyway rxvt-unicode shouldn't care about it.

In detail I found out, that he problem occures when calling the function
check_our_parents(). I changed the XClearWindow calls into XClearArea
counterparts, which re-enable the exposure reporting. Anyway, this is
not a real fix, because it only works around the broken behavior of
rxvt-unicode to draw on windows it does not own, but at least window
managers get notified if rxvt-unicode does so.

diff -ur rxvt-unicode-7.7.orig/src/command.C rxvt-unicode-7.7/src/command.C
--- rxvt-unicode-7.7.orig/src/command.C 2006-05-18 16:00:56.000000000 +0200
+++ rxvt-unicode-7.7/src/command.C 2006-05-18 16:02:10.000000000 +0200
@@ -2565,8 +2565,7 @@
           XFreeGC (dpy, gc);
           XDestroyImage (image);
           XSetWindowBackgroundPixmap (dpy, parent[0], pixmap);
- XClearWindow (dpy, parent[0]);
+ XClearArea (dpy, parent[0], 0, 0, 0, 0, True);
           if (!am_transparent || !am_pixmap_trans)
             pchanged = 1;
@@ -2626,7 +2625,7 @@
           for (n = 0; n < (unsigned int)i; n++)
               XSetWindowBackgroundPixmap (dpy, parent[n], ParentRelative);
- XClearWindow (dpy, parent[n]);
+ XClearArea (dpy, parent[n], 0, 0, 0, 0, True);
           XSetWindowBackgroundPixmap (dpy, vt, ParentRelative);

However, this fix does not work with window managers who set their frame
window backgrounds to a not-ParentRelative pixmap, because
rxvt-unicode's transparency handling is based on suppressing the
exposure events - I think this hack prevents flicker in some
window managers (namely metacity or kwin), but no client should behave
that way.

To fix the overall transparency behavior, I make following proposals as
starting point:

- If you need (pseudo-)transparency, check if XROOTPMAP_ID is set as
  property of the root window, if so fetch this, if not, create a
  ParentRelative window (with override_redirect=1) of the screen-size,
  clear it and copy its background as value into a pixmap (use this
  pixmap as background instead), destroy this window afterwards (aterm
  did this strategy just as an example)
- Select input for PropertyNotify events to listen for XROOTPMAP_ID
  updates (if you receive such event, update your background pixmap)
- If tinting is enabled, tint the pixmap after each update to
  XROOTPMAP_ID or if you fetch it with the temporary ParentRelative
  window trick
- Instead of clearing the root window or any parent window (why does
  rxvt-unicode needs to know the parent windows at all?), use the
  geometry of the client (vt) window and perform refreshes as follows:
    - use an off-screen pixmap of the size of the vt window
    - map the matching pixmap area to the exposed area of this
    - do the glyph rendering/colorization
    - map the exposed area of the offscreen vt pixmap to the vt window
      (you won't notice any flicker)

Thus you don't need to clear any windows you don't own, you only need to
take care of your own vt window, and of the root window if you need to
fetch the XROOTPMAP_ID.


 Anselm R. Garbe  ><><  www.ebrag.de  ><><  GPG key: 0D73F361
----- End forwarded message -----
 Anselm R. Garbe  ><><  www.ebrag.de  ><><  GPG key: 0D73F361
Received on Fri May 19 2006 - 12:49:38 UTC

This archive was generated by hypermail 2.2.0 : Sun Jul 13 2008 - 16:05:37 UTC