From: jeb@lazarus.nrtc.northrop.com (Jim Brennan)
Newsgroups: fj.mail-lists.x-window
Subject: getting XShape extension events into Xt
Date: 10 Nov 92 10:02:04 GMT
Distribution: fj
Organization: Northrop Research and Technology Center, Palos Verdes, CA

Date: 5 Nov 92 01:28:48 GMT
Message-Id: <42367@gremlin.nrtc.northrop.com>
Newsgroups: comp.windows.x.intrinsics,comp.windows.x

I'm having this problem with Xt.  It appears that Xt does not
recognize the ShapeNotifyMask used by the Shape Extension.  The
ShapeNotify event is sent whenever the shape of a window changes.  In
order to tell the Shape Extension the you are interested in the
ShapeNotify event, a XShapeSelectInput call is made.  Then in the X
Event loop, the application watches for an event type of event_base +
ShapeNotify (see program #1).

This works great for when using an X Event loop.  The problem problem
arises when you want have the ShapeNotify events come through
Xt[App]MainLoop.  Looking in the extensions/shape.h file for
X11R5, you'll notice that the ShapeNotifyMask is defined as (1L << 0)
or 0x1.  Obviously this mask will not and does not work for a
XtAddEventHandler call.

The question is this: is there any way to have Xt[App]MainLoop call a
specified routine for extension events?

Note: the two following programs illustrate the problem.  The first
program is a strait X program and understands the ShapeNotify event.
The second program is a Xt based program and, as of yet, cannot
understand the ShapeNotify event.

Thanks for any help,

Jim Brennan
---
jeb@nrtc.northrop.com

-------------------------------------------------------------------------------
/* 
 * program 1: This provides a strait X program for which to test the 
 * ShapeNotify event.  To compile: cc -o program program.c -lXext -lX11. 
 * Do a button press over the rectangular area to re-shape the widget.
 */

#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/extensions/shape.h>

static void
ChangeShape (display, window, window_width, window_height)
    Display *display;
    Window   window;
    int      window_width;
    int      window_height;
{
	static int     call_cnt = 0;

	unsigned long  white_pixel;
	unsigned long  black_pixel;
	Pixmap         pixmap;
	GC             gc;
	XGCValues      gc_values;

	white_pixel = WhitePixel (display, DefaultScreen (display));
	black_pixel = BlackPixel (display, DefaultScreen (display));

	pixmap = XCreatePixmap (display, window, window_width,
				window_height,1);

	gc_values.line_width = 10;
	gc = XCreateGC (display, pixmap, GCLineWidth, &gc_values);

	XSetForeground (display, gc, white_pixel);
	XFillRectangle (display, pixmap, gc, 0, 0, window_width,
			window_height);
	XSetForeground (display, gc, black_pixel);

	if (call_cnt++ % 2 == 0)
	    XDrawLine (display, pixmap, gc, 0, 0, window_width, window_height);
	else
	    XDrawLine (display, pixmap, gc, window_width, 0, 0, window_height);

	XShapeCombineMask (display, window, ShapeBounding, 0, 0, pixmap,
			   ShapeSet);

	XFreeGC (display, gc);
	XFreePixmap (display, pixmap);
}

void
main ()
{
	Display       *display;
	Window         top;
	Window         shape;
	unsigned long  white_pixel;
	unsigned long  black_pixel;
	XEvent         event;
	int            event_base;
	int            error_base;

	/* Open the display */
	
	display = XOpenDisplay (NULL);

	white_pixel = WhitePixel (display, DefaultScreen (display));
	black_pixel = BlackPixel (display, DefaultScreen (display));

	/* 
	 * Does the server have the shape extension?  If no, print an 
	 * error message.
	 */

	if (!XShapeQueryExtension (display, &event_base, &error_base)) {
		printf ("shape extension required to run this program\n");
		exit (1);
	}

	/* Create the top window */

	top = XCreateSimpleWindow (display, DefaultRootWindow (display),
				   100, 100, 500, 500, 0, black_pixel,
				   white_pixel);
	XSelectInput (display, top, KeyPressMask);

	/* create the shaped window */

	shape = XCreateSimpleWindow (display, top, 100, 100, 100, 100, 0,
				     black_pixel, black_pixel);
	XSelectInput (display, shape,
		      ButtonPressMask | KeyPressMask | ShapeNotifyMask);
	XShapeSelectInput (display, shape, ShapeNotifyMask);

	XMapWindow (display, top);
	XMapWindow (display, shape);

	printf ("event_base: %d\n", event_base);
	while (1) {
		XNextEvent (display, &event);

		switch (event.type) {
		    case Expose:
			printf ("got Expose\n");
			break;
		    case ConfigureNotify:
			printf ("got ConfigureNotify\n");
			break;
		    case ButtonPress:
			printf ("got ButtonPress\n");
			ChangeShape (display, shape, 100, 100);
			break;
		    case KeyPress:
			exit (0);
			break;
		    default:
			if (event_base + ShapeNotify == event.type)
			    printf ("got ShapeNotify\n");
			else
			    printf ("got unknown event (%d)\n", event.type);
			break;
		}
	}
}

------------------------------------------------------------------------------
/* 
 * program 2: This provides a Xt based program for testing the 
 * ShapeNotify event.  To compile: cc -o program program.c -lXt -lXext -lX11.
 * Do a button press over the rectangular area to re-shape the widget.
 */

#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/extensions/shape.h>
#include <X11/Intrinsic.h>

static void
ChangeShape (display, window, window_width, window_height)
    Display *display;
    Window   window;
    int      window_width;
    int      window_height;
{
	static int     call_cnt = 0;

	unsigned long  white_pixel;
	unsigned long  black_pixel;
	Pixmap         pixmap;
	GC             gc;
	XGCValues      gc_values;

	white_pixel = WhitePixel (display, DefaultScreen (display));
	black_pixel = BlackPixel (display, DefaultScreen (display));

	pixmap = XCreatePixmap (display, window, window_width,
				window_height,1);

	gc_values.line_width = 10;
	gc = XCreateGC (display, pixmap, GCLineWidth, &gc_values);

	XSetForeground (display, gc, white_pixel);
	XFillRectangle (display, pixmap, gc, 0, 0, window_width,
			window_height);
	XSetForeground (display, gc, black_pixel);

	if (call_cnt++ % 2 == 0)
	    XDrawLine (display, pixmap, gc, 0, 0, window_width, window_height);
	else
	    XDrawLine (display, pixmap, gc, window_width, 0, 0, window_height);

	XShapeCombineMask (display, window, ShapeBounding, 0, 0, pixmap,
			   ShapeSet);

	XFreeGC (display, gc);
	XFreePixmap (display, pixmap);
}

static void
ExitEH (w, client_data, event, continue_to_dispatch)
    Widget     w;
    XtPointer  client_data;
    XEvent    *event;
    Boolean   *continue_to_dispatch;
{
	exit (0);
}

static void
ButtonPressEH (w, client_data, event, continue_to_dispatch)
    Widget     w;
    XtPointer  client_data;
    XEvent    *event;
    Boolean   *continue_to_dispatch;
{
	Dimension width, height;

	XtVaGetValues (w, "width", &width, "height", &height);

	ChangeShape (XtDisplay (w), XtWindow (w), width, height);
}

static void
ShapeChangeEH (w, event_base, event, continue_to_dispatch)
    Widget     w;
    int        event_base;
    XEvent    *event;
    Boolean   *continue_to_dispatch;
{
	printf ("shape change (%d)\n", event->type);
}

void
main (argc, argv)
    int   argc;
    char *argv[];
{
	Widget         top;
	Widget         composite;
	Widget         shape;
	unsigned long  white_pixel;
	unsigned long  black_pixel;
	XEvent         event;
	int            event_base;
	int            error_base;

	top = XtInitialize ("shapeTest", "ShapeTest", NULL, 0, &argc, argv);

	white_pixel = WhitePixel (XtDisplay (top),
				  DefaultScreen (XtDisplay (top)));
	black_pixel = BlackPixel (XtDisplay (top),
				  DefaultScreen (XtDisplay (top)));

	/* 
	 * Does the server have the shape extension?  If no, print an 
	 * error message.
	 */

	if (!XShapeQueryExtension (XtDisplay (top), &event_base, &error_base)){
		printf ("shape extension required to run this program\n");
		exit (1);
	}

	/* create the shaped window */

	composite = XtVaCreateManagedWidget ("himom", compositeWidgetClass,
					     top, "width", 500, "height", 500,
					     "white", black_pixel, NULL);
	XtAddEventHandler (composite, KeyPressMask, False, ExitEH, NULL);

	shape = XtVaCreateManagedWidget ("himom", coreWidgetClass, composite,
					 "x", 100, "y", 100,
					 "width", 100, "height", 100,
					 "background", black_pixel, NULL);
	XtAddEventHandler (shape, KeyPressMask, False, ExitEH, NULL);

	XtRealizeWidget (top);

	XShapeSelectInput (XtDisplay (top), XtWindow (shape), ShapeNotifyMask);

	XtAddEventHandler (shape, ButtonPressMask, False, ButtonPressEH, NULL);

	/* 
	 * The following call does not do anything.  ShapeChangeEH is 
	 * never called.  Any ideas on how to get it called?
	 */
	
/*	XtAddEventHandler (shape, ShapeNotifyMask, False, ShapeChangeEH,
			   event_base);*/


	XtMainLoop ();
}

------------------------------------------------------------------------------