#include	<Xm/PushB.h>
#include	<signal.h>

XtAppContext app;
Widget top, pb;

void done_process(Widget w, XtPointer c, XEvent *ev, Boolean *dis);
void do_process(Widget w, XtPointer c, XtPointer s);

void
sigchld()
{
    wait(NULL);
}

int
main(int ac, char *av[])
{
    top = XtAppInitialize(&app, "Sample",
		    NULL, 0, &ac, av, NULL, NULL, 0);
    XtAddEventHandler(top, NoEventMask, True, done_process, NULL);
    signal(SIGCHLD, sigchld);

    pb = XmCreatePushButton(top, "Push me !!", NULL, 0);
    XtAddCallback(pb, XmNactivateCallback, do_process, NULL);
    XtManageChild(pb);

    XtRealizeWidget(top);
    XtAppMainLoop(app);
    return 0;
}

void ChildProcess();

void
do_process(Widget w, XtPointer c, XtPointer s)
{
    int pid;
    
    pid = fork();
    if (pid == -1) exit(1);
    else if (!pid) {
    	ChildProcess();
    }
    /* 子プロセス開始時に行う処理 */
    XtSetSensitive(w, False);
}

void
done_process(Widget w, XtPointer c, XEvent *ev, Boolean *dis)
{
    Atom msgtype;

    /* イベントの種類をチェック */
    msgtype = XInternAtom(XtDisplay(w), "_MY_PROTOCOLS", False);
    if (ev->type != ClientMessage ||
	ev->xclient.message_type != msgtype) return;

    /* 子プロセス終了時に実行する処理 */
    XtSetSensitive(pb, True);
}

void SendMessage(Widget w);

void
ChildProcess()
{
    puts("start");
    sleep(10); /* ここに実際に行う処理を入れてね */
    puts("done");

    SendMessage(top);
    exit(0);
}

void
SendMessage(Widget w)
{
    XClientMessageEvent ev;
    Display *dpy;

    /* サーバとの接続を張り直す */
    dpy = XtDisplay(w);
    close(ConnectionNumber(dpy));
    dpy = XOpenDisplay(DisplayString(dpy));
    /**/
    ev.display = dpy;
    ev.window = XtWindow(w);
    ev.type = ClientMessage;
    ev.message_type = XInternAtom(dpy, "_MY_PROTOCOLS", False);
    ev.format = 32;
    XSendEvent(dpy, ev.window, False, NoEventMask, (XEvent *)&ev);
    XCloseDisplay(dpy);
}
