[comp.windows.x] Can "widgetClass" widget do graphics? Really?

cowan@soleil.sps.mot.com (Andrew H Cowan) (03/29/91)

A while back I saw mention of a "poor man's graphics" widget that
was created by using the core widget "widgetClass".  I've tried 
using this to create a simple graphics window in which I can
draw stuff, but to no avail.

The following program creates a core widget "widgetClass" and a
pixmap.  I draw a rectangle into the pixmap then "XCopyPlane" the
pixmap to the widget.  Am I way off base?

I get the widget up, but no graphics appear.  

Please give me a clue.

        **                   /   \                   **
     ** **                  |     |                  **
     ** ** **                \___/                   ** **
     ********                                        ** **
      ******         __                  **          ****
        **        \_/oo\_/              ****         **
........**..........\||/................****.........**...........
Andy Cowan...........||.............cowan@soleil.sps.mot.com......

Define these resources:
	ClueMe*drawingarea.height: 300
	ClueMe*drawingarea.width: 600

Compile with (on a Sun4 or Solbourne): 
	cc -o ClueMe main.c -g -DXAW_BC -Dsun -DDEBUG -DX11R4 -I. -lXaw -lXmu -lXext -lXt -lX11

============ program start ===========

#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/Text.h>
#include <X11/Xaw/AsciiText.h>

Display *AppDisplay;
Widget Toplevel;     /* The Top of the widget hierarchy */
Widget drawingarea;  /* Global Core widget "widgetClass" drawing area widget */
Pixmap drawpixmap;   /* Pixmap for drawing graphics */
GC cleargc,drawgc;   /* GCs for clearing the pixmap, and drawing into the pixmap */

main(argc, argv)
int argc;
char *argv[];
{
   int i;
   Window win;
   XtAppContext ClueMeappcon;	

   Toplevel = XtAppInitialize( &ClueMeappcon, "ClueMe",
			       NULL, 0,
			       &argc, argv,
                               NULL, 
                               NULL, 0 );

   initdrawingarea( Toplevel );  /* inits drawingarea widget & drawgc GC */

   XtRealizeWidget( Toplevel );

   /* Draw a rectangle in the pixmap */
   XDrawRectangle( XtDisplay( drawingarea ),  
		   drawpixmap, 
		   drawgc, 
		   15,15, 10, 10 );

   updatescreen();                   /* Copy the pixmap to the screen */

   XtAppMainLoop(ClueMeappcon);

}

initdrawingarea( parent )
Widget parent;
{
   Arg widgetargs[15];
   XGCValues values;
   XtGCMask mask = GCForeground | GCBackground;
   char *fontname = "9x15";
   XFontStruct *fontinfo;

   int j,width;

   /* Core widget "widgetClass" to create drawing area */
   j=0;
   printf( "Creating drawing area.\n" );
   drawingarea = XtCreateManagedWidget( "drawingarea",
      widgetClass,
      parent,
      widgetargs, j );

   /* Offscren pixmap to draw stuff into.  Pixmap is then     */
   /* copied to the window so that you can see fucking thing. */

   if ( drawpixmap == NULL ){
      /* allocate pixmap, and allocate a GC to clear the pixmap */
      drawpixmap = XCreatePixmap( XtDisplay( drawingarea ),
			RootWindow( XtDisplay(drawingarea),DefaultScreen( XtDisplay( drawingarea ))),
			drawingarea->core.width,
			drawingarea->core.height,
			1 );
      values.foreground = 0;
      values.background = 0;
      cleargc = XCreateGC(XtDisplay(drawingarea),
			drawpixmap,
			mask, &values);
		
      /* Now clear out the pixmap */
      XFillRectangle( XtDisplay(drawingarea),
			drawpixmap,
			cleargc,
			0, 0,
			drawingarea->core.width,
			drawingarea->core.height );

      /* Now making a GC for use when drawing into the pixmap */
      fontinfo = XLoadQueryFont( XtDisplay(drawingarea), fontname);
      
      mask = GCForeground | GCBackground | GCDashOffset | GCDashList | GCLineStyle | GCFillStyle | GCFont;
      values.foreground = 1;
      values.background = 0;
      values.dashes = 1;
      values.dash_offset = 0;
      values.line_style = LineSolid;
      values.fill_style = FillSolid;
      values.font = fontinfo->fid;
      drawgc = XCreateGC( XtDisplay(drawingarea),
			  drawpixmap,
			  mask,
			  &values );

   }
}
updatescreen()
{
   GC copygc;
   XtGCMask mask_copygc = GCForeground | GCBackground;
   XGCValues values_copygc;

   values_copygc.background = drawingarea->core.background_pixel;
   values_copygc.foreground = 1;

   copygc = XtGetGC( drawingarea, mask_copygc, &values_copygc );

   if ( XtIsRealized( drawingarea )){ 
      printf( "Updating screen. %d x %d\n", drawingarea->core.width, drawingarea->core.height );
      /* Use XCopyArea on mono-chrome displays */
      XCopyPlane( XtDisplay( drawingarea ), 
		  drawpixmap, 
		  XtWindow(drawingarea), 
		  copygc, 
		  0,0, drawingarea->core.width, drawingarea->core.height,
	          0, 0, 1 );
   }

}

cjmchale@cs.tcd.ie (Ciaran McHale) (03/30/91)

In <957@nddsun1.sps.mot.com> cowan@soleil.sps.mot.com (Andrew H Cowan) writes:

>A while back I saw mention of a "poor man's graphics" widget that
>was created by using the core widget "widgetClass".  I've tried 
>using this to create a simple graphics window in which I can
>draw stuff, but to no avail.
>
>The following program creates a core widget "widgetClass" and a
>pixmap.  I draw a rectangle into the pixmap then "XCopyPlane" the
>pixmap to the widget.  Am I way off base?

You should wait until you get an Expose event before you draw anything.
Your program doesn't and that is why no graphics appear. The core widget
(widgetClass) does not have any Expose callback resource so you can't
register a callback routine onto it directly. Instead, you can use the
function XtAddEventHandler() to get the intrinsics to invoke a procedure
when an Expose event is received. Your expose handler will be passed the
relevant widget as one of its parameters. Perform your drawing operations
on the window returned by XtWindow(). (There is another function,
XtDisplay(), which you'll also find useful.)

An alternative would be to obtain/write a widget which does have an
expose callback. Then you just register your expose handler via
XtAddCallback() rather than use XtAddEventHandler(). Such a widget comes
with the xball program which somebody posted a while back to (I think)
comp.sources.x. If you want a copy, and can't find it locally, then send
me email. It's 51k long, including the widget, docs and xball program.


Ciaran.
-- 
Ciaran McHale           "There's a lot to be said for verbosity."     ----
Department of Computer Science, Trinity College, Dublin 2, Ireland.   \  /
Telephone: +353-1-772941 ext 1538       FAX: +353-1-772204             \/
Telex: 93782 TCD EI                     email: cjmchale@cs.tcd.ie