Properly destroying a window

ok, this has come up since i ported from sdl to glx/xlib. what is the best way to destroy your window cleanly?

originally, i did this:

glXDestroyContext(disp, context);
XDestroyWindow(disp, xWin);
XCloseDisplay(disp);
exit(1);

but there were some strange artifacts left on the screen (black bars where the window had been, moving a window over them made them go away). so i looked at the man pages, and they said that XCloseDisplay(disp) would destroy all the windows and contexts that i had added to that display, so right now, im just using that. is that good enough, or am i leaving things laying around that i have to destroy explicitly?

also, when you click the close button in most window managers, what do they do to the window? i dont seem to be getting any unmap or destroy events when i click on the button. (but there is a message printed to the console: “X connection to :0.0 broken (explicit kill or server shutdown).”) does that just kill the process without letting me clean up afterwards (im using kde, with kwin, btw). is that supposed to happen, or does kwin just do it wrong?

thanks for any help

You should have checked out the link I posted before http://toolbox.sgi.com/linux/documents/OpenGL/overviews.html#OglXIn

Close the window before destroying it. Using XCloseDisplay seems to be pretty violent. I am using GLUT but is not closing the window with the close button the same as calling exit? If so use atexit but all this should be in the link above.

ok, none of those programs did anything other than call exit(), so perhaps X windows uses atexit, and destroys the windows properly on its own. is there any way to tell what is being left behind (like a program that lists all open windows, graphics contexts, etc)?

also, when i said i was using kde/kwin, i was not saying i am programing in kde, just saying what window manager i am using…

Actually, when you call exit(), you implicitely close the connection to the X server : under Linux and Unices in general, open files and sockets are closed when the process quits (including segfault!). The X server will thus detect the connection break and clean all the ressources allocated to the client (windows, etc). From the client side, any allocated memory will be automagically freed in any case (using malloc()or new()), but third party ressources might not. This can be the case of a GL context, you can’t make any assumption on it.

That said, it is a good practice to clean ressources at exit. Your sequence is allright. If you encounter any bug (crap on the desktop, etc), this can never be a programming fault, this is the display driver’s. I encountered such bugs occasionnaly with the 2313 version, but it’s harmless (once filled up an entire virtual desktop with garbage for no reason). Use the ‘xrefresh’ command to force a desktop redraw in these cases.

also, when you click the close button in most window managers, what do they do to the window? i dont seem to be getting any unmap or destroy events when i click on the button.

This one is always disturbing . Window decorations are not handled by the X server, but by the window manager, which is no more that another X client. X has no idea of what’s happening around windows (that’s why you can see so weird window managers under Unix ) : the close, minimize, maximize, and whatever-fuzzy-option buttons are window-manager specific.

That said, there is a minimum standard across window managers. For instance, they all provide a close button, and a default behaviour of proposing to kill the client/connection associated to the window. To override this, you have to intercept a message that is not coming from the X server, but from the window manager. This is inter-client communication. More precisely, the protocol used by window managers is called ICCCM (see http://tronche.com/gui/x/ for the whole story).

Now, how it works ? You need to fetch two atoms (= server ‘globals’ shared by all its clients) :

Atom wm_protocol = XInternAtom (disp, “WM_PROTOCOLS”, False);
Atom wm_close = XInternAtom (disp, “WM_DELETE_WINDOW”, False);

Next we elect to receive the ‘close’ event from the WM:

XSetWMProtocols (disp, win, &wm_close, 1);

From this point, our window can receive special X events (client messages) from the window manager. Let’s handle it :

switch (event.any.type) {
case ClientMessage:
if ((event.xclient.message_type == wm_protocol) // OK, it’s comming from the WM
&& ((Atom)event.xclient.data.l[0] == wm_delete)) // This is a close event
{

}
}

When you elect to receive the close event, the window manager won’t display the default dialog (proposing to kill your client). It’s now up to your app to decide, ignoring the close button being a possible decision, but it’s driving users mad (you still have ‘xkill’ left).

Now you understand why people use toolkits under X. This hide a lot of tidbits and does the right thing without you even know how the whole thing works. I must say programming the GDI or X is almost the same experience regarding those complicated details, but X has a much cleaner and modular design (it’s running on a wealth of platform and has a bunch of implementation, all perfectly interchangeable !).

[This message has been edited by zerodeux (edited 12-10-2001).]

ok, thanks a lot. it seems that if i close the glX context, and close the display, i get artifacts (regardless of what i do with the window) but any other combination of those three calls doesnt leave any artifacts. like you said, i also suspect this is a bug in the nvidia drivers, especially since i didnt have this problem before i upgraded to their latest drivers (2313), and i had the same problem when i was using sdl (again, it started after upgrading)…

again, thanks for all your help…

Interesting, I’ll try to investigate, but if you could make a precise bug report (different destroy sequence, what’s happening, your setup - kernel version, hardware, etc), it might help Nvidia ( linux-bugs@nvidia.com )

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.