[comp.windows.x] trapping ClientMessage

loo@mprgate.mpr.ca (Richard Loo) (12/12/90)

Hi, Can someone point out why I am having problems trapping ClientMessages 
using the following program?

This little program is an experiment to trap client messages in one of two
ways:

1. Writing a main loop that specifically cases on a ClientMessage event type.
This works; i.e., the cleanUp function does get invoked when I close the
window using the window manager menu.

2. Using XtMainLoop directly.  In this case, the idea is to trap the Client
Message with an event handler. This does not work; i.e., msgTrap declared
as the event handler does not get invoked.

I am using X11R3 and Motif 1.0.

Any insight into why Method 2 does not work will be greatly appreciated; 
thanks in advance.

Richard

------------------------------------------------------------------------------
#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xatom.h>
#include <Xm/Xm.h>
#include <Xm/Label.h>

static Atom WmDeleteWindowAtom = None;
static Atom WmProtocolAtom = None;

static void cleanUp(void);
static void declareProtocol( Widget topLevel);
static void msgTrap( Widget w, caddr_t client_data, XEvent *event);
static void quit( Widget w, caddr_t client_data, XEvent *event);

void main(
    int     argc,
    char  **argv)
{
    Widget   toplevel, msg_widget;
    Arg      args[5];
    int      n;
    char     message[10] = "hello";
    XEvent   event;

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

    n = 0;
    XtSetArg(args[n], 
             XmNlabelString, 
             XmStringCreate(message, "")); n++;

    msg_widget = XtCreateManagedWidget ( "msg",
                                         xmLabelWidgetClass,
                                         toplevel, args, n);

    XtAddEventHandler ( msg_widget, ButtonPressMask, FALSE, quit, NULL);

    XtAddEventHandler ( msg_widget, NoEventMask, TRUE, msgTrap, NULL);

    XtRealizeWidget(toplevel);

    declareProtocol(toplevel);

/*  Method 1 (works)  */
    while (1)
    {
        XtNextEvent ( &event );
        switch (event.type) {
        case ClientMessage:
          if ((event.xclient.message_type == WmProtocolAtom) &&
              (event.xclient.data.l[0]    == WmDeleteWindowAtom))
            {
              cleanUp();
            }
          break;
        }
        XtDispatchEvent(&event);
    }

/*  Mechod 2 (does not work)
    XtMainLoop();
*/

}

static void declareProtocol(
    Widget topLevel)
{
    WmDeleteWindowAtom = XInternAtom(XtDisplay(topLevel),
                                    "WM_DELETE_WINDOW",
                                     False);

    WmProtocolAtom = XInternAtom(XtDisplay(topLevel),
                                "WM_PROTOCOLS",
                                 False);

    if ((WmDeleteWindowAtom == None)||(WmProtocolAtom == None))
        return;

    XChangeProperty(XtDisplay(topLevel),
                    XtWindow(topLevel),
                    WmProtocolAtom,
                    XA_ATOM,
                    32,
                    PropModeReplace,
                    (unsigned char *) &WmDeleteWindowAtom,
                    1);

    printf("@declareProtocol: DeleteWindowAtom = %u, ProtocolAtom = %u\n",
                              WmDeleteWindowAtom,    WmProtocolAtom);
}

static void cleanUp()
{
    printf("@cleanUp\n");
}

static void msgTrap(
    Widget   w,
    caddr_t  client_data,
    XEvent  *event)
{
    printf("@msgTrap\n");
}

static void quit(
    Widget   w,
    caddr_t  client_data,
    XEvent  *event)
{
    printf("@quit\n");
}