1 ;;; xlib-xr.el --- X receive part.
3 ;; Copyright (C) 2003-2005 by XWEM Org.
5 ;; Author: Eric M. Ludlam <zappo@gnu.ai.mit.edu>
6 ;; Zajcev Evgeny <zevlg@yandex.ru>
7 ;; Keywords: xlib, xwem
8 ;; X-CVS: $Id: xlib-xr.el,v 1.10 2005-04-04 19:55:30 lg Exp $
10 ;; This file is part of XWEM.
12 ;; XWEM is free software; you can redistribute it and/or modify it
13 ;; under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
17 ;; XWEM is distributed in the hope that it will be useful, but WITHOUT
18 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
20 ;; License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with XEmacs; see the file COPYING. If not, write to the Free
24 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 ;;; Synched up with: Not in FSF
39 ;; GNU Emacs compatibility
40 (unless (fboundp 'define-error)
41 (defun define-error (err-sym doc-string &optional inherits-from)
42 "Define a new error, denoted by ERR-SYM."
43 (put err-sym 'error-message doc-string)
45 (setq inherits-from 'error))
46 (let ((conds (get inherits-from 'error-conditions)))
47 (or conds (signal 'error (list "Not an error symbol" err-sym)))
48 (put err-sym 'error-conditions (cons err-sym conds)))))
50 (define-error 'X-Error
53 (define-error 'X-Events-stop
54 "Error used to stop X events processing.")
57 (defun XVectorizeList (lst)
58 "Take list LST and turn it into a vector.
59 This makes random access of its fields much faster."
60 (let ((nv (make-vector (length lst) nil))
63 (aset nv cnt (if (and (car lst) (listp (car lst)))
64 (XVectorizeList (car lst))
70 (defvar X-Event-LASTEvent 128
71 "Any event must be less then this one.
72 NOTE: * Core event are less than 35, but extensions may generate greater.
73 * Eight bit is syntetic bit.")
75 (defvar X-EventsList (make-vector X-Event-LASTEvent ["Unknown" nil 0 0])
76 "List of event descriptions.")
78 (defstruct (X-Event (:predicate X-Event-isevent-p))
81 synth-p ; non-nil if event came from SendEvent request
82 evdata ; binary event represetation
83 evinfo ; parsed variant of evdata
85 list ;for use in X-Generate-message
86 properties ; User defined plist
89 (defsubst X-Event-put-property (xev prop val)
90 "Put property PROP with value VAL in XEV's properties list."
91 (setf (X-Event-properties xev)
92 (plist-put (X-Event-properties xev) prop val)))
94 (defsubst X-Event-get-property (xev prop)
95 "Get property PROP from XEV's properties list."
96 (plist-get (X-Event-properties xev) prop))
98 (defsubst X-Event-rem-property (xev prop)
99 "Remove property PROP from XEV's properties list."
100 (setf (X-Event-properties xev) (plist-remprop (X-Event-properties xev) prop)))
102 (defun X-Event-p (ev &optional sig)
103 "Return non-nil if EV is X-Event."
104 (let ((isev (X-Event-isevent-p ev)))
105 (if (and (not isev) sig)
106 (signal 'wrong-type-argument (list sig 'X-Event-p ev))
109 (defsubst X-Event-detail (xev)
110 "Return detail info stored in XEV."
111 (nth 0 (X-Event-evinfo xev)))
113 (defsubst X-Event-seq (xev)
114 "Return sequence number of XEvent XEV."
115 (nth 1 (X-Event-evinfo xev)))
117 (defsubst X-Event-win (xev)
118 "Return window which is the subject of the XEV.
119 Return nil if there no such window."
120 (let ((evd (aref (aref X-EventsList (X-Event-type xev)) 2)))
121 (and (numberp evd) (nth evd (X-Event-evinfo xev)))))
123 (defsubst X-Event-win-event (xev)
124 "Return window for which XEV is generated.
125 Return nil if there is no such window."
126 (let ((evd (aref (aref X-EventsList (X-Event-type xev)) 3)))
127 (and (numberp evd) (nth evd (X-Event-evinfo xev)))))
129 (defsubst X-Event-name (xev)
130 "Return symbolic XEV name."
131 (aref (aref X-EventsList (X-Event-type xev)) 0))
133 (defun X-Event-make (&rest args)
134 "Like `make-X-Event', but also fills list field automatically."
135 (let* ((xev (apply 'make-X-Event args))
136 (evspec (aref (X-Event-type xev) X-EventsList)))
140 (defmacro X-Event-declare (type ev-name ev-msg &optional win-idx event-win-idx)
141 "Only declare event of TYPE with DESCR in `X-EventsList'."
142 `(aset X-EventsList ,type
143 (vector ,ev-name (quote ,ev-msg) ,win-idx (or ,event-win-idx ,win-idx))))
145 (defmacro X-Event-define (type name dnames ev-name ev-msg &optional win-idx event-win-idx)
146 "Define new event of TYPE, NAME and description of event DESCR."
149 (push `(aset X-EventsList ,type
150 (vector ,ev-name (quote ,ev-msg) ,win-idx (or ,event-win-idx ,win-idx)))
154 (setq fsym (intern (concat "X-Event-" name "-" (symbol-name (car dnames)))))
155 (push `(defsubst* ,fsym (ev)
156 (nth ,offs (X-Event-evinfo ev)))
158 (setq offs (1+ offs))
159 (setq dnames (cdr dnames)))
162 (defun X-Event->symbolkey (xev)
163 "Convert XEV type to symbolic name, return keyword."
164 (let ((evt (X-Event-type xev)))
165 (cond ((= evt X-KeyPress) :X-KeyPress)
166 ((= evt X-KeyRelease) :X-KeyRelease)
167 ((= evt X-ButtonPress) :X-ButtonPress)
168 ((= evt X-ButtonRelease) :X-ButtonRelease)
169 ((= evt X-MotionNotify) :X-MotionNotify)
170 ((= evt X-EnterNotify) :X-EnterNotify)
171 ((= evt X-LeaveNotify) :X-LeaveNotify)
172 ((= evt X-FocusIn) :X-FocusIn)
173 ((= evt X-FocusOut) :X-FocusOut)
174 ((= evt X-KeymapNotify) :X-KeymapNotify)
175 ((= evt X-Expose) :X-Expose)
176 ((= evt X-GraphicsExpose) :X-GraphicsExpose)
177 ((= evt X-NoExpose) :X-NoExpose)
178 ((= evt X-VisibilityNotify) :X-VisibilityNotify)
179 ((= evt X-CreateNotify) :X-CreateNotify)
180 ((= evt X-DestroyNotify) :X-DestroyNotify)
181 ((= evt X-UnmapNotify) :X-UnmapNotify)
182 ((= evt X-MapNotify) :X-MapNotify)
183 ((= evt X-MapRequest) :X-MapRequest)
184 ((= evt X-ReparentNotify) :X-ReparentNotify)
185 ((= evt X-ConfigureRequest) :X-ConfigureRequest)
186 ((= evt X-ConfigureNotify) :X-ConfigureNotify)
187 ((= evt X-GravityNotify) :X-GravityNotify)
188 ((= evt X-ResizeRequest) :X-ResizeRequest)
189 ((= evt X-CirculateNotify) :X-CirculateNotify)
190 ((= evt X-CirculateRequest) :X-CirculateRequest)
191 ((= evt X-PropertyNotify) :X-PropertyNotify)
192 ((= evt X-SelectionClear) :X-SelectionClear)
193 ((= evt X-SelectionRequest) :X-SelectionRequest)
194 ((= evt X-SelectionNotify) :X-SelectionNotify)
195 ((= evt X-ColormapNotify) :X-ColormapNotify)
196 ((= evt X-ClientMessage) :X-ClientMessage)
197 ((= evt X-MappingNotify) :X-MappingNotify)
201 (defmacro X-Event-CASE (xev &rest body)
202 "Run event case. BODY in form (EVTYPE FORMS) (EVTYPE FORMS) ..
203 EVTYPE is one of :X-KeyPress, :X-KeyRelease etc."
204 `(case (X-Event->symbolkey ,xev)
207 (put 'X-Event-CASE 'lisp-indent-function 1)
209 (defstruct X-EventHandler
211 evtypes-list ; list of event types
212 handler ; function to call
213 (active t) ; Non-nil mean event handler activated
215 plist) ; user defined plist
218 (defun X-EventHandler-add (evhlist handler &optional priority evtypes-list)
219 "To event handlers list EVHLIST add event HANDLER.
221 HANDLER is function which should accept three arguments - xdpy(X-Dpy),
222 xwin(X-Win) and xev(X-Event). Only events with type that in
223 EVTYPES-LIST are passed to HANDLER. By default all events passed.
224 PRIORITY is place in events handler list, i.e. when HANDLER will be
225 called. Higher priorities runs first.
227 Return new list, use it like `(setq lst (X-EventHandler-add lst 'handler))'."
231 (let ((xeh (make-X-EventHandler :priority priority
232 :evtypes-list evtypes-list
235 ;; Insert new event handler and sort event handlers by priority.
236 (sort (cons xeh evhlist)
237 #'(lambda (xeh1 xeh2)
238 (> (X-EventHandler-priority xeh1)
239 (X-EventHandler-priority xeh2))))))
242 (defun X-EventHandler-isset (evhlist handler &optional prioritiy evtypes-list)
243 "Examine EVHLIST and return X-EventHandler with HANDLER, PRIORITY and EVTYPES-LIST.
244 If you does not specify PRIORITY and EVTYPES-LIST, only matching with HANDLER occurs.
245 If event handler not found - nil will be returned."
246 (let ((evhs evhlist))
247 ;; Find appopriate handler
249 (not (and (eq (X-EventHandler-handler (car evhs)) handler)
250 (if prioritiy (equal prioritiy (X-EventHandler-priority (car evhs))) t)
251 (if evtypes-list (equal evtypes-list (X-EventHandler-evtypes-list (car evhs))) t))))
252 (setq evhs (cdr evhs)))
257 (defun X-EventHandler-rem (evhlist handler &optional prioritiy evtypes-list)
258 "From EVHLIST remove event HANDLER with PRIORITY and EVTYPES-LIST.
259 If you does not specify PRIORITY and EVTYPES-LIST, only matching with HANDLER occurs.
260 Return new list, use it like `(setq lst (X-EventHandler-rem lst 'handler))'."
261 (let ((xeh (X-EventHandler-isset evhlist handler prioritiy evtypes-list)))
263 (setq evhlist (delete xeh evhlist)))
267 (defun X-EventHandler-enable (evhlist handler &optional prioritiy evtypes-list)
268 "In event handlers list EVHLIST mark HANDLER with PRIORITY and EVTYPES-LIST as active."
269 (let ((xeh (X-EventHandler-isset evhlist handler prioritiy evtypes-list)))
271 (setf (X-EventHandler-active xeh) t))))
274 (defun X-EventHandler-disable (evhlist handler &optional prioritiy evtypes-list)
275 "In event handlers list EVHLIST mark HANDLER with PRIORITY and EVTYPES-LIST as inactive."
276 (let ((xeh (X-EventHandler-isset evhlist handler prioritiy evtypes-list)))
278 (setf (X-EventHandler-active xeh) nil))))
281 (defun X-EventHandler-runall (evhlist xev)
282 "Run all event handlers in EVHLIST on XEV.
283 Signal `X-Events-stop' to stop events processing."
284 (let ((evhs evhlist)) ; EVHS should be already sorted by priority
287 ;; Check is there appopriate event handler to handle XEV event.
288 (when (and (X-EventHandler-active (car evhs))
289 (or (null (X-EventHandler-evtypes-list (car evhs)))
290 (memq (X-Event-type xev) (X-EventHandler-evtypes-list (car evhs)))))
291 (funcall (X-EventHandler-handler (car evhs)) (X-Event-dpy xev) (X-Event-win xev) xev))
292 (setq evhs (cdr evhs)))
293 (X-Events-stop nil))))
295 ;;; X Events description.
298 ;; - Should be X-Dpy depended to support extensions derived events
299 (X-Event-define X-KeyPress "xkey" (keycode nil time root event child root-x root-y event-x event-y state same-screen)
301 ([1 integerp] ; keycode
302 [2 integerp] ; sequence
305 [4 :X-Win] ; event (WIN-EVENT)
307 [2 integerp] ; root_x
308 [2 integerp] ; root_y
309 [2 integerp] ; event_x
310 [2 integerp] ; event_y
312 [1 booleanp] ; same_screen
315 (X-Event-declare X-KeyRelease
317 ([1 integerp] ; keycode
318 [2 integerp] ; sequence
323 [2 integerp] ; root_x
324 [2 integerp] ; root_y
325 [2 integerp] ; event_x
326 [2 integerp] ; event_y
328 [1 booleanp] ; same_screen
331 (X-Event-define X-ButtonPress "xbutton" (button nil time root event child root-x root-y event-x event-y state same-screen)
333 ( [1 integerp] ; button
334 [2 integerp] ; sequence
339 [2 integerp] ; root_x
340 [2 integerp] ; root_y
341 [2 integerp] ; event_x
342 [2 integerp] ; event_y
344 [1 booleanp] ; same_screen
347 (X-Event-declare X-ButtonRelease
349 ( [1 integerp] ; button
350 [2 integerp] ; sequence
355 [2 integerp] ; root_x
356 [2 integerp] ; root_y
357 [2 integerp] ; event_x
358 [2 integerp] ; event_y
360 [1 booleanp] ; same_screen
363 (X-Event-define X-MotionNotify "xmotion" (nil nil time root event child root-x root-y event-x event-y state same-screen)
365 ( [1 integerp] ; detail
366 [2 integerp] ; sequence
371 [2 integerp] ; root_x
372 [2 integerp] ; root_y
373 [2 integerp] ; event_x
374 [2 integerp] ; event_y
376 [1 booleanp] ; same_screen
379 (X-Event-define X-EnterNotify "xcrossing" (nil nil time root event child root-x root-y event-x event-y state mode same-screen-focus)
381 ( [1 integerp] ; detail
382 [2 integerp] ; sequence
387 [2 integerp] ; root_x
388 [2 integerp] ; root_y
389 [2 integerp] ; event_x
390 [2 integerp] ; event_y
393 [1 integerp]) ; same-screen, focus
395 (X-Event-declare X-LeaveNotify
397 ( [1 integerp] ; detail
398 [2 integerp] ; sequence
403 [2 integerp] ; root_x
404 [2 integerp] ; root_y
405 [2 integerp] ; event_x
406 [2 integerp] ; event_y
409 [1 integerp] ) ; same-screen, focus
411 (X-Event-define X-FocusIn "xfocus" (nil nil event mode)
413 ( [1 integerp] ; detail
414 [2 integerp] ; sequence
419 (X-Event-declare X-FocusOut
421 ( [1 integerp] ; detail
422 [2 integerp] ; sequence
428 ;; TODO: X-KeymapNotify
430 (X-Event-define X-Expose "xexpose" (nil nil window x y width height count)
432 ( [1 integerp] ; detail
433 [2 integerp] ; sequence
438 [2 integerp] ; height
442 (X-Event-define X-GraphicsExpose "xgraphicsexpose" (nil nil drawable x y width height minor-event count major-event)
446 [4 integerp] ; drawable
450 [2 integerp] ; height
451 [2 integerp] ; minorEvent
453 [1 integerp] ; majorEvent
456 (X-Event-define X-NoExpose "xnoexpose" (nil nil drawable minor-event major-event)
460 [4 integerp] ; drawable
461 [2 integerp] ; minorEvent
462 [1 integerp] ; majorEvent
465 (X-Event-define X-VisibilityNotify "xvisibility" (nil nil window state)
473 (X-Event-define X-CreateNotify "xcreatewindow" (nil nil parent window x y width height border-width override)
475 ([1 integerp] ; detail
476 [2 integerp] ; sequence
477 [4 :X-Win] ; parent window
482 [2 integerp] ; height
483 [2 integerp] ; border width
484 [1 booleanp] ; override-redirect
487 (X-Event-define X-DestroyNotify "xdestroywindow" (nil nil event window)
489 ( [1 integerp] ; detail
490 [2 integerp] ; sequence
491 [4 :X-Win] ; event window
495 (X-Event-define X-UnmapNotify "xunmap" (nil nil event window from-configure)
497 ( [1 integerp] ; detail
498 [2 integerp] ; sequence
501 [1 booleanp] ; fromconfigure
504 (X-Event-define X-MapNotify "xmap" (nil nil event window override)
506 ( [1 integerp] ; detail
507 [2 integerp] ; sequence
508 [4 :X-Win] ; event window
510 [1 booleanp] ; override-redirect
513 (X-Event-define X-MapRequest "xmaprequest" (nil nil parent window)
515 ( [1 integerp] ; detail
516 [2 integerp] ; sequence
517 [4 :X-Win] ; parent window
521 (X-Event-define X-ReparentNotify "xreparent" (nil nil event window parent x y override)
523 ( [1 integerp] ; detail
524 [2 integerp] ; sequence
530 [1 integerp] ; override
533 (X-Event-define X-ConfigureNotify "xconfigure" (nil nil event window above-sibling x y width height border-width override-redirect)
535 ( [1 integerp] ; detail
536 [2 integerp] ; sequence
539 [4 :X-Win] ; above-sibling
543 [2 integerp] ; height
544 [2 integerp] ; border-width
545 [1 booleanp] ; override-redirect
548 (X-Event-define X-ConfigureRequest "xconfigurerequest" (stackmode nil parent window sibling x y width height border-width value-mask)
550 ( [1 integerp] ; detail
551 [2 integerp] ; sequence
552 [4 :X-Win] ; parent window
558 [2 integerp] ; height
559 [2 integerp] ; border width
560 [2 integerp] ; value mask
563 (X-Event-define X-GravityNotify "xgravity" (nil nil event window x y)
567 [4 :X-Win] ; event window
573 (X-Event-define X-ResizeRequest "xresizerequest" (nil nil window width height)
575 ( [1 integerp] ; detail
576 [2 integerp] ; sequence
579 [2 integerp] ; height
582 (X-Event-define X-CirculateNotify "xcirculate" (nil nil event window parent place)
586 [4 :X-Win] ; event window
592 ;; The event field in the xcirculate record is really the parent when this
593 ;; is used as a CirculateRequest instead of a CircluateNotify
594 (X-Event-declare X-CirculateRequest
598 [4 :X-Win] ; event window
605 (X-Event-define X-PropertyNotify "xproperty" (nil nil window atom time state)
615 (X-Event-define X-SelectionClear "xselectionclear" (nil nil time window atom)
624 (X-Event-define X-SelectionRequest "xselectionrequest" (nil nil time owner requestor selection target property)
630 [4 :X-Win] ; requestor
631 [4 :X-Atom] ; selection atom
632 [4 :X-Atom] ; target atom
633 [4 :X-Atom] ; property atom
636 (X-Event-define X-SelectionNotify "xselection" (nil nil time requestor selection target property)
641 [4 :X-Win] ; requestor
642 [4 :X-Atom] ; selection atom
643 [4 :X-Atom] ; target atom
644 [4 :X-Atom] ; property atom
647 (X-Event-define X-ColormapNotify "xcolormap" (nil nil window colormap new state)
649 ([1 integerp] ; detail
650 [2 integerp] ; sequence
652 [4 integerp] ; colormap
657 (X-Event-define X-ClientMessage "xclient" (nil window atom msg)
659 ([1 length-1] ; format
660 [2 integerp] ; sequence number
663 ;; This reads in the correct number of integers of a type
664 ;; specified by the format which is 8, 16, or 32.
665 [(/ 20 (/ length-1 8)) ( [ (/ length-1 8) integerp ] ) ] )
667 (X-Event-define X-MappingNotify "xmapping" (nil nil request first-keycode count)
671 [1 integerp] ; request
672 [1 integerp] ; firstKeyCode
677 (X-Event-define 0 "xerror" (code nil resourceid min-op maj-op)
679 ([1 integerp] ; err code
680 [2 integerp] ; sequence
682 [2 integerp] ; minor opcode
683 [1 integerp] ; major opcode
686 ;;; All receive message types will exclude the first byte which IDs it.
688 ;; a symbol gets 'set, functions such as integerp mean turn it into that,
689 ;; and put it into the return list. 'arg means use next arg as this value.
691 "Return a the number LEN moded to 4."
692 (if (= (% len 4) 0) 0 (- 4 (% len 4))))
694 (defconst X-connect-response
696 (list [1 length-1] ; fail message len
697 [2 integerp] ; major version
698 [2 integerp] ; minor version
699 [2 length-2] ; pad length
700 [length-1 stringp] ; error conditions
701 [(X-mod-4 length-1) nil] ; padding
703 (list [1 nil] ; successful list (this is unused)
704 [2 integerp] ; major version
705 [2 integerp] ; minor version
706 [2 length-1] ; len additional data (pad)
707 [4 integerp] ; release number
708 [4 integerp] ; resource id base
709 [4 integerp] ; resource id mask
710 [4 integerp] ; motion buffer size
711 [2 length-2] ; vendor length
712 [2 integerp] ; max request len
713 [1 length-4] ; number of screens
714 [1 length-3] ; number of formats in pix list
715 [1 integerp] ; image byte order
716 [1 integerp] ; bitmap byte order
717 [1 integerp] ; bitmap format scanline thingy
718 [1 integerp] ; bitmap format scanline pad
719 [1 integerp] ; min keycode
720 [1 integerp] ; max keycode
722 [length-2 stringp] ; the vendor
723 [(X-mod-4 length-2) nil] ; padding
724 [length-3 ; sublist of formats
725 ( [1 integerp] ; depth
726 [1 integerp] ; bits/pixel
727 [1 integerp] ; scanline-pad
728 [5 nil] ) ] ; padding
730 ( [4 integerp] ; root window
731 [4 integerp] ; colormap
732 [4 integerp] ; white-pixel
733 [4 integerp] ; black-pixel
734 [4 integerp] ; event-flags
735 [2 integerp] ; screen-width
736 [2 integerp] ; screen-height
737 [2 integerp] ; milimeters width
738 [2 integerp] ; milimeters height
739 [2 integerp] ; min-installed-maps
740 [2 integerp] ; max installed maps
741 [4 integerp] ; visualid
742 [1 integerp] ; backingstores
743 [1 booleanp] ; save-unders
744 [1 integerp] ; root depth
745 [1 length-1] ; # depths in depth
746 [length-1 ; list of depths
747 ( [1 integerp] ; depth
749 [2 length-1] ; # visual types
751 [length-1 ; the visuals
752 ( [4 integerp] ; visual id
754 [1 integerp] ; bits/rgb value
755 [2 integerp] ; colormap entities
756 [4 integerp] ; red mask
757 [4 integerp] ; green mask
758 [4 integerp] ; blue mask
764 "Connection response structure.")
766 (defun X-invalidate-cl-struct (cl-x)
767 "Invalidate CL-X, after `X-invalidate-cl-struct' it won't be cl struct anymore.
768 NOTE: works only if CL-X is vector."
770 (let ((i (length cl-x)))
771 (while (>= (setq i (1- i)) 0)
775 ;;; Protecting macros
776 (defmacro X-Dpy-read-excursion (xdpy &rest forms)
777 "Execute FORMS in reading mode."
778 `(let ((gc-cons-threshold most-positive-fixnum)) ; inhibit GC'ing
779 (incf (X-Dpy-readings ,xdpy))
783 (t (decf (X-Dpy-readings ,xdpy))
784 (apply 'error (car err) (cdr err))))
785 (decf (X-Dpy-readings ,xdpy)))))
786 (put 'X-Dpy-read-excursion 'lisp-indent-function 1)
788 (defun X-Dpy-send-read (xdpy s rf)
789 "Send S to display XDPY and receive answer according to receive fields RF."
790 (let ((reqid (X-Dpy-rseq-id xdpy))) ; Remember request id
791 (X-Dpy-read-excursion xdpy
792 ;; Flush output buffer
794 (X-Dpy-send-flush xdpy)
795 (X-Dpy-parse-message rf reqid xdpy))))
798 (defvar X-default-timeout 60
799 "This should be big enought, larger than any XEmacs blocking.")
801 ;;; Reading and parsing
802 (defun X-Dpy-grab-bytes (xdpy num &optional to-secs to-msecs)
803 "On display XDPY, wait for at least NUM bytes and return string."
804 (X-Dpy-p xdpy 'X-Dpy-grab-bytes)
807 (while (< (length (X-Dpy-message-buffer xdpy)) num)
808 (when (null (accept-process-output (X-Dpy-proc xdpy)
809 (or to-secs X-default-timeout) (or to-msecs 0)))
811 (error "X: Timeout while reading from server.")))
813 (setq rstr (substring (X-Dpy-message-buffer xdpy) 0 num)) ; save bytes to string
815 ;; Update message-buffer
816 (setf (X-Dpy-message-buffer xdpy)
817 (substring (X-Dpy-message-buffer xdpy) num))
820 ;; These are defined so we can use them recursivly below
821 (defvar length-1 nil)
822 (defvar length-2 nil)
823 (defvar length-3 nil)
824 (defvar length-4 nil)
826 (defun X-Dpy-parse-message (message-s req-id xdpy &rest arglist)
827 "Receive (via filter and waiting) a response from the X server.
828 Parses MESSAGE-S structure. When MAY-GUESS is t then if 1st el is not 1 or 0,
829 we must process as an event instead. Then keep looping on guess until we get
830 a 0 or 1. If not, then we are processing sub-lists. Processing is done for
831 XDPY. ARGLIST is some list of arguments.
833 When FROM-X-PARSE-MESSAGE is non-nil than we are called from `X-Dpy-parse-message'.
835 MESSAGE-S is made of size vectors `X-Dpy-create-message':
839 SIZE is how many bytes it occupies in the message.
840 ENCODING is how to interpret it.
842 If encoding is 'success, then the following vectors are two lists.
843 The first is the Failure case. nil is a generic failure.
844 The second is the Success case.
846 Encoding can also be one of the following:
848 integerp -- Format integer
849 stringp -- Formatted string
850 length-# -- Number stored in variable `length-#' where # is 0-4.
852 The length-# variables are used to read a length from one section
853 of a message, and use it as the size field of a later occuring field.
854 A variable-length string can occur like this:
856 [2 length-0] ; length of string, does not appear in the list
857 [length-0 stringp] ; name"
859 (X-Dpy-p xdpy 'X-Dpy-parse-message)
861 (let ((inhibit-quit t) ; so C-g will not desync
864 (length-1 (if (boundp 'length-1) length-1 nil))
865 (length-2 (if (boundp 'length-2) length-2 nil))
866 (length-3 (if (boundp 'length-3) length-3 nil))
867 (length-4 (if (boundp 'length-4) length-4 nil)) )
868 (while (and message-s (listp message-s))
869 (let* ((tvec (car message-s))
871 (tval1 (aref tvec 1))
872 (tval (if (and (listp tval1)
873 (member (car tval1) '(or if cond))) ;XXX
876 (result (unless (and tval (listp tval))
877 ;; Do not grab bytes for sub-lists
878 (if (or (symbolp tlen) (listp tlen))
879 (X-Dpy-grab-bytes xdpy (eval tlen))
880 (X-Dpy-grab-bytes xdpy tlen)))))
882 ;; We need to put in code to represent sizes sometimes,
883 ;; this will get that size.
884 (when (or (listp tlen) (symbolp tlen))
885 (setq tlen (eval tlen)))
887 ;; Check for use of an argument.
888 (when (equal tval 'arg)
889 (setq tval (car arglist))
890 (setq arglist (cdr arglist)))
892 ;; If the val is a list, and it is an if statement, then
893 ;; we want to evaluate it to get the real tval type.
894 (when (and (listp tval)
895 (member (car tval) '(if or make-list)))
896 (setq tval (eval tval)))
899 ;; boolean success stories.
900 ((equal tval 'success)
902 (cond ((= (aref result 0) 1)
905 (X-Dpy-parse-message (car (cdr (cdr message-s)))
906 req-id xdpy arglist))
909 ;; Here is event or error arrived, process
910 ;; errors in time or store event in events
912 (X-Dpy-log xdpy 'x-event "!!: Inter Evaluating event ..")
913 (let ((xev (X-Dpy-parse-event
914 xdpy (Xforcenum (aref result 0))))
917 (if (and (= (X-Event-type xev) 0)
919 (logand req-id 65535)))
920 ;; Error of current request
923 ;; Repeat processing XXX excluding t or nil
924 (X-Dpy-log xdpy 'x-event "!!: Reprocessing: %d bytes pending, msg=%S"
925 '(length (X-Dpy-message-buffer xdpy)) 'message-s)
926 (setq pmsg (X-Dpy-parse-message
927 message-s req-id xdpy arglist)
929 (X-Dpy-log xdpy 'x-event "!!: Reprocessing done %d bytes pending."
930 '(length (X-Dpy-message-buffer xdpy)))
932 (X-Dpy-dispatch-event xev)))))))
933 (setq rlist (cons result sublst)))
936 (setq reverse-me nil))
938 ;; numberp means natural number, not safe!
940 (setq rlist (cons (funcall (if (<= tlen 2)
942 'string4->number) result)
945 ;; integerp means tac onto end of list as an int
948 (setq rlist (cons (string->int result) rlist))
949 (setq rlist (cons (string4->int result) rlist))))
951 ;; stringp means tac onto end of list as string (verbatim)
953 (setq rlist (cons result rlist)))
955 ;; booleans don't really exist, but turn a 0 into nil, and 1 into t
957 (setq rlist (cons (if (= 0 (string->int result)) nil t) rlist)))
959 ;; TODO: maybe add card8, card16, card32, int8, int16, int32,
960 ;; string8, string16, etc?
964 (setq tlen (/ tlen 8))
966 (setq rlist (cons (make-X-Rect :x (string->int (substring result 0 2))
967 :y (string->int (substring result 2 4))
968 :width (string->int (substring result 4 6))
969 :height (string->int (substring result 6 8)))
971 (setq result (substring result 8))
972 (setq tlen (1- tlen))))
975 (setq tlen (/ tlen 4))
977 (setq rlist (cons (X-Win-find-or-make xdpy (string4->int result))
979 (setq result (substring result 4))
980 (setq tlen (1- tlen))))
983 (setq tlen (/ tlen 4))
985 (setq rlist (cons (X-Atom-find-or-make xdpy (string4->int result))
987 (setq result (substring result 4))
988 (setq tlen (1- tlen))))
990 ;; if it is a list, then we need to recursivly call ourselvs X
992 ((and tval (listp tval))
993 ;; WARNING: subparts cannot use args. ;(
996 (setq sublst (cons (X-Dpy-parse-message tval req-id xdpy arglist) sublst))
997 (setq tlen (1- tlen)))
998 ;; The sub-list of items is backwards: fix
999 (setq rlist (cons (nreverse sublst) rlist))))
1001 ;; not a type, but some other symbol, then put it there!
1002 ;; if it is one of the lengththings, intify it.
1003 ((and tval (symbolp tval) (not (keywordp tval)))
1004 (if (string-match "length" (symbol-name tval))
1005 (set tval (string->int result))
1013 (error "Error parsing X response!!!"))))
1014 (setq message-s (cdr message-s)))
1016 ;; Now that that is over, conditionally reverse the list.
1021 (defun X-Dpy-eval-error-or-event (xdpy)
1022 "There data on XDPY, it is error or event."
1023 (X-Dpy-read-excursion xdpy
1024 (let* ((result (X-Dpy-grab-bytes xdpy 1))
1025 (evetype (Xforcenum (aref result 0))))
1027 (cond ((= evetype 1) ; reply, should not happen
1028 (X-Dpy-log xdpy 'x-error "Got unknown reply, while expecting XEvent! CRITICAL!")
1029 (error "Got unknown reply, while expecting XEvent!"))
1030 ;; Below code is not quite correct. Because X exntensions
1031 ;; that generates events may use values greater then
1033 ; ((>= evetype X-MaxEvent)
1034 ; (X-Dpy-log xdpy 'x-error "Got XEvent id(%d) greater than X-MaxEvent! CRITICAL!"
1036 ; (error (format "Got X Event id(%d) greater than X-MaxEvent!" evetype)))
1037 (t (X-Dpy-dispatch-event
1038 (X-Dpy-parse-event xdpy evetype)))) ; error or event
1041 ;; Events/Errors dispatchers
1042 (defvar xlib-opcodes-alist
1045 (2 . XChangeWindowAttributes)
1046 (3 . XGetWindowAttributes)
1047 (12 . XConfigureWindow)
1050 (4 . XDestroyWindow)
1051 (5 . XDestroySubwindows)
1055 (18 . XChangeProperty)
1056 (20 . XGetWindowProperty)
1057 (78 . XCreateColormap)
1058 (79 . XFreeColormap)
1060 (85 . XAllocNamedColor)
1061 (86 . XAllocColorCells)
1068 (59 . XSetClipRectangles)
1076 (66 . XDrawSegments)
1077 (67 . XDrawRectangles)
1078 (70 . XDrawRectangles)
1085 (22 . XSetSelectionOwner)
1086 (23 . XGetSelectionOwner)
1087 (24 . XConvertSelection)
1090 (37 . XUngrabServer)
1091 (38 . XQueryPointer)
1092 (31 . XGrabKeyboard)
1093 (32 . XUngrabKeyboard)
1095 (27 . XUngrabPointer)
1097 (29 . XUngrabButton)
1100 (43 . XGetInputFocus)
1101 (42 . XSetInputFocus)
1102 (7 . XReparentWindow)
1104 (40 . XTranslateCoordinates)
1105 (6 . XChangeSaveSet)
1108 (101 . XGetKeyboardMapping)
1109 (119 . XGetModifierMapping)
1112 (48 . XQueryTextExtents)
1113 (53 . XCreatePixmap)
1115 (93 . XCreateCursor)
1116 (94 . XCreateGlyphCursor)
1118 (96 . XRecolorCursor)
1119 (30 . XChangeActivePointerGrab)
1120 (98 . XQueryExtension)
1121 (107 . XSetScreenSaver)
1122 (108 . XGetScreenSaver)
1124 (115 . XForceScreenSaver))
1125 "Alist of X opcodes in form (OPCODE . FUNCTION).
1126 This is only informative variable.")
1128 (defun X-Dpy-run-error-hooks (xdpy xev)
1129 "Run XDPY's error hooks."
1130 (when (X-Dpy-error-hooks xdpy)
1131 (mapcar #'(lambda (fun)
1132 (funcall fun xdpy xev))
1133 (X-Dpy-error-hooks xdpy))))
1135 (defun X-Dpy-error-dispatch (xev)
1136 "Dispatch error event XEV."
1137 (let* ((xdpy (X-Event-dpy xev))
1138 (err (X-Event-xerror-code xev))
1139 (badth (X-Event-xerror-resourceid xev))
1140 (seq (X-Event-seq xev))
1141 (maj (X-Event-xerror-maj-op xev))
1142 (opfun (cdr (assq maj xlib-opcodes-alist)))
1143 (min (X-Event-xerror-min-op xev))
1144 (bstr (cond ((= err 1) "Request")
1146 ((= err 3) "Window")
1147 ((= err 4) "Pixmap")
1149 ((= err 6) "Cursor")
1152 ((= err 9) "Drawable")
1153 ((= err 10) "Access")
1154 ((= err 11) "Alloc")
1155 ((= err 12) "Color")
1157 ((= err 14) "IDChoice")
1159 ((= err 16) "Length")
1160 ((= err 17) "Implementation")
1161 ((= err 128) "FirstExtension")
1162 ((= err 255) "LastExtension")
1164 (declare (special bstr))
1165 (declare (special min))
1166 (declare (special opfun))
1167 (declare (special seq))
1168 (declare (special badth))
1169 (X-Dpy-log xdpy 'x-error "X-Error: Bad %s %f seq=%f:%d ops=%d:%d/%S"
1170 'bstr 'badth 'seq '(X-Dpy-rseq-id xdpy) 'maj 'min 'opfun)
1172 ;; Now run hooks if any
1173 (X-Dpy-run-error-hooks xdpy xev)))
1175 ;;; Some usefull macroses (NOT USED)
1176 (defmacro X-Generic-enqueue (obj queue)
1177 "Enqueue object QBJ into setf'able QUEUE."
1179 (setf ,queue (list ,obj))
1180 (setcdr (last ,queue) (list ,obj))))
1182 (defmacro X-Generic-prequeue (obj queue)
1183 "Prepend object OBJ into setf'able QUEUE."
1184 `(setf ,queue (cons ,obj ,queue)))
1186 (defmacro X-Generic-dequeue (queue)
1187 "Dequeue first object from setf'able QUEUE."
1188 `(let ((obj (car ,queue)))
1189 (setf ,queue (cdr ,queue))
1192 ;;; Events queue support
1193 (defun X-Dpy-default-events-dispatcher (xdpy xev)
1194 "Default events dispatcher."
1195 (let ((win-ev (X-Event-win-event xev)))
1196 (when (X-Win-p win-ev)
1197 ;; First run display handlers
1198 (when (X-Dpy-event-handlers xdpy)
1199 (X-Dpy-EventHandler-runall xdpy xev))
1201 ;; Then run WIN specific handlers
1202 (when (X-Win-event-handlers win-ev)
1203 ;; WIN has its own event handlers
1204 (X-Win-EventHandler-runall win-ev xev)))))
1206 (defun X-Dpy-event-dispatch (xev)
1207 "Dispatch event XEV."
1208 (let ((xdpy (X-Event-dpy xev)))
1209 (X-Dpy-log xdpy 'x-event "Got X event: %S for win %S / %S"
1211 '(if (X-Win-p (X-Event-win-event xev))
1212 (X-Win-id (X-Event-win-event xev))
1213 (X-Event-win-event xev))
1214 '(if (X-Win-p (X-Event-win xev))
1215 (X-Win-id (X-Event-win xev))
1218 (when (X-Dpy-events-dispatcher xdpy)
1219 (funcall (X-Dpy-events-dispatcher xdpy) xdpy xev))))
1221 (defsubst X-Dpy-event-enqueue (event)
1222 "Enqueue EVENT in XDPY's events queue."
1223 (enqueue-eval-event 'X-Dpy-event-dispatch event))
1225 (defun X-Dpy-dispatch-event (xev)
1226 "Dispatch X Event or error XEV."
1227 (if (= (X-Event-type xev) 0)
1228 (X-Dpy-error-dispatch xev)
1229 (X-Dpy-event-enqueue xev)))
1231 (defun X-Dpy-parse-event (xdpy evtype)
1232 "On XDPY construct and enqueue event of EVTYPE type."
1233 ;; TODO: what about X-Event-evdata?
1234 ;; (evdata (substring (X-Dpy-message-buffer xdpy) 0 31))
1235 ;; :evdata (concat (char-to-string (XCharacter type)) evdata)
1236 (X-Dpy-read-excursion xdpy
1237 (let* ((type evtype)
1238 (synth (= (logand X-SyntheticMask type) X-SyntheticMask))
1239 (type (if synth (- type X-SyntheticMask) type))
1240 (xev (make-X-Event :dpy xdpy :type type :synth-p synth))
1241 (evspec (aref X-EventsList type))
1242 (evin (X-Dpy-parse-message (or (and evspec (aref evspec 1)) (list [31 nil])) 0 xdpy)))
1243 (setf (X-Event-evinfo xev) evin)
1245 (X-Dpy-log xdpy 'x-event "XLIB: Get new event %d(%s) win=%S ...."
1246 '(X-Event-type xev) '(X-Event-name xev)
1247 '(and (X-Win-p (X-Event-win xev))
1248 (X-Win-id (X-Event-win xev))))
1252 ;;; Function to call when there data in XDPY, but noone reading it.
1253 (defun X-Dpy-parse-message-guess (xdpy)
1254 "There is data waiting on XDPY, but no-one is reading it.
1255 Try to guess what it is."
1256 (X-Dpy-p xdpy 'X-Dpy-parse-message-guess)
1258 ;; If no-one reading now, mean than error or event arrived.
1259 (while (and (zerop (X-Dpy-readings xdpy))
1260 (> (length (X-Dpy-message-buffer xdpy)) 0))
1261 (X-Dpy-eval-error-or-event xdpy)))
1266 ;;; xlib-xr.el ends here