CLIM mail archive


Killing CLIM frames

Dear CLIMers,

In converting an application from Symblics Dynamic Windows to CLIM 1.0,
I discovered that there was no (documented) way to do some of the things
that I had done in DW.  No big surprise, and I worked around most of the
changes, but one piece of functionality is vital.  The application
spawns gobs of processes, and I need some way to kill them whenever I
use the system menu to kill the frame.  Okay, okay, I could explicitly
execute an application command to kill them before using the system
menu, but that's a hassle.

This is actually a two-part gripe:

   1. There is no concept of "killing" an application frame in CLIM.
      Calling FRAME-EXIT just exits the current command loop; when you
      run (or select) the application again, you get the same instance
      of the application frame class (at least in Genera 8.1).  Killing
      a frame ought to remove it from any lists maintained by the
      underlying OS, and release any resources that it has allocated.

      In addition, there may be other system events for which CLIM might
      provide hooks:  frame exposure, deexposure, activation,
      deactivation, and selection come to mind, when they make sense
      for a particular platform.

   2. Even if I invent my own kill method, there's no (documented) way
      in Genera to invoke it when I kill the frame from the system menu
      (i.e., no equivalent of DW:BEFORE-PROGRAM-FRAME-KILL-HANDLER).

Included below is some code I wrote to address these problems.  Comments
about the code or about the concepts themselves are solicited!

Finally, there seems to be a bug in Symbolics CLIM 1.0 in which the
top-level process associated with an application frame is left running
when the application is killed via the system menu.  This may just be
something that was missed in the attempt to integrate CLIM and Genera.
The bug fix is also included.

Thanks mucho!

Phil Stubblefield                                        (415) 325-7165
Rockwell Palo Alto Laboratory          


;;; -*- Mode: LISP; Syntax: Common-lisp; Package: CLIM; Base: 10 -*-

;;;; Protocols for killing CLIM frames.
;;; The code in this file provides a protocol for killing CLIM frames
;;; when they are no longer needed.

(cl:in-package "CLIM")


;;;; The FRAME-KILL generic function.
;;; Called when the frame is no longer needed.  Methods defined by the
;;; user might take such actions as releasing resources that are no
;;; longer needed.  The default primary method does nothing, while an
;;; :AFTER method exits the frame if necessary.

(defgeneric frame-kill (frame))

(defmethod frame-kill ((frame application-frame))

(defmethod frame-kill :after ((frame application-frame))
  (when (and (boundp '*application-frame*)
	     (eq *application-frame* frame))
    (frame-exit frame)))

;;; In Genera, FRAME-KILL is invoked by this :AFTER method on the :KILL
;;; message.  (I found the connection from sheet to frame by examining
;;; Genera 8.1 source code.)

(scl:defmethod (:kill clim-sheet :after) ()
  (let* ((window (clim-window-for-host-window scl:self :error-if-no-match nil))
	 (frame (and window (window-stream-to-frame window))))
    (unless (null frame)
      (frame-kill frame))))


;;;; A Genera bug-fix.

;;; DW:PROGRAM-FRAME, the analog of CLIM::CLIM-SHEET, is built on
;;; TV:PROCESS-MIXIN, which provides a slot for the associated process,
;;; and a wrapper method for the :KILL message that kills the process if
;;; the frame is killed.
;;; CLIM::CLIM-SHEET is built on TV:SELECT-MIXIN, which also associates
;;; a process with an application, but which does not provide a method
;;; to kill the process when necessary.  Consequently, when CLIM frames
;;; are killed from the system menu, their processes are left hanging
;;; around.
;;; The following wrapper was adapted from the one on TV:PROCESS-MIXIN
;;; in the Genera 8.1 source code.

(scl:defwrapper (:kill clim-sheet) (() . body)
     (let ((process (scl:send scl:self :process)))
       (unless (null process)
	 (when (eq process tv:*selected-process*)
	   (setq tv:*selected-process* nil))
	 (process:kill process)))))

Main Index | Thread Index