CLIM mail archive
[Prev][Next][Index][Thread]
CLIM philosophy wrt to X.
Platform: SUN, LISP: Lucid 4.0, CLIM: 1.0 Beta,
listener: Gnuemacs buffer (CMU Ilisp)
One of the things about X that is different from other window system
is the buffering of commands. What is the general rule of thumb here?
Does one always set *CLX-FORCE-OUTPUT* to T so that all commands are
immediately rendered on the medium? Or only in development mode? Is
it all a question of efficiency (ie., it is faster to perform all
operations and then flush the buffer than to flush after any
operation)? It would seem that to ensure that it behaves similarly to
other window systems like Dynamic window, it should be T. What window
substrate be taken to be the "standard"?
It seems to me that there is a dichotomy between operations that work
on the windows itself vs graphical operations, ie., window operations
like expose, raise, bury, etc., vs drawing operations, etc. One
prolly want operations on windows to happen immediately (eg., if I
execute an EXPOSE-WINDOW command, I expect to see the window exposed
immediately, not in the indefinite future when some operation flushes
the buffer). Whereas when one is doing many graphical operations,
immediate flushing seems to be a loser, things slows down
significantly. This is rather important for some user-interface
programs like ACCEPT for eg., especially if one is to pop it up in
it's own window - if *CLX-FORCE-OUTPUT* is not true, the window is not
gonna pop.
What do more experienced CLIM users/designers think? Here's a simple
program that illustrate the difference rather nicely, plus some
additional questions...
;;***********************************************************************************
(setq *root* (clim::open-root-window :clx :host "brahms.isi.edu"))
(defmacro mid-point (pt1 pt2)
`(round (/ (+ ,pt1 ,pt2) 2)))
(defun get-options (w force-p)
(let ((clim::*clx-force-output* t)
a b)
(clim::accepting-values (w :own-window t)
(setq a (clim::accept 'integer
:prompt "Maximum number of iteration"
:default 1000))
;; problem here, what is *query-io*?
(terpri *query-io*)
(setq b (clim::accept '(member t nil)
:prompt "Immediate Flushing"
:default force-p)))
;; Makes sure the window is still on top ...
(clim::window-stack-on-top w)
(values a b)))
(defun chaos (&key (offset 10) (random-shape t) &aux chaos-window)
(declare (special *root* clim::*clx-force-output*))
(let ((chaos-window (clim::open-window-stream :parent sims::*root* :width 300 :height 500
:scroll-bars nil :save-under t
:stream-background clim::+misty-rose+
:stream-foreground clim::+black+))
(old-flush clim::*clx-force-output*)
max-iteration width height vertices cur-x cur-y line-orig dice)
(clim::window-expose chaos-window)
(multiple-value-setq (max-iteration clim::*clx-force-output*)
(get-options chaos-window clim::*clx-force-output*))
;; wished dimensional info was updated if user rubberbanded the size...
(setf width (- (clim::window-inside-width chaos-window) offset)
height (- (clim::window-inside-height chaos-window) offset)
;; two of the vertex are fixed at the bottom, the third one is random
vertices (make-array '(3 2) :element-type 'integer :initial-contents
`((,offset ,height)
(,(if random-shape
(+ offset (random (- width offset)))
(round (/ width 2)))
,offset)
(,width ,height)))
cur-x (+ offset (random (- width offset)))
cur-y (+ offset (random (- height offset)))
line-orig (ash offset -1))
(clim::draw-point* chaos-window cur-x cur-y)
(clim::draw-line* chaos-window line-orig (1- line-orig) width (1- line-orig))
(unwind-protect
(loop do (loop for i from 0 to max-iteration
with w = (- width line-orig) do
(setf dice (random 3))
(setf cur-x (ash (+ cur-x (aref vertices dice 0)) -1)
cur-y (ash (+ cur-y (aref vertices dice 1)) -1))
;; Makes it easier to tell where the point is by moving the mouse there
(when clim::*clx-force-output*
(clim::stream-set-pointer-position* chaos-window cur-x cur-y))
(clim::draw-point* chaos-window cur-x cur-y )
(when (zerop (mod i 100))
(clim::draw-line* chaos-window line-orig line-orig
(round (+ line-orig (* (/ i max-iteration) w))) line-orig)
(clim::clx-force-output-if-necessary *root* t)))
when (zerop (multiple-value-setq (max-iteration clim::*clx-force-output*)
(get-options chaos-window clim::*clx-force-output*)))
return 'done
else do (clim::with-drawing-options (chaos-window :ink clim::+misty-rose+)
(clim::draw-line* chaos-window line-orig line-orig width line-orig)
(clim::clx-force-output-if-necessary *root* t)
))
(setq clim::*clx-force-output* old-flush)
(clim::close chaos-window))))
;;****************************************************************************************************
Additional questions:
1. Is there a way to automatically make the window popped up by
ACCEPTING-VALUES be near the mouse (even better have the mouse in
it) - I believe DW in Genera did it so (:near-mouse?). Pretty
important in X as the input focus is by default associated with the
window the mouse is in.
2. The standard streams, (*terminal-io*, *query-io*, etc.) are not
CLIM stream, and as such cannot be used as arguments for functions
like ACCEPTING-VALUES. How do people handle this? I've taken to
using *ROOT* which is my root window, which is really not good
when an OWN-WINDOW option is used since the standard streams are
then bound to something else, and TERPRI doesn't do the right
thing.
3. Updating of window size. If one uses the middle button when
placing the window, one can rubberband the window size and hence
end up with a window whose size is different from what is
specified. How does one force the updating to happen so that
the new info. is now accessible?
4. I think CLIM::CLOSE is wrong when *CLX-FORCE-OUTPUT* is non-nil,
it tries to do a CLX-FORCE-OUTPUT-IF-NECESSARY on the stream arg.
after it destroys it. Destroy apparently munges up the stream
arg so that it is no longer a valid instance, which means that
CLX-FORCE-OUTPUT-IF-NECESSARY will barf. The right thing to do
is prolly do a CLX-FORCE-OUTPUT-IF-NECESSARY on it's parent. ie.,
(in-package 'clim)
(defmethod close ((STREAM clx-window) &KEY ABORT &ALLOW-OTHER-KEYS)
abort ;; not sure what to do with this
(xlib::destroy-window (clx-stream-window stream))
(when *clx-force-output*
(clx-force-output-if-necessary (window-parent stream) t)))
0,,
Follow-Ups:
Main Index |
Thread Index