1 ;;; xlib-xwin.el --- Core X structures.
3 ;; Copyright (C) 2003-2005 by XWEM Org.
5 ;; Author: Zajcev Evgeny <zevlg@yandex.ru>
6 ;; Created: 18 October 2003
7 ;; Keywords: xlib, xwem
8 ;; X-CVS: $Id: xlib-xwin.el,v 1.9 2005-04-04 19:55:31 lg Exp $
9 ;; X-URL: http://lgarc.narod.ru/xwem/index.html
11 ;; This file is part of XWEM.
13 ;; XWEM is free software; you can redistribute it and/or modify it
14 ;; under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 2, or (at your option)
18 ;; XWEM is distributed in the hope that it will be useful, but WITHOUT
19 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
21 ;; License for more details.
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with XEmacs; see the file COPYING. If not, write to the Free
25 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 ;;; Synched up with: Not in FSF
40 (autoload el "xlib-xlib"))
41 '(X-invalidate-cl-struct XOpenFont XQueryFont XQueryTextExtents))
46 ;; Point is either a cons cell in form (x . y) or X-Point structure
47 (defstruct (X-Point (:predicate X-Point-ispoint-p))
50 (defsubst X-Point-p (xpnt &optional sig)
51 "Return non-nil if XPNT is point."
52 (let ((ispnt (or (consp xpnt) (X-Point-ispoint-p xpnt))))
53 (if (and sig (not ispnt))
54 (signal 'wrong-type-argument (list sig 'X-Point-p xpnt))
57 (defmacro X-Point-x (xpnt)
62 (defmacro X-Point-y (xpnt)
67 (defsetf X-Point-x (xpnt) (val)
70 (setf (X-Point-xx ,xpnt) ,val)))
72 (defsetf X-Point-y (xpnt) (val)
75 (setf (X-Point-yy ,xpnt) ,val)))
77 (defun X-Point-message (xpnt)
78 "Return string representing x point XPNT."
79 (concat (int->string2 (X-Point-x xpnt))
80 (int->string2 (X-Point-y xpnt))))
82 ;; Segment is a pair of points
83 (defun X-Segment-message (xseg)
84 "Return string representing x segment XSEG."
85 (concat (X-Point-message (car xseg))
86 (X-Point-message (cdr xseg))))
89 (defstruct (X-Rect (:predicate X-Rect-isrect-p))
92 (defsubst X-Rect-p (xrect &optional sig)
93 "Return non-nil if XRECT is X-Rect structure."
94 (X-Generic-p 'X-Rect 'X-Rect-isrect-p xrect sig))
96 (defun X-Rect-internal-intersect-p (xrect1 xrect2)
97 "Return non-nil if two rectangles XRECT1 and XRECT2 have common part."
98 (let ((minx (min (X-Rect-x xrect1) (X-Rect-x xrect2)))
99 (maxx (max (+ (X-Rect-x xrect1) (X-Rect-width xrect1))
100 (+ (X-Rect-x xrect2) (X-Rect-width xrect2))))
101 (miny (min (X-Rect-y xrect1) (X-Rect-y xrect2)))
102 (maxy (max (+ (X-Rect-y xrect1) (X-Rect-height xrect1))
103 (+ (X-Rect-y xrect2) (X-Rect-height xrect2)))))
105 (and (> (+ (X-Rect-width xrect1) (X-Rect-width xrect2))
108 (> (+ (X-Rect-height xrect1) (X-Rect-height xrect2))
111 (defun X-Rect-intersect-p (&rest xrects)
112 "Return non-nil if rectangles in XRECTS are intersects."
114 (not (member t (mapcar #'(lambda (r)
115 (X-Rect-internal-intersect-p (car xrects) r))
117 (setq xrects (cdr xrects)))
121 (defun X-Rect-message (xrect)
122 "Return string representing X-Rect XRECT."
123 (concat (int->string2 (X-Rect-x xrect))
124 (int->string2 (X-Rect-y xrect))
125 (int->string2 (X-Rect-width xrect))
126 (int->string2 (X-Rect-height xrect))))
129 (defstruct (X-Geom (:include X-Rect)
130 (:predicate X-Geom-isgeom-p))
133 (defun X-Geom-p (geom &optional sig)
134 "Return non-nil if GEOM is X-Geom structure.
135 If SIG is gived and GEOM is not X-Geom structure, SIG will be signaled."
136 (X-Generic-p 'X-Geom 'X-Geom-isgeom-p geom sig))
138 (defun X-Geom-apply (fn geom1 geom2)
139 "Apply function FN to each element of GEOM1 and GEOM2.
141 (X-Geom-p geom1 'X-Geom-apply)
142 (X-Geom-p geom2 'X-Geom-apply)
144 (make-X-Geom :x (funcall fn (X-Geom-x geom1) (X-Geom-x geom2))
145 :y (funcall fn (X-Geom-y geom1) (X-Geom-y geom2))
146 :width (funcall fn (X-Geom-width geom1) (X-Geom-width geom2))
147 :height (funcall fn (X-Geom-height geom1) (X-Geom-height geom2))
148 :border-width (funcall fn (X-Geom-border-width geom1) (X-Geom-border-width geom2))))
150 (defun X-Geom-sum (geom1 geom2)
151 "Create new geometry which elements is sum of corresponded elements of GEOM1 and GEOM2."
152 (X-Geom-apply '+ geom1 geom2))
154 (defun X-Geom-sub (geom1 geom2)
155 (X-Geom-apply '- geom1 geom2))
157 (defun X-Geom-width-with-borders (geom)
158 "Return GEOM width including border's width."
159 (+ (X-Geom-width geom)
160 (* 2 (X-Geom-border-width geom))))
162 (defun X-Geom-height-with-borders (geom)
163 "Return GEOM height including border's width."
164 (+ (X-Geom-height geom)
165 (* 2 (X-Geom-border-width geom))))
167 ;;; X-Geom <--> X-Rect conversation
168 (defun X-Geom-to-X-Rect (xgeom)
169 "Convert XGEOM to X-Rect."
170 (make-X-Rect :x (X-Geom-x xgeom)
172 :width (X-Geom-width xgeom)
173 :height (X-Geom-height xgeom)))
175 (defun X-Rect-to-X-Geom (xrect)
176 "Convert XRECT to X-Geom."
177 (make-X-Geom :x (X-Rect-x xrect)
179 :width (X-Rect-width xrect)
180 :height (X-Rect-height xrect)))
183 (defstruct (X-Arc (:include X-Rect)
184 (:predicate X-Arc-isarc-p))
187 (defsubst X-Arc-p (xarc &optional sig)
188 "Return non-nil xf XARC is X-Arc structure."
189 (X-Generic-p 'X-Arc 'X-Arc-isarc-p xarc sig))
191 (defun X-Arc-message (xarc)
192 "Return string representing XARC."
193 (concat (int->string2 (X-Arc-x xarc))
194 (int->string2 (X-Arc-y xarc))
195 (int->string2 (X-Arc-width xarc))
196 (int->string2 (X-Arc-height xarc))
197 (int->string2 (* 64 (X-Arc-angle1 xarc)))
198 (int->string2 (* 64 (X-Arc-angle2 xarc)))))
201 (defstruct (X-Atom (:predicate X-Atom-isatom-p))
204 (defsubst X-Atom-p (atom &optional sig)
205 "Return non-nil if ATOM is atom structure.
206 If SIG is given and ATOM is not atom structure, SIG will be signaled."
207 (X-Generic-p 'X-Atom 'X-Atom-isatom-p atom sig))
209 (defsubst X-Atom-insert (xdpy atom)
210 "Insert ATOM in XDPY's atoms list, if not already there."
211 (pushnew atom (X-Dpy-atoms xdpy)
212 :test #'(lambda (a1 a2)
213 (= (X-Atom-id a1) (X-Atom-id a2)))))
215 (defsubst X-Atom-find (xdpy aid)
216 "Find atom with id AID on X display XDPY."
217 (X-Dpy-p xdpy 'X-Atom-find)
219 (let ((al (X-Dpy-atoms xdpy)))
220 (while (and al (not (= (X-Atom-id (car al)) aid)))
225 (defsubst X-Atom-find-or-make (xdpy aid)
226 "On XDPY find atom with id AID, if no such atom, create new one."
227 (X-Dpy-p xdpy 'X-Atom-find-or-make)
229 (or (X-Atom-find xdpy aid)
230 (car (X-Atom-insert xdpy (make-X-Atom :dpy xdpy :id aid)))))
232 (defsubst X-Atom-find-by-name (xdpy aname)
233 "Find atom with name ANAME on X display XDPY."
234 (let ((al (X-Dpy-atoms xdpy)))
235 (while (and al (not (string= (X-Atom-name (car al)) aname)))
239 (defsubst X-Atom-equal (a1 a2)
240 "Return non-nil if two atoms A1 and A2 are equal."
241 (eq (and (X-Atom-p a1) (X-Atom-id a1))
242 (and (X-Atom-p a2) (X-Atom-id a2))))
245 (defconst XA-AnyPropertyType (make-X-Atom :id 0.0 :name "") "Any atom.")
246 (defconst XA-primary (make-X-Atom :id 1.0 :name "PRIMARY") "Atom primary encoding.")
247 (defconst XA-secondary (make-X-Atom :id 2.0 :name "SECONDARY") "Atom secondary encoding.")
248 (defconst XA-arc (make-X-Atom :id 3.0 :name "ARC") "Atom arc encoding.")
249 (defconst XA-atom (make-X-Atom :id 4.0 :name "ATOM") "Atom atom encoding.")
250 (defconst XA-bitmap (make-X-Atom :id 5.0 :name "BITMAP") "Atom bitmap encoding.")
251 (defconst XA-cardinal (make-X-Atom :id 6.0 :name "CARDINAL") "Atom cardinal encoding.")
252 (defconst XA-colormap (make-X-Atom :id 7.0 :name "COLORMAP") "Atom colormap encoding.")
253 (defconst XA-cursor (make-X-Atom :id 8.0 :name "CURSOR") "Atom cursor encoding.")
254 (defconst XA-cut-buffer0 (make-X-Atom :id 9.0 :name "XA_CUT_BUFFER0") "Atom cut-buffer0 encoding.")
255 (defconst XA-cut-buffer1 (make-X-Atom :id 10.0 :name "CUT_BUFFER1") "Atom cut-buffer1 eoncoding.")
256 (defconst XA-cut-buffer2 (make-X-Atom :id 11.0 :name "CUT_BUFFER2") "Atom cut-buffer2 eoncoding.")
257 (defconst XA-cut-buffer3 (make-X-Atom :id 12.0 :name "CUT_BUFFER3") "Atom cut-buffer3 eoncoding.")
258 (defconst XA-cut-buffer4 (make-X-Atom :id 13.0 :name "CUT_BUFFER4") "Atom cut-buffer4 eoncoding.")
259 (defconst XA-cut-buffer5 (make-X-Atom :id 14.0 :name "CUT_BUFFER5") "Atom cut-buffer5 eoncoding.")
260 (defconst XA-cut-buffer6 (make-X-Atom :id 15.0 :name "CUT_BUFFER6") "Atom cut-buffer6 eoncoding.")
261 (defconst XA-cut-buffer7 (make-X-Atom :id 16.0 :name "CUT_BUFFER7") "Atom cut-buffer7 eoncoding.")
262 (defconst XA-drawable (make-X-Atom :id 17.0 :name "XA_DRAWABLE") "Atom drawable eoncoding.")
263 (defconst XA-font (make-X-Atom :id 18.0 :name "FONT") "Atom font eoncoding.")
264 (defconst XA-integer (make-X-Atom :id 19.0 :name "INTEGER") "Atom integer eoncoding.")
265 (defconst XA-pixmap (make-X-Atom :id 20.0 :name "PIXMAP") "Atom pixmap eoncoding.")
266 (defconst XA-point (make-X-Atom :id 21.0 :name "POINT") "Atom point eoncoding.")
267 (defconst XA-rectangle (make-X-Atom :id 22.0 :name "RECTANGLE") "Atom rectangle eoncoding.")
268 (defconst XA-resource-manager (make-X-Atom :id 23.0 :name "RESOURCE_MANAGER") "Atom resource-manager eoncoding.")
269 (defconst XA-rgb-color-map (make-X-Atom :id 24.0 :name "RGB_COLOR_MAP") "Atom rgb-color-map eoncoding.")
270 (defconst XA-rgb-best-map (make-X-Atom :id 25.0 :name "RGB_BEST_MAP") "Atom rgb-best-map eoncoding.")
271 (defconst XA-rgb-blue-map (make-X-Atom :id 26.0 :name "RGB_BLUE_MAP") "Atom rgb-blue-map eoncoding.")
272 (defconst XA-rgb-default-map (make-X-Atom :id 27.0 :name "RGB_DEFAULT_MAP") "Atom rgb-default-map eoncoding.")
273 (defconst XA-rgb-gray-map (make-X-Atom :id 28.0 :name "RGB_GRAY_MAP") "Atom rgb-gray-map eoncoding.")
274 (defconst XA-rgb-green-map (make-X-Atom :id 29.0 :name "RGB_GREEN_MAP") "Atom rgb-green-map eoncoding.")
275 (defconst XA-rgb-red-map (make-X-Atom :id 30.0 :name "RGB_RED_MAP") "Atom rgb-red-map eoncoding.")
276 (defconst XA-string (make-X-Atom :id 31.0 :name "STRING") "Atom string eoncoding.")
277 (defconst XA-visualid (make-X-Atom :id 32.0 :name "VISUALID") "Atom visualid eoncoding.")
278 (defconst XA-window (make-X-Atom :id 33.0 :name "WINDOW") "Atom window eoncoding.")
279 (defconst XA-wm-command (make-X-Atom :id 34.0 :name "WM_COMMAND") "Atom wm-command eoncoding.")
280 (defconst XA-wm-hints (make-X-Atom :id 35.0 :name "WM_HINTS") "Atom wm-hints eoncoding.")
281 (defconst XA-wm-client-machine (make-X-Atom :id 36.0 :name "WM_CLIENT_MACHINE") "Atom wm-client-machine eoncoding.")
282 (defconst XA-wm-icon-name (make-X-Atom :id 37.0 :name "WM_ICON_NAME") "Atom wm-icon-name eoncoding.")
283 (defconst XA-wm-icon-size (make-X-Atom :id 38.0 :name "WM_ICON_SIZE") "Atom wm-icon-size eoncoding.")
284 (defconst XA-wm-name (make-X-Atom :id 39.0 :name "WM_NAME") "Atom wm-name eoncoding.")
285 (defconst XA-wm-normal-hints (make-X-Atom :id 40.0 :name "WM_NORMAL_HINTS") "Atom wm-normal-hints eoncoding.")
286 (defconst XA-wm-size-hints (make-X-Atom :id 41.0 :name "WM_SIZE_HINTS") "Atom wm-size-hints eoncoding.")
287 (defconst XA-wm-zoom-hints (make-X-Atom :id 42.0 :name "WM_ZOOM_HINTS") "Atom wm-zoom-hints eoncoding.")
288 (defconst XA-min-space (make-X-Atom :id 43.0 :name "MIN_SPACE") "Atom min-space eoncoding.")
289 (defconst XA-norm-space (make-X-Atom :id 44.0 :name "NORM_SPACE") "Atom norm-space eoncoding.")
290 (defconst XA-max-space (make-X-Atom :id 45.0 :name "MAX_SPACE") "Atom max-space eoncoding.")
291 (defconst XA-end-space (make-X-Atom :id 46.0 :name "END_SPACE") "Atom end-space eoncoding.")
292 (defconst XA-superscript-x (make-X-Atom :id 47.0 :name "SUPERSCRIPT_X") "Atom superscript-x eoncoding.")
293 (defconst XA-superscript-y (make-X-Atom :id 48.0 :name "SUPERSCRIPT_Y") "Atom superscript-y eoncoding.")
294 (defconst XA-subscript-x (make-X-Atom :id 49.0 :name "SUBSCRIPT_X") "Atom subscript-x eoncoding.")
295 (defconst XA-subscript-y (make-X-Atom :id 50.0 :name "SUBSCRIPT_Y") "Atom subscript-y eoncoding.")
296 (defconst XA-underline-position (make-X-Atom :id 51.0 :name "UNDERLINE_POSITION") "Atom underline-position eoncoding.")
297 (defconst XA-underline-thickness (make-X-Atom :id 52.0 :name "UNDERLINE_THICKNESS") "Atom underline-thickness eoncoding.")
298 (defconst XA-strikeout-ascent (make-X-Atom :id 53.0 :name "STRIKEOUT_ASCENT") "Atom strikeout-ascent eoncoding.")
299 (defconst XA-strikeout-descent (make-X-Atom :id 54.0 :name "STRIKEOUT_DESCENT") "Atom strikeout-descent eoncoding.")
300 (defconst XA-italic-angle (make-X-Atom :id 55.0 :name "ITALIC_ANGLE") "Atom italic-angle eoncoding.")
301 (defconst XA-x-height (make-X-Atom :id 56.0 :name "X_HEIGHT") "Atom x-height eoncoding.")
302 (defconst XA-quad-width (make-X-Atom :id 57.0 :name "QUAD_WIDTH") "Atom quad-width eoncoding.")
303 (defconst XA-weight (make-X-Atom :id 58.0 :name "WEIGHT") "Atom weight eoncoding.")
304 (defconst XA-point-size (make-X-Atom :id 59.0 :name "POINT_SIZE") "Atom point-size eoncoding.")
305 (defconst XA-resolution (make-X-Atom :id 60.0 :name "RESOLUTION") "Atom resolution eoncoding.")
306 (defconst XA-copyright (make-X-Atom :id 61.0 :name "COPYRIGHT") "Atom copyright eoncoding.")
307 (defconst XA-notice (make-X-Atom :id 62.0 :name "NOTICE") "Atom notice eoncoding.")
308 (defconst XA-font-name (make-X-Atom :id 63.0 :name "FONT_NAME") "Atom font-name eoncoding.")
309 (defconst XA-family-name (make-X-Atom :id 64.0 :name "FAMILY_NAME") "Atom family-name eoncoding.")
310 (defconst XA-full-name (make-X-Atom :id 65.0 :name "FULL_NAME") "Atom full-name eoncoding.")
311 (defconst XA-cap-height (make-X-Atom :id 66.0 :name "CAP_HEIGHT") "Atom cap-height eoncoding.")
312 (defconst XA-wm-class (make-X-Atom :id 67.0 :name "WM_CLASS") "Atom wm-class eoncoding.")
313 (defconst XA-wm-transient-for (make-X-Atom :id 68.0 :name "WM_TRANSIENT_FOR") "Atom wm-transient-for eoncoding.")
316 ;;; Common predicates
317 (defsubst X-Win-p (win &optional sig)
318 "Return non-nil if WIN is X-Win structure.
319 If SIG is given and WIN is not X-Win structure, SIG will
321 (X-Generic-p 'X-Win 'X-Win-iswin-p win sig))
323 (defsubst X-Pixmap-p (pixmap &optional sig)
324 "Return non-nil if PIXMAP is X-Pixmap structure.
325 If SIG is given and PIXMAP is not X-Pixmap structure, SIG will be signaled."
326 (X-Generic-p 'X-Pixmap 'X-Pixmap-ispixmap-p pixmap sig))
328 (defsubst X-Colormap-p (cmap &optional sig)
329 "Return non-nil if CMAP is X-Colormap structure.
330 If SIG is given and CMAP is not X-Colormap structure, SIG will be signaled."
331 (X-Generic-p 'X-Colormap 'X-Colormap-iscmap-p cmap sig))
333 (defsubst X-Cursor-p (cursor &optional sig)
334 (X-Generic-p 'X-Cursor 'X-Cursor-iscursor-p cursor sig))
337 ;;; Attributes operations
338 (defstruct (X-Attr (:predicate X-Attr-isattr-p))
339 ;; any *-pixel is X-Color structure
341 background-pixmap background-pixel
342 border-pixmap border-pixel
343 bit-gravity win-gravity
344 backing-store backing-planes backing-pixel
348 do-not-propagate-mask
349 colormap ; X-Colormap
353 ;; List of extractors
355 (cons #'(lambda (attr)
356 (if (X-Pixmap-p (X-Attr-background-pixmap attr))
357 (X-Pixmap-id (X-Attr-background-pixmap attr))
358 (X-Attr-background-pixmap attr)))
360 (cons #'(lambda (attr)
361 (if (X-Color-p (X-Attr-background-pixel attr))
362 (X-Color-id (X-Attr-background-pixel attr))
363 (X-Attr-background-pixel attr)))
365 (cons #'(lambda (attr)
366 (if (X-Pixmap-p (X-Attr-border-pixmap attr))
367 (X-Pixmap-id (X-Attr-border-pixmap attr))
368 (X-Attr-border-pixmap attr)))
370 (cons #'(lambda (attr)
371 (if (X-Color-p (X-Attr-border-pixel attr))
372 (X-Color-id (X-Attr-border-pixel attr))
373 (X-Attr-border-pixel attr)))
375 (cons 'X-Attr-bit-gravity 1)
376 (cons 'X-Attr-win-gravity 1)
377 (cons 'X-Attr-backing-store 1)
378 (cons 'X-Attr-backing-planes 4)
379 (cons #'(lambda (attr)
380 (if (X-Color-p (X-Attr-backing-pixel attr))
381 (X-Color-id (X-Attr-backing-pixel attr))
382 (X-Attr-backing-pixel attr)))
384 (cons 'X-Attr-override-redirect 1)
385 (cons 'X-Attr-save-under 1)
386 (cons 'X-Attr-event-mask 4)
387 (cons 'X-Attr-do-not-propagate-mask 4)
388 (cons #'(lambda (attr)
389 (if (X-Colormap-p (X-Attr-colormap attr))
390 (X-Colormap-id (X-Attr-colormap attr))
391 (X-Attr-colormap attr)))
393 (cons #'(lambda (attr)
394 (if (X-Cursor-p (X-Attr-cursor attr))
395 (X-Cursor-id (X-Attr-cursor attr))
396 (X-Attr-cursor attr)))
399 (defun X-Attr-p (attr &optional sig)
400 "Return non-nil if ATTR is attributes structure.
401 If SIG is given and ATTR is not attributes structure, SIG will be signaled."
402 (let ((isattr (X-Attr-isattr-p attr)))
403 (if (and (not isattr) sig)
404 (signal 'wrong-type-argument (list sig 'X-Attr-p attr))
407 (defun X-Attr-message (attr)
408 "Return a string representing the attributes ATTR."
409 (X-Generate-message 'X-Attr attr))
411 ;;;Configure window structure
413 (defstruct (X-Conf (:predicate X-Conf-isconf-p))
422 (cons 'X-Conf-width 2)
423 (cons 'X-Conf-height 2)
424 (cons 'X-Conf-border-width 2)
425 (cons #'(lambda (conf)
426 (if (X-Win-p (X-Conf-sibling conf))
427 (X-Win-id (X-Conf-sibling conf))
428 (X-Conf-sibling conf)))
430 (cons 'X-Conf-stackmode 1))))
432 (defsubst X-Conf-p (conf &optional sig)
433 "Return non-nil if CONF is X-Conf structure.
434 If SIG is given and CONF is not X-Conf structure, SIG will be signaled."
435 (X-Generic-p 'X-Conf 'X-Conf-isconf-p conf sig))
437 (defun X-Conf-message (conf)
438 "Return a string representing the configuration CONF."
439 (X-Generate-message 'X-Conf conf 2))
441 ;;; Window allocation/testing/setting routines.
442 (defstruct (X-Win (:predicate X-Win-iswin-p))
445 event-handlers ; list of X-EventHandler
447 plist) ; user defined plist
449 (defun X-Win-invalidate (xdpy win)
450 "Remove WIN from dpy list and invalidate cl struct."
451 (add-timeout X-default-timeout
453 (setf (X-Dpy-windows (car xdpy-win))
454 (delq (cdr xdpy-win) (X-Dpy-windows (car xdpy-win))))
455 (X-invalidate-cl-struct (cdr xdpy-win)))
458 ;; Properties list operations
459 (defsubst X-Win-put-prop (win prop val)
460 (setf (X-Win-plist win) (plist-put (X-Win-plist win) prop val)))
462 (defsubst X-Win-get-prop (win prop)
463 (plist-get (X-Win-plist win) prop))
465 (defsubst X-Win-rem-prop (win prop)
466 (setf (X-Win-plist win) (plist-remprop (X-Win-plist win) prop)))
468 (defsubst X-Win-equal (win1 win2)
469 "Return non-nil if id's of WIN1 and WIN2 are equal."
470 (equal (X-Win-id win1) (X-Win-id win2)))
472 (defsubst X-Win-EventHandler-add (win handler &optional priority evtypes-list)
473 "To X-Win add events HANDLER.
475 HANDLER is function which should accept three arguments - xdpy(X-Dpy),
476 xwin(X-Win) and xev(X-Event). Only events with type that in
477 EVTYPES-LIST are passed to HANDLER. By default all events passed.
478 PRIORITY is place in events handler list, i.e. when HANDLER will be
479 called. Higher priorities runs first."
480 (setf (X-Win-event-handlers win)
481 (X-EventHandler-add (X-Win-event-handlers win) handler priority evtypes-list)))
483 (defsubst X-Win-EventHandler-isset (win handler &optional priority evtypes-list)
484 "For WIN's event handlers return X-EventHandler with HANDLER, PRIORITY and EVTYPES-LIST.
485 If you does not specify PRIORITY and EVTYPES-LIST, only matching with HANDLER occurs.
486 If event handler not found - nil will be returned."
487 (X-EventHandler-isset (X-Win-event-handlers win) handler priority evtypes-list))
489 (defsubst X-Win-EventHandler-add-new (win handler &optional priority evtypes-list)
490 "To X-Win add events HANDLER, only if no such handler already installed.
492 HANDLER is function which should accept three arguments - xdpy(X-Dpy),
493 xwin(X-Win) and xev(X-Event). Only events with type that in
494 EVTYPES-LIST are passed to HANDLER. By default all events passed.
495 PRIORITY is place in events handler list, i.e. when HANDLER will be
496 called. Higher priorities runs first."
497 (unless (X-Win-EventHandler-isset win handler priority evtypes-list)
498 (setf (X-Win-event-handlers win)
499 (X-EventHandler-add (X-Win-event-handlers win) handler priority evtypes-list))
502 (defsubst X-Win-EventHandler-rem (win handler &optional priority evtypes-list)
503 "From WIN's events handlers remove event HANDLER with PRIORITY and EVTYPES-LIST.
504 If you does not specify PRIORITY and EVTYPES-LIST, only matching with HANDLER occurs."
505 (setf (X-Win-event-handlers win)
506 (X-EventHandler-rem (X-Win-event-handlers win) handler priority evtypes-list)))
508 (defsubst X-Win-EventHandler-enable (win handler &optional priority evtypes-list)
509 "In WIN's event handlers list mark HANDLER with PRIORITY and EVTYPES-LIST as active."
510 (X-EventHandler-enable (X-Win-event-handlers win) handler priority evtypes-list))
512 (defsubst X-Win-EventHandler-disable (win handler &optional priority evtypes-list)
513 "In WIN's event handlers list mark HANDLER with PRIORITY and EVTYPES-LIST as inactive."
514 (X-EventHandler-disable (X-Win-event-handlers win) handler priority evtypes-list))
516 (defsubst X-Win-EventHandler-runall (win xev)
517 "Run all WIN's event handlers on XEV.
518 Signal `X-Events-stop' to stop events processing."
519 (X-EventHandler-runall (X-Win-event-handlers win) xev))
521 (defun X-Win-find (xdpy wid)
522 "Find X-Win with id WID on XDPY."
523 (X-Dpy-p xdpy 'X-Win-find)
525 (let ((wl (X-Dpy-windows xdpy)))
526 (while (and wl (not (= (X-Win-id (car wl)) wid)))
530 (defun X-Win-find-or-make (xdpy wid)
531 "Find X-Win with id WID on display XDPY, or make new one if not found."
532 (X-Dpy-p xdpy 'X-Win-find-or-make)
534 (or (X-Win-find xdpy wid)
535 (let ((xwin (make-X-Win :dpy xdpy :id wid)))
536 (X-Dpy-log xdpy 'x-event "XDPY Adding new window: %S" 'wid)
537 (push xwin (X-Dpy-windows xdpy))
541 (defstruct (X-Pixmap (:predicate X-Pixmap-ispixmap-p))
544 plist) ; User defined plist
546 (defun X-Pixmap-find-or-make (dpy id)
547 (make-X-Pixmap :dpy dpy :id id))
549 ;; Properties list operations
550 (defsubst X-Pixmap-put-prop (pixmap prop val)
551 (setf (X-Pixmap-plist pixmap) (plist-put (X-Pixmap-plist pixmap) prop val)))
553 (defsubst X-Pixmap-get-prop (pixmap prop)
554 (plist-get (X-Pixmap-plist pixmap) prop))
556 (defsubst X-Pixmap-rem-prop (pixmap prop)
557 (setf (X-Pixmap-plist pixmap) (plist-remprop (X-Pixmap-plist pixmap) prop)))
559 (defsubst X-Pixmap-width (pixmap)
560 "Return PIXMAP's width."
561 (X-Pixmap-get-prop pixmap 'width))
562 (defsetf X-Pixmap-width (pixmap) (nw)
563 `(X-Pixmap-put-prop ,pixmap 'width ,nw))
565 (defsubst X-Pixmap-height (pixmap)
566 "Return PIXMAP's height."
567 (X-Pixmap-get-prop pixmap 'height))
568 (defsetf X-Pixmap-height (pixmap) (nh)
569 `(X-Pixmap-put-prop ,pixmap 'height ,nh))
571 (defsubst X-Pixmap-depth (pixmap)
572 "Return PIXMAP's depth."
573 (X-Pixmap-get-prop pixmap 'depth))
574 (defsetf X-Pixmap-depth (pixmap) (nd)
575 `(X-Pixmap-put-prop ,pixmap 'depth ,nd))
578 ;; DRAWABLE stuff. A drawable is something you can draw to,
579 ;; therefore, the only fn we need, is a drawable-p function.
581 ;; Each time we make a new drawable surface, add that to the list
584 (defun X-Drawable-p (d &optional sig)
585 "Return non-nil if D is drawable.
586 If SIG, then signal on error."
587 (let ((isdp (or (X-Win-p d) (X-Pixmap-p d))))
588 (if (and sig (not isdp))
589 (signal 'wrong-type-argument (list sig 'X-Drawable-p d))
592 (defun X-Drawable-id (d)
593 "Return id of drawable D."
594 (X-Drawable-p d 'X-Drawable-id)
600 (defun X-Drawable-dpy (d)
601 "Return dpy of drawable D."
602 (X-Drawable-p d 'X-Drawable-dpy)
609 (defstruct (X-Colormap (:predicate X-Colormap-iscmap-p))
611 colors) ; list of X-Color [unused]
613 (defun X-Colormap-lookup-by-rgb (cmap col)
614 "Lookup color in colormap CMAP by R G B values of X-Color COL."
615 (let ((cols (X-Colormap-colors cmap)))
617 (not (and (= (X-Color-red col)
618 (X-Color-red (car cols)))
619 (= (X-Color-green col)
620 (X-Color-green (car cols)))
621 (= (X-Color-blue col)
622 (X-Color-blue (car cols))))))
623 (setq cols (cdr cols)))
627 (defun X-Colormap-lookup-by-name (cmap color-name)
628 "Lookup in CMAP color cache color named by COLOR-NAME."
629 (let ((cols (X-Colormap-colors cmap)))
631 (not (and (stringp (X-Color-name (car cols)))
632 (string= (X-Color-name (car cols)) color-name))))
633 (setq cols (cdr cols)))
636 (defun X-Colormap-lookup-by-id (cmap id)
637 "Lookup color in colormap CMAP by ID."
638 (let ((cols (X-Colormap-colors cmap)))
639 (while (and cols (not (= id (X-Color-id (car cols)))))
640 (setq cols (cdr cols)))
644 (defstruct (X-Color (:predicate X-Color-iscolor-p))
646 cmap ; back reference to X-Colormap
647 red green blue ; RGB values
648 name ; non-nil if allocated using `XAllocNamedColor'
651 (defun X-Color-p (col &optional sig)
652 (X-Generic-p 'X-Color 'X-Color-iscolor-p col sig))
654 (defun X-Color-message (col)
655 "Convert COL into X request message."
656 (X-Create-message (list [4 (X-Color-id col)]
657 [2 (X-Color-red col)] ; red
658 [2 (X-Color-green col)] ; green
659 [2 (X-Color-blue col)] ; blue
660 [1 (or (X-Color-flags col) X-DoRedGreenBlue)]
663 ;;; Graphical context structure
665 (defstruct (X-Gc (:predicate X-Gc-isgc-p))
673 line-style cap-style join-style fill-style
674 fill-rule tile stipple
675 tile-stipple-x-origin tile-stipple-y-origin
685 (cons 'X-Gc-function 1)
686 (cons 'X-Gc-plane-mask 4)
688 (if (X-Color-p (X-Gc-foreground gc))
689 (X-Color-id (X-Gc-foreground gc))
690 (X-Gc-foreground gc)))
693 (if (X-Color-p (X-Gc-background gc))
694 (X-Color-id (X-Gc-background gc))
695 (X-Gc-background gc)))
697 (cons 'X-Gc-line-width 2)
698 (cons 'X-Gc-line-style 1)
699 (cons 'X-Gc-cap-style 1)
700 (cons 'X-Gc-join-style 1)
701 (cons 'X-Gc-fill-style 1)
702 (cons 'X-Gc-fill-rule 1)
704 (cons 'X-Gc-stipple 4)
705 (cons 'X-Gc-tile-stipple-x-origin 2)
706 (cons 'X-Gc-tile-stipple-y-origin 2)
708 (if (X-Font-p (X-Gc-font gc))
709 (X-Font-id (X-Gc-font gc))
712 (cons 'X-Gc-subwindow-mode 1)
713 (cons 'X-Gc-graphics-exposures 1)
714 (cons 'X-Gc-clip-x-origin 2)
715 (cons 'X-Gc-clip-y-origin 2)
717 (if (X-Pixmap-p (X-Gc-clip-mask gc))
718 (X-Pixmap-id (X-Gc-clip-mask gc))
719 (X-Gc-clip-mask gc)))
721 (cons 'X-Gc-dash-offset 2)
722 (cons 'X-Gc-dashes 1)
723 (cons 'X-Gc-arc-mode 1))))
725 (defun X-Gc-p (gc &optional sig)
726 (X-Generic-p 'X-Gc 'X-Gc-isgc-p gc sig))
728 (defun X-Gc-real-line-width (gc)
729 "Return real GC's line width.
730 The thing is that 0 line width is actually 1, but uses hardware
731 assistance to draw such lines."
732 (let ((lw (X-Gc-line-width gc)))
733 (if (zerop lw) 1 lw)))
735 (defun X-Gc-message (gc)
736 "Convert GC into message string."
737 (X-Generate-message 'X-Gc gc))
740 (defstruct (X-CharInfo (:predicate X-CharInfo-ischarinfo-p))
743 (defstruct (X-Font (:predicate X-Font-isfont-p))
753 fontascent fontdescent
756 (defun X-Font-p (font &optional sig)
757 (X-Generic-p 'X-Font 'X-Font-isfont-p font sig))
759 (defun X-Font-find (xdpy fid)
760 "Find font with id FID on X display XDPY."
761 (X-Dpy-p xdpy 'X-Font-find)
763 (let ((fl (X-Dpy-fonts xdpy)))
764 (while (and fl (not (= (X-Font-id (car fl)) fid)))
768 (defcustom X-use-queryfont t "*Non-nil mean use QueryFont.")
770 (defun X-Font-get (xdpy fname)
771 "Get font by its name FNAME on display XDPY."
772 (X-Dpy-p xdpy 'X-Font-get)
774 (let ((fl (X-Dpy-fonts xdpy))
777 (while (and fl (not (string= (X-Font-name (car fl)) fname)))
784 ;; Else query X server for font
785 (setq rfn (make-X-Font :dpy xdpy :id (X-Dpy-get-id xdpy) :name fname))
787 (when X-use-queryfont
788 (unless (XQueryFont xdpy rfn)
792 (pushnew rfn (X-Dpy-fonts xdpy)))
795 ;; TODO: X-Font-height, X-Font-width, etc
796 (defun X-Font-heigth (font)
797 "Return FONT height."
798 (+ (X-Font-fontascent font)
799 (X-Font-fontdescent font)))
801 ;; NOTE: what if chr is '\n', '\t' or such?
802 (defun X-Font-char-width (chr font)
803 "Return CHR width for FONT."
804 (let* ((idx (- (Xforcenum chr) (X-Font-micob font)))
806 (if (> (length (X-Font-chinfo font)) idx)
807 (aref (X-Font-chinfo font) idx)
808 (X-Font-maxb font)) 2)))
811 (defun X-Text-ascent (dpy font text &optional font-asc)
812 "Return overall TEXT's ascent.
813 If FONT-ASC is non-nil, return FONT's ascent."
814 (if (not X-use-queryfont)
815 (let ((qtex (XQueryTextExtents dpy font text)))
816 (nth (if font-asc 3 5) qtex))
817 (X-Font-fontascent font)))
819 (defun X-Text-descent (dpy font text &optional font-desc)
820 "Return overall TEXT's descent.
821 If FONT-DESC is non-nil, return FONT's descent."
822 (if (not X-use-queryfont)
823 (let ((qtex (XQueryTextExtents dpy font text)))
824 (nth (if font-desc 4 6) qtex))
825 (X-Font-fontdescent font)))
827 (defun X-Text-height (dpy font text)
828 "Return TEXT height for FONT."
829 (if (not X-use-queryfont)
830 (let ((qtex (XQueryTextExtents dpy font text)))
831 (+ (nth 3 qtex) (nth 4 qtex)))
832 (X-Font-heigth font)))
834 (defun X-Text-width (dpy font text)
835 "Return width of TEXT when it will be displayed in FONT."
836 (if (not X-use-queryfont)
837 (nth 7 (XQueryTextExtents dpy font text))
839 (apply '+ (mapcar #'(lambda (chr)
840 (X-Font-char-width chr font))
844 (defun X-Fontable-p (fa &optional sig)
845 "Return non-nil if FA is fontable object.
846 If SIG, then signal on error."
847 (let ((isdp (or (X-Font-p fa) (X-Gc-p fa))))
848 (if (and sig (not isdp))
849 (signal 'wrong-type-argument (list sig 'X-Fontable-p fa))
852 (defun X-Fontable-id (fa)
853 "Return id of fontable object FA."
854 (X-Fontable-p fa 'X-Fontable-p)
860 (defun X-Fontable-dpy (fa)
861 "Return dpy of fontable object FA."
862 (X-Fontable-p fa 'X-Fontable-dpy)
868 ;;; Cursors structure
869 (defstruct (X-Cursor (:predicate X-Cursor-iscursor-p))
878 (cons #'(lambda (curs)
879 (if (X-Font-p (X-Cursor-source curs))
880 (X-Font-id (X-Cursor-source curs))
881 (X-Cursor-source curs)))
883 (cons #'(lambda (curs)
884 (if (X-Font-p (X-Cursor-mask curs))
885 (X-Font-id (X-Cursor-mask curs))
886 (X-Cursor-mask curs)))
888 (cons 'X-Cursor-src-char 2)
889 (cons 'X-Cursor-msk-char 2)
890 (cons 'X-Cursor-fgred 2)
891 (cons 'X-Cursor-fggreen 2)
892 (cons 'X-Cursor-fgblue 2)
893 (cons 'X-Cursor-bgred 2)
894 (cons 'X-Cursor-bggreen 2)
895 (cons 'X-Cursor-bgblue 2))))
897 (defun X-Cursor-find-or-make (dpy id)
898 (make-X-Cursor :dpy dpy :id id))
900 (defsubst X-Cursor-message (cursor)
901 "Turn CURSOR into the text of a message."
902 (X-Generate-simple-message 'X-Cursor cursor))
905 (defstruct (X-WMSize (:predicate X-WMSize-issize-p))
911 min-aspect-x min-aspect-y
912 max-aspect-x max-aspect-y
913 base-width base-height ; added by ICCCM v1
916 (defsubst X-WMSize-p (wms &optional sig)
917 (X-Generic-p 'X-WMSize 'X-WMSize-issize-p wms sig))
919 (defsubst X-WMSize-uspos-p (wms)
920 "Return non-nil if WMS have user specified x, y."
921 (Xtest (X-WMSize-flags wms) 1))
923 (defsubst X-WMSize-ussize-p (wms)
924 "Return non-nil if WMS have user specified width, height."
925 (Xtest (X-WMSize-flags wms) 2))
927 (defsubst X-WMSize-ppos-p (wms)
928 "Return non-nil if WMS have program specified position."
929 (Xtest (X-WMSize-flags wms) 4))
931 (defsubst X-WMSize-psize-p (wms)
932 "Return non-nil if WMS have program specified size."
933 (Xtest (X-WMSize-flags wms) 8))
935 (defsubst X-WMSize-pminsize-p (wms)
936 "Return non-nil if WMS have program specified minimum size."
937 (Xtest (X-WMSize-flags wms) 16))
939 (defsubst X-WMSize-pmaxsize-p (wms)
940 "Return non-nil if WMS have program specified maximum size."
941 (Xtest (X-WMSize-flags wms) 32))
943 (defsubst X-WMSize-presizeinc-p (wms)
944 "Return non-nil if WMS have program specified resize increments."
945 (Xtest (X-WMSize-flags wms) 64))
947 (defsubst X-WMSize-paspect-p (wms)
948 "Return non-nil if WMS have program specified min and max aspect ratios."
949 (Xtest (X-WMSize-flags wms) 128))
951 (defsubst X-WMSize-pbasesize-p (wms)
952 "Return non-nil if WMS have program specified base for incrementing."
953 (Xtest (X-WMSize-flags wms) 256))
955 (defsubst X-WMSize-pgravity-p (wms)
956 "Return non-nil if WMS have program specified window graivty."
957 (Xtest (X-WMSize-flags wms) 512))
959 (defstruct (X-WMHints (:predicate X-WMHints-ishints-p))
961 input ;does this app rely on the window manager to get keyboard input?
963 icon-pixmap ; X-Pixmap
967 window-group ; X-Win id
970 (defsubst X-WMHints-input-p (wmh)
971 "Return non-nil if WMH have InputHint."
972 (Xtest (X-WMHints-flags wmh) 1))
974 (defsubst X-WMHints-state-p (wmh)
975 "Return non-nil if WMH have StateHint."
976 (Xtest (X-WMHints-flags wmh) 2))
978 (defsubst X-WMHints-iconpixmap-p (wmh)
979 "Return non-nil if WMH have IconPixmapHint."
980 (Xtest (X-WMHints-flags wmh) 4))
982 (defsubst X-WMHints-iconwindow-p (wmh)
983 "Return non-nil if WMH have IconWindowHint."
984 (Xtest (X-WMHints-flags wmh) 8))
986 (defsubst X-WMHints-iconpos-p (wmh)
987 "Return non-nil if WMH have IconPositionHint."
988 (Xtest (X-WMHints-flags wmh) 16))
990 (defsubst X-WMHints-iconmask-p (wmh)
991 "Return non-nil if WMH have IconMaskHint."
992 (Xtest (X-WMHints-flags wmh) 32))
994 (defsubst X-WMHints-wingroup-p (wmh)
995 "Return non-nil if WMH have WindowGroupHint."
996 (Xtest (X-WMHints-flags wmh) 64))
998 (defsubst X-WMHints-urgency-p (wmh)
999 "Return non-nil if WMH have UrgencyHint."
1000 (Xtest (X-WMHints-flags wmh) 256))
1002 ;; Generic functions
1003 (defun X-Generic-struct-p (gstruct)
1004 "Return non-nil if GSTRUCT is generic struct which have id field."
1005 ;; DO NOT USE THIS FUNCTION
1006 (and (vectorp gstruct) (intern (concat (substring (symbol-name (aref gstruct 0)) 10) "-id"))))
1008 (defun X-Generic-p (type pfunc thing &optional sig)
1009 "Returns non-nil if THING is of TYPE, using predicate PFUNC.
1010 If SIG is given, then signal if error."
1012 (let ((isit (funcall pfunc thing)))
1013 (if (and (not isit) sig)
1014 (signal 'wrong-type-argument (list sig type thing))
1017 (defun X-Generate-message (type attr &optional bitmask-size)
1018 "Convert the attribute structure ATTR to a string.
1019 The string is the message starting with VALUE_MASK, needed for
1020 variable length requests, and the LISTofVALUE parts, depending if
1021 those parts have been set.
1022 Optional BITMASK-SIZE determines how much space is used by the bitmask
1023 used in the message. If it is excluded, then it defaults to 4."
1025 (funcall (intern (format "%s-p" type)) attr 'X-Generate-message)
1027 (when (null bitmask-size)
1028 (setq bitmask-size 4))
1030 (let* ((gc-cons-threshold most-positive-fixnum) ; inhibit gc'ing
1031 (m (float 0)) ; mask o parts
1032 (l (cond ((= bitmask-size 4) ; the mask o given parts
1035 (list [2 nil] ; reversed later
1039 (t (error "Unsupported bitmask-size! Update the code."))))
1040 (sal (funcall (intern (format "%s-list" type)) attr)) ; saved attr list
1042 (tempv nil)) ;temp vector
1044 (flet ((getval (what)
1045 (funcall what attr)))
1047 (when (or (= bitmask-size 0)
1048 (getval (caar xal)))
1049 ;; set the value part
1050 (setq l (cons (progn
1051 (setq tempv (make-vector 2 nil))
1052 (aset tempv 0 (cdar xal)) ;size
1053 (aset tempv 1 (getval (caar xal)))
1057 ;; put in padding if we need it.
1058 ;; put it only if bitmask-size > 0
1059 (when (and (> bitmask-size 0) (< (cdar xal) 4))
1060 (setq l (cons (progn
1061 (setq tempv (make-vector 2 nil))
1062 (aset tempv 0 (- 4 (cdar xal)))
1066 (setq m (Xmask-or m (Xmask (- (length sal) (length xal))))))
1067 (setq xal (cdr xal))))
1069 (when (<= bitmask-size 2)
1070 (setq m (truncate m)))
1072 (X-Create-message (reverse l) (= bitmask-size 0))))
1074 (defun X-Generate-simple-message (type struct)
1075 "Same as `X-Generate-message', but does not put value_mask."
1076 (X-Generate-message type struct 0))
1078 (defun X-Generate-message-for-list (structs-list genfun)
1079 "For given list of structures STRUCTS-LIST, generate message using function GENFUNC.
1080 Each element in STRUCTS-LIST is of STRUCT-TYPE."
1081 (mapconcat genfun structs-list ""))
1084 (provide 'xlib-xwin)
1086 ;;; xlib-xwin.el ends here