1 /* -*-C-*-
2
3 Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
4 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
5 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Massachusetts
6 Institute of Technology
7
8 This file is part of MIT/GNU Scheme.
9
10 MIT/GNU Scheme is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or (at
13 your option) any later version.
14
15 MIT/GNU Scheme is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with MIT/GNU Scheme; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
23 USA.
24
25 */
26
27 /* Common X11 support. */
28
29 #include "scheme.h"
30 #include "prims.h"
31 #include "ux.h"
32 #include "osio.h"
33 #include "x11.h"
34 #include <X11/Xmd.h>
35 #include <X11/keysym.h>
36
37 extern void block_signals (void);
38 extern void unblock_signals (void);
39
40 #ifndef X_DEFAULT_FONT
41 # define X_DEFAULT_FONT "fixed"
42 #endif
43
44 int x_debug = 0;
45 static int initialization_done = 0;
46 static const char * x_default_font = 0;
47
48 #define INITIALIZE_ONCE() \
49 { \
50 if (!initialization_done) \
51 initialize_once (); \
52 }
53
54 static void initialize_once (void);
55
56 static void move_window (struct xwindow *, int, int);
57 static void check_expected_move (struct xwindow *);
58
59 void *
x_malloc(unsigned int size)60 x_malloc (unsigned int size)
61 {
62 void * result = (UX_malloc (size));
63 if (result == 0)
64 error_external_return ();
65 return (result);
66 }
67
68 void *
x_realloc(void * ptr,unsigned int size)69 x_realloc (void * ptr, unsigned int size)
70 {
71 void * result = (UX_realloc (ptr, size));
72 if (result == 0)
73 error_external_return ();
74 return (result);
75 }
76
77 /* Allocation Tables */
78
79 struct allocation_table
80 {
81 void ** items;
82 int length;
83 };
84
85 static struct allocation_table x_display_table;
86 static struct allocation_table x_window_table;
87 static struct allocation_table x_image_table;
88 static struct allocation_table x_visual_table;
89 static struct allocation_table x_colormap_table;
90
91 static void
allocation_table_initialize(struct allocation_table * table)92 allocation_table_initialize (struct allocation_table * table)
93 {
94 (table->length) = 0;
95 }
96
97 static unsigned int
allocate_table_index(struct allocation_table * table,void * item)98 allocate_table_index (struct allocation_table * table, void * item)
99 {
100 unsigned int length = (table->length);
101 unsigned int new_length;
102 void ** items = (table->items);
103 void ** new_items;
104 void ** scan;
105 void ** end;
106 if (length == 0)
107 {
108 new_length = 4;
109 new_items = (x_malloc ((sizeof (void *)) * new_length));
110 }
111 else
112 {
113 scan = items;
114 end = (scan + length);
115 while (scan < end)
116 if ((*scan++) == 0)
117 {
118 (*--scan) = item;
119 return (scan - items);
120 }
121 new_length = (length * 2);
122 new_items = (x_realloc (items, ((sizeof (void *)) * new_length)));
123 }
124 scan = (new_items + length);
125 end = (new_items + new_length);
126 (*scan++) = item;
127 while (scan < end)
128 (*scan++) = 0;
129 (table->items) = new_items;
130 (table->length) = new_length;
131 return (length);
132 }
133
134 static void *
allocation_item_arg(unsigned int arg,struct allocation_table * table)135 allocation_item_arg (unsigned int arg, struct allocation_table * table)
136 {
137 unsigned int index = (arg_index_integer (arg, (table->length)));
138 void * item = ((table->items) [index]);
139 if (item == 0)
140 error_bad_range_arg (arg);
141 return (item);
142 }
143
144 struct xdisplay *
x_display_arg(unsigned int arg)145 x_display_arg (unsigned int arg)
146 {
147 INITIALIZE_ONCE ();
148 return (allocation_item_arg (arg, (&x_display_table)));
149 }
150
151 struct xwindow *
x_window_arg(unsigned int arg)152 x_window_arg (unsigned int arg)
153 {
154 INITIALIZE_ONCE ();
155 return (allocation_item_arg (arg, (&x_window_table)));
156 }
157
158 static struct xwindow *
x_window_to_xw(Display * display,Window window)159 x_window_to_xw (Display * display, Window window)
160 {
161 struct xwindow ** scan = ((struct xwindow **) (x_window_table.items));
162 struct xwindow ** end = (scan + (x_window_table.length));
163 while (scan < end)
164 {
165 struct xwindow * xw = (*scan++);
166 if ((xw != 0)
167 && ((XW_DISPLAY (xw)) == display)
168 && ((XW_WINDOW (xw)) == window))
169 return (xw);
170 }
171 return (0);
172 }
173
174 struct ximage *
x_image_arg(unsigned int arg)175 x_image_arg (unsigned int arg)
176 {
177 INITIALIZE_ONCE ();
178 return (allocation_item_arg (arg, (&x_image_table)));
179 }
180
181 unsigned int
allocate_x_image(XImage * image)182 allocate_x_image (XImage * image)
183 {
184 struct ximage * xi = (x_malloc (sizeof (struct ximage)));
185 unsigned int index = (allocate_table_index ((&x_image_table), xi));
186 (XI_ALLOCATION_INDEX (xi)) = index;
187 (XI_IMAGE (xi)) = image;
188 return (index);
189 }
190
191 void
deallocate_x_image(struct ximage * xi)192 deallocate_x_image (struct ximage * xi)
193 {
194 ((x_image_table.items) [XI_ALLOCATION_INDEX (xi)]) = 0;
195 free (xi);
196 }
197
198 struct xvisual *
x_visual_arg(unsigned int arg)199 x_visual_arg (unsigned int arg)
200 {
201 INITIALIZE_ONCE ();
202 return (allocation_item_arg (arg, (&x_visual_table)));
203 }
204
205 unsigned int
allocate_x_visual(Visual * visual)206 allocate_x_visual (Visual * visual)
207 {
208 struct xvisual * xv = (x_malloc (sizeof (struct xvisual)));
209 unsigned int index = (allocate_table_index ((&x_visual_table), xv));
210 (XV_ALLOCATION_INDEX (xv)) = index;
211 (XV_VISUAL (xv)) = visual;
212 return (index);
213 }
214
215 void
deallocate_x_visual(struct xvisual * xv)216 deallocate_x_visual (struct xvisual * xv)
217 {
218 ((x_visual_table.items) [XV_ALLOCATION_INDEX (xv)]) = 0;
219 free (xv);
220 }
221
222 struct xcolormap *
x_colormap_arg(unsigned int arg)223 x_colormap_arg (unsigned int arg)
224 {
225 INITIALIZE_ONCE ();
226 return (allocation_item_arg (arg, (&x_colormap_table)));
227 }
228
229 unsigned int
allocate_x_colormap(Colormap colormap,struct xdisplay * xd)230 allocate_x_colormap (Colormap colormap, struct xdisplay * xd)
231 {
232 struct xcolormap * xcm = (x_malloc (sizeof (struct xcolormap)));
233 unsigned int index = (allocate_table_index ((&x_colormap_table), xcm));
234 (XCM_ALLOCATION_INDEX (xcm)) = index;
235 (XCM_COLORMAP (xcm)) = colormap;
236 (XCM_XD (xcm)) = xd;
237 return (index);
238 }
239
240 void
deallocate_x_colormap(struct xcolormap * xcm)241 deallocate_x_colormap (struct xcolormap * xcm)
242 {
243 ((x_colormap_table.items) [XCM_ALLOCATION_INDEX (xcm)]) = 0;
244 free (xcm);
245 }
246
247 /* Error Handlers */
248
249 static int
x_io_error_handler(Display * display)250 x_io_error_handler (Display * display)
251 {
252 fprintf (stderr, "\nX IO Error\n");
253 fflush (stderr);
254 termination_eof ();
255 return (0);
256 }
257
258 typedef struct
259 {
260 char message [2048];
261 char terminate_p;
262 unsigned char code;
263 } x_error_info_t;
264
265 static x_error_info_t x_error_info;
266
267 static int
x_error_handler(Display * display,XErrorEvent * error_event)268 x_error_handler (Display * display, XErrorEvent * error_event)
269 {
270 (x_error_info.code) = (error_event->error_code);
271 XGetErrorText (display,
272 (error_event->error_code),
273 (x_error_info.message),
274 (sizeof (x_error_info.message)));
275 if (x_error_info.terminate_p)
276 {
277 fprintf (stderr, "\nX Error: %s\n", (x_error_info.message));
278 fprintf (stderr, " Request code: %d\n",
279 (error_event->request_code));
280 fprintf (stderr, " Error serial: %lx\n", (error_event->serial));
281 fflush (stderr);
282 termination_eof ();
283 }
284 return (0);
285 }
286
287 static void
unbind_x_error_info(void * storage)288 unbind_x_error_info (void * storage)
289 {
290 x_error_info = (* ((x_error_info_t *) storage));
291 }
292
293 static void *
push_x_error_info(Display * display)294 push_x_error_info (Display * display)
295 {
296 void * handle;
297 x_error_info_t * storage;
298
299 XSync (display, False);
300 handle = dstack_position;
301 storage = (dstack_alloc (sizeof (x_error_info_t)));
302 (*storage) = x_error_info;
303 ((x_error_info.message) [0]) = '\0';
304 (x_error_info.terminate_p) = 0;
305 (x_error_info.code) = 0;
306 dstack_protect (unbind_x_error_info, storage);
307 return (handle);
308 }
309
310 static void
pop_x_error_info(void * handle)311 pop_x_error_info (void * handle)
312 {
313 dstack_set_position (handle);
314 }
315
316 static unsigned char
x_error_code(Display * display)317 x_error_code (Display * display)
318 {
319 XSync (display, False);
320 return (x_error_info.code);
321 }
322
323 static int
any_x_errors_p(Display * display)324 any_x_errors_p (Display * display)
325 {
326 return ((x_error_code (display)) != 0);
327 }
328
329 /* Defaults and Attributes */
330
331 static int
x_decode_color(Display * display,Colormap color_map,const char * color_name,unsigned long * color_return)332 x_decode_color (Display * display,
333 Colormap color_map,
334 const char * color_name,
335 unsigned long * color_return)
336 {
337 XColor cdef;
338 if ((XParseColor (display, color_map, color_name, (&cdef)))
339 && (XAllocColor (display, color_map, (&cdef))))
340 {
341 (*color_return) = (cdef.pixel);
342 return (1);
343 }
344 return (0);
345 }
346
347 Colormap
xw_color_map(struct xwindow * xw)348 xw_color_map (struct xwindow * xw)
349 {
350 XWindowAttributes a;
351 if (! (XGetWindowAttributes ((XW_DISPLAY (xw)), (XW_WINDOW (xw)), (&a))))
352 error_external_return ();
353 return (a.colormap);
354 }
355
356 static unsigned long
arg_window_color(unsigned int arg,Display * display,struct xwindow * xw)357 arg_window_color (unsigned int arg, Display * display, struct xwindow * xw)
358 {
359 unsigned long result;
360 SCHEME_OBJECT object = (ARG_REF (arg));
361 if (INTEGER_P (object))
362 {
363 if (! (integer_to_ulong_p (object)))
364 error_bad_range_arg (arg);
365 result = (integer_to_ulong (object));
366 }
367 else if (! (x_decode_color
368 (display, (xw_color_map (xw)), (STRING_ARG (arg)), (&result))))
369 error_bad_range_arg (arg);
370 return (result);
371 }
372
373 static void
x_set_mouse_colors(Display * display,Colormap color_map,Cursor mouse_cursor,unsigned long mouse_pixel,unsigned long background_pixel)374 x_set_mouse_colors (Display * display,
375 Colormap color_map,
376 Cursor mouse_cursor,
377 unsigned long mouse_pixel,
378 unsigned long background_pixel)
379 {
380 XColor mouse_color;
381 XColor background_color;
382 (mouse_color.pixel) = mouse_pixel;
383 XQueryColor (display, color_map, (&mouse_color));
384 (background_color.pixel) = background_pixel;
385 XQueryColor (display, color_map, (&background_color));
386 XRecolorCursor (display, mouse_cursor, (&mouse_color), (&background_color));
387 }
388
389 const char *
x_get_default(Display * display,const char * resource_name,const char * resource_class,const char * property_name,const char * property_class,const char * sdefault)390 x_get_default (Display * display,
391 const char * resource_name,
392 const char * resource_class,
393 const char * property_name,
394 const char * property_class,
395 const char * sdefault)
396 {
397 const char * result = (XGetDefault (display, resource_name, property_name));
398 if (result != 0)
399 return (result);
400 result = (XGetDefault (display, resource_class, property_name));
401 if (result != 0)
402 return (result);
403 result = (XGetDefault (display, resource_name, property_class));
404 if (result != 0)
405 return (result);
406 result = (XGetDefault (display, resource_class, property_class));
407 if (result != 0)
408 return (result);
409 return (sdefault);
410 }
411
412 static unsigned long
x_default_color(Display * display,const char * resource_name,const char * resource_class,const char * property_name,const char * property_class,unsigned long default_color)413 x_default_color (Display * display,
414 const char * resource_name,
415 const char * resource_class,
416 const char * property_name,
417 const char * property_class,
418 unsigned long default_color)
419 {
420 const char * color_name
421 = (x_get_default (display, resource_name, resource_class,
422 property_name, property_class, 0));
423 unsigned long result;
424 return
425 (((color_name != 0)
426 && (x_decode_color (display,
427 (DefaultColormap (display,
428 (DefaultScreen (display)))),
429 color_name,
430 (&result))))
431 ? result
432 : default_color);
433 }
434
435 void
x_default_attributes(Display * display,const char * resource_name,const char * resource_class,struct drawing_attributes * attributes)436 x_default_attributes (Display * display,
437 const char * resource_name,
438 const char * resource_class,
439 struct drawing_attributes * attributes)
440 {
441 int screen_number = (DefaultScreen (display));
442 (attributes->font)
443 = (XLoadQueryFont (display,
444 ((x_default_font != 0)
445 ? x_default_font
446 : (x_get_default (display,
447 resource_name, resource_class,
448 "font", "Font",
449 X_DEFAULT_FONT)))));
450 if ((attributes->font) == 0)
451 error_external_return ();
452 {
453 const char * s
454 = (x_get_default (display,
455 resource_name, resource_class,
456 "borderWidth", "BorderWidth",
457 0));
458 (attributes->border_width) = ((s == 0) ? 0 : (atoi (s)));
459 }
460 {
461 const char * s
462 = (x_get_default (display,
463 resource_name, resource_class,
464 "internalBorder", "BorderWidth",
465 0));
466 (attributes->internal_border_width)
467 = ((s == 0) ? (attributes->border_width) : (atoi (s)));
468 }
469 {
470 unsigned long white_pixel = (WhitePixel (display, screen_number));
471 unsigned long black_pixel = (BlackPixel (display, screen_number));
472 unsigned long foreground_pixel;
473 (attributes->background_pixel)
474 = (x_default_color (display,
475 resource_name, resource_class,
476 "background", "Background",
477 white_pixel));
478 foreground_pixel
479 = (x_default_color (display,
480 resource_name, resource_class,
481 "foreground", "Foreground",
482 black_pixel));
483 (attributes->foreground_pixel) = foreground_pixel;
484 (attributes->border_pixel)
485 = (x_default_color (display,
486 resource_name, resource_class,
487 "borderColor", "BorderColor",
488 foreground_pixel));
489 (attributes->cursor_pixel)
490 = (x_default_color (display,
491 resource_name, resource_class,
492 "cursorColor", "Foreground",
493 foreground_pixel));
494 (attributes->mouse_pixel)
495 = (x_default_color (display,
496 resource_name, resource_class,
497 "pointerColor", "Foreground",
498 foreground_pixel));
499 }
500 }
501
502 static int
get_wm_decor_geometry(struct xwindow * xw)503 get_wm_decor_geometry (struct xwindow * xw)
504 {
505 Display * display = (XW_DISPLAY (xw));
506 Window decor = (XW_WINDOW (xw));
507 void * handle = (push_x_error_info (display));
508 Window root;
509 unsigned int depth;
510
511 {
512 Window parent;
513 Window * children;
514 unsigned int n_children;
515 while (1)
516 {
517 if ((!XQueryTree (display, decor,
518 (&root), (&parent), (&children), (&n_children)))
519 || (any_x_errors_p (display)))
520 {
521 pop_x_error_info (handle);
522 error_external_return ();
523 }
524 if (children != 0)
525 XFree (children);
526 if (parent == root)
527 break;
528 decor = parent;
529 }
530 }
531 if ((!XGetGeometry (display,
532 decor,
533 (&root),
534 (& (XW_WM_DECOR_X (xw))),
535 (& (XW_WM_DECOR_Y (xw))),
536 (& (XW_WM_DECOR_PIXEL_WIDTH (xw))),
537 (& (XW_WM_DECOR_PIXEL_HEIGHT (xw))),
538 (& (XW_WM_DECOR_BORDER_WIDTH (xw))),
539 (&depth)))
540 || (any_x_errors_p (display)))
541 {
542 pop_x_error_info (handle);
543 error_external_return ();
544 }
545 pop_x_error_info (handle);
546 /* Return true iff the window has been reparented by the WM. */
547 return (decor != (XW_WINDOW (xw)));
548 }
549
550 /* Open/Close Windows */
551
552 #define MAKE_GC(gc, fore, back) \
553 { \
554 XGCValues gcv; \
555 (gcv.font) = fid; \
556 (gcv.foreground) = (fore); \
557 (gcv.background) = (back); \
558 (gc) = \
559 (XCreateGC (display, \
560 window, \
561 (GCFont | GCForeground | GCBackground), \
562 (& gcv))); \
563 }
564
565 struct xwindow *
x_make_window(struct xdisplay * xd,Window window,int x_size,int y_size,struct drawing_attributes * attributes,struct xwindow_methods * methods,unsigned int size)566 x_make_window (struct xdisplay * xd,
567 Window window,
568 int x_size,
569 int y_size,
570 struct drawing_attributes * attributes,
571 struct xwindow_methods * methods,
572 unsigned int size)
573 {
574 GC normal_gc;
575 GC reverse_gc;
576 GC cursor_gc;
577 struct xwindow * xw;
578 Display * display = (XD_DISPLAY (xd));
579 Font fid = ((attributes->font) -> fid);
580 unsigned long foreground_pixel = (attributes->foreground_pixel);
581 unsigned long background_pixel = (attributes->background_pixel);
582 Cursor mouse_cursor = (XCreateFontCursor (display, XC_left_ptr));
583 MAKE_GC (normal_gc, foreground_pixel, background_pixel);
584 MAKE_GC (reverse_gc, background_pixel, foreground_pixel);
585 MAKE_GC (cursor_gc, background_pixel, (attributes->cursor_pixel));
586 x_set_mouse_colors
587 (display,
588 (DefaultColormap (display, (DefaultScreen (display)))),
589 mouse_cursor,
590 (attributes->mouse_pixel),
591 background_pixel);
592 XDefineCursor (display, window, mouse_cursor);
593 XSelectInput (display, window, 0);
594 if (size < (sizeof (struct xwindow)))
595 error_external_return ();
596 xw = (x_malloc (size));
597 (XW_ALLOCATION_INDEX (xw)) = (allocate_table_index ((&x_window_table), xw));
598 (XW_XD (xw)) = xd;
599 (XW_WINDOW (xw)) = window;
600 (XW_X_SIZE (xw)) = x_size;
601 (XW_Y_SIZE (xw)) = y_size;
602 (XW_CLIP_X (xw)) = 0;
603 (XW_CLIP_Y (xw)) = 0;
604 (XW_CLIP_WIDTH (xw)) = x_size;
605 (XW_CLIP_HEIGHT (xw)) = y_size;
606 (xw->attributes) = (*attributes);
607 (xw->methods) = (*methods);
608 (XW_NORMAL_GC (xw)) = normal_gc;
609 (XW_REVERSE_GC (xw)) = reverse_gc;
610 (XW_CURSOR_GC (xw)) = cursor_gc;
611 (XW_MOUSE_CURSOR (xw)) = mouse_cursor;
612 (XW_EVENT_MASK (xw)) = 0;
613 (XW_CHECK_EXPECTED_MOVE_P (xw)) = 0;
614 (XW_MOVE_OFFSET_X (xw)) = 0;
615 (XW_MOVE_OFFSET_Y (xw)) = 0;
616 return (xw);
617 }
618
619 static jmp_buf x_close_window_jmp_buf;
620
621 static int
x_close_window_io_error(Display * display)622 x_close_window_io_error (Display * display)
623 {
624 longjmp (x_close_window_jmp_buf, 1);
625 /*NOTREACHED*/
626 return (0);
627 }
628
629 static void
x_close_window(struct xwindow * xw)630 x_close_window (struct xwindow * xw)
631 {
632 Display * display = (XW_DISPLAY (xw));
633 ((x_window_table.items) [XW_ALLOCATION_INDEX (xw)]) = 0;
634 if ((setjmp (x_close_window_jmp_buf)) == 0)
635 {
636 XSetIOErrorHandler (x_close_window_io_error);
637 {
638 x_deallocator_t deallocator = (XW_DEALLOCATOR (xw));
639 if (deallocator != 0)
640 (*deallocator) (xw);
641 }
642 {
643 XFontStruct * font = (XW_FONT (xw));
644 if (font != 0)
645 XFreeFont (display, font);
646 }
647 XDestroyWindow (display, (XW_WINDOW (xw)));
648 /* Guarantee that the IO error occurs while the IO error handler
649 is rebound, if at all. */
650 XFlush (display);
651 }
652 XSetIOErrorHandler (x_io_error_handler);
653 free (xw);
654 }
655
656 /* Initialize/Close Displays */
657
658 #define MODIFIER_INDEX_TO_MASK(N) (1 << (N))
659
660 /* Grovel through the X server's keycode and modifier mappings to find
661 out what we ought to interpret as Meta, Hyper, and Super, based on
662 what modifiers are associated with keycodes that are associated with
663 keysyms Meta_L, Meta_R, Alt_L, Alt_R, Hyper_L, &c.
664
665 Adapted from GNU Emacs. */
666
667 static void
x_initialize_display_modifier_masks(struct xdisplay * xd)668 x_initialize_display_modifier_masks (struct xdisplay * xd)
669 {
670 int min_keycode;
671 int max_keycode;
672 XModifierKeymap * modifier_keymap;
673 KeyCode * modifier_to_keycodes_table;
674 int keycodes_per_modifier;
675 KeySym * keycode_to_keysyms_table;
676 int keysyms_per_keycode;
677
678 (XD_MODIFIER_MASK_META (xd)) = 0;
679 (XD_MODIFIER_MASK_SUPER (xd)) = 0;
680 (XD_MODIFIER_MASK_HYPER (xd)) = 0;
681
682 modifier_keymap = (XGetModifierMapping ((XD_DISPLAY (xd))));
683 modifier_to_keycodes_table = (modifier_keymap->modifiermap);
684 keycodes_per_modifier = (modifier_keymap->max_keypermod);
685
686 XDisplayKeycodes ((XD_DISPLAY (xd)), (& min_keycode), (& max_keycode));
687
688 keycode_to_keysyms_table
689 = (XGetKeyboardMapping ((XD_DISPLAY (xd)),
690 min_keycode,
691 (max_keycode - min_keycode + 1),
692 (& keysyms_per_keycode)));
693
694 /* Go through each of the 8 non-preassigned modifiers, which start at
695 3 (Mod1), after Shift, Control, and Lock. For each modifier, go
696 through all of the (non-zero) keycodes attached to it; for each
697 keycode, go through all of the keysyms attached to it; check each
698 keysym for the modifiers that we're interested in (Meta, Hyper,
699 and Super). */
700
701 {
702 int modifier_index;
703
704 for (modifier_index = 3; (modifier_index < 8); modifier_index += 1)
705 {
706 int modifier_mask = (MODIFIER_INDEX_TO_MASK (modifier_index));
707 KeyCode * keycodes
708 = (& (modifier_to_keycodes_table
709 [modifier_index * keycodes_per_modifier]));
710
711 /* This is a flag specifying whether the modifier has already
712 been identified as Meta, which takes precedence over Hyper
713 and Super. (What about precedence between Hyper and
714 Super...? This is GNU Emacs's behaviour.) */
715 int modifier_is_meta_p = 0;
716
717 int keycode_index;
718
719 for (keycode_index = 0;
720 (keycode_index < keycodes_per_modifier);
721 keycode_index += 1)
722 {
723 KeyCode keycode = (keycodes [keycode_index]);
724
725 if (keycode == 0)
726 continue;
727
728 {
729 int keysym_index;
730 KeySym * keysyms
731 = (& (keycode_to_keysyms_table
732 [(keycode - min_keycode) * keysyms_per_keycode]));
733
734 for (keysym_index = 0;
735 (keysym_index < keysyms_per_keycode);
736 keysym_index += 1)
737 switch (keysyms [keysym_index])
738 {
739 case XK_Meta_L:
740 case XK_Meta_R:
741 case XK_Alt_L:
742 case XK_Alt_R:
743 modifier_is_meta_p = 1;
744 (XD_MODIFIER_MASK_META (xd)) |= modifier_mask;
745 break;
746
747 case XK_Hyper_L:
748 case XK_Hyper_R:
749 if (! modifier_is_meta_p)
750 (XD_MODIFIER_MASK_HYPER (xd)) |= modifier_mask;
751 goto next_modifier;
752
753 case XK_Super_L:
754 case XK_Super_R:
755 if (! modifier_is_meta_p)
756 (XD_MODIFIER_MASK_SUPER (xd)) |= modifier_mask;
757 goto next_modifier;
758 }
759 }
760 }
761
762 next_modifier:
763 continue;
764 }
765 }
766
767 XFree (((char *) keycode_to_keysyms_table));
768 XFreeModifiermap (modifier_keymap);
769 }
770
771 static void
x_close_display(struct xdisplay * xd)772 x_close_display (struct xdisplay * xd)
773 {
774 struct xwindow ** scan = ((struct xwindow **) (x_window_table.items));
775 struct xwindow ** end = (scan + (x_window_table.length));
776 while (scan < end)
777 {
778 struct xwindow * xw = (*scan++);
779 if ((xw != 0) && ((XW_XD (xw)) == xd))
780 x_close_window (xw);
781 }
782 ((x_display_table.items) [XD_ALLOCATION_INDEX (xd)]) = 0;
783 XCloseDisplay (XD_DISPLAY (xd));
784 }
785
786 static void
x_close_all_displays(void)787 x_close_all_displays (void)
788 {
789 struct xdisplay ** scan = ((struct xdisplay **) (x_display_table.items));
790 struct xdisplay ** end = (scan + (x_display_table.length));
791 while (scan < end)
792 {
793 struct xdisplay * xd = (*scan++);
794 if (xd != 0)
795 x_close_display (xd);
796 }
797 }
798
799 /* Window Manager Properties */
800
801 static void
xw_set_class_hint(struct xwindow * xw,const char * name,const char * class)802 xw_set_class_hint (struct xwindow * xw, const char * name, const char * class)
803 {
804 XClassHint * class_hint = (XAllocClassHint ());
805 if (class_hint == 0)
806 error_external_return ();
807 /* This structure is misdeclared, so cast the args. */
808 (class_hint->res_name) = ((char *) name);
809 (class_hint->res_class) = ((char *) class);
810 XSetClassHint ((XW_DISPLAY (xw)), (XW_WINDOW (xw)), class_hint);
811 XFree (class_hint);
812 }
813
814 void
xw_set_wm_input_hint(struct xwindow * xw,int input_hint)815 xw_set_wm_input_hint (struct xwindow * xw, int input_hint)
816 {
817 XWMHints * hints = (XAllocWMHints ());
818 if (hints == 0)
819 error_external_return ();
820 (hints->flags) = InputHint;
821 (hints->input) = (input_hint != 0);
822 XSetWMHints ((XW_DISPLAY (xw)), (XW_WINDOW (xw)), hints);
823 XFree (hints);
824 }
825
826 void
xw_set_wm_name(struct xwindow * xw,const char * name)827 xw_set_wm_name (struct xwindow * xw, const char * name)
828 {
829 XTextProperty property;
830 if ((XStringListToTextProperty (((char **) (&name)), 1, (&property))) == 0)
831 error_external_return ();
832 XSetWMName ((XW_DISPLAY (xw)), (XW_WINDOW (xw)), (&property));
833 }
834
835 void
xw_set_wm_icon_name(struct xwindow * xw,const char * name)836 xw_set_wm_icon_name (struct xwindow * xw, const char * name)
837 {
838 XTextProperty property;
839 if ((XStringListToTextProperty (((char **) (&name)), 1, (&property))) == 0)
840 error_external_return ();
841 XSetWMIconName ((XW_DISPLAY (xw)), (XW_WINDOW (xw)), (&property));
842 }
843
844 void
x_decode_window_map_arg(SCHEME_OBJECT map_arg,const char ** resource_name,const char ** resource_class,int * map_p)845 x_decode_window_map_arg (SCHEME_OBJECT map_arg,
846 const char ** resource_name,
847 const char ** resource_class,
848 int * map_p)
849 {
850 (*map_p) = 0;
851 if (map_arg == SHARP_F)
852 (*map_p) = 1;
853 else if ((PAIR_P (map_arg))
854 && (STRING_P (PAIR_CAR (map_arg)))
855 && (STRING_P (PAIR_CDR (map_arg))))
856 {
857 (*resource_name) = (STRING_POINTER (PAIR_CAR (map_arg)));
858 (*resource_class) = (STRING_POINTER (PAIR_CDR (map_arg)));
859 (*map_p) = 1;
860 }
861 else if ((VECTOR_P (map_arg))
862 && ((VECTOR_LENGTH (map_arg)) == 3)
863 && (BOOLEAN_P (VECTOR_REF (map_arg, 0)))
864 && (STRING_P (VECTOR_REF (map_arg, 1)))
865 && (STRING_P (VECTOR_REF (map_arg, 2))))
866 {
867 (*resource_name) = (STRING_POINTER (VECTOR_REF (map_arg, 1)));
868 (*resource_class) = (STRING_POINTER (VECTOR_REF (map_arg, 2)));
869 (*map_p) = (OBJECT_TO_BOOLEAN (VECTOR_REF (map_arg, 0)));
870 }
871 }
872
873 void
xw_make_window_map(struct xwindow * xw,const char * resource_name,const char * resource_class,int map_p)874 xw_make_window_map (struct xwindow * xw,
875 const char * resource_name,
876 const char * resource_class,
877 int map_p)
878 {
879 xw_set_class_hint (xw, resource_name, resource_class);
880 if (map_p)
881 {
882 XMapWindow ((XW_DISPLAY (xw)), (XW_WINDOW (xw)));
883 XFlush (XW_DISPLAY (xw));
884 }
885 }
886
887 /* Event Processing */
888
889 /* Returns non-zero value if caller should ignore the event. */
890
891 static int
xw_process_event(struct xwindow * xw,XEvent * event)892 xw_process_event (struct xwindow * xw, XEvent * event)
893 {
894 if (x_debug > 0)
895 {
896 const char * type_name;
897 fprintf (stderr, "\nX event on 0x%lx: ", ((event->xany) . window));
898 switch (event->type)
899 {
900 case ButtonPress: type_name = "ButtonPress"; break;
901 case ButtonRelease: type_name = "ButtonRelease"; break;
902 case CirculateNotify: type_name = "CirculateNotify"; break;
903 case CreateNotify: type_name = "CreateNotify"; break;
904 case DestroyNotify: type_name = "DestroyNotify"; break;
905 case EnterNotify: type_name = "EnterNotify"; break;
906 case Expose: type_name = "Expose"; break;
907 case FocusIn: type_name = "FocusIn"; break;
908 case FocusOut: type_name = "FocusOut"; break;
909 case GraphicsExpose: type_name = "GraphicsExpose"; break;
910 case GravityNotify: type_name = "GravityNotify"; break;
911 case KeyPress: type_name = "KeyPress"; break;
912 case KeyRelease: type_name = "KeyRelease"; break;
913 case LeaveNotify: type_name = "LeaveNotify"; break;
914 case MapNotify: type_name = "MapNotify"; break;
915 case MappingNotify: type_name = "MappingNotify"; break;
916 case MotionNotify: type_name = "MotionNotify"; break;
917 case NoExpose: type_name = "NoExpose"; break;
918 case ReparentNotify: type_name = "ReparentNotify"; break;
919 case SelectionClear: type_name = "SelectionClear"; break;
920 case SelectionRequest: type_name = "SelectionRequest"; break;
921 case UnmapNotify: type_name = "UnmapNotify"; break;
922
923 case VisibilityNotify:
924 fprintf (stderr, "VisibilityNotify; state=");
925 switch ((event->xvisibility) . state)
926 {
927 case VisibilityUnobscured:
928 fprintf (stderr, "unobscured");
929 break;
930 case VisibilityPartiallyObscured:
931 fprintf (stderr, "partially-obscured");
932 break;
933 case VisibilityFullyObscured:
934 fprintf (stderr, "fully-obscured");
935 break;
936 default:
937 fprintf (stderr, "%d", ((event->xvisibility) . state));
938 break;
939 }
940 goto debug_done;
941
942 case ConfigureNotify:
943 fprintf (stderr, "ConfigureNotify; x=%d y=%d width=%d height=%d",
944 ((event->xconfigure) . x),
945 ((event->xconfigure) . y),
946 ((event->xconfigure) . width),
947 ((event->xconfigure) . height));
948 goto debug_done;
949
950 case ClientMessage:
951 {
952 struct xdisplay * xd = (XW_XD (xw));
953 if ((((event->xclient) . message_type) == (XD_WM_PROTOCOLS (xd)))
954 && (((event->xclient) . format) == 32))
955 {
956 if (((Atom) (((event->xclient) . data . l) [0]))
957 == (XD_WM_DELETE_WINDOW (xd)))
958 type_name = "WM_DELETE_WINDOW";
959 else if (((Atom) (((event->xclient) . data . l) [0]))
960 == (XD_WM_TAKE_FOCUS (xd)))
961 type_name = "WM_TAKE_FOCUS";
962 else
963 type_name = "WM_PROTOCOLS";
964 }
965 else
966 {
967 fprintf (stderr, "ClientMessage; message_type=0x%x format=%d",
968 ((unsigned int) ((event->xclient) . message_type)),
969 ((event->xclient) . format));
970 goto debug_done;
971 }
972 }
973 break;
974 case PropertyNotify:
975 {
976 fprintf (stderr, "PropertyNotify; atom=%ld time=%ld state=%d",
977 ((event->xproperty) . atom),
978 ((event->xproperty) . time),
979 ((event->xproperty) . state));
980 goto debug_done;
981 }
982 case SelectionNotify:
983 {
984 fprintf
985 (stderr, "SelectionNotify; sel=%ld targ=%ld prop=%ld t=%ld",
986 ((event->xselection) . selection),
987 ((event->xselection) . target),
988 ((event->xselection) . property),
989 ((event->xselection) . time));
990 goto debug_done;
991 }
992 default: type_name = 0; break;
993 }
994 if (type_name != 0)
995 fprintf (stderr, "%s", type_name);
996 else
997 fprintf (stderr, "%d", (event->type));
998 debug_done:
999 fprintf (stderr, "%s\n",
1000 (((event->xany) . send_event) ? "; synthetic" : ""));
1001 fflush (stderr);
1002 }
1003 switch (event->type)
1004 {
1005 case MappingNotify:
1006 switch ((event->xmapping) . request)
1007 {
1008 case MappingModifier:
1009 x_initialize_display_modifier_masks ((XW_XD (xw)));
1010 /* Fall through. */
1011 case MappingKeyboard:
1012 XRefreshKeyboardMapping (& (event->xmapping));
1013 break;
1014 }
1015 break;
1016 }
1017 if (xw != 0)
1018 {
1019 switch (event->type)
1020 {
1021 case ReparentNotify:
1022 get_wm_decor_geometry (xw);
1023 /* Perhaps reparented due to a WM restart. Reset this. */
1024 (XW_WM_TYPE (xw)) = X_WMTYPE_UNKNOWN;
1025 break;
1026
1027 case ConfigureNotify:
1028 /* If the window has been reparented, don't check
1029 non-synthetic events. */
1030 if ((XW_CHECK_EXPECTED_MOVE_P (xw))
1031 && (! ((get_wm_decor_geometry (xw))
1032 && (! ((event->xconfigure) . send_event)))))
1033 check_expected_move (xw);
1034 break;
1035 }
1036 (* (XW_EVENT_PROCESSOR (xw))) (xw, event);
1037 }
1038 return (0);
1039 }
1040
1041 enum event_type
1042 {
1043 event_type_button_down,
1044 event_type_button_up,
1045 event_type_configure,
1046 event_type_enter,
1047 event_type_focus_in,
1048 event_type_focus_out,
1049 event_type_key_press,
1050 event_type_leave,
1051 event_type_motion,
1052 event_type_expose,
1053 event_type_delete_window,
1054 event_type_map,
1055 event_type_unmap,
1056 event_type_take_focus,
1057 event_type_visibility,
1058 event_type_selection_clear,
1059 event_type_selection_notify,
1060 event_type_selection_request,
1061 event_type_property_notify,
1062 event_type_supremum
1063 };
1064
1065 #define EVENT_MASK_ARG(arg) \
1066 (arg_ulong_index_integer \
1067 ((arg), (1 << ((unsigned int) event_type_supremum))))
1068
1069 #define EVENT_ENABLED(xw, type) \
1070 (((XW_EVENT_MASK (xw)) & (1 << ((unsigned int) (type)))) != 0)
1071
1072 #define EVENT_0 2
1073 #define EVENT_1 3
1074 #define EVENT_2 4
1075 #define EVENT_3 5
1076 #define EVENT_4 6
1077
1078 #define EVENT_INTEGER(event, slot, number) \
1079 VECTOR_SET ((event), (slot), (long_to_integer (number)))
1080
1081 #define EVENT_ULONG_INTEGER(event, slot, number) \
1082 VECTOR_SET ((event), (slot), (ulong_to_integer (number)))
1083
1084 static SCHEME_OBJECT
make_event_object(struct xwindow * xw,enum event_type type,unsigned int extra)1085 make_event_object (struct xwindow * xw,
1086 enum event_type type,
1087 unsigned int extra)
1088 {
1089 SCHEME_OBJECT result = (allocate_marked_vector (TC_VECTOR, (2 + extra), 1));
1090 VECTOR_SET (result, 0, (LONG_TO_UNSIGNED_FIXNUM ((long) type)));
1091 VECTOR_SET (result, 1, ((xw == 0) ? SHARP_F : (XW_TO_OBJECT (xw))));
1092 return (result);
1093 }
1094
1095 /* This handles only the modifier bits that Scheme supports.
1096 At the moment, these are Control, Meta, Super, and Hyper.
1097 This might want to change if the character abstraction were ever to
1098 change, or if the X11 interface were to be changed to use something
1099 other than Scheme characters to convey key presses. */
1100
1101 static unsigned long
x_modifier_mask_to_bucky_bits(unsigned int mask,struct xdisplay * xd)1102 x_modifier_mask_to_bucky_bits (unsigned int mask, struct xdisplay * xd)
1103 {
1104 unsigned long bucky = 0;
1105 if (X_MODIFIER_MASK_CONTROL_P (mask, xd)) bucky |= CHAR_BITS_CONTROL;
1106 if (X_MODIFIER_MASK_META_P (mask, xd)) bucky |= CHAR_BITS_META;
1107 if (X_MODIFIER_MASK_SUPER_P (mask, xd)) bucky |= CHAR_BITS_SUPER;
1108 if (X_MODIFIER_MASK_HYPER_P (mask, xd)) bucky |= CHAR_BITS_HYPER;
1109 return (bucky);
1110 }
1111
1112 /* I'm not sure why we have a function for this. */
1113
1114 static SCHEME_OBJECT
x_key_button_mask_to_scheme(unsigned int x_state)1115 x_key_button_mask_to_scheme (unsigned int x_state)
1116 {
1117 unsigned long scheme_state = 0;
1118 if (x_state & ControlMask) scheme_state |= 0x0001;
1119 if (x_state & Mod1Mask) scheme_state |= 0x0002;
1120 if (x_state & Mod2Mask) scheme_state |= 0x0004;
1121 if (x_state & Mod3Mask) scheme_state |= 0x0008;
1122 if (x_state & ShiftMask) scheme_state |= 0x0010;
1123 if (x_state & LockMask) scheme_state |= 0x0020;
1124 if (x_state & Mod4Mask) scheme_state |= 0x0040;
1125 if (x_state & Mod5Mask) scheme_state |= 0x0080;
1126 if (x_state & Button1Mask) scheme_state |= 0x0100;
1127 if (x_state & Button2Mask) scheme_state |= 0x0200;
1128 if (x_state & Button3Mask) scheme_state |= 0x0400;
1129 if (x_state & Button4Mask) scheme_state |= 0x0800;
1130 if (x_state & Button5Mask) scheme_state |= 0x1000;
1131 return (ULONG_TO_FIXNUM (scheme_state));
1132 }
1133
1134 static SCHEME_OBJECT
button_event(struct xwindow * xw,XButtonEvent * event,enum event_type type)1135 button_event (struct xwindow * xw, XButtonEvent * event, enum event_type type)
1136 {
1137 SCHEME_OBJECT result = (make_event_object (xw, type, 4));
1138 EVENT_INTEGER (result, EVENT_0, (event->x));
1139 EVENT_INTEGER (result, EVENT_1, (event->y));
1140 VECTOR_SET
1141 (result, EVENT_2,
1142 ((((event->button) >= 1) && ((event->button) <= 256))
1143 ? (ULONG_TO_FIXNUM
1144 (((event->button) - 1)
1145 | ((x_modifier_mask_to_bucky_bits ((event->state), (XW_XD (xw))))
1146 << 8)))
1147 : SHARP_F));
1148 EVENT_ULONG_INTEGER (result, EVENT_3, (event->time));
1149 return (result);
1150 }
1151
1152 static XComposeStatus compose_status;
1153
1154 static SCHEME_OBJECT
key_event(struct xwindow * xw,XKeyEvent * event,enum event_type type)1155 key_event (struct xwindow * xw, XKeyEvent * event, enum event_type type)
1156 {
1157 char copy_buffer [80];
1158 KeySym keysym;
1159 int nbytes;
1160 SCHEME_OBJECT result;
1161
1162 /* Make ShiftLock modifier not affect keys with other modifiers. */
1163 if ((event->state)
1164 & (ShiftMask || ControlMask
1165 || Mod1Mask || Mod2Mask || Mod3Mask || Mod4Mask || Mod5Mask))
1166 {
1167 if (((event->state) & LockMask) != 0)
1168 (event->state) &=~ LockMask;
1169 }
1170 nbytes
1171 = (XLookupString (event,
1172 copy_buffer,
1173 (sizeof (copy_buffer)),
1174 (&keysym),
1175 (&compose_status)));
1176 if (keysym == NoSymbol)
1177 return (SHARP_F);
1178 /* If the BackSpace keysym is received, and XLookupString has
1179 translated it into ASCII backspace, substitute ASCII DEL
1180 instead. */
1181 if ((keysym == XK_BackSpace)
1182 && (nbytes == 1)
1183 && ((copy_buffer[0]) == '\b'))
1184 (copy_buffer[0]) = '\177';
1185 if (IsModifierKey (keysym))
1186 return (SHARP_F);
1187
1188 result = (make_event_object (xw, type, 4));
1189 VECTOR_SET (result, EVENT_0,
1190 (memory_to_string (nbytes, ((unsigned char *) copy_buffer))));
1191 /* Create Scheme bucky bits (kept independent of the character).
1192 X has already controlified, so Scheme may choose to ignore
1193 the control bucky bit. */
1194 VECTOR_SET (result, EVENT_1,
1195 (ULONG_TO_FIXNUM
1196 (x_modifier_mask_to_bucky_bits ((event->state),
1197 (XW_XD (xw))))));
1198 VECTOR_SET (result, EVENT_2, (ulong_to_integer (keysym)));
1199 EVENT_ULONG_INTEGER (result, EVENT_3, (event->time));
1200 return (result);
1201 }
1202
1203 #define CONVERT_TRIVIAL_EVENT(scheme_name) \
1204 if (EVENT_ENABLED (xw, scheme_name)) \
1205 result = (make_event_object (xw, scheme_name, 0)); \
1206 break
1207
1208 static SCHEME_OBJECT
x_event_to_object(XEvent * event)1209 x_event_to_object (XEvent * event)
1210 {
1211 struct xwindow * xw
1212 = (x_window_to_xw (((event->xany) . display),
1213 ((event->xany) . window)));
1214 SCHEME_OBJECT result = SHARP_F;
1215 if (xw == 0)
1216 return result;
1217 switch (event->type)
1218 {
1219 case KeyPress:
1220 if (EVENT_ENABLED (xw, event_type_key_press))
1221 result = (key_event (xw, (& (event->xkey)), event_type_key_press));
1222 break;
1223 case ButtonPress:
1224 if (EVENT_ENABLED (xw, event_type_button_down))
1225 result
1226 = (button_event (xw, (& (event->xbutton)), event_type_button_down));
1227 break;
1228 case ButtonRelease:
1229 if (EVENT_ENABLED (xw, event_type_button_up))
1230 result
1231 = (button_event (xw, (& (event->xbutton)), event_type_button_up));
1232 break;
1233 case MotionNotify:
1234 if (EVENT_ENABLED (xw, event_type_motion))
1235 {
1236 result = (make_event_object (xw, event_type_motion, 3));
1237 EVENT_INTEGER (result, EVENT_0, ((event->xmotion) . x));
1238 EVENT_INTEGER (result, EVENT_1, ((event->xmotion) . y));
1239 VECTOR_SET (result, EVENT_2,
1240 (x_key_button_mask_to_scheme
1241 (((event->xmotion) . state))));
1242 }
1243 break;
1244 case ConfigureNotify:
1245 if (EVENT_ENABLED (xw, event_type_configure))
1246 {
1247 result = (make_event_object (xw, event_type_configure, 2));
1248 EVENT_ULONG_INTEGER
1249 (result, EVENT_0, ((event->xconfigure) . width));
1250 EVENT_ULONG_INTEGER
1251 (result, EVENT_1, ((event->xconfigure) . height));
1252 }
1253 break;
1254 case Expose:
1255 if (EVENT_ENABLED (xw, event_type_expose))
1256 {
1257 result = (make_event_object (xw, event_type_expose, 5));
1258 EVENT_INTEGER (result, EVENT_0, ((event->xexpose) . x));
1259 EVENT_INTEGER (result, EVENT_1, ((event->xexpose) . y));
1260 EVENT_ULONG_INTEGER (result, EVENT_2, ((event->xexpose) . width));
1261 EVENT_ULONG_INTEGER (result, EVENT_3, ((event->xexpose) . height));
1262 VECTOR_SET (result, EVENT_4, (LONG_TO_UNSIGNED_FIXNUM (0)));
1263 }
1264 break;
1265 case GraphicsExpose:
1266 if (EVENT_ENABLED (xw, event_type_expose))
1267 {
1268 result = (make_event_object (xw, event_type_expose, 5));
1269 EVENT_INTEGER (result, EVENT_0, ((event->xgraphicsexpose) . x));
1270 EVENT_INTEGER (result, EVENT_1, ((event->xgraphicsexpose) . y));
1271 EVENT_ULONG_INTEGER
1272 (result, EVENT_2, ((event->xgraphicsexpose) . width));
1273 EVENT_ULONG_INTEGER
1274 (result, EVENT_3, ((event->xgraphicsexpose) . height));
1275 VECTOR_SET (result, EVENT_4, (LONG_TO_UNSIGNED_FIXNUM (1)));
1276 }
1277 break;
1278 case ClientMessage:
1279 {
1280 struct xdisplay * xd = (XW_XD (xw));
1281 if ((((event->xclient) . message_type) == (XD_WM_PROTOCOLS (xd)))
1282 && (((event->xclient) . format) == 32))
1283 {
1284 if (((Atom) (((event->xclient) . data . l) [0]))
1285 == (XD_WM_DELETE_WINDOW (xd)))
1286 {
1287 if (EVENT_ENABLED (xw, event_type_delete_window))
1288 result
1289 = (make_event_object (xw, event_type_delete_window, 0));
1290 }
1291 else if (((Atom) (((event->xclient) . data . l) [0]))
1292 == (XD_WM_TAKE_FOCUS (xd)))
1293 {
1294 if (EVENT_ENABLED (xw, event_type_take_focus))
1295 {
1296 result
1297 = (make_event_object (xw, event_type_take_focus, 1));
1298 EVENT_ULONG_INTEGER
1299 (result, EVENT_0, (((event->xclient) . data . l) [1]));
1300 }
1301 }
1302 }
1303 }
1304 break;
1305 case VisibilityNotify:
1306 if (EVENT_ENABLED (xw, event_type_visibility))
1307 {
1308 unsigned int state;
1309 switch ((event->xvisibility) . state)
1310 {
1311 case VisibilityUnobscured:
1312 state = 0;
1313 break;
1314 case VisibilityPartiallyObscured:
1315 state = 1;
1316 break;
1317 case VisibilityFullyObscured:
1318 state = 2;
1319 break;
1320 default:
1321 state = 3;
1322 break;
1323 }
1324 result = (make_event_object (xw, event_type_visibility, 1));
1325 EVENT_ULONG_INTEGER (result, EVENT_0, state);
1326 }
1327 break;
1328 case SelectionClear:
1329 if (EVENT_ENABLED (xw, event_type_selection_clear))
1330 {
1331 result = (make_event_object (xw, event_type_selection_clear, 2));
1332 EVENT_ULONG_INTEGER
1333 (result, EVENT_0, ((event->xselectionclear) . selection));
1334 EVENT_ULONG_INTEGER
1335 (result, EVENT_1, ((event->xselectionclear) . time));
1336 }
1337 break;
1338 case SelectionNotify:
1339 if (EVENT_ENABLED (xw, event_type_selection_notify))
1340 {
1341 result = (make_event_object (xw, event_type_selection_notify, 5));
1342 EVENT_ULONG_INTEGER
1343 (result, EVENT_0, ((event->xselection) . requestor));
1344 EVENT_ULONG_INTEGER
1345 (result, EVENT_1, ((event->xselection) . selection));
1346 EVENT_ULONG_INTEGER
1347 (result, EVENT_2, ((event->xselection) . target));
1348 EVENT_ULONG_INTEGER
1349 (result, EVENT_3, ((event->xselection) . property));
1350 EVENT_ULONG_INTEGER
1351 (result, EVENT_4, ((event->xselection) . time));
1352 }
1353 break;
1354 case SelectionRequest:
1355 if (EVENT_ENABLED (xw, event_type_selection_request))
1356 {
1357 result = (make_event_object (xw, event_type_selection_request, 5));
1358 EVENT_ULONG_INTEGER
1359 (result, EVENT_0, ((event->xselectionrequest) . requestor));
1360 EVENT_ULONG_INTEGER
1361 (result, EVENT_1, ((event->xselectionrequest) . selection));
1362 EVENT_ULONG_INTEGER
1363 (result, EVENT_2, ((event->xselectionrequest) . target));
1364 EVENT_ULONG_INTEGER
1365 (result, EVENT_3, ((event->xselectionrequest) . property));
1366 EVENT_ULONG_INTEGER
1367 (result, EVENT_4, ((event->xselectionrequest) . time));
1368 }
1369 break;
1370 case PropertyNotify:
1371 if (EVENT_ENABLED (xw, event_type_property_notify))
1372 {
1373 result = (make_event_object (xw, event_type_property_notify, 4));
1374 /* Must store window element separately because this window
1375 might not have a corresponding XW object. */
1376 EVENT_ULONG_INTEGER
1377 (result, EVENT_0, ((event->xproperty) . window));
1378 EVENT_ULONG_INTEGER
1379 (result, EVENT_1, ((event->xproperty) . atom));
1380 EVENT_ULONG_INTEGER
1381 (result, EVENT_2, ((event->xproperty) . time));
1382 EVENT_ULONG_INTEGER
1383 (result, EVENT_3, ((event->xproperty) . state));
1384 }
1385 break;
1386 case EnterNotify: CONVERT_TRIVIAL_EVENT (event_type_enter);
1387 case LeaveNotify: CONVERT_TRIVIAL_EVENT (event_type_leave);
1388 case FocusIn: CONVERT_TRIVIAL_EVENT (event_type_focus_in);
1389 case FocusOut: CONVERT_TRIVIAL_EVENT (event_type_focus_out);
1390 case MapNotify: CONVERT_TRIVIAL_EVENT (event_type_map);
1391 case UnmapNotify: CONVERT_TRIVIAL_EVENT (event_type_unmap);
1392 }
1393 return (result);
1394 }
1395
1396 static void
update_input_mask(struct xwindow * xw)1397 update_input_mask (struct xwindow * xw)
1398 {
1399 {
1400 unsigned long event_mask = 0;
1401 if (EVENT_ENABLED (xw, event_type_expose))
1402 event_mask |= ExposureMask;
1403 if ((EVENT_ENABLED (xw, event_type_configure))
1404 || (EVENT_ENABLED (xw, event_type_map))
1405 || (EVENT_ENABLED (xw, event_type_unmap)))
1406 event_mask |= StructureNotifyMask;
1407 if (EVENT_ENABLED (xw, event_type_button_down))
1408 event_mask |= ButtonPressMask;
1409 if (EVENT_ENABLED (xw, event_type_button_up))
1410 event_mask |= ButtonReleaseMask;
1411 if (EVENT_ENABLED (xw, event_type_key_press))
1412 event_mask |= KeyPressMask;
1413 if (EVENT_ENABLED (xw, event_type_enter))
1414 event_mask |= EnterWindowMask;
1415 if (EVENT_ENABLED (xw, event_type_leave))
1416 event_mask |= LeaveWindowMask;
1417 if ((EVENT_ENABLED (xw, event_type_focus_in))
1418 || (EVENT_ENABLED (xw, event_type_focus_out)))
1419 event_mask |= FocusChangeMask;
1420 if (EVENT_ENABLED (xw, event_type_motion))
1421 event_mask |= (PointerMotionMask | PointerMotionHintMask);
1422 if (EVENT_ENABLED (xw, event_type_visibility))
1423 event_mask |= VisibilityChangeMask;
1424 if (EVENT_ENABLED (xw, event_type_property_notify))
1425 event_mask |= PropertyChangeMask;
1426 XSelectInput ((XW_DISPLAY (xw)), (XW_WINDOW (xw)), event_mask);
1427 }
1428 {
1429 struct xdisplay * xd = (XW_XD (xw));
1430 Atom protocols [2];
1431 unsigned int n_protocols = 0;
1432 if (EVENT_ENABLED (xw, event_type_delete_window))
1433 (protocols[n_protocols++]) = (XD_WM_DELETE_WINDOW (xd));
1434 if (EVENT_ENABLED (xw, event_type_take_focus))
1435 (protocols[n_protocols++]) = (XD_WM_TAKE_FOCUS (xd));
1436 if (n_protocols > 0)
1437 XSetWMProtocols
1438 ((XW_DISPLAY (xw)), (XW_WINDOW (xw)), (&protocols[0]), n_protocols);
1439 }
1440 }
1441
1442 static void
ping_server(struct xdisplay * xd)1443 ping_server (struct xdisplay * xd)
1444 {
1445 /* Periodically ping the server connection to see if it has died. */
1446 (XD_SERVER_PING_TIMER (xd)) += 1;
1447 if ((XD_SERVER_PING_TIMER (xd)) >= 100)
1448 {
1449 (XD_SERVER_PING_TIMER (xd)) = 0;
1450 XNoOp (XD_DISPLAY (xd));
1451 XFlush (XD_DISPLAY (xd));
1452 }
1453 }
1454
1455 /* The use of `XD_CACHED_EVENT' prevents an event from being lost due
1456 to garbage collection. First `XD_CACHED_EVENT' is set to hold the
1457 current event, then the allocations are performed. If one of them
1458 fails, the primitive will exit, and when it reenters it will notice
1459 the cached event and use it. It is important that this be the only
1460 entry that reads events -- or else that all other event readers
1461 cooperate with this strategy. */
1462
1463 static SCHEME_OBJECT
xd_process_events(struct xdisplay * xd)1464 xd_process_events (struct xdisplay * xd)
1465 {
1466 Display * display = (XD_DISPLAY (xd));
1467 unsigned int events_queued;
1468 XEvent event;
1469 SCHEME_OBJECT result = SHARP_F;
1470 if (x_debug > 1)
1471 {
1472 fprintf (stderr, "Enter xd_process_events\n");
1473 fflush (stderr);
1474 }
1475 if (XD_CACHED_EVENT_P (xd))
1476 {
1477 events_queued = (XEventsQueued (display, QueuedAlready));
1478 event = (XD_CACHED_EVENT (xd));
1479 goto restart;
1480 }
1481 ping_server (xd);
1482 events_queued = (XEventsQueued (display, QueuedAfterReading));
1483 while (0 < events_queued)
1484 {
1485 events_queued -= 1;
1486 XNextEvent (display, (&event));
1487 if ((event.type) == KeymapNotify)
1488 continue;
1489 {
1490 struct xwindow * xw
1491 = (x_window_to_xw (display, (event.xany.window)));
1492 if ((xw == 0)
1493 && (! (((event.type) == PropertyNotify)
1494 || ((event.type) == SelectionClear)
1495 || ((event.type) == SelectionNotify)
1496 || ((event.type) == SelectionRequest))))
1497 continue;
1498 if (xw_process_event (xw, (&event)))
1499 continue;
1500 }
1501 (XD_CACHED_EVENT (xd)) = event;
1502 (XD_CACHED_EVENT_P (xd)) = 1;
1503 restart:
1504 result = (x_event_to_object (&event));
1505 (XD_CACHED_EVENT_P (xd)) = 0;
1506 if (result != SHARP_F)
1507 break;
1508 }
1509 if (x_debug > 1)
1510 {
1511 fprintf (stderr, "Return from xd_process_events: ");
1512 if (result == SHARP_F)
1513 fprintf (stderr, "#f");
1514 else if (VECTOR_P (result))
1515 fprintf (stderr, "[vector]");
1516 else
1517 fprintf (stderr, "[other: 0x%lx]", ((unsigned long) result));
1518 fprintf (stderr, "\n");
1519 fflush (stderr);
1520 }
1521 return (result);
1522 }
1523
1524 /* Open/Close Primitives */
1525
1526 static void
initialize_once(void)1527 initialize_once (void)
1528 {
1529 allocation_table_initialize (&x_display_table);
1530 allocation_table_initialize (&x_window_table);
1531 allocation_table_initialize (&x_image_table);
1532 ((x_error_info.message) [0]) = '\0';
1533 (x_error_info.terminate_p) = 1;
1534 (x_error_info.code) = 0;
1535 XSetErrorHandler (x_error_handler);
1536 XSetIOErrorHandler (x_io_error_handler);
1537 #ifndef COMPILE_AS_MODULE
1538 add_reload_cleanup (x_close_all_displays);
1539 #endif
1540 initialization_done = 1;
1541 }
1542
1543 DEFINE_PRIMITIVE ("X-DEBUG", Prim_x_debug, 1, 1, 0)
1544 {
1545 PRIMITIVE_HEADER (1);
1546 {
1547 SCHEME_OBJECT object = (ARG_REF (1));
1548 if (object == SHARP_F)
1549 x_debug = 0;
1550 else if (UNSIGNED_FIXNUM_P (object))
1551 x_debug = (UNSIGNED_FIXNUM_TO_LONG (object));
1552 else
1553 x_debug = 1;
1554 }
1555 PRIMITIVE_RETURN (UNSPECIFIC);
1556 }
1557
1558 DEFINE_PRIMITIVE ("X-OPEN-DISPLAY", Prim_x_open_display, 1, 1, 0)
1559 {
1560 PRIMITIVE_HEADER (1);
1561 INITIALIZE_ONCE ();
1562 {
1563 struct xdisplay * xd = (x_malloc (sizeof (struct xdisplay)));
1564 /* Added 7/95 by Nick in an attempt to fix problem Hal was having
1565 with SWAT over PPP (i.e. slow connections). */
1566 block_signals ();
1567 (XD_DISPLAY (xd))
1568 = (XOpenDisplay (((ARG_REF (1)) == SHARP_F) ? 0 : (STRING_ARG (1))));
1569 unblock_signals ();
1570 if ((XD_DISPLAY (xd)) == 0)
1571 {
1572 free (xd);
1573 PRIMITIVE_RETURN (SHARP_F);
1574 }
1575 (XD_ALLOCATION_INDEX (xd))
1576 = (allocate_table_index ((&x_display_table), xd));
1577 (XD_SERVER_PING_TIMER (xd)) = 0;
1578 (XD_WM_PROTOCOLS (xd))
1579 = (XInternAtom ((XD_DISPLAY (xd)), "WM_PROTOCOLS", False));
1580 (XD_WM_DELETE_WINDOW (xd))
1581 = (XInternAtom ((XD_DISPLAY (xd)), "WM_DELETE_WINDOW", False));
1582 (XD_WM_TAKE_FOCUS (xd))
1583 = (XInternAtom ((XD_DISPLAY (xd)), "WM_TAKE_FOCUS", False));
1584 (XD_CACHED_EVENT_P (xd)) = 0;
1585 x_initialize_display_modifier_masks (xd);
1586 XRebindKeysym ((XD_DISPLAY (xd)), XK_BackSpace, 0, 0,
1587 ((unsigned char *) "\177"), 1);
1588 PRIMITIVE_RETURN (XD_TO_OBJECT (xd));
1589 }
1590 }
1591
1592 DEFINE_PRIMITIVE ("X-CLOSE-DISPLAY", Prim_x_close_display, 1, 1, 0)
1593 {
1594 PRIMITIVE_HEADER (1);
1595 x_close_display (x_display_arg (1));
1596 PRIMITIVE_RETURN (UNSPECIFIC);
1597 }
1598
1599 DEFINE_PRIMITIVE ("X-CLOSE-ALL-DISPLAYS", Prim_x_close_all_displays, 0, 0, 0)
1600 {
1601 PRIMITIVE_HEADER (0);
1602 INITIALIZE_ONCE ();
1603 x_close_all_displays ();
1604 PRIMITIVE_RETURN (UNSPECIFIC);
1605 }
1606
1607 DEFINE_PRIMITIVE ("X-DISPLAY-GET-SIZE", Prim_x_display_get_size, 2, 2, 0)
1608 {
1609 PRIMITIVE_HEADER (2);
1610 {
1611 struct xdisplay * xd = (x_display_arg (1));
1612 Display * display = (XD_DISPLAY (xd));
1613 long screen = (arg_nonnegative_integer (2));
1614 PRIMITIVE_RETURN
1615 (cons ((ulong_to_integer (DisplayWidth (display, screen))),
1616 (ulong_to_integer (DisplayHeight (display, screen)))));
1617 }
1618 }
1619
1620 DEFINE_PRIMITIVE ("X-CLOSE-WINDOW", Prim_x_close_window, 1, 1, 0)
1621 {
1622 PRIMITIVE_HEADER (1);
1623 {
1624 struct xwindow * xw = (x_window_arg (1));
1625 Display * display = (XW_DISPLAY (xw));
1626 x_close_window (xw);
1627 XFlush (display);
1628 }
1629 PRIMITIVE_RETURN (UNSPECIFIC);
1630 }
1631
1632 DEFINE_PRIMITIVE ("X-SET-DEFAULT-FONT", Prim_x_set_default_font, 2, 2, 0)
1633 {
1634 PRIMITIVE_HEADER (2);
1635 {
1636 struct xdisplay * xd = (x_display_arg (1));
1637 Display * display = (XD_DISPLAY (xd));
1638 const char * name = (STRING_ARG (2));
1639 XFontStruct * font = (XLoadQueryFont (display, name));
1640 if (font == 0)
1641 PRIMITIVE_RETURN (SHARP_F);
1642 XFreeFont (display, font);
1643 if (x_default_font != 0)
1644 OS_free ((void *) x_default_font);
1645 {
1646 char * copy = (OS_malloc ((strlen (name)) + 1));
1647 const char * s1 = name;
1648 char * s2 = copy;
1649 while (1)
1650 {
1651 char c = (*s1++);
1652 (*s2++) = c;
1653 if (c == '\0')
1654 break;
1655 }
1656 x_default_font = copy;
1657 }
1658 }
1659 PRIMITIVE_RETURN (SHARP_T);
1660 }
1661
1662 /* Event Processing Primitives */
1663
1664 DEFINE_PRIMITIVE ("X-DISPLAY-DESCRIPTOR", Prim_x_display_descriptor, 1, 1, 0)
1665 {
1666 PRIMITIVE_HEADER (1);
1667 PRIMITIVE_RETURN
1668 (long_to_integer (ConnectionNumber (XD_DISPLAY (x_display_arg (1)))));
1669 }
1670
1671 DEFINE_PRIMITIVE ("X-MAX-REQUEST-SIZE", Prim_x_max_request_size, 1, 1, 0)
1672 {
1673 PRIMITIVE_HEADER (1);
1674 PRIMITIVE_RETURN
1675 (long_to_integer (XMaxRequestSize (XD_DISPLAY (x_display_arg (1)))));
1676 }
1677
1678 DEFINE_PRIMITIVE ("X-DISPLAY-PROCESS-EVENTS", Prim_x_display_process_events, 2, 2, 0)
1679 {
1680 PRIMITIVE_HEADER (2);
1681 {
1682 struct xdisplay * xd = (x_display_arg (1));
1683 SCHEME_OBJECT how = (ARG_REF (2));
1684 /* Previously, the `how' argument could be #F (block, select), 0
1685 (don't block, select), 1 (block, don't select), 2 (don't block,
1686 don't select). Now we never select or block -- it is up to the
1687 caller to do that. #F and 0 have been unused for a long time,
1688 and the only caller that used 1 in the system already selected
1689 and blocked anyway. */
1690 if ((how != (LONG_TO_UNSIGNED_FIXNUM (1)))
1691 && (how != (LONG_TO_UNSIGNED_FIXNUM (2))))
1692 error_bad_range_arg (2);
1693 PRIMITIVE_RETURN (xd_process_events (xd));
1694 }
1695 }
1696
1697 DEFINE_PRIMITIVE ("X-SELECT-INPUT", Prim_x_select_input, 3, 3, 0)
1698 {
1699 PRIMITIVE_HEADER (3);
1700 XSelectInput ((XD_DISPLAY (x_display_arg (1))),
1701 (arg_ulong_integer (2)),
1702 (arg_integer (3)));
1703 PRIMITIVE_RETURN (UNSPECIFIC);
1704 }
1705
1706 DEFINE_PRIMITIVE ("X-WINDOW-EVENT-MASK", Prim_x_window_event_mask, 1, 1, 0)
1707 {
1708 PRIMITIVE_HEADER (1);
1709 PRIMITIVE_RETURN (ulong_to_integer (XW_EVENT_MASK (x_window_arg (1))));
1710 }
1711
1712 DEFINE_PRIMITIVE ("X-WINDOW-SET-EVENT-MASK", Prim_x_window_set_event_mask, 2, 2, 0)
1713 {
1714 PRIMITIVE_HEADER (2);
1715 {
1716 struct xwindow * xw = (x_window_arg (1));
1717 (XW_EVENT_MASK (xw)) = (EVENT_MASK_ARG (2));
1718 update_input_mask (xw);
1719 }
1720 PRIMITIVE_RETURN (UNSPECIFIC);
1721 }
1722
1723 DEFINE_PRIMITIVE ("X-WINDOW-OR-EVENT-MASK", Prim_x_window_or_event_mask, 2, 2, 0)
1724 {
1725 PRIMITIVE_HEADER (2);
1726 {
1727 struct xwindow * xw = (x_window_arg (1));
1728 (XW_EVENT_MASK (xw)) |= (EVENT_MASK_ARG (2));
1729 update_input_mask (xw);
1730 }
1731 PRIMITIVE_RETURN (UNSPECIFIC);
1732 }
1733
1734 DEFINE_PRIMITIVE ("X-WINDOW-ANDC-EVENT-MASK", Prim_x_window_andc_event_mask, 2, 2, 0)
1735 {
1736 PRIMITIVE_HEADER (2);
1737 {
1738 struct xwindow * xw = (x_window_arg (1));
1739 (XW_EVENT_MASK (xw)) &=~ (EVENT_MASK_ARG (2));
1740 update_input_mask (xw);
1741 }
1742 PRIMITIVE_RETURN (UNSPECIFIC);
1743 }
1744
1745 /* Miscellaneous Primitives */
1746
1747 DEFINE_PRIMITIVE ("X-WINDOW-DISPLAY", Prim_x_window_display, 1, 1, 0)
1748 {
1749 PRIMITIVE_HEADER (1);
1750 PRIMITIVE_RETURN (XD_TO_OBJECT (XW_XD (x_window_arg (1))));
1751 }
1752
1753 DEFINE_PRIMITIVE ("X-WINDOW-X-SIZE", Prim_x_window_x_size, 1, 1, 0)
1754 {
1755 PRIMITIVE_HEADER (1);
1756 PRIMITIVE_RETURN (ulong_to_integer (XW_X_SIZE (x_window_arg (1))));
1757 }
1758
1759 DEFINE_PRIMITIVE ("X-WINDOW-Y-SIZE", Prim_x_window_y_size, 1, 1, 0)
1760 {
1761 PRIMITIVE_HEADER (1);
1762 PRIMITIVE_RETURN (ulong_to_integer (XW_Y_SIZE (x_window_arg (1))));
1763 }
1764
1765 DEFINE_PRIMITIVE ("X-WINDOW-BEEP", Prim_x_window_beep, 1, 1, 0)
1766 {
1767 PRIMITIVE_HEADER (1);
1768 XBell ((XW_DISPLAY (x_window_arg (1))), 0); /* base value */
1769 PRIMITIVE_RETURN (UNSPECIFIC);
1770 }
1771
1772 DEFINE_PRIMITIVE ("X-WINDOW-CLEAR", Prim_x_window_clear, 1, 1, 0)
1773 {
1774 PRIMITIVE_HEADER (1);
1775 {
1776 struct xwindow * xw = (x_window_arg (1));
1777 if (((XW_CLIP_X (xw)) == 0)
1778 && ((XW_CLIP_Y (xw)) == 0)
1779 && ((XW_CLIP_WIDTH (xw)) == (XW_X_SIZE (xw)))
1780 && ((XW_CLIP_HEIGHT (xw)) == (XW_Y_SIZE (xw))))
1781 XClearWindow ((XW_DISPLAY (xw)), (XW_WINDOW (xw)));
1782 else
1783 XClearArea ((XW_DISPLAY (xw)),
1784 (XW_WINDOW (xw)),
1785 ((XW_CLIP_X (xw)) + (XW_INTERNAL_BORDER_WIDTH (xw))),
1786 ((XW_CLIP_Y (xw)) + (XW_INTERNAL_BORDER_WIDTH (xw))),
1787 (XW_CLIP_WIDTH (xw)),
1788 (XW_CLIP_HEIGHT (xw)),
1789 False);
1790 }
1791 PRIMITIVE_RETURN (UNSPECIFIC);
1792 }
1793
1794 DEFINE_PRIMITIVE ("X-DISPLAY-FLUSH", Prim_x_display_flush, 1, 1, 0)
1795 {
1796 PRIMITIVE_HEADER (1);
1797 XFlush (XD_DISPLAY (x_display_arg (1)));
1798 PRIMITIVE_RETURN (UNSPECIFIC);
1799 }
1800
1801 DEFINE_PRIMITIVE ("X-WINDOW-FLUSH", Prim_x_window_flush, 1, 1, 0)
1802 {
1803 PRIMITIVE_HEADER (1);
1804 XFlush (XW_DISPLAY (x_window_arg (1)));
1805 PRIMITIVE_RETURN (UNSPECIFIC);
1806 }
1807
1808 DEFINE_PRIMITIVE ("X-DISPLAY-SYNC", Prim_x_display_sync, 2, 2, 0)
1809 {
1810 PRIMITIVE_HEADER (2);
1811 XSync ((XD_DISPLAY (x_display_arg (1))), (BOOLEAN_ARG (2)));
1812 PRIMITIVE_RETURN (UNSPECIFIC);
1813 }
1814
1815 DEFINE_PRIMITIVE ("X-DISPLAY-GET-DEFAULT", Prim_x_display_get_default, 3, 3, 0)
1816 {
1817 PRIMITIVE_HEADER (3);
1818 {
1819 char * result
1820 = (XGetDefault ((XD_DISPLAY (x_display_arg (1))),
1821 (STRING_ARG (2)),
1822 (STRING_ARG (3))));
1823 PRIMITIVE_RETURN
1824 ((result == 0)
1825 ? SHARP_F
1826 : (char_pointer_to_string (result)));
1827 }
1828 }
1829
1830 DEFINE_PRIMITIVE ("X-WINDOW-COORDS-ROOT->LOCAL", Prim_x_window_coords_root2local, 3, 3, 0)
1831 {
1832 PRIMITIVE_HEADER (3);
1833 {
1834 SCHEME_OBJECT result = (cons (SHARP_F, SHARP_F));
1835 struct xwindow * xw = (x_window_arg (1));
1836 Display * display = (XW_DISPLAY (xw));
1837 int rx = (arg_integer (2));
1838 int ry = (arg_integer (3));
1839 int wx;
1840 int wy;
1841 Window child;
1842 if (! (XTranslateCoordinates
1843 (display,
1844 (RootWindow (display, (DefaultScreen (display)))),
1845 (XW_WINDOW (xw)),
1846 rx, ry, (&wx), (&wy), (&child))))
1847 error_bad_range_arg (1);
1848 SET_PAIR_CAR (result, (long_to_integer (wx)));
1849 SET_PAIR_CDR (result, (long_to_integer (wy)));
1850 PRIMITIVE_RETURN (result);
1851 }
1852 }
1853
1854 DEFINE_PRIMITIVE ("X-WINDOW-COORDS-LOCAL->ROOT", Prim_x_window_coords_local2root, 3, 3, 0)
1855 {
1856 PRIMITIVE_HEADER (3);
1857 {
1858 SCHEME_OBJECT result = (cons (SHARP_F, SHARP_F));
1859 struct xwindow * xw = (x_window_arg (1));
1860 Display * display = (XW_DISPLAY (xw));
1861 int wx = (arg_integer (2));
1862 int wy = (arg_integer (3));
1863 int rx;
1864 int ry;
1865 Window child;
1866 if (! (XTranslateCoordinates
1867 (display,
1868 (XW_WINDOW (xw)),
1869 (RootWindow (display, (DefaultScreen (display)))),
1870 wx, wy, (&rx), (&ry), (&child))))
1871 error_bad_range_arg (1);
1872 SET_PAIR_CAR (result, (long_to_integer (rx)));
1873 SET_PAIR_CDR (result, (long_to_integer (ry)));
1874 PRIMITIVE_RETURN (result);
1875 }
1876 }
1877
1878 DEFINE_PRIMITIVE ("X-WINDOW-QUERY-POINTER", Prim_x_window_query_pointer, 1, 1, 0)
1879 {
1880 PRIMITIVE_HEADER (1);
1881 {
1882 SCHEME_OBJECT result = (allocate_marked_vector (TC_VECTOR, 5, 1));
1883 struct xwindow * xw = (x_window_arg (1));
1884 Window root;
1885 Window child;
1886 int root_x;
1887 int root_y;
1888 int win_x;
1889 int win_y;
1890 unsigned int keys_buttons;
1891 if (!XQueryPointer ((XW_DISPLAY (xw)),
1892 (XW_WINDOW (xw)),
1893 (&root), (&child),
1894 (&root_x), (&root_y),
1895 (&win_x), (&win_y),
1896 (&keys_buttons)))
1897 PRIMITIVE_RETURN (SHARP_F);
1898 VECTOR_SET (result, 0, (long_to_integer (root_x)));
1899 VECTOR_SET (result, 1, (long_to_integer (root_y)));
1900 VECTOR_SET (result, 2, (long_to_integer (win_x)));
1901 VECTOR_SET (result, 3, (long_to_integer (win_y)));
1902 VECTOR_SET (result, 4, (x_key_button_mask_to_scheme (keys_buttons)));
1903 PRIMITIVE_RETURN (result);
1904 }
1905 }
1906
1907 DEFINE_PRIMITIVE ("X-WINDOW-ID", Prim_x_window_id, 1, 1, 0)
1908 {
1909 PRIMITIVE_HEADER (1);
1910 PRIMITIVE_RETURN (ulong_to_integer (XW_WINDOW (x_window_arg (1))));
1911 }
1912
1913 DEFINE_PRIMITIVE ("X-ID->WINDOW", Prim_x_id_to_window, 2, 2, 0)
1914 {
1915 PRIMITIVE_HEADER (2);
1916 {
1917 struct xwindow * xw
1918 = (x_window_to_xw ((XD_DISPLAY (x_display_arg (1))),
1919 (arg_ulong_integer (2))));
1920 PRIMITIVE_RETURN ((xw == 0) ? SHARP_F : (XW_TO_OBJECT (xw)));
1921 }
1922 }
1923
1924 /* Appearance Control Primitives */
1925
1926 DEFINE_PRIMITIVE ("X-WINDOW-SET-FOREGROUND-COLOR", Prim_x_window_set_foreground_color, 2, 2, 0)
1927 {
1928 PRIMITIVE_HEADER (2);
1929 {
1930 struct xwindow * xw = (x_window_arg (1));
1931 Display * display = (XW_DISPLAY (xw));
1932 unsigned long foreground_pixel = (arg_window_color (2, display, xw));
1933 (XW_FOREGROUND_PIXEL (xw)) = foreground_pixel;
1934 XSetForeground (display, (XW_NORMAL_GC (xw)), foreground_pixel);
1935 XSetBackground (display, (XW_REVERSE_GC (xw)), foreground_pixel);
1936 }
1937 PRIMITIVE_RETURN (UNSPECIFIC);
1938 }
1939
1940 DEFINE_PRIMITIVE ("X-WINDOW-SET-BACKGROUND-COLOR", Prim_x_window_set_background_color, 2, 2, 0)
1941 {
1942 PRIMITIVE_HEADER (2);
1943 {
1944 struct xwindow * xw = (x_window_arg (1));
1945 Display * display = (XW_DISPLAY (xw));
1946 unsigned long background_pixel = (arg_window_color (2, display, xw));
1947 (XW_BACKGROUND_PIXEL (xw)) = background_pixel;
1948 XSetWindowBackground (display, (XW_WINDOW (xw)), background_pixel);
1949 XSetBackground (display, (XW_NORMAL_GC (xw)), background_pixel);
1950 XSetForeground (display, (XW_REVERSE_GC (xw)), background_pixel);
1951 XSetForeground (display, (XW_CURSOR_GC (xw)), background_pixel);
1952 x_set_mouse_colors (display,
1953 (xw_color_map (xw)),
1954 (XW_MOUSE_CURSOR (xw)),
1955 (XW_MOUSE_PIXEL (xw)),
1956 background_pixel);
1957 }
1958 PRIMITIVE_RETURN (UNSPECIFIC);
1959 }
1960
1961 DEFINE_PRIMITIVE ("X-WINDOW-SET-BORDER-COLOR", Prim_x_window_set_border_color, 2, 2, 0)
1962 {
1963 PRIMITIVE_HEADER (2);
1964 {
1965 struct xwindow * xw = (x_window_arg (1));
1966 Display * display = (XW_DISPLAY (xw));
1967 unsigned long border_pixel = (arg_window_color (2, display, xw));
1968 (XW_BORDER_PIXEL (xw)) = border_pixel;
1969 XSetWindowBorder (display, (XW_WINDOW (xw)), border_pixel);
1970 }
1971 PRIMITIVE_RETURN (UNSPECIFIC);
1972 }
1973
1974 DEFINE_PRIMITIVE ("X-WINDOW-SET-CURSOR-COLOR", Prim_x_window_set_cursor_color, 2, 2, 0)
1975 {
1976 PRIMITIVE_HEADER (2);
1977 {
1978 struct xwindow * xw = (x_window_arg (1));
1979 Display * display = (XW_DISPLAY (xw));
1980 unsigned long cursor_pixel = (arg_window_color (2, display, xw));
1981 (XW_CURSOR_PIXEL (xw)) = cursor_pixel;
1982 XSetBackground (display, (XW_CURSOR_GC (xw)), cursor_pixel);
1983 }
1984 PRIMITIVE_RETURN (UNSPECIFIC);
1985 }
1986
1987 DEFINE_PRIMITIVE ("X-WINDOW-SET-MOUSE-COLOR", Prim_x_window_set_mouse_color, 2, 2, 0)
1988 {
1989 PRIMITIVE_HEADER (2);
1990 {
1991 struct xwindow * xw = (x_window_arg (1));
1992 Display * display = (XW_DISPLAY (xw));
1993 unsigned long mouse_pixel = (arg_window_color (2, display, xw));
1994 (XW_MOUSE_PIXEL (xw)) = mouse_pixel;
1995 x_set_mouse_colors (display,
1996 (xw_color_map (xw)),
1997 (XW_MOUSE_CURSOR (xw)),
1998 mouse_pixel,
1999 (XW_BACKGROUND_PIXEL (xw)));
2000 }
2001 PRIMITIVE_RETURN (UNSPECIFIC);
2002 }
2003
2004 DEFINE_PRIMITIVE ("X-WINDOW-SET-MOUSE-SHAPE", Prim_x_window_set_mouse_shape, 2, 2, 0)
2005 {
2006 PRIMITIVE_HEADER (2);
2007 {
2008 struct xwindow * xw = (x_window_arg (1));
2009 Display * display = (XW_DISPLAY (xw));
2010 Window window = (XW_WINDOW (xw));
2011 {
2012 Cursor old_cursor = (XW_MOUSE_CURSOR (xw));
2013 Cursor mouse_cursor
2014 = (XCreateFontCursor
2015 (display, (2 * (arg_index_integer (2, (XC_num_glyphs / 2))))));
2016 x_set_mouse_colors (display,
2017 (xw_color_map (xw)),
2018 mouse_cursor,
2019 (XW_MOUSE_PIXEL (xw)),
2020 (XW_BACKGROUND_PIXEL (xw)));
2021 (XW_MOUSE_CURSOR (xw)) = mouse_cursor;
2022 XDefineCursor (display, window, mouse_cursor);
2023 XFreeCursor (display, old_cursor);
2024 }
2025 }
2026 PRIMITIVE_RETURN (UNSPECIFIC);
2027 }
2028
2029 DEFINE_PRIMITIVE ("X-WINDOW-SET-FONT", Prim_x_window_set_font, 2, 2, 0)
2030 {
2031 PRIMITIVE_HEADER (2);
2032 {
2033 struct xwindow * xw = (x_window_arg (1));
2034 Display * display = (XW_DISPLAY (xw));
2035 XFontStruct * font = (XLoadQueryFont (display, (STRING_ARG (2))));
2036 if (font == 0)
2037 PRIMITIVE_RETURN (SHARP_F);
2038 XFreeFont (display, (XW_FONT (xw)));
2039 (XW_FONT (xw)) = font;
2040 {
2041 Font fid = (font->fid);
2042 XSetFont (display, (XW_NORMAL_GC (xw)), fid);
2043 XSetFont (display, (XW_REVERSE_GC (xw)), fid);
2044 XSetFont (display, (XW_CURSOR_GC (xw)), fid);
2045 }
2046 if ((XW_UPDATE_NORMAL_HINTS (xw)) != 0)
2047 (* (XW_UPDATE_NORMAL_HINTS (xw))) (xw);
2048 }
2049 PRIMITIVE_RETURN (SHARP_T);
2050 }
2051
2052 DEFINE_PRIMITIVE ("X-WINDOW-SET-BORDER-WIDTH", Prim_x_window_set_border_width, 2, 2, 0)
2053 {
2054 PRIMITIVE_HEADER (2);
2055 {
2056 struct xwindow * xw = (x_window_arg (1));
2057 Display * display = (XW_DISPLAY (xw));
2058 unsigned int border_width = (arg_nonnegative_integer (2));
2059 (XW_BORDER_WIDTH (xw)) = border_width;
2060 XSetWindowBorderWidth (display, (XW_WINDOW (xw)), border_width);
2061 }
2062 PRIMITIVE_RETURN (UNSPECIFIC);
2063 }
2064
2065 DEFINE_PRIMITIVE ("X-WINDOW-SET-INTERNAL-BORDER-WIDTH", Prim_x_window_set_internal_border_width, 2, 2, 0)
2066 {
2067 PRIMITIVE_HEADER (2);
2068 {
2069 struct xwindow * xw = (x_window_arg (1));
2070 unsigned int internal_border_width = (arg_nonnegative_integer (2));
2071 (XW_INTERNAL_BORDER_WIDTH (xw)) = internal_border_width;
2072 if ((XW_UPDATE_NORMAL_HINTS (xw)) != 0)
2073 (* (XW_UPDATE_NORMAL_HINTS (xw))) (xw);
2074 XResizeWindow ((XW_DISPLAY (xw)),
2075 (XW_WINDOW (xw)),
2076 ((XW_X_SIZE (xw)) + (2 * internal_border_width)),
2077 ((XW_Y_SIZE (xw)) + (2 * internal_border_width)));
2078 }
2079 PRIMITIVE_RETURN (UNSPECIFIC);
2080 }
2081
2082 /* WM Communication Primitives */
2083
2084 DEFINE_PRIMITIVE ("X-WINDOW-SET-NAME", Prim_x_window_set_name, 2, 2,
2085 "Set the name of WINDOW to STRING.")
2086 {
2087 PRIMITIVE_HEADER (2);
2088 xw_set_wm_name ((x_window_arg (1)), (STRING_ARG (2)));
2089 PRIMITIVE_RETURN (UNSPECIFIC);
2090 }
2091
2092 DEFINE_PRIMITIVE ("X-WINDOW-SET-ICON-NAME", Prim_x_window_set_icon_name, 2, 2,
2093 "Set the icon name of WINDOW to STRING.")
2094 {
2095 PRIMITIVE_HEADER (2);
2096 xw_set_wm_icon_name ((x_window_arg (1)), (STRING_ARG (2)));
2097 PRIMITIVE_RETURN (UNSPECIFIC);
2098 }
2099
2100 DEFINE_PRIMITIVE ("X-WINDOW-SET-CLASS-HINT", Prim_x_window_set_class_hint, 3, 3,
2101 "Set the class hint of WINDOW to RESOURCE_NAME and RESOURCE_CLASS.")
2102 {
2103 PRIMITIVE_HEADER (3);
2104 xw_set_class_hint ((x_window_arg (1)), (STRING_ARG (2)), (STRING_ARG (3)));
2105 PRIMITIVE_RETURN (UNSPECIFIC);
2106 }
2107
2108 DEFINE_PRIMITIVE ("X-WINDOW-SET-INPUT-HINT", Prim_x_window_set_input_hint, 2, 2,
2109 "Set the input hint of WINDOW to INPUT.")
2110 {
2111 PRIMITIVE_HEADER (2);
2112 xw_set_wm_input_hint ((x_window_arg (1)), (BOOLEAN_ARG (2)));
2113 PRIMITIVE_RETURN (UNSPECIFIC);
2114 }
2115
2116 DEFINE_PRIMITIVE ("X-WINDOW-SET-INPUT-FOCUS", Prim_x_window_set_input_focus, 2, 2, 0)
2117 {
2118 PRIMITIVE_HEADER (2);
2119 {
2120 struct xwindow * xw = (x_window_arg (1));
2121 Display * display = (XW_DISPLAY (xw));
2122 void * handle = (push_x_error_info (display));
2123
2124 XSetInputFocus (display,
2125 (XW_WINDOW (xw)),
2126 RevertToParent,
2127 ((Time) (arg_ulong_integer (2))));
2128 if (any_x_errors_p (display))
2129 {
2130 pop_x_error_info (handle);
2131 error_bad_range_arg (1);
2132 }
2133 pop_x_error_info (handle);
2134 }
2135 PRIMITIVE_RETURN (UNSPECIFIC);
2136 }
2137
2138 DEFINE_PRIMITIVE ("X-WINDOW-SET-TRANSIENT-FOR-HINT", Prim_x_window_set_transient_for, 2, 2,
2139 "Set the transient-for hint of WINDOW to PRIMARY-WINDOW.")
2140 {
2141 PRIMITIVE_HEADER (2);
2142 {
2143 struct xwindow * xw = (x_window_arg (1));
2144 struct xwindow * transient_for = (x_window_arg (2));
2145 if ((xw == transient_for) || ((XW_XD (xw)) != (XW_XD (transient_for))))
2146 error_bad_range_arg (2);
2147 XSetTransientForHint
2148 ((XW_DISPLAY (xw)),
2149 (XW_WINDOW (xw)),
2150 (XW_WINDOW (transient_for)));
2151 }
2152 PRIMITIVE_RETURN (UNSPECIFIC);
2153 }
2154
2155 /* WM Control Primitives */
2156
2157 DEFINE_PRIMITIVE ("X-WINDOW-MAP", Prim_x_window_map, 1, 1, 0)
2158 {
2159 PRIMITIVE_HEADER (1);
2160 {
2161 struct xwindow * xw = (x_window_arg (1));
2162 XMapWindow ((XW_DISPLAY (xw)), (XW_WINDOW (xw)));
2163 }
2164 PRIMITIVE_RETURN (UNSPECIFIC);
2165 }
2166
2167 DEFINE_PRIMITIVE ("X-WINDOW-ICONIFY", Prim_x_window_iconify, 1, 1, 0)
2168 {
2169 PRIMITIVE_HEADER (1);
2170 {
2171 struct xwindow * xw = (x_window_arg (1));
2172 Display * display = (XW_DISPLAY (xw));
2173 XIconifyWindow (display, (XW_WINDOW (xw)), (DefaultScreen (display)));
2174 }
2175 PRIMITIVE_RETURN (UNSPECIFIC);
2176 }
2177
2178 DEFINE_PRIMITIVE ("X-WINDOW-WITHDRAW", Prim_x_window_withdraw, 1, 1, 0)
2179 {
2180 PRIMITIVE_HEADER (1);
2181 {
2182 struct xwindow * xw = (x_window_arg (1));
2183 Display * display = (XW_DISPLAY (xw));
2184 XWithdrawWindow (display, (XW_WINDOW (xw)), (DefaultScreen (display)));
2185 }
2186 PRIMITIVE_RETURN (UNSPECIFIC);
2187 }
2188
2189 /* The following shouldn't be used on top-level windows. Instead use
2190 ICONIFY or WITHDRAW. */
2191 DEFINE_PRIMITIVE ("X-WINDOW-UNMAP", Prim_x_window_unmap, 1, 1, 0)
2192 {
2193 PRIMITIVE_HEADER (1);
2194 {
2195 struct xwindow * xw = (x_window_arg (1));
2196 XUnmapWindow ((XW_DISPLAY (xw)), (XW_WINDOW (xw)));
2197 }
2198 PRIMITIVE_RETURN (UNSPECIFIC);
2199 }
2200
2201 DEFINE_PRIMITIVE ("X-WINDOW-SET-SIZE", Prim_x_window_set_size, 3, 3, 0)
2202 {
2203 PRIMITIVE_HEADER (3);
2204 {
2205 struct xwindow * xw = (x_window_arg (1));
2206 unsigned int extra = (2 * (XW_INTERNAL_BORDER_WIDTH (xw)));
2207 XResizeWindow ((XW_DISPLAY (xw)),
2208 (XW_WINDOW (xw)),
2209 ((arg_ulong_integer (2)) + extra),
2210 ((arg_ulong_integer (3)) + extra));
2211 }
2212 PRIMITIVE_RETURN (UNSPECIFIC);
2213 }
2214
2215 DEFINE_PRIMITIVE ("X-WINDOW-RAISE", Prim_x_window_raise, 1, 1, 0)
2216 {
2217 PRIMITIVE_HEADER (1);
2218 {
2219 struct xwindow * xw = (x_window_arg (1));
2220 XRaiseWindow ((XW_DISPLAY (xw)), (XW_WINDOW (xw)));
2221 }
2222 PRIMITIVE_RETURN (UNSPECIFIC);
2223 }
2224
2225 DEFINE_PRIMITIVE ("X-WINDOW-LOWER", Prim_x_window_lower, 1, 1, 0)
2226 {
2227 PRIMITIVE_HEADER (1);
2228 {
2229 struct xwindow * xw = (x_window_arg (1));
2230 XLowerWindow ((XW_DISPLAY (xw)), (XW_WINDOW (xw)));
2231 }
2232 PRIMITIVE_RETURN (UNSPECIFIC);
2233 }
2234
2235 DEFINE_PRIMITIVE ("X-WINDOW-GET-SIZE", Prim_x_window_get_size, 1, 1, 0)
2236 {
2237 PRIMITIVE_HEADER (1);
2238 {
2239 struct xwindow * xw = (x_window_arg (1));
2240 unsigned int extra;
2241
2242 get_wm_decor_geometry (xw);
2243 extra = (2 * (XW_WM_DECOR_BORDER_WIDTH (xw)));
2244 PRIMITIVE_RETURN
2245 (cons ((ulong_to_integer ((XW_WM_DECOR_PIXEL_WIDTH (xw)) + extra)),
2246 (ulong_to_integer ((XW_WM_DECOR_PIXEL_HEIGHT (xw)) + extra))));
2247 }
2248 }
2249
2250 DEFINE_PRIMITIVE ("X-WINDOW-GET-POSITION", Prim_x_window_get_position, 1, 1, 0)
2251 {
2252 PRIMITIVE_HEADER (1);
2253 {
2254 struct xwindow * xw = (x_window_arg (1));
2255 get_wm_decor_geometry (xw);
2256 PRIMITIVE_RETURN (cons ((long_to_integer (XW_WM_DECOR_X (xw))),
2257 (long_to_integer (XW_WM_DECOR_Y (xw)))));
2258 }
2259 }
2260
2261 DEFINE_PRIMITIVE ("X-WINDOW-SET-POSITION", Prim_x_window_set_position, 3, 3, 0)
2262 {
2263 PRIMITIVE_HEADER (3);
2264 move_window ((x_window_arg (1)),
2265 (arg_integer (2)),
2266 (arg_integer (3)));
2267 PRIMITIVE_RETURN (UNSPECIFIC);
2268 }
2269
2270 static void
move_window(struct xwindow * xw,int x,int y)2271 move_window (struct xwindow * xw, int x, int y)
2272 {
2273 if ((XW_UPDATE_NORMAL_HINTS (xw)) != 0)
2274 (* (XW_UPDATE_NORMAL_HINTS (xw))) (xw);
2275 if ((XW_WM_TYPE (xw)) == X_WMTYPE_A)
2276 {
2277 x += (XW_MOVE_OFFSET_X (xw));
2278 y += (XW_MOVE_OFFSET_Y (xw));
2279 }
2280 XMoveWindow ((XW_DISPLAY (xw)), (XW_WINDOW (xw)), x, y);
2281 if ((XW_WM_TYPE (xw)) == X_WMTYPE_UNKNOWN)
2282 {
2283 (XW_EXPECTED_X (xw)) = x;
2284 (XW_EXPECTED_Y (xw)) = y;
2285 (XW_CHECK_EXPECTED_MOVE_P (xw)) = 1;
2286 }
2287 }
2288
2289 static void
check_expected_move(struct xwindow * xw)2290 check_expected_move (struct xwindow * xw)
2291 {
2292 if (((XW_WM_DECOR_X (xw)) == (XW_EXPECTED_X (xw)))
2293 && ((XW_WM_DECOR_Y (xw)) == (XW_EXPECTED_Y (xw))))
2294 {
2295 if ((XW_WM_TYPE (xw)) == X_WMTYPE_UNKNOWN)
2296 (XW_WM_TYPE (xw)) = X_WMTYPE_B;
2297 }
2298 else
2299 {
2300 (XW_WM_TYPE (xw)) = X_WMTYPE_A;
2301 (XW_MOVE_OFFSET_X (xw)) = ((XW_EXPECTED_X (xw)) - (XW_WM_DECOR_X (xw)));
2302 (XW_MOVE_OFFSET_Y (xw)) = ((XW_EXPECTED_Y (xw)) - (XW_WM_DECOR_Y (xw)));
2303 move_window (xw, (XW_EXPECTED_X (xw)), (XW_EXPECTED_Y (xw)));
2304 }
2305 (XW_CHECK_EXPECTED_MOVE_P (xw)) = 0;
2306 }
2307
2308 /* Font Structure Primitive */
2309
2310 #define FONT_STRUCTURE_MAX_CONVERTED_SIZE (10+1 + 256+1 + ((5+1) * (256+2)))
2311 /* font-structure-words +
2312 char-struct-vector +
2313 char-struct-words * maximum-number-possible */
2314
2315 static SCHEME_OBJECT
convert_char_struct(XCharStruct * char_struct)2316 convert_char_struct (XCharStruct * char_struct)
2317 {
2318 if (((char_struct->lbearing) == 0)
2319 && ((char_struct->rbearing) == 0)
2320 && ((char_struct->width) == 0)
2321 && ((char_struct->ascent) == 0)
2322 && ((char_struct->descent) == 0))
2323 return (SHARP_F);
2324 {
2325 SCHEME_OBJECT result = (allocate_marked_vector (TC_VECTOR, 5, true));
2326 VECTOR_SET (result, 0, (long_to_integer (char_struct->lbearing)));
2327 VECTOR_SET (result, 1, (long_to_integer (char_struct->rbearing)));
2328 VECTOR_SET (result, 2, (long_to_integer (char_struct->width)));
2329 VECTOR_SET (result, 3, (long_to_integer (char_struct->ascent)));
2330 VECTOR_SET (result, 4, (long_to_integer (char_struct->descent)));
2331 return (result);
2332 }
2333 }
2334
2335 static SCHEME_OBJECT
convert_font_struct(SCHEME_OBJECT font_name,XFontStruct * font)2336 convert_font_struct (SCHEME_OBJECT font_name, XFontStruct * font)
2337 {
2338 SCHEME_OBJECT result;
2339 if (font == 0)
2340 return SHARP_F;
2341 /* Handle only 8-bit fonts because of laziness. */
2342 if (((font->min_byte1) != 0) || ((font->max_byte1) != 0))
2343 return SHARP_F;
2344
2345 result = (allocate_marked_vector (TC_VECTOR, 10, true));
2346 if ((font->per_char) == 0)
2347 VECTOR_SET (result, 6, SHARP_F);
2348 else
2349 {
2350 unsigned int start_index = (font->min_char_or_byte2);
2351 unsigned int length = ((font->max_char_or_byte2) - start_index + 1);
2352 SCHEME_OBJECT character_vector
2353 = (allocate_marked_vector (TC_VECTOR, length, true));
2354 unsigned int index;
2355 for (index = 0; (index < length); index += 1)
2356 VECTOR_SET (character_vector,
2357 index,
2358 (convert_char_struct ((font->per_char) + index)));
2359 VECTOR_SET (result, 6, (ulong_to_integer (start_index)));
2360 VECTOR_SET (result, 7, character_vector);
2361 }
2362 VECTOR_SET (result, 0, font_name);
2363 VECTOR_SET (result, 1, (ulong_to_integer (font->direction)));
2364 VECTOR_SET (result, 2,
2365 (BOOLEAN_TO_OBJECT ((font->all_chars_exist) == True)));
2366 VECTOR_SET (result, 3, (ulong_to_integer (font->default_char)));
2367 VECTOR_SET (result, 4, (convert_char_struct (& (font->min_bounds))));
2368 VECTOR_SET (result, 5, (convert_char_struct (& (font->max_bounds))));
2369 VECTOR_SET (result, 8, (long_to_integer (font->ascent)));
2370 VECTOR_SET (result, 9, (long_to_integer (font->descent)));
2371
2372 return result;
2373 }
2374
2375 DEFINE_PRIMITIVE ("X-FONT-STRUCTURE", Prim_x_font_structure, 2, 2,
2376 "(DISPLAY FONT)\n\
2377 FONT is either a font name or a font ID.")
2378 {
2379 PRIMITIVE_HEADER (2);
2380 Primitive_GC_If_Needed (FONT_STRUCTURE_MAX_CONVERTED_SIZE);
2381 {
2382 SCHEME_OBJECT font_name = (ARG_REF (2));
2383 Display * display = (XD_DISPLAY (x_display_arg (1)));
2384 XFontStruct * font = 0;
2385 bool by_name = STRING_P (font_name);
2386 SCHEME_OBJECT result;
2387
2388 if (by_name)
2389 font = XLoadQueryFont (display, (STRING_POINTER (font_name)));
2390 else
2391 font = XQueryFont (display, ((XID) (integer_to_ulong (ARG_REF (2)))));
2392
2393 if (font == 0)
2394 PRIMITIVE_RETURN (SHARP_F);
2395
2396 result = convert_font_struct (font_name, font);
2397
2398 if (by_name)
2399 XFreeFont (display, font);
2400 PRIMITIVE_RETURN (result);
2401 }
2402 }
2403
2404 DEFINE_PRIMITIVE ("X-WINDOW-FONT-STRUCTURE", Prim_x_window_font_structure, 1, 1,
2405 "(X-WINDOW)\n\
2406 Returns the font-structure for the font currently associated with X-WINDOW.")
2407 {
2408 XFontStruct *font;
2409 PRIMITIVE_HEADER (1);
2410 Primitive_GC_If_Needed (FONT_STRUCTURE_MAX_CONVERTED_SIZE);
2411 font = XW_FONT (x_window_arg (1));
2412 PRIMITIVE_RETURN (convert_font_struct (ulong_to_integer (font->fid), font));
2413 }
2414
2415 DEFINE_PRIMITIVE ("X-LIST-FONTS", Prim_x_list_fonts, 3, 3,
2416 "(DISPLAY PATTERN LIMIT)\n\
2417 LIMIT is an exact non-negative integer or #F for no limit.\n\
2418 Returns #F or a vector of at least one string.")
2419 {
2420 PRIMITIVE_HEADER (1);
2421 {
2422 int actual_count = 0;
2423 char ** names
2424 = (XListFonts ((XD_DISPLAY (x_display_arg (1))),
2425 (STRING_ARG (2)),
2426 ((FIXNUM_P (ARG_REF (3)))
2427 ? (FIXNUM_TO_LONG (ARG_REF (3)))
2428 : 1000000),
2429 (&actual_count)));
2430 if (names == 0)
2431 PRIMITIVE_RETURN (SHARP_F);
2432 {
2433 unsigned int words = (actual_count + 1); /* the vector of strings */
2434 unsigned int i;
2435 for (i = 0; (i < actual_count); i += 1)
2436 words += (STRING_LENGTH_TO_GC_LENGTH (strlen (names[i])));
2437 if (GC_NEEDED_P (words))
2438 {
2439 /* this causes the primitive to be restarted, so deallocate names */
2440 XFreeFontNames (names);
2441 Primitive_GC (words);
2442 /* notreached */
2443 }
2444 }
2445 {
2446 SCHEME_OBJECT result
2447 = (allocate_marked_vector (TC_VECTOR, actual_count, false));
2448 unsigned int i;
2449 for (i = 0; (i < actual_count); i += 1)
2450 VECTOR_SET (result, i, (char_pointer_to_string (names[i])));
2451 XFreeFontNames (names);
2452 PRIMITIVE_RETURN (result);
2453 }
2454 }
2455 }
2456
2457 /* Atoms */
2458
2459 DEFINE_PRIMITIVE ("X-INTERN-ATOM", Prim_x_intern_atom, 3, 3, 0)
2460 {
2461 PRIMITIVE_HEADER (3);
2462 PRIMITIVE_RETURN
2463 (ulong_to_integer (XInternAtom ((XD_DISPLAY (x_display_arg (1))),
2464 (STRING_ARG (2)),
2465 (BOOLEAN_ARG (3)))));
2466 }
2467
2468 DEFINE_PRIMITIVE ("X-GET-ATOM-NAME", Prim_x_get_atom_name, 2, 2, 0)
2469 {
2470 PRIMITIVE_HEADER (2);
2471 {
2472 struct xdisplay * xd = (x_display_arg (1));
2473 Display * display = (XD_DISPLAY (xd));
2474 void * handle = (push_x_error_info (display));
2475 char * name = (XGetAtomName (display, (arg_ulong_integer (2))));
2476 unsigned char error_code = (x_error_code (display));
2477 SCHEME_OBJECT result
2478 = ((error_code == 0)
2479 ? (char_pointer_to_string (name))
2480 : (ulong_to_integer (error_code)));
2481 if (name != 0)
2482 XFree (name);
2483 pop_x_error_info (handle);
2484 PRIMITIVE_RETURN (result);
2485 }
2486 }
2487
2488 /* Window Properties */
2489
2490 static SCHEME_OBJECT
char_ptr_to_prop_data_32(const unsigned char * data,unsigned long nitems)2491 char_ptr_to_prop_data_32 (const unsigned char * data, unsigned long nitems)
2492 {
2493 SCHEME_OBJECT result = (allocate_marked_vector (TC_VECTOR, nitems, 1));
2494 unsigned long index;
2495 for (index = 0; (index < nitems); index += 1)
2496 VECTOR_SET (result, index, (ulong_to_integer (((CARD32 *) data) [index])));
2497 return (result);
2498 }
2499
2500 static SCHEME_OBJECT
char_ptr_to_prop_data_16(const unsigned char * data,unsigned long nitems)2501 char_ptr_to_prop_data_16 (const unsigned char * data, unsigned long nitems)
2502 {
2503 SCHEME_OBJECT result = (allocate_marked_vector (TC_VECTOR, nitems, 1));
2504 unsigned long index;
2505 for (index = 0; (index < nitems); index += 1)
2506 VECTOR_SET (result, index, (ulong_to_integer (((CARD16 *) data) [index])));
2507 return (result);
2508 }
2509
2510 static const unsigned char *
prop_data_32_to_char_ptr(SCHEME_OBJECT vector,unsigned long * length_return)2511 prop_data_32_to_char_ptr (SCHEME_OBJECT vector, unsigned long * length_return)
2512 {
2513 unsigned long nitems = (VECTOR_LENGTH (vector));
2514 unsigned long length = (nitems * 4);
2515 unsigned char * data = (dstack_alloc (length));
2516 unsigned long index;
2517 for (index = 0; (index < nitems); index += 1)
2518 {
2519 SCHEME_OBJECT n = (VECTOR_REF (vector, index));
2520 if (!integer_to_ulong_p (n))
2521 return (0);
2522 (((CARD32 *) data) [index]) = (integer_to_ulong (n));
2523 }
2524 (*length_return) = length;
2525 return (data);
2526 }
2527
2528 static const unsigned char *
prop_data_16_to_char_ptr(SCHEME_OBJECT vector,unsigned long * length_return)2529 prop_data_16_to_char_ptr (SCHEME_OBJECT vector, unsigned long * length_return)
2530 {
2531 unsigned long nitems = (VECTOR_LENGTH (vector));
2532 unsigned long length = (nitems * 2);
2533 unsigned char * data = (dstack_alloc (length));
2534 unsigned long index;
2535 for (index = 0; (index < nitems); index += 1)
2536 {
2537 SCHEME_OBJECT n = (VECTOR_REF (vector, index));
2538 unsigned long un;
2539 if (!integer_to_ulong_p (n))
2540 return (0);
2541 un = (integer_to_ulong (n));
2542 if (un >= 65536)
2543 return (0);
2544 (((CARD16 *) data) [index]) = un;
2545 }
2546 (*length_return) = length;
2547 return (data);
2548 }
2549
2550 DEFINE_PRIMITIVE ("X-GET-WINDOW-PROPERTY", Prim_x_get_window_property, 7, 7, 0)
2551 {
2552 PRIMITIVE_HEADER (7);
2553 {
2554 Display * display = (XD_DISPLAY (x_display_arg (1)));
2555 Window window = (arg_ulong_integer (2));
2556 Atom property = (arg_ulong_integer (3));
2557 long long_offset = (arg_nonnegative_integer (4));
2558 long long_length = (arg_nonnegative_integer (5));
2559 Bool delete = (BOOLEAN_ARG (6));
2560 Atom req_type = (arg_ulong_integer (7));
2561
2562 Atom actual_type;
2563 int actual_format;
2564 unsigned long nitems;
2565 unsigned long bytes_after;
2566 unsigned char * data;
2567
2568 if ((XGetWindowProperty (display, window, property, long_offset,
2569 long_length, delete, req_type, (&actual_type),
2570 (&actual_format), (&nitems), (&bytes_after),
2571 (&data)))
2572 != Success)
2573 error_external_return ();
2574 if (actual_format == 0)
2575 {
2576 XFree (data);
2577 PRIMITIVE_RETURN (SHARP_F);
2578 }
2579 if (! ((actual_format == 8)
2580 || (actual_format == 16)
2581 || (actual_format == 32)))
2582 error_external_return ();
2583 {
2584 SCHEME_OBJECT result = (allocate_marked_vector (TC_VECTOR, 4, 1));
2585 VECTOR_SET (result, 0, (ulong_to_integer (actual_type)));
2586 VECTOR_SET (result, 1, (long_to_integer (actual_format)));
2587 VECTOR_SET (result, 2, (ulong_to_integer (bytes_after)));
2588 VECTOR_SET (result, 3,
2589 (((req_type != AnyPropertyType)
2590 && (req_type != actual_type))
2591 ? SHARP_F
2592 : (actual_format == 32)
2593 ? (char_ptr_to_prop_data_32 (data, nitems))
2594 : (actual_format == 16)
2595 ? (char_ptr_to_prop_data_16 (data, nitems))
2596 : (memory_to_string (nitems, data))));
2597 XFree (data);
2598 PRIMITIVE_RETURN (result);
2599 }
2600 }
2601 }
2602
2603 DEFINE_PRIMITIVE ("X-CHANGE-PROPERTY", Prim_x_change_property, 7, 7, 0)
2604 {
2605 PRIMITIVE_HEADER (7);
2606 {
2607 Display * display = (XD_DISPLAY (x_display_arg (1)));
2608 Window window = (arg_ulong_integer (2));
2609 Atom property = (arg_ulong_integer (3));
2610 Atom type = (arg_ulong_integer (4));
2611 int format = (arg_nonnegative_integer (5));
2612 int mode = (arg_index_integer (6, 3));
2613 unsigned long dlen = 0;
2614 const unsigned char * data = 0;
2615 void * handle;
2616 unsigned char error_code;
2617
2618 handle = (push_x_error_info (display));
2619 switch (format)
2620 {
2621 case 8:
2622 CHECK_ARG (7, STRING_P);
2623 data = (STRING_BYTE_PTR (ARG_REF (7)));
2624 dlen = (STRING_LENGTH (ARG_REF (7)));
2625 break;
2626 case 16:
2627 CHECK_ARG (7, VECTOR_P);
2628 data = (prop_data_16_to_char_ptr ((ARG_REF (7)), (&dlen)));
2629 if (data == 0)
2630 error_bad_range_arg (7);
2631 break;
2632 case 32:
2633 CHECK_ARG (7, VECTOR_P);
2634 data = (prop_data_32_to_char_ptr ((ARG_REF (7)), (&dlen)));
2635 if (data == 0)
2636 error_bad_range_arg (7);
2637 break;
2638 default:
2639 error_bad_range_arg (5);
2640 break;
2641 }
2642 XChangeProperty (display, window, property, type, format, mode, data, dlen);
2643 error_code = (x_error_code (display));
2644 pop_x_error_info (handle);
2645 PRIMITIVE_RETURN (ulong_to_integer (error_code));
2646 }
2647 }
2648
2649 DEFINE_PRIMITIVE ("X-DELETE-PROPERTY", Prim_x_delete_property, 3, 3, 0)
2650 {
2651 PRIMITIVE_HEADER (3);
2652 XDeleteProperty ((XD_DISPLAY (x_display_arg (1))),
2653 (arg_ulong_integer (2)),
2654 (arg_ulong_integer (3)));
2655 PRIMITIVE_RETURN (UNSPECIFIC);
2656 }
2657
2658 /* Selections */
2659
2660 DEFINE_PRIMITIVE ("X-SET-SELECTION-OWNER", Prim_x_set_selection_owner, 4, 4, 0)
2661 {
2662 PRIMITIVE_HEADER (4);
2663 XSetSelectionOwner ((XD_DISPLAY (x_display_arg (1))),
2664 (arg_ulong_integer (2)),
2665 (arg_ulong_integer (3)),
2666 (arg_ulong_integer (4)));
2667 PRIMITIVE_RETURN (UNSPECIFIC);
2668 }
2669
2670 DEFINE_PRIMITIVE ("X-GET-SELECTION-OWNER", Prim_x_get_selection_owner, 2, 2, 0)
2671 {
2672 PRIMITIVE_HEADER (2);
2673 PRIMITIVE_RETURN
2674 (ulong_to_integer (XGetSelectionOwner ((XD_DISPLAY (x_display_arg (1))),
2675 (arg_ulong_integer (2)))));
2676 }
2677
2678 DEFINE_PRIMITIVE ("X-CONVERT-SELECTION", Prim_x_convert_selection, 6, 6, 0)
2679 {
2680 PRIMITIVE_HEADER (6);
2681 XConvertSelection ((XD_DISPLAY (x_display_arg (1))),
2682 (arg_ulong_integer (2)),
2683 (arg_ulong_integer (3)),
2684 (arg_ulong_integer (4)),
2685 (arg_ulong_integer (5)),
2686 (arg_ulong_integer (6)));
2687 PRIMITIVE_RETURN (UNSPECIFIC);
2688 }
2689
2690 DEFINE_PRIMITIVE ("X-SEND-SELECTION-NOTIFY", Prim_x_send_selection_notify, 6, 6, 0)
2691 {
2692 PRIMITIVE_HEADER (6);
2693 {
2694 struct xdisplay * xd = (x_display_arg (1));
2695 Window requestor = (arg_ulong_integer (2));
2696 XSelectionEvent event;
2697 (event.type) = SelectionNotify;
2698 (event.display) = (XD_DISPLAY (xd));
2699 (event.requestor) = requestor;
2700 (event.selection) = (arg_ulong_integer (3));
2701 (event.target) = (arg_ulong_integer (4));
2702 (event.property) = (arg_ulong_integer (5));
2703 (event.time) = (arg_ulong_integer (6));
2704 XSendEvent ((XD_DISPLAY (xd)), requestor, False, 0, ((XEvent *) (&event)));
2705 }
2706 PRIMITIVE_RETURN (UNSPECIFIC);
2707 }
2708
2709 #ifdef COMPILE_AS_MODULE
2710
2711 /* sed -n -e 's/^DEFINE_PRIMITIVE *(\([^)]*\))$/ declare_primitive (\1);/pg' \
2712 -e 's/^DEFINE_PRIMITIVE *(\([^)]*\)$/ declare_primitive (\1 0);/pg' */
2713
2714 void
dload_initialize_x11base(void)2715 dload_initialize_x11base (void)
2716 {
2717 declare_primitive ("X-CHANGE-PROPERTY", Prim_x_change_property, 7, 7, 0);
2718 declare_primitive ("X-CLOSE-ALL-DISPLAYS", Prim_x_close_all_displays, 0, 0, 0);
2719 declare_primitive ("X-CLOSE-DISPLAY", Prim_x_close_display, 1, 1, 0);
2720 declare_primitive ("X-CLOSE-WINDOW", Prim_x_close_window, 1, 1, 0);
2721 declare_primitive ("X-CONVERT-SELECTION", Prim_x_convert_selection, 6, 6, 0);
2722 declare_primitive ("X-DEBUG", Prim_x_debug, 1, 1, 0);
2723 declare_primitive ("X-DELETE-PROPERTY", Prim_x_delete_property, 3, 3, 0);
2724 declare_primitive ("X-DISPLAY-DESCRIPTOR", Prim_x_display_descriptor, 1, 1, 0);
2725 declare_primitive ("X-DISPLAY-FLUSH", Prim_x_display_flush, 1, 1, 0);
2726 declare_primitive ("X-DISPLAY-GET-DEFAULT", Prim_x_display_get_default, 3, 3, 0);
2727 declare_primitive ("X-DISPLAY-GET-SIZE", Prim_x_display_get_size, 2, 2, 0);
2728 declare_primitive ("X-DISPLAY-PROCESS-EVENTS", Prim_x_display_process_events, 2, 2, 0);
2729 declare_primitive ("X-DISPLAY-SYNC", Prim_x_display_sync, 2, 2, 0);
2730 declare_primitive ("X-FONT-STRUCTURE", Prim_x_font_structure, 2, 2, 0);
2731 declare_primitive ("X-GET-ATOM-NAME", Prim_x_get_atom_name, 2, 2, 0);
2732 declare_primitive ("X-GET-SELECTION-OWNER", Prim_x_get_selection_owner, 2, 2, 0);
2733 declare_primitive ("X-GET-WINDOW-PROPERTY", Prim_x_get_window_property, 7, 7, 0);
2734 declare_primitive ("X-ID->WINDOW", Prim_x_id_to_window, 2, 2, 0);
2735 declare_primitive ("X-INTERN-ATOM", Prim_x_intern_atom, 3, 3, 0);
2736 declare_primitive ("X-LIST-FONTS", Prim_x_list_fonts, 3, 3, 0);
2737 declare_primitive ("X-MAX-REQUEST-SIZE", Prim_x_max_request_size, 1, 1, 0);
2738 declare_primitive ("X-OPEN-DISPLAY", Prim_x_open_display, 1, 1, 0);
2739 declare_primitive ("X-SELECT-INPUT", Prim_x_select_input, 3, 3, 0);
2740 declare_primitive ("X-SEND-SELECTION-NOTIFY", Prim_x_send_selection_notify, 6, 6, 0);
2741 declare_primitive ("X-SET-DEFAULT-FONT", Prim_x_set_default_font, 2, 2, 0);
2742 declare_primitive ("X-SET-SELECTION-OWNER", Prim_x_set_selection_owner, 4, 4, 0);
2743 declare_primitive ("X-WINDOW-ANDC-EVENT-MASK", Prim_x_window_andc_event_mask, 2, 2, 0);
2744 declare_primitive ("X-WINDOW-BEEP", Prim_x_window_beep, 1, 1, 0);
2745 declare_primitive ("X-WINDOW-CLEAR", Prim_x_window_clear, 1, 1, 0);
2746 declare_primitive ("X-WINDOW-COORDS-LOCAL->ROOT", Prim_x_window_coords_local2root, 3, 3, 0);
2747 declare_primitive ("X-WINDOW-COORDS-ROOT->LOCAL", Prim_x_window_coords_root2local, 3, 3, 0);
2748 declare_primitive ("X-WINDOW-DISPLAY", Prim_x_window_display, 1, 1, 0);
2749 declare_primitive ("X-WINDOW-EVENT-MASK", Prim_x_window_event_mask, 1, 1, 0);
2750 declare_primitive ("X-WINDOW-FLUSH", Prim_x_window_flush, 1, 1, 0);
2751 declare_primitive ("X-WINDOW-FONT-STRUCTURE", Prim_x_window_font_structure, 1, 1, 0);
2752 declare_primitive ("X-WINDOW-GET-POSITION", Prim_x_window_get_position, 1, 1, 0);
2753 declare_primitive ("X-WINDOW-GET-SIZE", Prim_x_window_get_size, 1, 1, 0);
2754 declare_primitive ("X-WINDOW-ICONIFY", Prim_x_window_iconify, 1, 1, 0);
2755 declare_primitive ("X-WINDOW-ID", Prim_x_window_id, 1, 1, 0);
2756 declare_primitive ("X-WINDOW-LOWER", Prim_x_window_lower, 1, 1, 0);
2757 declare_primitive ("X-WINDOW-MAP", Prim_x_window_map, 1, 1, 0);
2758 declare_primitive ("X-WINDOW-OR-EVENT-MASK", Prim_x_window_or_event_mask, 2, 2, 0);
2759 declare_primitive ("X-WINDOW-QUERY-POINTER", Prim_x_window_query_pointer, 1, 1, 0);
2760 declare_primitive ("X-WINDOW-RAISE", Prim_x_window_raise, 1, 1, 0);
2761 declare_primitive ("X-WINDOW-SET-BACKGROUND-COLOR", Prim_x_window_set_background_color, 2, 2, 0);
2762 declare_primitive ("X-WINDOW-SET-BORDER-COLOR", Prim_x_window_set_border_color, 2, 2, 0);
2763 declare_primitive ("X-WINDOW-SET-BORDER-WIDTH", Prim_x_window_set_border_width, 2, 2, 0);
2764 declare_primitive ("X-WINDOW-SET-CLASS-HINT", Prim_x_window_set_class_hint, 3, 3, 0);
2765 declare_primitive ("X-WINDOW-SET-CURSOR-COLOR", Prim_x_window_set_cursor_color, 2, 2, 0);
2766 declare_primitive ("X-WINDOW-SET-EVENT-MASK", Prim_x_window_set_event_mask, 2, 2, 0);
2767 declare_primitive ("X-WINDOW-SET-FONT", Prim_x_window_set_font, 2, 2, 0);
2768 declare_primitive ("X-WINDOW-SET-FOREGROUND-COLOR", Prim_x_window_set_foreground_color, 2, 2, 0);
2769 declare_primitive ("X-WINDOW-SET-ICON-NAME", Prim_x_window_set_icon_name, 2, 2, 0);
2770 declare_primitive ("X-WINDOW-SET-INPUT-FOCUS", Prim_x_window_set_input_focus, 2, 2, 0);
2771 declare_primitive ("X-WINDOW-SET-INPUT-HINT", Prim_x_window_set_input_hint, 2, 2, 0);
2772 declare_primitive ("X-WINDOW-SET-INTERNAL-BORDER-WIDTH", Prim_x_window_set_internal_border_width, 2, 2, 0);
2773 declare_primitive ("X-WINDOW-SET-MOUSE-COLOR", Prim_x_window_set_mouse_color, 2, 2, 0);
2774 declare_primitive ("X-WINDOW-SET-MOUSE-SHAPE", Prim_x_window_set_mouse_shape, 2, 2, 0);
2775 declare_primitive ("X-WINDOW-SET-NAME", Prim_x_window_set_name, 2, 2, 0);
2776 declare_primitive ("X-WINDOW-SET-POSITION", Prim_x_window_set_position, 3, 3, 0);
2777 declare_primitive ("X-WINDOW-SET-SIZE", Prim_x_window_set_size, 3, 3, 0);
2778 declare_primitive ("X-WINDOW-SET-TRANSIENT-FOR-HINT", Prim_x_window_set_transient_for, 2, 2, 0);
2779 declare_primitive ("X-WINDOW-UNMAP", Prim_x_window_unmap, 1, 1, 0);
2780 declare_primitive ("X-WINDOW-WITHDRAW", Prim_x_window_withdraw, 1, 1, 0);
2781 declare_primitive ("X-WINDOW-X-SIZE", Prim_x_window_x_size, 1, 1, 0);
2782 declare_primitive ("X-WINDOW-Y-SIZE", Prim_x_window_y_size, 1, 1, 0);
2783 }
2784
2785 void
dload_finalize_x11base(void)2786 dload_finalize_x11base (void)
2787 {
2788 if (initialization_done)
2789 x_close_all_displays ();
2790 }
2791
2792 #endif /* defined (COMPILE_AS_MODULE) */
2793