From: richm@netcom.com (Richard Mauri)
Subject: Re: Drawing w/clipmask to obscurred window doesn't draw!
Date: Mon, 14 Sep 92 17:20:22 GMT
Organization: Netcom - Online Communication Services  (408 241-9760 guest) 
Keywords: ClipMask gc

In article <07xns4#.richm@netcom.com> richm@netcom.com (Richard Mauri) writes:
>In article <1992Sep11.184158.3825@miki.pictel.com> oj@miki.pictel.com (Oliver Jones) writes:
>>In article <4ssn2pm.richm@netcom.com>, richm@netcom.com (Richard Mauri) writes:
>>> I have a motif drawing area widget (destination window)
>>> that I draw vectors to with XDrawSegments() using a gc 
>>> w/o a clip mask. Then I draw a filled rectangle using 
>>> a gc with a clip mask....
>>> The problem is when
>>> the destination window is obscurred at the time of drawing,
>>> and then the destination window is exposed, only the segments,
>>> not the clipmasked rectangle, get redrawn. Backing store
>>> isn't doing it's job and I get no expose events either!
>>
>>I take it things work properly if you disable backing store by setting
>>it to NotUseful? ("Properly" means your program receives and processes
>>the Expose event generated when the destination window is exposed.)
>>If so, this is your workaround.  If not, I'd try to find out what's
>>going on with your client before looking to the server as the source
>>of the problem.
>>
>>In article <18n56rINN2df@fbi-news.Informatik.Uni-Dortmund.DE> 
>>   klute@heike.informatik.uni-dortmund.de (Rainer Klute) quotes 
>>   from the Xlib spec:
>>
>>>From chapter 3.2.4: ...
>>>While the X server maintains the window's contents, Expose events
>>>normally are not generated, but the X server may stop maintaining
>>>contents at any time.
>>
>>I always thought this meant that the server was supposed to 
>>start generating Expose events again at the time it chose to 
>>"stop maintaining" backing-store contents.  In particular,
>>I thought the word "while" meant "during the time."
>>
>>It's possible Richard Mauri has found a bug.  I would have thought
>>that the act of filling a rectangle through a GC clip (or any other
>>drawing) into an obscured part of a window should have one of two
>>effects:
>>
>>1) draw correctly into the backing store
>>2) cause the server to decide to stop maintaining the
>>   backing store, therefore causing it to perform
>>   expose processing the next time the obscured part
>>   of the window became uncovered.
>>
>>I didn't think the server had the option of BOTH ignoring a draw
>>operation to backing store AND omitting subsequent expose processing.
>>It's hard to imagine how a client would have the slightest chance of
>>maintaining valid visible window contents under these circumstances.
>>
>>Can anyone clarify this?  Am I missing something?
>>
>
>When I DON'T request backing store prior to performing the
>drawing and I perform the same sequence of events everything is OK.
>My application gets an expose event and I can redraw. This "workaround"
>basically says to me that backing store is USELESS for anything but
>the most trivial drawing. I also thought that if a sever dishonors
>backing store that it was guaranteed to pass expose events, but this
>does not to seem to be true. More troubling is that this is not confined
>to the xsun x11r4 server, my hp7000 server does this also!
>
>Is this truely a bug. Does it exist in x11r5 (I don't have that server yet)
>
>Has anyone ever managed to draw a graphic to a window with a clip mask,
>while backing store was requested and previously honored,
>while the window was obscurred and then exposed thew window and seen
>the graphic or at least received an expose event?
>
>Rich

This is a server bug as I carefully characterized and proved it to myself.

Here is a small program you can use to test an X server for this bug.
Note I have tested a few servers myself and feel this is
valuable knowledge for others.
 Rich

----------cut here---------------
/*
 * bsbug.c
 *
 *      Used to characterize a possible server bug.
 *
 * Here's a small program that demonstrates the server bug
 * You can use it to qualify your X servers.
 * Simply run bsbug with the top half of its window obscurred by say
 * an xterm. Then press button1 in the bsbug window. Then expose all
 * the bsbug window. If you see a bullseye then your server is ok,
 * otherwise add it to the list and beware. 
 * I was happy to find the X11R5 works, but we're not at R5 yet, 
 * so I have to live with the bug....
 *
 *      The problem occurs when a graphic is drawn to an
 *      obscurred window while backing store is enabled
 *      and a glip mask is used and then the window is
 *      exposed. The graphic is not refreshed by backing store
 *      and no expose events are generated.
 *
 *	This problem does NOT appear on at least:
 *	    MIT X11R5 Xsun server patch level 0
 *	    Tektronix TekExpress XP29  (R4 server)
 *	    DECstation 5000 (R4 server)
 *	    NCD 19 Xterminal
 *
 *	The problem does appear on:
 *	    MIT X11R4 Xsun patch level 18
 *	    HP 700/RX Xterminal
 *	    Openwindows 2.0 (sorta works; awfull rendering)
 *
 *	To build simply:
 *	   cc -c bsbug.c;cc -o bsbug bsbug.o -L/usr/lib/X11 -lXt -lXll
 *
 * Rich Mauri 9/12/92 (richm@netcom.com)
 */
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Core.h>
#include <X11/Xlib.h>
#include "bullseye.h"
#include <stdio.h>

static void exposeit();
static void drawit ();
static void AddBackingStore();

main (argc, argv)
  int    argc;
  char  *argv[];
{
  Widget toplevel, w;

  toplevel = XtInitialize (argv[0], "Bsbug", NULL, 0, &argc, argv);

  w = XtVaCreateManagedWidget ("bsbug", widgetClass, toplevel,
        XtNwidth, 100, XtNheight, 100, NULL);

  XtRealizeWidget (toplevel);

  XtAddEventHandler (w, ExposureMask, False, exposeit, NULL);
  XtAddEventHandler (w, ButtonPressMask|KeyPressMask,False, drawit, NULL);

  XtMainLoop();
}

static void exposeit(widget, unused, ev)
  Widget widget;
  XtPointer unused;
  XEvent * ev;
{
  AddBackingStore(widget);
}

static void drawit ( widget, unused, ev )
  Widget widget;
  XtPointer unused;
  XEvent * ev;
{
   static GC gc;
   static Display *dpy;
   static unsigned int width, height;
   static Drawable win;
   static Pixmap symbol;

   printf("drawit() \n");

   if (gc == NULL) {
        int xhot, yhot;
        unsigned long vmask = GCForeground;
        XGCValues v;

        v.foreground = BlackPixelOfScreen(XtScreen(widget));

        win = XtWindow(widget);
        dpy = XtDisplay(widget);
        gc  = XCreateGC(dpy, XtWindow(widget), vmask, v);

        if (BitmapSuccess != XReadBitmapFile (dpy, win, "bullseye.h",
            &width, &height, &symbol, &xhot, &yhot)) {
                printf(" Cant read bitmap file bullseye.h\n");
                return;
        }

        XSetClipMask (dpy, gc, symbol);
        XSetClipOrigin (dpy, gc, 10, 10);
   }

   XCopyPlane (dpy, symbol, win, gc, 0, 0, width, height, 10, 10, 1);

}

static void AddBackingStore(widget)
  Widget widget;
{
  static Bool first = True;

  if (first) {
    first = False;

    if (DoesBackingStore(XtScreen(widget))) {
        XSetWindowAttributes attr2;
        unsigned long mask;

        attr2.backing_store = Always;
        mask = CWBackingStore;
        XChangeWindowAttributes(XtDisplay(widget), XtWindowOfObject(widget),
            mask, &attr2);
        printf(" adding backing store\n");
    }
  }
}
-- 
Richard Mauri               // Not ready to face the winter.
SW Eng / X hack             // Pray for wind.
Trimble Navigation Ltd.     // Pay the bills.
richm@netcom.com	    // Hope nothing breaks
Newsgroups: comp.windows.x,comp.human-factors