Catching window managed events

Toplevels may be closed by several means, including with the X button on top or Alt-F4. Here's example code how to react to this event and have it confirmed. Code for saving files, status, etc. could also go in there (before the exit, of course ;-)

    wm protocol . WM_DELETE_WINDOW {
        if {[tk_messageBox \
                    -icon    question \
                    -type    yesno \
                    -default no \
                    -message "Do you want to go?" \
                    -title   "Quit Application?"] == "yes"} {
            exit
        }
    } ;# DKF - brought here by RS.

Jeffrey Hobbs writes: However, you can do the usual:

    bind . <Destroy> { puts "away I go" }

The advantage with the first (wm protocol .. [L1 ]) is just that you get it before the window goes away (in fact, you have to explicitly have that destroy or it will stay), which means it still exists and you can save info that might still be in the widgets. With the latter, you are already on the way down, but it still works. In the latter you also have to ensure you check on the %W, because <Destroy> will otherwise trigger for all the widgets in .top (bindtags).

DKF - This illustrates quite nicely the difference between trapping a request (what [wm protocol] handles) and a notification (what <Destroy> notices.) By the time the <Destroy> arrives it is too late to veto it - the window in question has already gone the way of the dodo - whereas WM_DELETE_WINDOW is really the window manager saying "Would you mind deleting this window, please?" and as such you can do whatever you want with it. Making it pop up 30 new windows in response is probably not a good move though... :^)

NEM - One point to remember with WM_DELETE_WINDOW though, is to make certain that your code for the handler is completely bug free (or you catch all errors). Otherwise, you can be left with a window that is impossible to close, without forcibly killing the process.

Brian Theado 19Mar05 - One thing to watch out for with binding the <Destroy> event to "." is that the binding fires for all destroyed windows. For Tk Game Pack, I was using code like the following to ensure the slave interpreter exits when the toplevel goes away (not shown - exit is aliased to just delete the slave interpreter):

 bind . <Destroy> +exit

This was causing an exit upon any destroyed windows. I changed it to

 bind . <Destroy> +[list if {"%W" == "."} exit]

and now it behaves the way I want. Now that I think about it, I realize this happens because by default the root window is in the bindtags for all widgets.


Donal explain that, in such usages as

      wm protocol <window> WM_DELETE_WINDOW {#}

"An empty string is taken as asking for the default behaviour (to destroy the appropriate toplevel.) Workaround is to set the protocol handler to a non-empty do-nothing script (comments are a favourite...)"


The syntax is

      wm protocol window ?name? ?command?

?name? here names "an atom corresponding to a window manager protocol ..." These atoms therefore are dependent on the governing window managers. Among those generally available are

  • WM_SAVE_YOURSELF
  • WM_DELETE_WINDOW
  • WM_TAKE_FOCUS
  • ...

The first three have a historical association with Motif, or ICCCM more specifically.

WM_SAVE_YOURSELF handlers must call "wm command ...". This will update the WM_COMMAND property on the top-level window, notifying the session manager (or whoever sent the message) that the message has been handled.

LV: Does anyone have a sample application which makes use of WM_SAVE_YOURSELF to save off options and then restore them at next execution of the application? In particular, I'd like to find someone with such an application that GNOME can identify and make a part of the current session upon request, without the user having to manually add to the session.

Tk applications should not register a protocol handler for WM_TAKE_FOCUS: the proper handling of WM_TAKE_FOCUS is very complicated and should be left to the toolkit. WM_TAKE_FOCUS is there to support a seldom-used keyboard focus model, which doesn't apply to Tk programs.

There apparently are not recognized WM_ICONIFY and such; instead, study "How I catch iconification and such".

"wm transient ..." can also help with some window managers ...

DKF: There's one more, _NET_WM_PING, but Tk does that for you without asking. (Scripts can't respond to it anyway.)


Also see the FAQ [L2 ].