resize-sheet :after
Paul Werkowski
pw at snoopy.qozzy.com
Wed Dec 30 15:06:59 UTC 2020
(defmethod resize-sheet :after ((pane example-pane) width height)
(window-clear pane)
(redisplay-frame-pane (pane-frame pane) pane))
Apparently no developer has tried this as there are two time bombs
waiting to blow up the call stack.
WINDOW-CLEAR, besides writing +background-ink+ over the pane, goes on to
set width and height of the sheet to zero and then call
CHANGE-SPACE-REQUIREMENTS, which calls RESIZE-SHEET --> BOOM!
REDISPLAY-FRAME-PANE is implemented using RESTART-CASE, which in my 35
years with CL I have never had the occasion to use. Its restartable-form
manages to call itself via CALL-NEXT-METHOD (I think) which then blows
the stack, which then unwinds back through various restart clauses (some
which also call WINDOW-CLEAR), finally resulting in getting back to a
listener prompt where one can bail out.
For my use, I have re-written those two methods in a way that works for
the several places where I use resize-sheet :after with good results.
The attachment is one of the test cases I used to diagnose the stack
blowup. It displays a green filled circle in the center of the pane.
Drag a side or corner of the frame around with your pointer device to
cause the resize events to occur.
With those two changes my 15 year old CLIM2 plotting applications works
quite well although there is still a few places where pointer motion or
dragging yield strange results.
One other thing, if frame startup manages to silently load the NULL
port, it may take a very long time to figure out why the lisp listener
is dead. 🙁
Wishing you all a great new year!
Paul
-------------- next part --------------
(defpackage :junk (:use :clim-lisp :clim))
(in-package :junk)
(defclass example-pane2 (application-pane)
())
#+McCLIM ; from McCLIM source
(defmethod window-clear ((pane example-pane2))
(stream-close-text-output-record pane)
(let ((output-history (stream-output-history pane)))
(with-bounding-rectangle* (left top right bottom) output-history
(when (sheet-viewable-p pane)
(medium-clear-area (sheet-medium pane) left top right bottom)))
(clear-output-record output-history))
(window-erase-viewport pane)
(alexandria:when-let ((cursor (stream-text-cursor pane)))
(setf (cursor-position cursor)
(clim-extensions:stream-cursor-initial-position pane)))
#+()
(progn ; why is this here? Infinite recursion results
(setf (climi::stream-width pane) 0)
(setf (climi::stream-height pane) 0)
(scroll-extent pane 0 0)
(change-space-requirements pane)))
#+McCLIM
(defmethod redisplay-frame-pane :around
((frame application-frame) (pane climi::pane-display-mixin) &key force-p)
(declare (ignore force-p))
(funcall (climi::pane-display-function pane) (pane-frame pane) pane))
(defmethod resize-sheet :after ((pane example-pane2) x y)
(declare (ignore x y))
(window-clear pane)
#| stack blown with redisplay-frame-pane
44 Clear the output history of the pane and reattempt forceful redisplay.
45 Clear the output history of the pane, but don't redisplay.
46 Skip this redisplay.
47 Clear the output history of the pane and reattempt forceful redisplay.
48 Clear the output history of the pane, but don't redisplay.
49 Skip this redisplay.
50 (abort) Return to top loop level 0.
|#
;#+clim-2.0
(redisplay-frame-pane (pane-frame pane) pane)
;#+McCLIM (cpd2 (pane-frame pane) pane)
)
(defun cpd2 (frame pane) ; display function
(with-bounding-rectangle* (x1 y1 x2 y2) pane
(let* ((w (- x2 x1))
(h (- y2 y1))
(r (* .1 (min w h))))
(updating-output (pane)
(draw-ellipse* pane (/ w 2) (/ h 2) r 0 0 r :ink +green+)))))
(define-application-frame test2 ()
()
(:panes
(p1 (make-pane 'example-pane2
:width 300 :max-width +fill+
:height 300 :max-height +fill+
:display-function 'cpd2
:incremental-redisplay t
)))
(:layouts
(vertically p1)))
(defun tryit ()
;; grab edge or corner with mouse pointer and stretch
#+:CLX
(pushnew :clx *default-server-path*)
(run-frame-top-level
(make-application-frame 'test2)))
More information about the mcclim-devel
mailing list