;; Author: David Frese ;; create-window takes an alist of names and values - see ;; change-window-attributes and configure-window. Mandatory arguments for ;; create-window are 'parent, 'width and 'height. Example: ;; (create-window 'parent root 'width 500 'height 300 '((border-width . 4))) ;; Returns the new window or raises an exception if something went wrong. (define (create-window . args) (let ((alist (named-args->alist args))) (receive (x y width height border-width parent change-win-attr-list) (alist-split alist '((x . 0) (y . 0) (width . #f) (height . #f) (border-width . 2) (parent . #f))) (let* ((change-win-attr-list (map cons (map car change-win-attr-list) (map (lambda (obj) (cond ((pixel? obj) (pixel-Xpixel obj)) ((pixmap? obj) (pixmap-Xpixmap obj)) ((colormap? obj) (colormap-Xcolormap obj)) ;; cursor...?? (else obj))) (map cdr change-win-attr-list)))) (display (window-display parent)) (Xwindow (%create-window (display-Xdisplay display) (window-Xwindow parent) x y width height border-width change-win-attr-list))) (if (= Xwindow 0) (error "cannot create window") (make-window Xwindow display #t)))))) (import-lambda-definition %create-window (Xdisplay Xparent x y width height border-width attrAlist) "scx_Create_Window") ;; change-window-attributes takes an alist of names and values... ;; names can be: background-pixmap, background-pixel, border-pixmap, ;; border-pixel, bit-gravity, gravity, backing-store, backing-planes, ;; backing-pixel, save-under, event-mask, do-not-propagate-mask, ;; override-redirect, colormap, cursor. (define (change-window-attributes window . attrs) (let* ((alist (named-args->alist attrs)) (prep-alist (map cons (map car alist) (map (lambda (value) (cond ;; Abstractions ?? : ((pixmap? value) (pixmap-Xpixmap value)) ((pixel? value) (pixel-Xpixel value)) ((colormap? value) (colormap-Xcolormap value)) ((cursor? value) (cursor-Xcursor value)) (else value))) (map cdr alist))))) (%change-window-attributes (window-Xwindow window) (display-Xdisplay (window-display window)) prep-alist))) (import-lambda-definition %change-window-attributes (Xwindow Xdisplay alist) "scx_Change_Window_Attributes") ;; simple functions that use change-window-attributes ;; TODO: a caching system for multiple calls to these functions (define (make-win-attr-setter name) (lambda (window value) (change-window-attributes window (list (cons name value))))) (define set-window-background-pixmap! (make-win-attr-setter 'background-pixmap)) (define set-window-background-pixel! (make-win-attr-setter 'background-pixel)) (define set-window-border-pixmap! (make-win-attr-setter 'border-pixmap)) (define set-window-border-pixel! (make-win-attr-setter 'border-pixel)) (define set-window-bit-gravity! (make-win-attr-setter 'bit-gravity)) (define set-window-gravity! (make-win-attr-setter 'gravity)) (define set-window-backing-store! (make-win-attr-setter 'backing-store)) (define set-window-backing-planes! (make-win-attr-setter 'backing-planes)) (define set-window-backing-pixel! (make-win-attr-setter 'backing-pixel)) (define set-window-save-under! (make-win-attr-setter 'save-under)) (define set-window-event-mask! (make-win-attr-setter 'event-mask)) (define set-window-do-not-propagate-mask! (make-win-attr-setter 'do-not-propagate-mask)) (define set-window-override-redirect! (make-win-attr-setter 'override-redirect)) (define set-window-colormap! (make-win-attr-setter 'colormap)) (define set-window-cursor! (make-win-attr-setter 'cursor)) ;; get-window-attributes gives back the same attributes that ;; set-window-attributes sets and some more ... (define (get-window-attributes window) (let ((Xwindow (window-Xwindow window)) (Xdisplay (display-Xdisplay (window-display window)))) (let ((v (%get-window-attributes Xdisplay Xwindow))) (if (not v) (error "cannot get window attributes." window) (let* ((comp (lambda (i f) (vector-set! v i (f (vector-ref v i))))) (mod-v (begin (comp 13 make-pixel) ;; backing-pixel (comp 7 (lambda (Xwin) ;; root (make-window Xwin (window-display window) #f))) (comp 15 (lambda (Xcolormap) (make-colormap Xcolormap (window-display window) #f))) ;; font, visual ?? v)) (alist (map cons '(x y width height border-width depth visual root class bit-gravity win-gravity backing-store backing-planes backing-pixel save-under colormap map-installed map-state all-event-masks your-event-mask do-not-propagate-mask override-redirect screen ; screen not supported ) (vector->list mod-v)))) alist))))) (import-lambda-definition %get-window-attributes (Xdisplay Xwindow) "scx_Get_Window_Attributes") (define (make-win-attr-getter name) (lambda (window) (cdr (assq name (get-window-attributes window))))) (define window-x (make-win-attr-getter 'x)) (define window-y (make-win-attr-getter 'y)) (define window-width (make-win-attr-getter 'width)) (define window-height (make-win-attr-getter 'height)) (define window-border-width (make-win-attr-getter 'border-width)) (define window-depth (make-win-attr-getter 'depth)) (define window-visual (make-win-attr-getter 'visual)) (define window-root (make-win-attr-getter 'root)) (define window-class (make-win-attr-getter 'class)) (define window-bit-gravity (make-win-attr-getter 'bit-gravity)) (define window-backing-store (make-win-attr-getter 'backing-store)) (define window-backing-planes (make-win-attr-getter 'backing-planes)) (define window-backing-pixel (make-win-attr-getter 'backing-pixel)) (define window-save-under (make-win-attr-getter 'save-under)) (define window-colormap (make-win-attr-getter 'colormap)) (define window-map-installed (make-win-attr-getter 'map-installed)) (define window-map-state (make-win-attr-getter 'map-state)) (define window-all-event-masks (make-win-attr-getter 'all-event-masks)) (define window-your-event-mask (make-win-attr-getter 'your-event-mask)) (define window-do-not-propagate-mask (make-win-attr-getter 'do-not-propagate-mask)) (define window-override-redirect (make-win-attr-getter 'override-redirect)) ;; This sets the window-attributes listed below - call like create-window. (define (configure-window window . args) (let* ((args (named-args->alist args)) (prep-alist (map cons (map car args) (map (lambda (val) (if (window? val) (window-Xwindow val) val)) (map cdr args))))) (%configure-window (window-Xwindow window) (display-Xdisplay (window-display window)) prep-alist))) (import-lambda-definition %configure-window (Xwindow Xdisplay alist) "scx_Configure_Window") ;; the following mutators are based on configure-window (define (make-win-configurer name) (lambda (window value) (configure-window window (list (cons name value))))) (define set-window-x! (make-win-configurer 'x)) (define set-window-y! (make-win-configurer 'y)) (define set-window-width! (make-win-configurer 'width)) (define set-window-height! (make-win-configurer 'height)) (define set-window-border-width! (make-win-configurer 'border-width)) (define set-window-sibling! (make-win-configurer 'sibling)) (define set-window-stack-mode! (make-win-configurer 'stack-mode)) ;; The map-window function maps the window and all of its subwindows that have ;; had map requests. See XMapWindow. (define (map-window window) (%map-window (window-Xwindow window) (display-Xdisplay (window-display window)))) (import-lambda-definition %map-window (Xwindow Xdisplay) "scx_Map_Window") ;; The unmap-window function unmaps the specified window and causes the ;; X server to generate an unmap-notify event. See XUnmapWindow. (define (unmap-window window) (%unmap-window (window-Xwindow window) (display-Xdisplay (window-display window)))) (import-lambda-definition %unmap-window (Xwindow Xdisplay) "scx_Unmap_Window") ;; The destroy-subwindows function destroys all inferior windows of the ;; specified window, in bottom-to-top stacking order. See XDestroySubWindows. (define (destroy-subwindows window) (%destroy-subwindows (window-Xwindow window) (display-Xdisplay (window-display window)))) (import-lambda-definition %destroy-subwindows (Xwindow Xdisplay) "scx_Destroy_Subwindows") ;; The map-subwindows function maps all subwindows for a specified window in ;; top-to-bottom stacking order. See XMapSubwindows (define (map-subwindows window) (%map-subwindows (window-Xwindow window) (display-Xdisplay (window-display window)))) (import-lambda-definition %map-subwindows (Xwindow Xdisplay) "scx_Map_Subwindows") ;; The unmap-subwindows function unmaps all subwindows for each subwindow ;; and expose events on formerly obscured windows. See XUnmapSubwindow. (define (unmap-subwindows window) (%unmap-subwindows (window-Xwindow window) (display-Xdisplay (window-display window)))) (import-lambda-definition %unmap-subwindows (Xwindow Xdisplay) "scx_Unmap_Subwindows") ;; See XCirculateSubwindows. (define (circulate-subwindows window direction) (%destroy-subwindows (window-Xwindow window) (display-Xdisplay (window-display window)) (eq? direction 'lower-highest))) ; other is: 'raise-lower / exception?? (import-lambda-definition %circulate-subwindows (Xwindow Xdisplay dir) "scx_Circulate_Subwindows") ;; The clear-window function clears the entire area in the specified window. ;; See XClearWindow. (define (clear-window window) (clear-area window 0 0 0 0 #f)) ;; The raise-window (lower-window) function raises (lowers) the specified window ;; to the top (button) of the stack so that no sibling window obscures it (it ;; does not obscure any sibling windows). See XRaiseWindow. (define (raise-window window) (set-window-stack-mode! window 'above)) (define (lower-window window) (set-window-stack-mode! window 'below)) ;; The restack-windows function restacks the windows in the order specified, ;; from top to bottom. The stacking order of the first window in the windows ;; list is unaffected, but the other windows in the array are stacked underneath ;; the first window, in the order of the list. See XRestackWindows. (define (restack-windows window-list) (let loop ((w (car window-list)) (t (cdr window-list))) (if (not (null? t)) (let ((n (car t))) (set-window-sibling! n w) (set-window-stack-mode! n 'below) (loop n (cdr t)))))) ;; query-tree returns a list of three elements: root window, parent window and ;; child windows of the given window. See XQueryTree. (define (query-tree window) (let* ((display (window-display window)) (res (%query-tree (window-Xwindow window) (display-Xdisplay display)))) (list (make-window (vector-ref res 0) display #f) (make-window (vector-ref res 1) display #f) (vector->list (vector-map! (lambda (Xwindow) (make-window Xwindow display #f)) (vector-ref res 2)))))) (import-lambda-definition %query-tree (Xwindow Xdisplay) "scx_Query_Tree") ;; translate-coordinates takes the x and y coordinates relative to the source ;; window's origin and returns a list of three elements: the x and y coordinates ;; relative to the destination window's origin. If the source window and the ;; destination window are on different screens the result is #f. See ;; XTranslateCoordinates. (define (translate-coordinates src-window x y dst-window) (let* ((display (window-display src-window)) (res (%translate-coordinates (display-Xdisplay display) (window-Xwindow src-window) x y (window-Xwindow dst-window)))) (if res (begin (vector-set! res 2 (make-window (vector-ref res 2) display #f)) (vector->list res)) #f))) (import-lambda-definition %translate-coordinates (Xdisplay srcXwindow x y srcXwindow) "scx_Translate_Coordinates") ;; query-pointer returns a list of eight elements: x and y coordinates, a ;; boolean indicating whether the pointer is on the same screen as the specified ;; window, the root window, the root window's x and y coordinates, the child ;; window and a list of modifier names (see grab-button). See XQueryPointer. (define (query-pointer window) (let* ((display (window-display window)) (res (%query-pointer (display-Xdisplay display) (window-Xwindow window)))) (vector-set! res 3 (make-window (vector-ref res 3) display #f)) (vector-set! res 6 (make-window (vector-ref res 6) display #f)) (vector->list res))) (import-lambda-definition %query-pointer (Xdisplay Xwindow) "scx_Query_Pointer")