[gnu.ghostscript.bug] The solution to the x_open getchar mystery

hrp@boring.cray.com (Hal Peterson) (07/28/89)

That's quick.  I got this message from Peter Phillips in response to
my question about the getchar in x_open:

    Return-Path: <pphillip@cs.ubc.ca>
    Date: 25 Jul 89 17:03 -0700
    From: Peter Phillips <pphillip@cs.ubc.ca>
    To: Hal Peterson <hrp@cray.com>
    Subject: getchar in x open: superfluous?

    In gnu.ghostscript.bug, you wrote:

[my query deleted. -hrp]

    The problem was explained by Dana Chee in comp.windows.x:

    >Article 10377 of comp.windows.x:
    >Path: ubc-cs!uw-beaver!cornell!mailrus!tut.cis.ohio-state.edu!unmvax!deimos.cis.ksu.edu!rutgers!bellcore!dana
    >From: dana@dino.bellcore.com (Dana A. Chee)
    >Newsgroups: comp.windows.x
    >Subject: Re: Simple programming quiz
    >Message-ID: <DANA.89Jun15063723@dino.bellcore.com>
    >Date: 15 Jun 89 10:37:23 GMT
    >References: <29675@ucbvax.BERKELEY.EDU>
    >Sender: news@bellcore.bellcore.com
    >Organization: Bellcore, Morristown, NJ  USA
    >Lines: 78
    >In-reply-to: elf@gilan.Berkeley.EDU's message of 14 Jun 89 21:45:10 GMT
    >
    >In article <29675@ucbvax.BERKELEY.EDU> elf@gilan.Berkeley.EDU (Marc Singer) writes:
    >
    >   Why does this apparently simple X program not work?
    >
    >   ----------------------
    >
    >   /* test.c
    >   */
    >   #include <X11/Xlib.h>
    >
    >   static char szLabel[] = "Hi there.";
    >
    >   main()
    >   {
    >     Display *display;
    >     Window xwnd;
    >     XSetWindowAttributes attrib;
    >     XGCValues xgcv;
    >     GC gc;
    >     char ch;
    >
    >     display = XOpenDisplay(0);
    >
    >     attrib.background_pixel = WhilePixel(display, 0);
    >     attrib.border_pixel =     BlackPixel(display, 0);
    >     xwnd = XCreateWindow(display, RootWindow(display, 0),
    >			  10, 10, 500, 40,
    >			  2, CopyFromParent, InputOutput, CopyFromParent,
    >			  CWBackPixel | CWBorderPixel | CWEventMask, &attrib);
    >
    >What's the event mask (attrib.event_mask = ?), since you set the flags
    >saying you were going to set it? (for problem below, you need at least
    >attrib.event_mask = Expose;)

      [ oops.  That should be "attrib.event_mask = ExposureMask" ]

    >
    >
    >     XMapWindow(display, xwnd);
    >     XFlush(display);
    >
    >Great, now wait for an expose event that says your window has been
    >mapped.  Until that comes, you are drawing on the window before it is
    >being mapped and your strings and lines are going directly into the
    >bit bucket.  Add the following line (and define "Event event" above)
    >
    >XNextEvent(display, &event);
    >
    >   /*  xgcv.foreground = BlackPixel(display, 0); */
    >   /*  xgcv.function = GXinvert; */
    >   /*  xgcv.plane_mask = AllPlanes; */
    >   /*  gc = XCreateGC(display, xwnd, GCForeground | GCFunction | GCPlaneMask,
    >		    &xgcv); */
    >     gc = XCreateGC(display, xwnd, 0, 0);
    >     XDrawString(display, xwnd, gc, 10, 10, szLabel, strlen(szLabel));
    >     XDrawLine(display, xwnd, gc, 0, 0, 500, 40);
    >   /*  XFillRectangle(display, xwnd, gc, 0, 0, 1000, 1000); */
    >     XFlush(display);
    >     ch = getchar();
    >   }  /* main */
    >
    >   ------------------  
    >
    >   I know that some of the attributes for the window and the GC are
    >   redundant.  And I have tried specifying the visual and depth
    >   of the XCreateWindow explicitly.  Still, why do I not get anything
    >   other than a background in the window?
    >
    >  Marc Singer
    >	   "When fullness is taken from fullness,
    >	    fullness still remains."
    >			   Invocation of the Isha Upanishad
    >
    >
    >The great "Drawing in an unmapped window" error strikes again.
    >
    >--
    >			Dana Chee
    >			Bellcore
    >			MRE 2Q-250
    >			(201) 829-4488
    >			dana@bellcore.com

    This is exactly ghostscript's problem. The fix, as outlined above, is
    quite trivial.  I send a patch to the author but it must have gotten lost.
    It is a real bug if the server is slow and can't map the window on the screen
    before ghostscript starts sending graphics requests.  Here's a diff to
    gdevx.c, version 1.2, that fixes the problem.  It should be easy to apply
    the same fix to 1.3.

[diff deleted. -hrp]

    Hope this helps.

    Peter Phillips <pphillip@cs.ubc.ca> (604)-228-4392

It helps quite a lot.  Here are new diffs to the 1.3 gdevx.c that
insert the wait for the exposure event.

--
Hal Peterson			Domain:  hrp@cray.com
Cray Research			Old style:  hrp%cray.com@uc.msc.umn.edu
1440 Northland Dr.		UUCP:  uunet!cray!hrp
Mendota Hts, MN  55120  USA	Telephone:  +1 612 681 3145

========================================================================
*** gdevx-DIST.c        Sun Jul 23 13:28:29 1989
--- gdevx.c     Thu Jul 27 16:18:03 1989
***************
*** 166,171 ****
--- 166,172 ----
  {     XSetWindowAttributes xswa;
        int winW, winH;
        int winX, winY;
+       XEvent event;
  #ifdef DEBUG
  if ( gs_debug['X'] )
        { extern int _Xdebug;
***************
*** 217,223 ****
        xdev->ht.pixmap = (Pixmap)0;
        xdev->ht.bits = 0;
        xdev->fill_style = FillSolid;
!       xswa.event_mask = 0;
        xswa.background_pixel = xdev->black;
        xdev->win = XCreateWindow(xdev->dpy, RootWindowOfScreen(xdev->scr),
                              winX, winY, winW, winH, 0,
--- 218,224 ----
        xdev->ht.pixmap = (Pixmap)0;
        xdev->ht.bits = 0;
        xdev->fill_style = FillSolid;
!       xswa.event_mask = ExposureMask;
        xswa.background_pixel = xdev->black;
        xdev->win = XCreateWindow(xdev->dpy, RootWindowOfScreen(xdev->scr),
                              winX, winY, winW, winH, 0,
***************
*** 227,232 ****
--- 228,235 ----
        XChangeProperty(xdev->dpy, xdev->win, XA_WM_NAME, XA_STRING, 8,
                        PropModeReplace, "Ghostscript", 11);
        XMapWindow(xdev->dpy, xdev->win);
+       XFlush(xdev->dpy);
+       XNextEvent(xdev->dpy, &event); /* Wait for exposure. */
        xdev->ht.no_pixmap = XCreatePixmap(xdev->dpy, xdev->win, 1, 1,
                                     DefaultDepthOfScreen(xdev->scr));
        /* Set up a graphics context */