[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: WDEF in Lisp!

You seem to have figured out your problems since yesterday, but
hopefully this will be helpful anyway.


At 15:07 2/11/93 -0600, language@skdad.usask.ca wrote:
>ok, I've successfully written an entire WDEF in lisp.  It draws
>a simple window, with a close box and a grow region.  It does all
>the usual grafport preservation, etc.  However, I have come across
>one problem. the WDEF function returns #$wInGrow whenever a click
>is made in the grow region of the window (and I even checked
>to see if _FindWindow was returning the correct result--5), however
>Lisp doesn't make any calls to #_GrowWindow in response to this
>result code as it should.  Why is this?  do I have to put a call to
>#_GrowWindow in myself?  does #_GrowWindow only get called for
>documentProc type windows?  I also made window class defining
>the method window-grow-event-handler and it doesn't get called either?
>BUT! it does get called for regular documentProc style windows?
>what's the difference?  both WDEF's return a #$wInGrow when a click
>happens in the grow region, infact, they're functionally identical...

MCL calls #_GrowWindow only if (grow-icon-p <window>) returns true,
i.e. you created the window with:

   (make-instance '<window-class> ... :grow-icon-p t)

Unfortunately, if (grow-icon-p <window>) is true, MCL will call
#_DrawGrowIcon with drawing clipped to the 15 pixel square at the
lower right hand corner of the window's view-size rectangle.
This will be wrong for a custom WDEF.

You can partially fix this by specializing the ccl::window-draw-grow-icon
method. You also need to specialize ccl::invalidate-grow-icon,
which is not a generic function. I have prepared a patch that makes
invalidate-grow-icon a generic function. Ask for "grow-icon-patch".
With the patch installed you can say something like (warning, untested
code follows):


(defclass my-wdef-window (window)

(defmacro with-grow-icon-clip-region ((w rgn) &body body)
  (let ((thunk (gensym)))
    `(let ((,thunk #'(lambda (,rgn) ,@body)))
       (call-with-grow-icon-clip-region ,w ,thunk))))

(defun call-with-grow-icon-clip-region (w thunk)
  (with-macptrs (rgn)
        (%setf-macptr rgn (#_NewRgn))
        (get-grow-icon-clip-region w rgn)
        (funcall thunk rgn))
      (unless (%null-ptr-p rgn)
        (#_DisposeRgn rgn)))))

(defmethod ccl::window-draw-grow-icon ((w my-wdef-window))
  (with-grow-icon-clip-region (w rgn)
     (let ((temp-rgn ccl::*temp-rgn*))
       (#_GetClip temp-rgn)
           (#_SetClip rgn)
         (#_SetClip temp-rgn))))))

(defmethod ccl::invalidate-grow-icon ((w my-wdef-window) &optional erase-p)
  (with-grow-icon-clip-region (w rgn)
    (invalidate-region w rgn erase-p)))
(defmethod get-grow-icon-clip-region (w rgn)
  ; Doing nothing makes an infinitely large region

(defmethod get-grow-icon-clip-region ((w my-wdef-window) rgn)


Another probable problem with your DEFPASCAL WDEF code is that
a WDEF is called for hit testing when you click on a window and
the Finder is the active application. This can callback to MCL
while the garbage collector is running, which will likely cause
your DEFPASCAL code to crash. I fixed this problem for MCL's
WINDOID wdef. The solution is to call ccl::MAKE-WINDOID-WDEF to
wrap some assembly language code around your WDEF that knows not
to call the DEFPASCAL code if the GC is running. Instead it does
nothing for all but the #$whit message, for which it returns #$wInContent
if the point is inside the window's structure region, and #$wNoHit otherwise.
"ccl:lib;windoids.lisp" (which is on the MCL 2.0 CD) does the following
to initialize its WDEF:

(defvar *windoid-wdef-handle*)

(def-load-pointers windoid-wdef-handle ()
  (setq *windoid-wdef-handle* (ccl::make-wdef-handle ccl::windoid-wdef)))

It also installs the WDEF in an :after initialize-instance method.
I probably should have done this with a WDEF-MIXIN class, but I didn't.
Note that the code for this on the CD has been changed by one of the
two distributed patches.