I'm just trying to learn my way around Xlib, as I'm a Win32 programmer, and Xlib seems to be the closest counterpart to the Windows Api with Linux. I have various docs I've downloaded, and an old book vintage 1995 by Adrian Nye "Xlib Programming Manual". Anyway, in all the examples I've seen, it seems that everyone is doing absolutely everything remotely conceivable to skirt around the issue of trapping a DestroyWindow event so as to show how an application might call clean up code to release resources, etc. In Windows, if someone clicks the mouse on the little 'x' up in the upper right-hand corner of the window, Windows will send the window's Window Procedure a WM_CLOSE message. This gives an app time to call clean up procedures or bypass ending entirely.
After spending days trying to figure this out in Xlib I'm pretty much throwing up my hands in defeat! Below is the closest thing I have been able to come up with, but it does completely fail. The name of the program is CW2.c and at top is my command line for compiling it...
Code:
/*
gcc CW2.c -o CW2 -L/usr/X11R6/lib -lX11
*/
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
Display* display;
int blackColor,whiteColor;
Window hRootWnd,hMainWnd;
XEvent e;
display=XOpenDisplay(0);
if(!display)
return 1;
hRootWnd=DefaultRootWindow(display);
printf("hRootWnd=%u\n",hRootWnd);
blackColor=BlackPixel(display,DefaultScreen(display));
whiteColor=WhitePixel(display,DefaultScreen(display));
hMainWnd=
XCreateSimpleWindow
(
display,
DefaultRootWindow(display),
200,200,400,350,0,
blackColor,
whiteColor
);
printf("hMainWnd=%u\n",hMainWnd);
XSelectInput(display,hRootWnd,SubstructureNotifyMask);
XMapWindow(display,hMainWnd);
while(1)
{
XNextEvent(display,&e);
switch(e.type)
{
case Expose:
printf("Received Expose Event!\n");
break;
case MapNotify:
printf("Received MapNotify Event!\n");
break;
case UnmapNotify:
printf("Received UnmapNotify Event!\n");
break;
case ConfigureNotify:
printf("Received ConfigureNotify Event!\n");
break;
case DestroyNotify:
if(e.xdestroywindow.window==hRootWnd)
{
printf
(
"Received DestroyNotify Event From hRootWnd! -- hRootWnd=%u\n",
e.xdestroywindow.window
);
XCloseDisplay(display);
exit(1);
}
if(e.xdestroywindow.window==hMainWnd)
{
printf
(
"Received DestroyNotify Event For Main Window! -- hMainWnd=%u\n",
e.xdestroywindow.window
);
XCloseDisplay(display);
exit(1);
}
else
{
printf
(
"Received DestroyNotify Event But Not For Any Known Window! -- e.xdestroywindow.window=%u\n",
e.xdestroywindow.window
);
XCloseDisplay(display);
exit(1);
}
break;
default:
break;
}
}
return 0;
}
In terms of explanation, note that I defined two variables to hold what I'd refer to in Windows as window handles, i.e., the variables returned by a CreateWindow() call, here XCreateSimpleWindow(). I've come to understand that the main desktop window is called the 'Root Window', and that the DefaultRootWindow(display) function returns a window handle (id in Linux speak) for that window. I've further come to understand that the DestroyWindow event can only be caught by the parent of the main app through a
XSelectInput(display,hRootWnd,SubstructureNotifyMask);
call with SubstructureNotifyMask for the mask parameter. I've fooled around with all types of masks with both the root window and the main window, but under no circumstanes can I figure out a fool proof way of determining when the 'x' button on the main app window has been clicked. Below is the Terminal output from the above program showing compilation through a run of the program...
Code:
fredharris@CODEWARRIOR:~/CloseWindow$ gcc CW2.c -o CW2 -L/usr/X11R6/lib -lX11
fredharris@CODEWARRIOR:~/CloseWindow$ ./CW2
hRootWnd=69
hMainWnd=41943041
Received ConfigureNotify Event!
Received ConfigureNotify Event!
Received ConfigureNotify Event!
Received MapNotify Event!
Received UnmapNotify Event!
Received UnmapNotify Event!
Received ConfigureNotify Event!
Received ConfigureNotify Event!
Received MapNotify Event!
Received UnmapNotify Event!
Received UnmapNotify Event!
Received DestroyNotify Event But Not For Any Known Window! -- e.xdestroywindow.window=10552202
fredharris@CODEWARRIOR:~/CloseWindow$
Interestingly, the code above was able to catch a DestroyNotify event, but not for any window known to this application! Note that I printf'd the root window id ( 69 ), and the main windows's id (41,943,041), but the e.xdestroywindow.window's id pertaining to the DestroyWindow event was 10,552,202! Now which window is that? Would anyone be able to set me on the path to figuring out how to catch an app termination event caused by a click on the little 'x' in the title bar of the window???
Fred