1 #!/usr/bin/env gsi-script
5 ;;; Copyright (c) 2005-2011 by Marc Feeley, All Rights Reserved.
7 ;;; Create two windows and bounce many colored balls in them.
9 (##include "Xlib#.scm") ;; import Xlib procedures and variables
11 (define win-width 600)
12 (define win-height 401)
13 (define ball-width 25)
14 (define ball-height 25)
27 (let loop ((i (- n 1)) (lst '()))
30 (loop (- i 1) (cons i lst)))))
32 (define (create-balls x11-display screen window)
33 (random-source-randomize! default-random-source)
35 (let* ((gc (XCreateGC x11-display window 0 #f))
36 (v (make-XGCValues-box))
37 (cmap (XDefaultColormapOfScreen screen))
38 (c (make-XColor-box)))
39 (XColor-red-set! c (random-integer 20000))
40 (XColor-green-set! c (random-integer 20000))
41 (XColor-blue-set! c (random-integer 20000))
42 (if (= (XAllocColor x11-display cmap c) 1)
44 (XGCValues-foreground-set! v (XColor-pixel c))
45 (XChangeGC x11-display
50 (* (random-real) (- win-width ball-width))
51 (* (random-real) (- win-height ball-height))
52 (- (* (random-real) 2.0) 1.0)
53 (- (* (random-real) 2.0) 1.0)
57 (define (draw-ball b x11-display window gc-text font)
58 (let ((x (inexact->exact (floor (ball-x b))))
59 (y (inexact->exact (floor (ball-y b))))
63 (ascent (XFontStruct-ascent font))
64 (descent (XFontStruct-descent font)))
77 (let* ((str (number->string (ball-id b)))
78 (n (string-length str))
79 (w (XTextWidth font str n)))
84 (+ x (quotient (- ball-width w) 2))
85 (+ y (quotient (+ ball-height ascent) 2))
89 (define (move-ball b steps)
97 (if (or (< (+ x dx) 0)
98 (>= (+ x dx) (- win-width ball-width)))
102 (if (or (< (+ y dy) 0)
103 (>= (+ y dy) (- win-height ball-height)))
115 (ball-dy-set! b dy)))))
117 (define (make-gate name)
120 (make-condition-variable name)))
122 (define (gate-pulse gate)
123 (let ((mut (vector-ref gate 1))
124 (cv (vector-ref gate 2)))
126 (vector-set! gate 0 #t)
127 (condition-variable-signal! cv)
128 (mutex-unlock! mut)))
130 (define (gate-wait gate timeout)
131 (let ((mut (vector-ref gate 1))
132 (cv (vector-ref gate 2)))
134 (if (mutex-lock! mut timeout)
135 (if (vector-ref gate 0) ;; pulsed?
137 (vector-set! gate 0 #f)
140 (if (mutex-unlock! mut cv timeout)
145 (define (make-x11-event-queue x11-display)
146 (let* ((x11-display-fd
147 (XConnectionNumber x11-display))
149 (##open-predefined 1 ;; (macro-direction-in)
152 (check-x11-connection-events
153 (make-gate 'check-x11-connection-get))
155 (make-gate 'get-x11-events))
156 (x11-connection-monitor-thread
161 ;; wait until we need to check for events from the connection
162 (gate-wait check-x11-connection-events +inf.0)
164 ;; wait until an event is available from the X11 connection
165 (##device-port-wait-for-input! x11-display-port)
167 ;; tell the event loop it should get events
168 (gate-pulse get-x11-events)
172 (thread-start! x11-connection-monitor-thread)
176 check-x11-connection-events
177 x11-connection-monitor-thread)))
179 (define (x11-event-get x11-event-queue absrel-timeout)
181 (vector-ref x11-event-queue 0))
183 (vector-ref x11-event-queue 1))
184 (check-x11-connection-events
185 (vector-ref x11-event-queue 2))
187 (if (time? absrel-timeout)
191 (time->seconds (current-time)))))))
193 (or (XCheckMaskEvent x11-display -1)
195 (gate-pulse check-x11-connection-events)
196 (if (gate-wait get-x11-events timeout)
204 (XDefaultScreen x11-display))
206 (XScreenOfDisplay x11-display screen-number))
208 (XRootWindow x11-display screen-number))
210 (XBlackPixel x11-display screen-number))
212 (XWhitePixel x11-display screen-number))
214 (make-x11-event-queue x11-display)))
216 (define (create-window)
232 (XLoadQueryFont x11-display
235 (XCreateGC x11-display window 0 #f)))
237 (let* ((v (make-XGCValues-box))
238 (cmap (XDefaultColormapOfScreen screen))
239 (c (make-XColor-box))
240 (x (XParseColor x11-display
244 (if (and (= (XAllocColor x11-display cmap c) 1) (= x 1) font)
246 (XGCValues-foreground-set! v (XColor-pixel c))
247 (XGCValues-font-set! v (XFontStruct-fid font))
248 (XChangeGC x11-display
250 (+ GCForeground GCFont)
253 (XMapWindow x11-display window)
268 (let ((balls (create-balls x11-display screen window)))
272 (let ((start (current-time)))
275 (lambda (b) (move-ball b 5))
278 (XClearWindow x11-display window)
282 (draw-ball b x11-display window gc-text font))
287 ;; slow down to about 30 frames per second
292 (time->seconds start)))))
294 (let ((ev (x11-event-get x11-event-queue timeout)))
297 (pp (convert-XEvent ev))
303 (lambda (b) (XFreeGC x11-display (ball-gc b)))
306 (XFreeGC x11-display gc-text)))))))
310 (list (create-window)
313 ;; Can't close display because closing the connection
314 ;; causes the (##device-port-wait-for-input! x11-display-port)
315 ;; to raise an os-exception (closed file descriptor).
317 ;; (XCloseDisplay x11-display)
322 ;; For checking memory leaks on Mac OS X:
325 (shell-command (string-append "leaks " (number->string (##os-getpid))))