[comp.windows.x] Simple programming quiz

elf@gilan.Berkeley.EDU (Marc Singer) (06/15/89)

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);

  XMapWindow(display, xwnd);
  XFlush(display);
/*  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

dana@dino.bellcore.com (Dana A. Chee) (06/15/89)

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;)

     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

mauney@cscadm.ncsu.edu (Jon Mauney) (06/16/89)

In article <DANA.89Jun15063723@dino.bellcore.com> dana@dino.bellcore.com (Dana A. Chee) writes:
>In article <29675@ucbvax.BERKELEY.EDU> elf@gilan.Berkeley.EDU (Marc Singer) writes:
>>
>>   Why does this apparently simple X program not work?
>>  	...
>>     XMapWindow(display, xwnd);
>>     XFlush(display);
>>     XDrawString(display, xwnd, gc, 10, 10, szLabel, strlen(szLabel));
>
>The great "Drawing in an unmapped window" error strikes again.
>

I would like to use this example as a springboard from which to
jump onto a soapbox and talk about the nature of Xlib programming.

The highly asynchronous nature of X takes quite a bit of getting
used to.  Therefore, those people who write about X need to be
careful to explain what is going on.

The "unmapped window" bug is a prime example.  I have two books
on Xlib programming, "X Window System" by Scheifler-Gettys-Newman,
and "Introduction to the Window X System" by Jones.  In neither
book does the discussion of XMapWindow even hint at this pitfall.
Even Dana Chee's explanation is subject to quibbling.  The Scheifler
book -- which I take as official, whether it is not -- says on p44
	"A window is considered mapped if an XMapWindow call has been
	made on it" (subject to various exceptions listed in subsequent
	paragraphs.)
Therefore the bug must be that the window is mapped but not exposed.

It seems reasonable that the X server will process requests in the
order that they are issued by the client.  Therefore it seems reasonable
that if I create a window, set its gc and attributes, and then
call XMapRaised followed by XFlush, then the window exists and
is mapped, and any subsequent draw requests should work.  If the server
needs extra time to finish mapping the window, well fine.  I issued
my requests in the proper order so I expect the server to service
them in the proper order.

Obviously, this is not actually the case.  I'm certain the Consortium
knows a good reason why it isn't the case.  I'm damn sure they aren't
going to change things at this point in the game.  But the Consortium
needs to make sure that the protocol definition is unambiguous about such
behavior, and writers of tutorials need to make such distinctions
blatantly obvious to the novice.

Obviously, all useful programs must have a loop that accepts expose
events, since a window may be obscured in many ways.  But there are
many reasons to want to write code that goes for quite a while before
looking at events, and during program development this is
especially true.


Jon Mauney  
Computer Science Dept, NCSU
mauney@cscadm.ncsu.edu   

colas@mirsa.inria.fr (Colas NAHABOO) (06/16/89)

From article <3184@ncsuvx.ncsu.edu>, by mauney@cscadm.ncsu.edu (Jon Mauney):
> Obviously, all useful programs must have a loop that accepts expose
> events, since a window may be obscured in many ways.  But there are
> many reasons to want to write code that goes for quite a while before
> looking at events, and during program development this is
> especially true.

No. All well-written (i.e working) programs on X MUST be event driven.

Colas NAHABOO        -- colas@mirsa.inria.fr
BULL Research FRANCE -- Koala Project -- GWM X11 Window Manager

dana@dino.bellcore.com (Dana A. Chee) (06/16/89)

In article <3184@ncsuvx.ncsu.edu> mauney@cscadm.ncsu.edu (Jon Mauney) writes:

   I would like to use this example as a springboard from which to
   jump onto a soapbox and talk about the nature of Xlib programming.

   Obviously, this is not actually the case.  I'm certain the Consortium
   knows a good reason why it isn't the case.  I'm damn sure they aren't
   going to change things at this point in the game.  But the Consortium
   needs to make sure that the protocol definition is unambiguous about such
   behavior, and writers of tutorials need to make such distinctions
   blatantly obvious to the novice.

I really should have gone further explaining this.  Here's "reality".
It is true that X processes events in the order received, but there
are a few 'gotchas' included in this, the prime one being the window
manager.  When a reparenting window manager is running (um, awm, twm,
etc), it tells X that it wants all Map and Configure events for the
children of the Root window (all top level windows) to be rerouted to
it (see SubstructureRedirectMask).  This means that the following
thing happens:

	client		Xserver		windowManager
	
	MapRequest ---->
			MapRequest --->
			(forwarded to wm)
	DrawRequest --->
	(notice map not done yet)
				<-----   MapRequest (for client)
			(window now mapped, but draw already done)

In a nutshell, the client sends in a MapRequest, the server forwards
that request to the windowmanager.  The client then sends in a Draw
request, which is ignored.  Some time later, after the window manager
has played around (creating title bars, etc), it sends the MapRequest
for the client's window to the server.  At this point, the window
becomes mapped.  So what is missing in the discussions is that
requests can be redirected, so things don't have to occur in the order
you supply them.

   Obviously, all useful programs must have a loop that accepts expose
   events, since a window may be obscured in many ways.  But there are
   many reasons to want to write code that goes for quite a while before
   looking at events, and during program development this is
   especially true.

But in this case you must, because without the expose event, you don't
know when the window manager has finished with your MapRequest and
given it back to the server.

Hope this helps clarify things.

   Jon Mauney  
   Computer Science Dept, NCSU
   mauney@cscadm.ncsu.edu   
--
			Dana Chee
			Bellcore
			MRE 2Q-250
			(201) 829-4488
			dana@bellcore.com

rws@EXPO.LCS.MIT.EDU (06/16/89)

   The Scheifler book -- which I take as official, whether it is not -- says on
   p44 ...

Yes, it says something bogus, thanks for pointing it out.  But note that in the
next paragraph it does go on to explain that a window manager may get in your
way.  Also, in the more "biblical" part of the book, MapWindow on page 368 has
a correct definition.  I'll agree the wording doesn't bludgeon you with a
warning.

    Therefore the bug must be that the window is mapped but not exposed.

Nope.

    If the server needs extra time to finish mapping the window, well fine.

Nope.  It's all on account of window manager redirection.

    But the Consortium needs to make sure that the protocol definition is
    unambiguous about such behavior,

I believe the protocol definition is unambiguous.  The Xlib manual has
wording that is clearly causing confusion for you.

egc@pie1.mach.cs.cmu.edu (eddie caplan) (06/20/89)

In article <188@mirsa.inria.fr> colas@mirsa.inria.fr (Colas NAHABOO) writes:
    >All well-written (i.e working) programs on X MUST be event driven.

i hope that you're joking.  i can think of X programs which just graphically
display data without taking any significant user input.  if you are suggesting
that X11 can't properly handle such programs then its time for X11 to pack its
bags and let a real windowing system become the standard.
-- 

jim@EXPO.LCS.MIT.EDU (Jim Fulton) (06/20/89)

> In article <188@mirsa.inria.fr> colas@mirsa.inria.fr (Colas NAHABOO) writes:
>     >All well-written (i.e working) programs on X MUST be event driven.
> 
> i hope that you're joking.  i can think of X programs which just graphically
> display data without taking any significant user input.

Events include more than just user input (e.g. Exposure).

toml@Solbourne.COM (Tom LaStrange) (06/20/89)

From article <5253@pt.cs.cmu.edu>, by egc@pie1.mach.cs.cmu.edu (eddie caplan):
>In article <188@mirsa.inria.fr> colas@mirsa.inria.fr (Colas NAHABOO) writes:
>    >All well-written (i.e working) programs on X MUST be event driven.
> 
>i hope that you're joking.  i can think of X programs which just graphically
>display data without taking any significant user input.  if you are suggesting
>that X11 can't properly handle such programs then its time for X11 to pack its
>bags and let a real windowing system become the standard.

Sure, you can write a program that pops up a window and starts drawing,  but
what happens when the window becomes obscured and then unobscured?  If you
always want your picture to be displayed correctly, you will either have
to put your program in a loop which continuously redraws your graphics
even though nothing may have changed, or you can at least handle an Expose
event in addition to waking up and doing something once in a while.  Two good
examples of this are xclock and xload.

Your X programs don't HAVE to be event driven, it just makes them more
efficient, i.e. "well-written".

--
Tom LaStrange

Solbourne Computer Inc.    ARPA: toml@Solbourne.COM
1900 Pike Rd.              UUCP: ...!{boulder,nbires,sun}!stan!toml
Longmont, CO  80501

peter@ficc.uu.net (Peter da Silva) (06/22/89)

[X window programs MUST be event-driven]

From article <5253@pt.cs.cmu.edu>, by egc@pie1.mach.cs.cmu.edu (eddie caplan):
>i hope that you're joking.

That was my response, too. Might as well program a Macintosh.

>i can think of X programs which just graphically
>display data without taking any significant user input.  if you are suggesting
>that X11 can't properly handle such programs then its time for X11 to pack its
>bags and let a real windowing system become the standard.

Unfortunately, you have to handle EXPOSE events.

In article <1493@imelda.Solbourne.COM>, toml@Solbourne.COM (Tom LaStrange) writes:
> Sure, you can write a program that pops up a window and starts drawing,  but
> what happens when the window becomes obscured and then unobscured?

Well, if X was a "real windowing system" (tm eddie caplan) the server would
recover the image from backing store (off-screen bitmaps, whatever).

Unfortunately X suffers from the Macintosh Syndrome... we'll make cuts in the
capability of the system to cram it into inadequate hardware and worry about
paying for it (in programmer time, poor matches to adequate hardware, and so
on) later on.
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.

Business: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.
Personal: ...!texbell!sugar!peter, peter@sugar.hackercorp.com.

mouse@LARRY.MCRCIM.MCGILL.EDU (der Mouse) (06/25/89)

>> Sure, you can write a program that pops up a window and starts
>> drawing, but what happens when the window becomes obscured and then
>> unobscured?

> Well, if X was a "real windowing system" (tm eddie caplan) the server
> would recover the image from backing store (off-screen bitmaps,
> whatever).

> Unfortunately X suffers from the Macintosh Syndrome... we'll make
> cuts in the capability of the system to cram it into inadequate
> hardware and worry about paying for it (in programmer time, poor
> matches to adequate hardware, and so on) later on.

If it bothers you that much, just give your windows a backing-store
hint of Always, or WhenMapped, or whatever your notion of a "real
windowing system" provides, and then document that it won't work
properly with servers that don't support "real windowing system"
backing-store semantics.  After all, if X required such things, your
program wouldn't run at all with such machines (they wouldn't havve
*any* server), so you haven't lost any potential usefulness....

What's the problem?

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu