home *** CD-ROM | disk | FTP | other *** search
- ;;; -*- Mode: LISP; Syntax: Common-lisp; Package: XLIB; Base: 10; Lowercase: Yes -*-
-
- ;;; This file contains definitions for the DISPLAY object for Common-Lisp X windows version 11
-
- ;;;
- ;;; TEXAS INSTRUMENTS INCORPORATED
- ;;; P.O. BOX 2909
- ;;; AUSTIN, TEXAS 78769
- ;;;
- ;;; Copyright (C) 1987 Texas Instruments Incorporated.
- ;;;
- ;;; Permission is granted to any individual or institution to use, copy, modify,
- ;;; and distribute this software, provided that this complete copyright and
- ;;; permission notice is maintained, intact, in all copies and supporting
- ;;; documentation.
- ;;;
- ;;; Texas Instruments Incorporated provides this software "as is" without
- ;;; express or implied warranty.
- ;;;
-
- (in-package :xlib)
-
- ;;
- ;; Resource id management
- ;;
- (defun initialize-resource-allocator (display)
- ;; Find the resource-id-byte (appropriate for LDB & DPB) from the resource-id-mask
- (let ((id-mask (display-resource-id-mask display)))
- (unless (zerop id-mask) ;; zero mask is an error
- (do ((first 0 (index1+ first))
- (mask id-mask (the mask32 (ash mask -1))))
- ((oddp mask)
- (setf (display-resource-id-byte display)
- (byte (integer-length mask) first)))
- (declare (type array-index first)
- (type mask32 mask))))))
-
- (defun resourcealloc (display)
- ;; Allocate a resource-id for in DISPLAY
- (declare (type display display))
- (declare (values resource-id))
- (dpb (incf (display-resource-id-count display))
- (display-resource-id-byte display)
- (display-resource-id-base display)))
-
- (defmacro allocate-resource-id (display object type)
- ;; Allocate a resource-id for OBJECT in DISPLAY
- (if (member (eval type) *clx-cached-types*)
- `(let ((id (funcall (display-xid ,display) ,display)))
- (save-id ,display id ,object)
- id)
- `(funcall (display-xid ,display) ,display)))
-
- (defmacro deallocate-resource-id (display id type)
- ;; Deallocate a resource-id for OBJECT in DISPLAY
- (when (member (eval type) *clx-cached-types*)
- `(deallocate-resource-id-internal ,display ,id)))
-
- (defun deallocate-resource-id-internal (display id)
- (remhash id (display-resource-id-map display)))
-
- (defun lookup-resource-id (display id)
- ;; Find the object associated with resource ID
- (gethash id (display-resource-id-map display)))
-
- (defun save-id (display id object)
- ;; Register a resource-id from another display.
- (declare (type display display)
- (type integer id)
- (type t object))
- (declare (values object))
- (setf (gethash id (display-resource-id-map display)) object))
-
- ;; Define functions to find the CLX data types given a display and resource-id
- ;; If the data type is being cached, look there first.
- (macrolet ((generate-lookup-functions (useless-name &body types)
- `(within-definition (,useless-name generate-lookup-functions)
- ,@(mapcar
- #'(lambda (type)
- `(defun ,(xintern 'lookup- type)
- (display id)
- (declare (type display display)
- (type resource-id id))
- (declare (values ,type))
- ,(if (member type *clx-cached-types*)
- `(let ((,type (lookup-resource-id display id)))
- (cond ((null ,type) ;; Not found, create and save it.
- (setq ,type (,(xintern 'make- type)
- :display display :id id))
- (save-id display id ,type))
- ;; Found. Check the type
- ,(cond ((null *type-check?*)
- `(t ,type))
- ((member type '(window pixmap))
- `((type? ,type 'drawable) ,type))
- (t `((type? ,type ',type) ,type)))
- ,@(when *type-check?*
- `((t (x-error 'lookup-error
- :id id
- :display display
- :type ',type
- :object ,type))))))
- ;; Not being cached. Create a new one each time.
- `(,(xintern 'make- type)
- :display display :id id))))
- types))))
- (generate-lookup-functions ignore
- drawable
- window
- pixmap
- gcontext
- cursor
- colormap
- font))
-
- (defun id-atom (id display)
- ;; Return the cached atom for an atom ID
- (declare (type resource-id id)
- (type display display))
- (declare (values (or null keyword)))
- (gethash id (display-atom-id-map display)))
-
- (defun atom-id (atom display)
- ;; Return the ID for an atom in DISPLAY
- (declare (type xatom atom)
- (type display display))
- (declare (values (or null resource-id)))
- (gethash (if (or (null atom) (keywordp atom)) atom (kintern atom))
- (display-atom-cache display)))
-
- (defun set-atom-id (atom display id)
- ;; Set the ID for an atom in DISPLAY
- (declare (type xatom atom)
- (type display display)
- (type resource-id id))
- (declare (values resource-id))
- (let ((atom (if (or (null atom) (keywordp atom)) atom (kintern atom))))
- (setf (gethash id (display-atom-id-map display)) atom)
- (setf (gethash atom (display-atom-cache display)) id)
- id))
-
- (defsetf atom-id set-atom-id)
-
- (defun initialize-predefined-atoms (display)
- (dotimes (i (length *predefined-atoms*))
- (declare (type resource-id i))
- (setf (atom-id (svref *predefined-atoms* i) display) i)))
-
- (defun visual-info (display visual-id)
- (declare (type display display)
- (type resource-id visual-id)
- (values visual-info))
- (when (zerop visual-id)
- (return-from visual-info nil))
- (dolist (screen (display-roots display))
- (declare (type screen screen))
- (dolist (depth (screen-depths screen))
- (declare (type cons depth))
- (dolist (visual-info (rest depth))
- (declare (type visual-info visual-info))
- (when (funcall (resource-id-map-test) visual-id (visual-info-id visual-info))
- (return-from visual-info visual-info)))))
- (error "Visual info not found for id #x~x in display ~s." visual-id display))
-
-
- ;;
- ;; Display functions
- ;;
- (defmacro with-display ((display &key timeout inline)
- &body body)
- ;; This macro is for use in a multi-process environment. It provides exclusive
- ;; access to the local display object for multiple request generation. It need not
- ;; provide immediate exclusive access for replies; that is, if another process is
- ;; waiting for a reply (while not in a with-display), then synchronization need not
- ;; (but can) occur immediately. Except where noted, all routines effectively
- ;; contain an implicit with-display where needed, so that correct synchronization
- ;; is always provided at the interface level on a per-call basis. Nested uses of
- ;; this macro will work correctly. This macro does not prevent concurrent event
- ;; processing; see with-event-queue.
- `(with-buffer (,display
- ,@(and timeout `(:timeout ,timeout))
- ,@(and inline `(:inline ,inline)))
- ,@body))
-
- (defmacro with-event-queue ((display &key timeout inline)
- &body body &environment env)
- ;; exclusive access to event queue
- `(macrolet ((with-event-queue ((display &key timeout) &body body)
- ;; Speedup hack for lexically nested with-event-queues
- `(progn
- (progn ,display ,@(and timeout `(,timeout)) nil)
- ,@body)))
- ,(if (and (null inline) (macroexpand '(use-closures) env))
- `(flet ((.with-event-queue-body. () ,@body))
- #+clx-ansi-common-lisp
- (declare (dynamic-extent #'.with-event-queue-body.))
- (with-event-queue-function
- ,display ,timeout #'.with-event-queue-body.))
- (let ((disp (if (or (symbolp display) (constantp display))
- display
- '.display.)))
- `(let (,@(unless (eq disp display) `((,disp ,display))))
- (holding-lock ((display-event-lock ,disp) ,disp "CLX Event Lock"
- ,@(and timeout `(:timeout ,timeout)))
- ,@body))))))
-
- (defun with-event-queue-function (display timeout function)
- (declare (type display display)
- (type (or null number) timeout)
- (type function function)
- #+clx-ansi-common-lisp
- (dynamic-extent function)
- #+(and lispm (not clx-ansi-common-lisp))
- (sys:downward-funarg function))
- (with-event-queue (display :timeout timeout :inline t)
- (funcall function)))
-
- (defmacro with-event-queue-internal ((display &key timeout) &body body)
- ;; exclusive access to the internal event queues
- (let ((disp (if (or (symbolp display) (constantp display)) display '.display.)))
- `(let (,@(unless (eq disp display) `((,disp ,display))))
- (holding-lock ((display-event-queue-lock ,disp) ,disp "CLX Event Queue Lock"
- ,@(and timeout `(:timeout ,timeout)))
- ,@body))))
-
- (defun open-display (host &rest options &key (display 0) protocol
- authorization-name authorization-data &allow-other-keys)
- ;; Implementation specific routine to setup the buffer for a specific host and display.
- ;; This must interface with the local network facilities, and will probably do special
- ;; things to circumvent the nework when displaying on the local host.
- ;;
- ;; A string must be acceptable as a host, but otherwise the possible types
- ;; for host and protocol are not constrained, and will likely be very
- ;; system dependent. The default protocol is system specific. Authorization,
- ;; if any, is assumed to come from the environment somehow.
- (declare (type integer display)
- (dynamic-extent options))
- (declare (values display))
- ;; PROTOCOL is the network protocol (something like :TCP :DNA or :CHAOS). See OPEN-X-STREAM.
- (let* ((stream (open-x-stream host display protocol))
- (disp (apply #'make-buffer
- *output-buffer-size*
- 'make-display-internal
- :host host
- :display display
- :output-stream stream
- :input-stream stream
- :allow-other-keys t
- options))
- (ok-p nil))
- (unwind-protect
- (progn
- (display-connect disp
- :authorization-name authorization-name
- :authorization-data authorization-data)
- (initialize-resource-allocator disp)
- (initialize-predefined-atoms disp)
- (initialize-extensions disp)
- (setq ok-p t))
- (unless ok-p (close-display disp :abort t)))
- disp))
-
- (defun display-force-output (display)
- ; Output is normally buffered, this forces any buffered output to the server.
- (declare (type display display))
- (with-display (display)
- (buffer-force-output display)))
-
- (defun close-display (display &key abort)
- ;; Close the host connection in DISPLAY
- (declare (type display display))
- (close-buffer display :abort abort))
-
- (defun display-connect (display &key authorization-name authorization-data)
- (unless authorization-name (setq authorization-name ""))
- (unless authorization-data (setq authorization-data ""))
- (with-buffer-output (display :sizes (8 16))
- (card8-put
- 0
- (ecase (display-byte-order display)
- (:lsbfirst #x6c) ;; Ascii lowercase l - Least Significant Byte First
- (:msbfirst #x42))) ;; Ascii uppercase B - Most Significant Byte First
- (card16-put 2 *protocol-major-version*)
- (card16-put 4 *protocol-minor-version*)
- (card16-put 6 (length authorization-name))
- (card16-put 8 (length authorization-data))
- (write-sequence-char display 12 authorization-name)
- (write-sequence-char display
- (lround (+ 12 (length authorization-name))) authorization-data))
- (buffer-force-output display)
- (let ((reply-buffer nil))
- (declare (type (or null reply-buffer) reply-buffer))
- (unwind-protect
- (progn
- (setq reply-buffer (allocate-reply-buffer #x1000))
- (with-buffer-input (reply-buffer :sizes (8 16 32))
- (buffer-input display buffer-bbuf 0 8)
- (let ((success (boolean-get 0))
- (reason-length (card8-get 1))
- (major-version (card16-get 2))
- (minor-version (card16-get 4))
- (total-length (card16-get 6))
- vendor-length
- num-roots
- num-formats)
- (declare (ignore total-length))
- (unless success
- (x-error 'connection-failure
- :major-version major-version
- :minor-version minor-version
- :host (display-host display)
- :display (display-display display)
- :reason
- (progn (buffer-input display buffer-bbuf 0 reason-length)
- (string-get reason-length 0 :reply-buffer reply-buffer))))
- (buffer-input display buffer-bbuf 0 32)
- (setf (display-protocol-major-version display) major-version)
- (setf (display-protocol-minor-version display) minor-version)
- (setf (display-release-number display) (card32-get 0))
- (setf (display-resource-id-base display) (card32-get 4))
- (setf (display-resource-id-mask display) (card32-get 8))
- (setf (display-motion-buffer-size display) (card32-get 12))
- (setq vendor-length (card16-get 16))
- (setf (display-max-request-length display) (card16-get 18))
- (setq num-roots (card8-get 20))
- (setq num-formats (card8-get 21))
- ;; Get the image-info
- (setf (display-image-lsb-first-p display) (zerop (card8-get 22)))
- (let ((format (display-bitmap-format display)))
- (declare (type bitmap-format format))
- (setf (bitmap-format-lsb-first-p format) (zerop (card8-get 23)))
- (setf (bitmap-format-unit format) (card8-get 24))
- (setf (bitmap-format-pad format) (card8-get 25)))
- (setf (display-min-keycode display) (card8-get 26))
- (setf (display-max-keycode display) (card8-get 27))
- ;; 4 bytes unused
- ;; Get the vendor string
- (buffer-input display buffer-bbuf 0 (lround vendor-length))
- (setf (display-vendor-name display)
- (string-get vendor-length 0 :reply-buffer reply-buffer))
- ;; Initialize the pixmap formats
- (dotimes (i num-formats) ;; loop gathering pixmap formats
- (declare (ignorable i))
- (buffer-input display buffer-bbuf 0 8)
- (push (make-pixmap-format :depth (card8-get 0)
- :bits-per-pixel (card8-get 1)
- :scanline-pad (card8-get 2))
- ; 5 unused bytes
- (display-pixmap-formats display)))
- (setf (display-pixmap-formats display)
- (nreverse (display-pixmap-formats display)))
- ;; Initialize the screens
- (dotimes (i num-roots)
- (declare (ignorable i))
- (buffer-input display buffer-bbuf 0 40)
- (let* ((root-id (card32-get 0))
- (root (make-window :id root-id :display display))
- (root-visual (card32-get 32))
- (default-colormap-id (card32-get 4))
- (default-colormap
- (make-colormap :id default-colormap-id :display display))
- (screen
- (make-screen
- :root root
- :default-colormap default-colormap
- :white-pixel (card32-get 8)
- :black-pixel (card32-get 12)
- :event-mask-at-open (card32-get 16)
- :width (card16-get 20)
- :height (card16-get 22)
- :width-in-millimeters (card16-get 24)
- :height-in-millimeters (card16-get 26)
- :min-installed-maps (card16-get 28)
- :max-installed-maps (card16-get 30)
- :backing-stores (member8-get 36 :never :when-mapped :always)
- :save-unders-p (boolean-get 37)
- :root-depth (card8-get 38)))
- (num-depths (card8-get 39))
- (depths nil))
- ;; Save root window for event reporting
- (save-id display root-id root)
- (save-id display default-colormap-id default-colormap)
- ;; Create the depth AList for a screen, (depth . visual-infos)
- (dotimes (j num-depths)
- (declare (ignorable j))
- (buffer-input display buffer-bbuf 0 8)
- (let ((depth (card8-get 0))
- (num-visuals (card16-get 2))
- (visuals nil)) ;; 4 bytes unused
- (dotimes (k num-visuals)
- (declare (ignorable k))
- (buffer-input display buffer-bbuf 0 24)
- (let* ((visual (card32-get 0))
- (visual-info (make-visual-info
- :id visual
- :display display
- :class (member8-get 4 :static-gray :gray-scale
- :static-color :pseudo-color
- :true-color :direct-color)
- :bits-per-rgb (card8-get 5)
- :colormap-entries (card16-get 6)
- :red-mask (card32-get 8)
- :green-mask (card32-get 12)
- :blue-mask (card32-get 16)
- ;; 4 bytes unused
- )))
- (push visual-info visuals)
- (when (funcall (resource-id-map-test) root-visual visual)
- (setf (screen-root-visual-info screen)
- (setf (colormap-visual-info default-colormap)
- visual-info)))))
- (push (cons depth (nreverse visuals)) depths)))
- (setf (screen-depths screen) (nreverse depths))
- (push screen (display-roots display))))
- (setf (display-roots display) (nreverse (display-roots display)))
- (setf (display-default-screen display) (first (display-roots display))))))
- (when reply-buffer
- (deallocate-reply-buffer reply-buffer))))
- display)
-
- (defun display-protocol-version (display)
- (declare (type display display))
- (declare (values major minor))
- (values (display-protocol-major-version display)
- (display-protocol-minor-version display)))
-
- (defun display-vendor (display)
- (declare (type display display))
- (declare (values name release))
- (values (display-vendor-name display)
- (display-release-number display)))
-
- (defun display-nscreens (display)
- (declare (type display display))
- (length (display-roots display)))
-
- #+comment ;; defined by the DISPLAY defstruct
- (defsetf display-error-handler (display) (handler)
- ;; All errors (synchronous and asynchronous) are processed by calling an error
- ;; handler in the display. If handler is a sequence it is expected to contain
- ;; handler functions specific to each error; the error code is used to index the
- ;; sequence, fetching the appropriate handler. Any results returned by the handler
- ;; are ignored; it is assumed the handler either takes care of the error
- ;; completely, or else signals. For all core errors, the keyword/value argument
- ;; pairs are:
- ;; :display display
- ;; :error-key error-key
- ;; :major integer
- ;; :minor integer
- ;; :sequence integer
- ;; :current-sequence integer
- ;; For :colormap, :cursor, :drawable, :font, :gcontext, :id-choice, :pixmap, and
- ;; :window errors another pair is:
- ;; :resource-id integer
- ;; For :atom errors, another pair is:
- ;; :atom-id integer
- ;; For :value errors, another pair is:
- ;; :value integer
- )
-
- ;; setf'able
- ;; If defined, called after every protocol request is generated, even those inside
- ;; explicit with-display's, but never called from inside the after-function itself.
- ;; The function is called inside the effective with-display for the associated
- ;; request. Default value is nil. Can be set, for example, to
- ;; #'display-force-output or #'display-finish-output.
-
- (defvar *inside-display-after-function* nil)
-
- (defun display-invoke-after-function (display)
- ; Called after every protocal request is generated
- (declare (type display display))
- (when (and (display-after-function display)
- (not *inside-display-after-function*))
- (let ((*inside-display-after-function* t)) ;; Ensure no recursive calls
- (funcall (display-after-function display) display))))
-
- (defun display-finish-output (display)
- ;; Forces output, then causes a round-trip to ensure that all possible
- ;; errors and events have been received.
- (declare (type display display))
- (with-buffer-request-and-reply (display *x-getinputfocus* 16 :sizes (8 32))
- ()
- )
- ;; Report asynchronous errors here if the user wants us to.
- (report-asynchronous-errors display :after-finish-output))
-
- (defparameter
- *request-names*
- '#("error" "CreateWindow" "ChangeWindowAttributes" "GetWindowAttributes"
- "DestroyWindow" "DestroySubwindows" "ChangeSaveSet" "ReparentWindow"
- "MapWindow" "MapSubwindows" "UnmapWindow" "UnmapSubwindows"
- "ConfigureWindow" "CirculateWindow" "GetGeometry" "QueryTree"
- "InternAtom" "GetAtomName" "ChangeProperty" "DeleteProperty"
- "GetProperty" "ListProperties" "SetSelectionOwner" "GetSelectionOwner"
- "ConvertSelection" "SendEvent" "GrabPointer" "UngrabPointer"
- "GrabButton" "UngrabButton" "ChangeActivePointerGrab" "GrabKeyboard"
- "UngrabKeyboard" "GrabKey" "UngrabKey" "AllowEvents"
- "GrabServer" "UngrabServer" "QueryPointer" "GetMotionEvents"
- "TranslateCoords" "WarpPointer" "SetInputFocus" "GetInputFocus"
- "QueryKeymap" "OpenFont" "CloseFont" "QueryFont"
- "QueryTextExtents" "ListFonts" "ListFontsWithInfo" "SetFontPath"
- "GetFontPath" "CreatePixmap" "FreePixmap" "CreateGC"
- "ChangeGC" "CopyGC" "SetDashes" "SetClipRectangles"
- "FreeGC" "ClearToBackground" "CopyArea" "CopyPlane"
- "PolyPoint" "PolyLine" "PolySegment" "PolyRectangle"
- "PolyArc" "FillPoly" "PolyFillRectangle" "PolyFillArc"
- "PutImage" "GetImage" "PolyText8" "PolyText16"
- "ImageText8" "ImageText16" "CreateColormap" "FreeColormap"
- "CopyColormapAndFree" "InstallColormap" "UninstallColormap" "ListInstalledColormaps"
- "AllocColor" "AllocNamedColor" "AllocColorCells" "AllocColorPlanes"
- "FreeColors" "StoreColors" "StoreNamedColor" "QueryColors"
- "LookupColor" "CreateCursor" "CreateGlyphCursor" "FreeCursor"
- "RecolorCursor" "QueryBestSize" "QueryExtension" "ListExtensions"
- "SetKeyboardMapping" "GetKeyboardMapping" "ChangeKeyboardControl" "GetKeyboardControl"
- "Bell" "ChangePointerControl" "GetPointerControl" "SetScreenSaver"
- "GetScreenSaver" "ChangeHosts" "ListHosts" "ChangeAccessControl"
- "ChangeCloseDownMode" "KillClient" "RotateProperties" "ForceScreenSaver"
- "SetPointerMapping" "GetPointerMapping" "SetModifierMapping" "GetModifierMapping"))
-