comparison src/device-x.c @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children ac2d302a0011
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 /* Device functions for X windows.
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
4
5 This file is part of XEmacs.
6
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 /* Synched up with: Not in FSF. */
23
24 /* Original authors: Jamie Zawinski and the FSF */
25 /* Rewritten by Ben Wing and Chuck Thompson. */
26
27 #include <config.h>
28 #include "lisp.h"
29
30 #include "console-x.h"
31 #include "xintrinsicp.h" /* CoreP.h needs this */
32 #include <X11/CoreP.h> /* Numerous places access the fields of
33 a core widget directly. We could
34 use XtVaGetValues(), but ... */
35 #include "xgccache.h"
36 #include <X11/Shell.h>
37 #include "xmu.h"
38 #include "glyphs-x.h"
39 #include "objects-x.h"
40
41 #include "buffer.h"
42 #include "events.h"
43 #include "faces.h"
44 #include "frame.h"
45 #include "redisplay.h"
46 #include "sysdep.h"
47 #include "window.h"
48
49 #include "sysfile.h"
50 #include "systime.h"
51
52 Lisp_Object Vdefault_x_device;
53
54 /* Qdisplay in general.c */
55 Lisp_Object Qx_error;
56 Lisp_Object Qinit_pre_x_win, Qinit_post_x_win;
57
58 /* The application class of Emacs. */
59 Lisp_Object Vx_emacs_application_class;
60
61 Lisp_Object Vx_initial_argv_list; /* #### ugh! */
62
63 static XrmOptionDescRec emacs_options[] =
64 {
65 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
66 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
67
68 {"-internal-border-width", "*EmacsFrame.internalBorderWidth", XrmoptionSepArg, NULL},
69 {"-ib", "*EmacsFrame.internalBorderWidth", XrmoptionSepArg, NULL},
70 {"-scrollbar-width", "*EmacsFrame.scrollBarWidth", XrmoptionSepArg, NULL},
71 {"-scrollbar-height", "*EmacsFrame.scrollBarHeight", XrmoptionSepArg, NULL},
72
73 /* #### Beware! If the type of the shell changes, update this. */
74 {"-T", "*TopLevelEmacsShell.title", XrmoptionSepArg, NULL},
75 {"-wn", "*TopLevelEmacsShell.title", XrmoptionSepArg, NULL},
76 {"-title", "*TopLevelEmacsShell.title", XrmoptionSepArg, NULL},
77 {"-iconname", "*TopLevelEmacsShell.iconName", XrmoptionSepArg, NULL},
78 {"-in", "*TopLevelEmacsShell.iconName", XrmoptionSepArg, NULL},
79 {"-mc", "*pointerColor", XrmoptionSepArg, NULL},
80 {"-cr", "*cursorColor", XrmoptionSepArg, NULL},
81 {"-fontset", "*FontSet", XrmoptionSepArg, NULL},
82 };
83
84 static void validify_resource_string (char *str);
85
86 /* Functions to synchronize mirroring resources and specifiers */
87 int in_resource_setting;
88 int in_specifier_change_function;
89
90
91 /************************************************************************/
92 /* helper functions */
93 /************************************************************************/
94
95 struct device *
96 get_device_from_display (Display *dpy)
97 {
98 Lisp_Object devcons, concons;
99
100 DEVICE_LOOP_NO_BREAK (devcons, concons)
101 {
102 struct device *d = XDEVICE (XCAR (devcons));
103 if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d) == dpy)
104 return d;
105 }
106
107 /* Only devices we are actually managing should ever be used as an
108 argument to this function. */
109 abort ();
110
111 return 0; /* suppress compiler warning */
112 }
113
114 struct device *
115 decode_x_device (Lisp_Object device)
116 {
117 XSETDEVICE (device, decode_device (device));
118 CHECK_X_DEVICE (device);
119 return XDEVICE (device);
120 }
121
122 Display *
123 get_x_display (Lisp_Object device)
124 {
125 return DEVICE_X_DISPLAY (decode_x_device (device));
126 }
127
128
129 /************************************************************************/
130 /* initializing an X connection */
131 /************************************************************************/
132
133 static void
134 allocate_x_device_struct (struct device *d)
135 {
136 d->device_data = (struct x_device *) xmalloc (sizeof (struct x_device));
137
138 /* zero out all slots. */
139 memset (d->device_data, 0, sizeof (struct x_device));
140 }
141
142 static void
143 Xatoms_of_device_x (struct device *d)
144 {
145 Display *display = DEVICE_X_DISPLAY (d);
146 #define ATOM(x) XInternAtom (display, (x), False)
147
148 DEVICE_XATOM_WM_PROTOCOLS (d) = ATOM ("WM_PROTOCOLS");
149 DEVICE_XATOM_WM_DELETE_WINDOW (d) = ATOM ("WM_DELETE_WINDOW");
150 DEVICE_XATOM_WM_SAVE_YOURSELF (d) = ATOM ("WM_SAVE_YOURSELF");
151 DEVICE_XATOM_WM_TAKE_FOCUS (d) = ATOM ("WM_TAKE_FOCUS");
152 DEVICE_XATOM_WM_STATE (d) = ATOM ("WM_STATE");
153 }
154
155 static void
156 sanity_check_geometry_resource (Display *dpy)
157 {
158 char *app_name, *app_class, *s;
159 char buf1 [255], buf2 [255];
160 char *type;
161 XrmValue value;
162 XtGetApplicationNameAndClass (dpy, &app_name, &app_class);
163 strcpy (buf1, app_name);
164 strcpy (buf2, app_class);
165 for (s = buf1; *s; s++) if (*s == '.') *s = '_';
166 strcat (buf1, "._no_._such_._resource_.geometry");
167 strcat (buf2, "._no_._such_._resource_.Geometry");
168 if (XrmGetResource (XtDatabase (dpy), buf1, buf2, &type, &value) == True)
169 {
170 warn_when_safe (Qgeometry, Qerror,
171 "\n"
172 "Apparently \"%s*geometry: %s\" or \"%s*geometry: %s\" was\n"
173 "specified in the resource database. Specifying \"*geometry\" will make\n"
174 "XEmacs (and most other X programs) malfunction in obscure ways. (i.e.\n"
175 "the Xt or Xm libraries will probably crash, which is a very bad thing.)\n"
176 "You should always use \".geometry\" or \"*EmacsFrame.geometry\" instead.\n",
177 app_name, (char *) value.addr,
178 app_class, (char *) value.addr);
179 suppress_early_backtrace = 1;
180 error ("Invalid geometry resource");
181 }
182 }
183
184 static void
185 x_init_device_class (struct device *d)
186 {
187 Display *dpy = DEVICE_X_DISPLAY (d);
188 if (DisplayCells (dpy, DefaultScreen (dpy)) > 2)
189 {
190 switch (DefaultVisualOfScreen (DefaultScreenOfDisplay (dpy))->class)
191 {
192 case StaticGray:
193 case GrayScale:
194 DEVICE_CLASS (d) = Qgrayscale;
195 break;
196 default:
197 DEVICE_CLASS (d) = Qcolor;
198 }
199 }
200 else
201 DEVICE_CLASS (d) = Qmono;
202 }
203
204 static void
205 x_init_device (struct device *d, Lisp_Object props)
206 {
207 Lisp_Object display;
208 Lisp_Object device;
209 Display *dpy;
210 int argc;
211 char **argv;
212 CONST char *app_class;
213 CONST char *disp_name;
214
215 XSETDEVICE (device, d);
216 display = DEVICE_CONNECTION (d);
217
218 allocate_x_device_struct (d);
219
220 if (NILP (Vdefault_x_device))
221 Vdefault_x_device = device;
222
223 make_argc_argv (Vx_initial_argv_list, &argc, &argv);
224
225 if (STRINGP (Vx_emacs_application_class) &&
226 string_length (XSTRING (Vx_emacs_application_class)) > 0)
227 GET_C_STRING_CTEXT_DATA_ALLOCA (Vx_emacs_application_class, app_class);
228 else
229 app_class = "Emacs";
230
231 GET_C_STRING_CTEXT_DATA_ALLOCA (display, disp_name);
232
233 slow_down_interrupts ();
234 /* The Xt code can't deal with signals here. Yuck. */
235 dpy = DEVICE_X_DISPLAY (d) =
236 XtOpenDisplay (Xt_app_con, disp_name, NULL, app_class, emacs_options,
237 XtNumber (emacs_options), &argc, argv);
238 speed_up_interrupts ();
239
240 if (dpy == 0)
241 {
242 suppress_early_backtrace = 1;
243 signal_simple_error ("X server not responding\n", display);
244 }
245
246 if (NILP (DEVICE_NAME (d)))
247 DEVICE_NAME (d) = display;
248
249 /* We're going to modify the string in-place, so be a nice XEmacs */
250 DEVICE_NAME (d) = Fcopy_sequence (DEVICE_NAME (d));
251 /* colons and periods can't appear in individual elements of resource
252 strings */
253 validify_resource_string ((char *) string_data (XSTRING (DEVICE_NAME (d))));
254 DEVICE_XT_APP_SHELL (d) = XtAppCreateShell (NULL, app_class,
255 applicationShellWidgetClass,
256 dpy, NULL, 0);
257
258
259 Vx_initial_argv_list = make_arg_list (argc, argv);
260 free_argc_argv (argv);
261
262 DEVICE_X_WM_COMMAND_FRAME (d) = Qnil;
263
264 sanity_check_geometry_resource (dpy);
265
266 /* In event-Xt.c */
267 x_init_modifier_mapping (d);
268
269 DEVICE_INFD (d) = DEVICE_OUTFD (d) = ConnectionNumber (dpy);
270 init_baud_rate (d);
271 init_one_device (d);
272
273 DEVICE_X_GC_CACHE (d) =
274 make_gc_cache (dpy, RootWindow (dpy, DefaultScreen (dpy)));
275 DEVICE_X_GRAY_PIXMAP (d) = None;
276 Xatoms_of_device_x (d);
277 Xatoms_of_xselect (d);
278 Xatoms_of_objects_x (d);
279 x_init_device_class (d);
280
281 /* Run the the elisp side of the X device initialization. */
282 call0 (Qinit_pre_x_win);
283 }
284
285 static void
286 x_finish_init_device (struct device *d, Lisp_Object props)
287 {
288 call0 (Qinit_post_x_win);
289 }
290
291 static void
292 x_mark_device (struct device *d, void (*markobj) (Lisp_Object))
293 {
294 ((markobj) (DEVICE_X_DATA (d)->WM_COMMAND_frame));
295 }
296
297
298 /************************************************************************/
299 /* closing an X connection */
300 /************************************************************************/
301
302 static void
303 free_x_device_struct (struct device *d)
304 {
305 xfree (d->device_data);
306 }
307
308 static void
309 x_delete_device (struct device *d)
310 {
311 Lisp_Object device;
312 Display *display;
313 #ifdef FREE_CHECKING
314 extern void (*__free_hook)();
315 int checking_free;
316 #endif
317
318 XSETDEVICE (device, d);
319 display = DEVICE_X_DISPLAY (d);
320
321 if (display)
322 {
323 #ifdef FREE_CHECKING
324 checking_free = (__free_hook != 0);
325
326 /* Disable strict free checking, to avoid bug in X library */
327 if (checking_free)
328 disable_strict_free_check ();
329 #endif
330
331 free_gc_cache (DEVICE_X_GC_CACHE (d));
332 if (DEVICE_X_DATA (d)->x_modifier_keymap)
333 XFreeModifiermap (DEVICE_X_DATA (d)->x_modifier_keymap);
334 if (DEVICE_X_DATA (d)->x_keysym_map)
335 XFree ((char *) DEVICE_X_DATA (d)->x_keysym_map);
336
337 XtCloseDisplay (display);
338 DEVICE_X_DISPLAY (d) = 0;
339 #ifdef FREE_CHECKING
340 if (checking_free)
341 enable_strict_free_check ();
342 #endif
343 }
344
345 if (EQ (device, Vdefault_x_device))
346 {
347 Lisp_Object devcons, concons;
348 /* #### handle deleting last X device */
349 Vdefault_x_device = Qnil;
350 DEVICE_LOOP_NO_BREAK (devcons, concons)
351 {
352 if (DEVICE_X_P (XDEVICE (XCAR (devcons))))
353 {
354 Vdefault_x_device = XCAR (devcons);
355 goto double_break;
356 }
357 }
358 }
359 double_break:
360 free_x_device_struct (d);
361 }
362
363
364 /************************************************************************/
365 /* handle X errors */
366 /************************************************************************/
367
368 static CONST char *events[] =
369 {
370 "0: ERROR!",
371 "1: REPLY",
372 "KeyPress",
373 "KeyRelease",
374 "ButtonPress",
375 "ButtonRelease",
376 "MotionNotify",
377 "EnterNotify",
378 "LeaveNotify",
379 "FocusIn",
380 "FocusOut",
381 "KeymapNotify",
382 "Expose",
383 "GraphicsExpose",
384 "NoExpose",
385 "VisibilityNotify",
386 "CreateNotify",
387 "DestroyNotify",
388 "UnmapNotify",
389 "MapNotify",
390 "MapRequest",
391 "ReparentNotify",
392 "ConfigureNotify",
393 "ConfigureRequest",
394 "GravityNotify",
395 "ResizeRequest",
396 "CirculateNotify",
397 "CirculateRequest",
398 "PropertyNotify",
399 "SelectionClear",
400 "SelectionRequest",
401 "SelectionNotify",
402 "ColormapNotify",
403 "ClientMessage",
404 "MappingNotify",
405 "LASTEvent"
406 };
407
408 CONST char *
409 x_event_name (int event_type)
410 {
411 if (event_type < 0) return 0;
412 if (event_type >= (sizeof (events) / sizeof (char *))) return 0;
413 return events [event_type];
414 }
415
416 /* Handling errors.
417
418 If an X error occurs which we are not expecting, we have no alternative
419 but to print it to stderr. It would be nice to stuff it into a pop-up
420 buffer, or to print it in the minibuffer, but that's not possible, because
421 one is not allowed to do any I/O on the display connection from an error
422 handler. The guts of Xlib expect these functions to either return or exit.
423
424 However, there are occasions when we might expect an error to reasonably
425 occur. The interface to this is as follows:
426
427 Before calling some X routine which may error, call
428 expect_x_error (dpy);
429
430 Just after calling the X routine, call either:
431
432 x_error_occurred_p (dpy);
433
434 to ask whether an error happened (and was ignored), or:
435
436 signal_if_x_error (dpy, resumable_p);
437
438 which will call Fsignal() with args appropriate to the X error, if there
439 was one. (Resumable_p is whether the debugger should be allowed to
440 continue from the call to signal.)
441
442 You must call one of these two routines immediately after calling the X
443 routine; think of them as bookends like BLOCK_INPUT and UNBLOCK_INPUT.
444 */
445
446 static int error_expected;
447 static int error_occurred;
448 static XErrorEvent last_error;
449
450 /* OVERKILL! */
451
452 #ifdef EXTERNAL_WIDGET
453 static Lisp_Object
454 x_error_handler_do_enqueue (Lisp_Object frame)
455 {
456 enqueue_magic_eval_event (io_error_delete_frame, frame);
457 return Qt;
458 }
459
460 static Lisp_Object
461 x_error_handler_error (Lisp_Object data, Lisp_Object dummy)
462 {
463 return Qnil;
464 }
465 #endif /* EXTERNAL_WIDGET */
466
467 int
468 x_error_handler (Display *disp, XErrorEvent *event)
469 {
470 if (error_expected)
471 {
472 error_expected = 0;
473 error_occurred = 1;
474 last_error = *event;
475 }
476 else
477 {
478 #ifdef EXTERNAL_WIDGET
479 struct frame *f;
480 struct device *d = get_device_from_display (disp);
481
482 if ((event->error_code == BadWindow ||
483 event->error_code == BadDrawable)
484 && ((f = x_any_window_to_frame (d, event->resourceid)) != 0))
485 {
486 Lisp_Object frame;
487
488 /* one of the windows comprising one of our frames has died.
489 This occurs particularly with ExternalShell frames when the
490 client that owns the ExternalShell's window dies.
491
492 We cannot do any I/O on the display connection so we need
493 to enqueue an eval event so that the deletion happens
494 later.
495
496 Furthermore, we need to trap any errors (out-of-memory) that
497 may occur when Fenqueue_eval_event is called.
498 */
499
500 if (f->being_deleted)
501 return 0;
502 XSETFRAME (frame, f);
503 if (!NILP (condition_case_1 (Qerror, x_error_handler_do_enqueue,
504 frame, x_error_handler_error, Qnil)))
505 {
506 f->being_deleted = 1;
507 f->visible = 0;
508 }
509 return 0;
510 }
511 #endif /* EXTERNAL_WIDGET */
512
513 stderr_out ("\n%s: ",
514 (STRINGP (Vinvocation_name)
515 ? (char *) string_data (XSTRING (Vinvocation_name))
516 : "xemacs"));
517 XmuPrintDefaultErrorMessage (disp, event, stderr);
518 }
519 return 0;
520 }
521
522 void
523 expect_x_error (Display *dpy)
524 {
525 assert (!error_expected);
526 XSync (dpy, 0); /* handle pending errors before setting flag */
527 error_expected = 1;
528 error_occurred = 0;
529 }
530
531 int
532 x_error_occurred_p (Display *dpy)
533 {
534 int val;
535 XSync (dpy, 0); /* handle pending errors before setting flag */
536 val = error_occurred;
537 error_expected = 0;
538 error_occurred = 0;
539 return val;
540 }
541
542 int
543 signal_if_x_error (Display *dpy, int resumable_p)
544 {
545 char buf[1024];
546 Lisp_Object data;
547 if (! x_error_occurred_p (dpy))
548 return 0;
549 data = Qnil;
550 sprintf (buf, "0x%X", (unsigned int) last_error.resourceid);
551 data = Fcons (build_string (buf), data);
552 {
553 char num [32];
554 sprintf (num, "%d", last_error.request_code);
555 XGetErrorDatabaseText (last_error.display, "XRequest", num, "",
556 buf, sizeof (buf));
557 if (! *buf)
558 sprintf (buf, "Request-%d", last_error.request_code);
559 data = Fcons (build_string (buf), data);
560 }
561 XGetErrorText (last_error.display, last_error.error_code, buf, sizeof (buf));
562 data = Fcons (build_string (buf), data);
563 again:
564 Fsignal (Qx_error, data);
565 if (! resumable_p) goto again;
566 return 1;
567 }
568
569 int
570 x_IO_error_handler (Display *disp)
571 {
572 /* This function can GC */
573 Lisp_Object dev;
574 struct device *d = get_device_from_display (disp);
575 XSETDEVICE (dev, d);
576
577 if (NILP (find_nonminibuffer_frame_not_on_device (dev)))
578 {
579 /* We're going down. */
580 stderr_out
581 ("\n%s: Fatal I/O Error %d (%s) on display connection \"%s\"\n",
582 (STRINGP (Vinvocation_name) ?
583 (char *) string_data (XSTRING (Vinvocation_name)) : "xemacs"),
584 errno, strerror (errno), DisplayString (disp));
585 stderr_out
586 (" after %lu requests (%lu known processed) with %d events remaining.\n",
587 NextRequest (disp) - 1, LastKnownRequestProcessed (disp),
588 QLength (disp));
589 /* assert (!_Xdebug); */
590 }
591 else
592 {
593 warn_when_safe
594 (Qx, Qcritical,
595 "I/O Error %d (%s) on display connection \"%s\"\n"
596 " after %lu requests (%lu known processed) with "
597 "%d events remaining.\n",
598 errno, strerror (errno), DisplayString (disp),
599 NextRequest (disp) - 1, LastKnownRequestProcessed (disp),
600 QLength (disp));
601 }
602
603 enqueue_magic_eval_event (io_error_delete_device, dev);
604
605 return 0;
606 }
607
608 DEFUN ("x-debug-mode", Fx_debug_mode, Sx_debug_mode, 1, 2, 0 /*
609 With a true arg, make the connection to the X server synchronous.
610 With false, make it asynchronous. Synchronous connections are much slower,
611 but are useful for debugging. (If you get X errors, make the connection
612 synchronous, and use a debugger to set a breakpoint on `x_error_handler'.
613 Your backtrace of the C stack will now be useful. In asynchronous mode,
614 the stack above `x_error_handler' isn't helpful because of buffering.)
615 If DEVICE is not specified, the selected device is assumed.
616
617 Calling this function is the same as calling the C function `XSynchronize',
618 or starting the program with the `-sync' command line argument.
619 */ )
620 (arg, device)
621 Lisp_Object arg, device;
622 {
623 struct device *d = decode_x_device (device);
624
625 XSynchronize (DEVICE_X_DISPLAY (d), !NILP (arg));
626
627 if (!NILP (arg))
628 message ("X connection is synchronous");
629 else
630 message ("X connection is asynchronous");
631
632 return arg;
633 }
634
635
636 /************************************************************************/
637 /* X resources */
638 /************************************************************************/
639
640 #if 0 /* bah humbug. The whole "widget == resource" stuff is such
641 a crock of shit that I'm just going to ignore it all. */
642
643 /* If widget is NULL, we are retrieving device or global face data. */
644
645 static void
646 construct_name_list (Display *display, Widget widget, char *fake_name,
647 char *fake_class, char *name, char *class)
648 {
649 char *stack [100][2];
650 Widget this;
651 int count = 0;
652 char *name_tail, *class_tail;
653
654 if (widget)
655 {
656 for (this = widget; this; this = XtParent (this))
657 {
658 stack [count][0] = this->core.name;
659 stack [count][1] = XtClass (this)->core_class.class_name;
660 count++;
661 }
662 count--;
663 }
664 else if (fake_name && fake_class)
665 {
666 stack [count][0] = fake_name;
667 stack [count][1] = fake_class;
668 count++;
669 }
670
671 /* The root widget is an application shell; resource lookups use the
672 specified application name and application class in preference to
673 the name/class of that widget (which is argv[0] / "ApplicationShell").
674 Generally the app name and class will be argv[0] / "Emacs" but
675 the former can be set via the -name command-line option, and the
676 latter can be set by changing `x-emacs-application-class' in
677 lisp/term/x-win.el.
678 */
679 XtGetApplicationNameAndClass (display,
680 &stack [count][0],
681 &stack [count][1]);
682
683 name [0] = 0;
684 class [0] = 0;
685
686 name_tail = name;
687 class_tail = class;
688 for (; count >= 0; count--)
689 {
690 strcat (name_tail, stack [count][0]);
691 for (; *name_tail; name_tail++)
692 if (*name_tail == '.') *name_tail = '_';
693 strcat (name_tail, ".");
694 name_tail++;
695
696 strcat (class_tail, stack [count][1]);
697 for (; *class_tail; class_tail++)
698 if (*class_tail == '.') *class_tail = '_';
699 strcat (class_tail, ".");
700 class_tail++;
701 }
702 }
703
704 #endif
705
706 /* Only the characters [-_A-Za-z0-9] are allowed in the individual
707 sections of a resource. Convert invalid characters to -. */
708
709 static void
710 validify_resource_string (char *str)
711 {
712 while (*str)
713 {
714 if (!strchr ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
715 "abcdefghijklmnopqrstuvwxyz"
716 "0123456789-_", *str))
717 *str = '-';
718 str++;
719 }
720 }
721
722 /* Given a locale and device specification from x-get-resource or
723 x-get-resource-prefix, return the resource prefix and display to
724 fetch the resource on. */
725
726 static void
727 x_get_resource_prefix (Lisp_Object locale, Lisp_Object device,
728 Display **display_out, char *name_out,
729 char *class_out)
730 {
731 char *appname, *appclass;
732
733 if (NILP (locale))
734 locale = Qglobal;
735 if (NILP (Fvalid_specifier_locale_p (locale)))
736 signal_simple_error ("Invalid locale", locale);
737 if (WINDOWP (locale))
738 /* #### I can't come up with any coherent way of naming windows.
739 By relative position? That seems tricky because windows
740 can change position, be split, etc. By order of creation?
741 That seems less than useful. */
742 signal_simple_error ("Windows currently can't be resourced", locale);
743
744 if (!NILP (device) && !DEVICEP (device))
745 CHECK_DEVICE (device);
746 if (DEVICEP (device) && !DEVICE_X_P (XDEVICE (device)))
747 device = Qnil;
748 if (NILP (device))
749 {
750 device = DFW_DEVICE (locale);
751 if (DEVICEP (device) && !DEVICE_X_P (XDEVICE (device)))
752 device = Qnil;
753 if (NILP (device))
754 device = Vdefault_x_device;
755 if (NILP (device))
756 {
757 *display_out = 0;
758 return;
759 }
760 }
761
762 *display_out = DEVICE_X_DISPLAY (XDEVICE (device));
763
764 XtGetApplicationNameAndClass (*display_out, &appname, &appclass);
765 strcpy (name_out, appname);
766 strcpy (class_out, appclass);
767 validify_resource_string (name_out);
768 validify_resource_string (class_out);
769
770 if (EQ (locale, Qglobal))
771 return;
772 if (BUFFERP (locale))
773 {
774 strcat (name_out, ".buffer.");
775 /* we know buffer is live; otherwise we got an error above. */
776 strcat (name_out,
777 (CONST char *) string_data (XSTRING (Fbuffer_name (locale))));
778 strcat (class_out, ".EmacsLocaleType.EmacsBuffer");
779 }
780 else if (FRAMEP (locale))
781 {
782 strcat (name_out, ".frame.");
783 /* we know frame is live; otherwise we got an error above. */
784 strcat (name_out,
785 (CONST char *) string_data (XSTRING (Fframe_name (locale))));
786 strcat (class_out, ".EmacsLocaleType.EmacsFrame");
787 }
788 else
789 {
790 assert (DEVICEP (locale));
791 strcat (name_out, ".device.");
792 /* we know device is live; otherwise we got an error above. */
793 strcat (name_out,
794 (CONST char *) string_data (XSTRING (Fdevice_name (locale))));
795 strcat (class_out, ".EmacsLocaleType.EmacsDevice");
796 }
797 return;
798 }
799
800 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 3, 6, 0 /*
801 Retrieve an X resource from the resource manager.
802
803 The first arg is the name of the resource to retrieve, such as \"font\".
804 The second arg is the class of the resource to retrieve, like \"Font\".
805 The third arg should be one of the symbols 'string, 'integer, 'natnum, or
806 'boolean, specifying the type of object that the database is searched for.
807 The fourth arg is the locale to search for the resources on, and can
808 currently be a a buffer, a frame, a device, or 'global. If omitted, it
809 defaults to 'global.
810 The fifth arg is the device to search for the resources on. (The resource
811 database for a particular device is constructed by combining non-device-
812 specific resources such any command-line resources specified and any
813 app-defaults files found [or the fallback resources supplied by XEmacs,
814 if no app-defaults file is found] with device-specific resources such as
815 those supplied using xrdb.) If omitted, it defaults to the device of
816 LOCALE, if a device can be derived (i.e. if LOCALE is a frame or device),
817 and otherwise defaults to the value of `default-x-device'.
818 The sixth arg NOERROR, if non-nil, means do not signal an error if a
819 bogus resource specification was retrieved (e.g. if a non-integer was
820 given when an integer was requested). In this case, a warning is issued
821 instead.
822
823 The resource names passed to this function are looked up relative to the
824 locale.
825
826 If you want to search for a subresource, you just need to specify the
827 resource levels in NAME and CLASS. For example, NAME could be
828 \"modeline.attributeFont\", and CLASS \"Face.AttributeFont\".
829
830 Specifically,
831
832 1) If LOCALE is a buffer, a call
833
834 (x-get-resource \"foreground\" \"Foreground\" 'string SOME-BUFFER)
835
836 is an interface to a C call something like
837
838 XrmGetResource (db, \"xemacs.buffer.BUFFER-NAME.foreground\",
839 \"Emacs.EmacsLocaleType.EmacsBuffer.Foreground\",
840 \"String\");
841
842 2) If LOCALE is a frame, a call
843
844 (x-get-resource \"foreground\" \"Foreground\" 'string SOME-FRAME)
845
846 is an interface to a C call something like
847
848 XrmGetResource (db, \"xemacs.frame.FRAME-NAME.foreground\",
849 \"Emacs.EmacsLocaleType.EmacsFrame.Foreground\",
850 \"String\");
851
852 3) If LOCALE is a device, a call
853
854 (x-get-resource \"foreground\" \"Foreground\" 'string SOME-DEVICE)
855
856 is an interface to a C call something like
857
858 XrmGetResource (db, \"xemacs.device.DEVICE-NAME.foreground\",
859 \"Emacs.EmacsLocaleType.EmacsDevice.Foreground\",
860 \"String\");
861
862 4) If LOCALE is 'global, a call
863
864 (x-get-resource \"foreground\" \"Foreground\" 'string 'global)
865
866 is an interface to a C call something like
867
868 XrmGetResource (db, \"xemacs.foreground\",
869 \"Emacs.Foreground\",
870 \"String\");
871
872 Note that for 'global, no prefix is added other than that of the
873 application itself; thus, you can use this locale to retrieve
874 arbitrary application resources, if you really want to.
875
876 The returned value of this function is nil if the queried resource is not
877 found. If the third arg is `string', a string is returned, and if it is
878 `integer', an integer is returned. If the third arg is `boolean', then the
879 returned value is the list (t) for true, (nil) for false, and is nil to
880 mean ``unspecified.''
881 */ )
882 (name, class, type, locale, device, no_error)
883 Lisp_Object name, class, type, locale, device, no_error;
884 {
885 /* #### fixed limit, could be overflowed */
886 char name_string[2048], class_string[2048];
887 char *raw_result;
888 XrmDatabase db;
889 Display *display;
890 Error_behavior errb = decode_error_behavior_flag (no_error);
891
892 CHECK_STRING (name);
893 CHECK_STRING (class);
894 CHECK_SYMBOL (type);
895
896 if (!EQ (type, Qstring) && !EQ (type, Qboolean) &&
897 !EQ (type, Qinteger) && !EQ (type, Qnatnum))
898 return maybe_signal_continuable_error
899 (Qwrong_type_argument,
900 list2 (build_translated_string
901 ("should be string, integer, natnum or boolean"),
902 type),
903 Qresource, errb);
904
905 x_get_resource_prefix (locale, device, &display, name_string,
906 class_string);
907 if (!display)
908 return Qnil;
909
910 db = XtDatabase (display);
911
912 strcat (name_string, ".");
913 strcat (name_string, (CONST char *) string_data (XSTRING (name)));
914 strcat (class_string, ".");
915 strcat (class_string, (CONST char *) string_data (XSTRING (class)));
916
917 {
918 XrmValue xrm_value;
919 XrmName namelist[100];
920 XrmClass classlist[100];
921 XrmName *namerest = namelist;
922 XrmClass *classrest = classlist;
923 XrmRepresentation xrm_type;
924 XrmRepresentation string_quark;
925 int result;
926 XrmStringToNameList (name_string, namelist);
927 XrmStringToClassList (class_string, classlist);
928 string_quark = XrmStringToQuark ("String");
929
930 /* ensure that they have the same length */
931 while (namerest[0] && classrest[0])
932 namerest++, classrest++;
933 if (namerest[0] || classrest[0])
934 signal_simple_error_2
935 ("class list and name list must be the same length", name, class);
936 result = XrmQGetResource (db, namelist, classlist, &xrm_type, &xrm_value);
937
938 if (result != True || xrm_type != string_quark)
939 return Qnil;
940 raw_result = (char *) xrm_value.addr;
941 }
942
943 if (EQ (type, Qstring))
944 return build_string (raw_result);
945 else if (EQ (type, Qboolean))
946 {
947 if (!strcasecmp (raw_result, "off") ||
948 !strcasecmp (raw_result, "false") ||
949 !strcasecmp (raw_result,"no"))
950 return Fcons (Qnil, Qnil);
951 else if (!strcasecmp (raw_result, "on") ||
952 !strcasecmp (raw_result, "true") ||
953 !strcasecmp (raw_result, "yes"))
954 return Fcons (Qt, Qnil);
955 else
956 return maybe_continuable_error (Qresource, errb,
957 "can't convert %s: %s to a Boolean",
958 name_string, raw_result);
959 }
960 else if (EQ (type, Qinteger) || EQ (type, Qnatnum))
961 {
962 int i;
963 char c;
964 if (1 != sscanf (raw_result, "%d%c", &i, &c))
965 return maybe_continuable_error
966 (Qresource, errb,
967 "can't convert %s: %s to an integer",
968 name_string, raw_result);
969 else if (EQ (type, Qnatnum) && i < 0)
970 return maybe_continuable_error
971 (Qresource, errb,
972 "invalid numerical value %d for resource %s",
973 i, name_string);
974 else
975 return make_int (i);
976 }
977 else
978 abort ();
979
980 /* Can't get here. */
981 return Qnil; /* shut up compiler */
982 }
983
984 DEFUN ("x-get-resource-prefix", Fx_get_resource_prefix,
985 Sx_get_resource_prefix, 1, 2, 0 /*
986 Return the resource prefix for LOCALE on DEVICE.
987 The resource prefix is the strings used to prefix resources if
988 the LOCALE and DEVICE arguments were passed to `x-get-resource'.
989 The returned value is a cons of a name prefix and a class prefix.
990 For example, if LOCALE is a frame, the returned value might be
991 \(\"xemacs.frame.FRAME-NAME\" . \"Emacs.EmacsLocaleType.EmacsFrame\").
992 If no valid X device for resourcing can be obtained, this function
993 returns nil. (In such a case, `x-get-resource' would always return nil.)
994 */ )
995 (locale, device)
996 Lisp_Object locale, device;
997 {
998 /* #### fixed limit, could be overflowed */
999 char name[1024], class[1024];
1000 Display *display;
1001
1002 x_get_resource_prefix (locale, device, &display, name, class);
1003 if (!display)
1004 return Qnil;
1005 return Fcons (build_string (name), build_string (class));
1006 }
1007
1008 DEFUN ("x-put-resource", Fx_put_resource, Sx_put_resource, 1, 2, 0 /*
1009 Add a resource to the resource database for DEVICE.
1010 RESOURCE-LINE specifies the resource to add and should be a
1011 standard resource specification.
1012 */ )
1013 (resource_line, device)
1014 Lisp_Object resource_line, device;
1015 {
1016 struct device *d = decode_device (device);
1017 char *str, *colon_pos;
1018
1019 CHECK_STRING (resource_line);
1020 str = (char *) string_data (XSTRING (resource_line));
1021 if (!(colon_pos = strchr (str, ':')) || strchr (str, '\n'))
1022 invalid:
1023 signal_simple_error ("Invalid resource line", resource_line);
1024 if (strspn (str,
1025 /* Only the following chars are allowed before the colon */
1026 " \t.*?abcdefghijklmnopqrstuvwxyz"
1027 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-") != colon_pos - str)
1028 goto invalid;
1029
1030 if (DEVICE_X_P (d))
1031 {
1032 XrmDatabase db = XtDatabase (DEVICE_X_DISPLAY (d));
1033 XrmPutLineResource (&db, str);
1034 }
1035
1036 return Qnil;
1037 }
1038
1039
1040 /************************************************************************/
1041 /* display information functions */
1042 /************************************************************************/
1043
1044 DEFUN ("default-x-device", Fdefault_x_device, Sdefault_x_device, 0, 0, 0 /*
1045 Return the default X device for resourcing.
1046 This is the first-created X device that still exists.
1047 */ )
1048 ()
1049 {
1050 return Vdefault_x_device;
1051 }
1052
1053 DEFUN ("x-display-visual-class", Fx_display_visual_class,
1054 Sx_display_visual_class, 0, 1, 0 /*
1055 Return the visual class of the X display `device' is on.
1056 The returned value will be one of the symbols `static-gray', `gray-scale',
1057 `static-color', `pseudo-color', `true-color', or `direct-color'.
1058 */ )
1059 (device)
1060 Lisp_Object device;
1061 {
1062 switch (DefaultVisualOfScreen
1063 (DefaultScreenOfDisplay (get_x_display (device)))->class)
1064 {
1065 case StaticGray: return (intern ("static-gray"));
1066 case GrayScale: return (intern ("gray-scale"));
1067 case StaticColor: return (intern ("static-color"));
1068 case PseudoColor: return (intern ("pseudo-color"));
1069 case TrueColor: return (intern ("true-color"));
1070 case DirectColor: return (intern ("direct-color"));
1071 default:
1072 error ("display has an unknown visual class");
1073 }
1074
1075 return Qnil; /* suppress compiler warning */
1076 }
1077
1078 static int
1079 x_device_pixel_width (struct device *d)
1080 {
1081 Display *dpy = DEVICE_X_DISPLAY (d);
1082
1083 return DisplayWidth (dpy, DefaultScreen (dpy));
1084 }
1085
1086 static int
1087 x_device_pixel_height (struct device *d)
1088 {
1089 Display *dpy = DEVICE_X_DISPLAY (d);
1090
1091 return DisplayHeight (dpy, DefaultScreen (dpy));
1092 }
1093
1094 static int
1095 x_device_mm_width (struct device *d)
1096 {
1097 Display *dpy = DEVICE_X_DISPLAY (d);
1098
1099 return DisplayWidthMM (dpy, DefaultScreen (dpy));
1100 }
1101
1102 static int
1103 x_device_mm_height (struct device *d)
1104 {
1105 Display *dpy = DEVICE_X_DISPLAY (d);
1106
1107 return DisplayHeightMM (dpy, DefaultScreen (dpy));
1108 }
1109
1110 static int
1111 x_device_bitplanes (struct device *d)
1112 {
1113 Display *dpy = DEVICE_X_DISPLAY (d);
1114
1115 return DisplayPlanes (dpy, DefaultScreen (dpy));
1116 }
1117
1118 static int
1119 x_device_color_cells (struct device *d)
1120 {
1121 Display *dpy = DEVICE_X_DISPLAY (d);
1122
1123 return DisplayCells (dpy, DefaultScreen (dpy));
1124 }
1125
1126 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0 /*
1127 Return the vendor ID string of the X server `device' on.
1128 */ )
1129 (device)
1130 Lisp_Object device;
1131 {
1132 Display *dpy = get_x_display (device);
1133 char *vendor = ServerVendor (dpy);
1134
1135 if (vendor)
1136 return (build_string (vendor));
1137 else
1138 return (build_string (""));
1139 }
1140
1141 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0 /*
1142 Return the version numbers of the X server `device' is on.
1143 The returned value is a list of three integers: the major and minor
1144 version numbers of the X Protocol in use, and the vendor-specific release
1145 number. See also `x-server-vendor'.
1146 */ )
1147 (device)
1148 Lisp_Object device;
1149 {
1150 Display *dpy = get_x_display (device);
1151
1152 return list3 (make_int (ProtocolVersion (dpy)),
1153 make_int (ProtocolRevision (dpy)),
1154 make_int (VendorRelease (dpy)));
1155 }
1156
1157 DEFUN ("x-valid-keysym-name-p", Fx_valid_keysym_name_p, Sx_valid_keysym_name_p,
1158 1, 1, 0 /*
1159 Return true if KEYSYM names a keysym that the X library knows about.
1160 Valid keysyms are listed in the files /usr/include/X11/keysymdef.h and in
1161 /usr/lib/X11/XKeysymDB, or whatever the equivalents are on your system.
1162 */ )
1163 (keysym)
1164 Lisp_Object keysym;
1165 {
1166 CONST char *keysym_ext;
1167
1168 CHECK_STRING (keysym);
1169 GET_C_STRING_CTEXT_DATA_ALLOCA (keysym, keysym_ext);
1170 if (XStringToKeysym (keysym_ext))
1171 return Qt;
1172 return Qnil;
1173 }
1174
1175 DEFUN ("x-keysym-on-keyboard-p", Fx_keysym_on_keyboard_p, Sx_keysym_on_keyboard_p,
1176 1, 2, 0 /*
1177 Return true if KEYSYM names a key on the keyboard of DEVICE.
1178 More precisely, return true if pressing a physical key
1179 on the keyboard of DEVICE without any modifier keys generates KEYSYM.
1180 Valid keysyms are listed in the files /usr/include/X11/keysymdef.h and in
1181 /usr/lib/X11/XKeysymDB, or whatever the equivalents are on your system.
1182 */ )
1183 (keysym, device)
1184 Lisp_Object keysym, device;
1185 {
1186 struct device *d = decode_device(device);
1187 CONST char *keysym_string;
1188 KeySym keysym_KeySym;
1189 KeySym *keysym_ptr, *keysym_last;
1190 int code, min_code, max_code, keysyms_per_code;
1191
1192 if (!DEVICE_X_P (d))
1193 signal_simple_error ("Not an X device", device);
1194 CHECK_STRING (keysym);
1195 GET_C_STRING_CTEXT_DATA_ALLOCA (keysym, keysym_string);
1196 keysym_KeySym = XStringToKeysym (keysym_string);
1197 if (!keysym_KeySym) /* Invalid keysym */
1198 return Qnil;
1199
1200 XDisplayKeycodes (DEVICE_X_DISPLAY (d), &min_code, &max_code);
1201 keysyms_per_code = DEVICE_X_DATA (d)->x_keysym_map_keysyms_per_code;
1202 keysym_ptr = DEVICE_X_DATA (d)->x_keysym_map;
1203 keysym_last = keysym_ptr + (max_code - min_code) * keysyms_per_code;
1204 for ( ; keysym_ptr <= keysym_last; keysym_ptr += keysyms_per_code)
1205 {
1206 if (keysym_KeySym == *keysym_ptr)
1207 return Qt;
1208 }
1209
1210 return Qnil;
1211 }
1212
1213
1214 /************************************************************************/
1215 /* grabs and ungrabs */
1216 /************************************************************************/
1217
1218 DEFUN ("x-grab-pointer", Fx_grab_pointer, Sx_grab_pointer, 0, 3, 0 /*
1219 Grab the pointer and restrict it to its current window.
1220 If optional DEVICE argument is nil, the default device will be used.
1221 If optional CURSOR argument is non-nil, change the pointer shape to that
1222 until `x-ungrab-pointer' is called (it should be an object returned by the
1223 `make-cursor-glyph' function).
1224 If the second optional argument IGNORE-KEYBOARD is non-nil, ignore all
1225 keyboard events during the grab.
1226 Returns t if the grab is successful, nil otherwise.
1227 */ )
1228 (device, cursor, ignore_keyboard)
1229 Lisp_Object device, cursor, ignore_keyboard;
1230 {
1231 Window w;
1232 int pointer_mode, result;
1233 struct device *d = decode_x_device (device);
1234
1235 if (!NILP (cursor))
1236 {
1237 CHECK_POINTER_GLYPH (cursor);
1238 cursor = glyph_image_instance (cursor, device, ERROR_ME, 0);
1239 }
1240
1241 if (!NILP (ignore_keyboard))
1242 pointer_mode = GrabModeSync;
1243 else
1244 pointer_mode = GrabModeAsync;
1245
1246 w = XtWindow (FRAME_X_TEXT_WIDGET (device_selected_frame (d)));
1247
1248 /* #### Possibly this needs to gcpro the cursor somehow, but it doesn't
1249 seem to cause a problem if XFreeCursor is called on a cursor in use
1250 in a grab; I suppose the X server counts the grab as a reference
1251 and doesn't free it until it exits? */
1252 result = XGrabPointer (DEVICE_X_DISPLAY (d), w,
1253 False,
1254 ButtonMotionMask | ButtonPressMask
1255 | ButtonReleaseMask | PointerMotionHintMask,
1256 GrabModeAsync, /* Keep pointer events flowing */
1257 pointer_mode, /* Stall keyboard events */
1258 w, /* Stay in this window */
1259 (NILP (cursor) ? 0
1260 : XIMAGE_INSTANCE_X_CURSOR (cursor)),
1261 CurrentTime);
1262 return ((result == GrabSuccess) ? Qt : Qnil);
1263 }
1264
1265 DEFUN ("x-ungrab-pointer", Fx_ungrab_pointer, Sx_ungrab_pointer, 0, 1, 0 /*
1266 Release a pointer grab made with `x-grab-pointer'.
1267 If optional first arg DEVICE is nil the default device is used.
1268 If it is t the pointer will be released on all X devices.
1269 */ )
1270 (device)
1271 Lisp_Object device;
1272 {
1273 if (!EQ (device, Qt))
1274 {
1275 Display *dpy = get_x_display (device);
1276 XUngrabPointer (dpy, CurrentTime);
1277 }
1278 else
1279 {
1280 Lisp_Object devcons, concons;
1281
1282 DEVICE_LOOP_NO_BREAK (devcons, concons)
1283 {
1284 struct device *d = XDEVICE (XCAR (devcons));
1285
1286 if (DEVICE_X_P (d))
1287 XUngrabPointer (DEVICE_X_DISPLAY (d), CurrentTime);
1288 }
1289 }
1290
1291 return Qnil;
1292 }
1293
1294 DEFUN ("x-grab-keyboard", Fx_grab_keyboard, Sx_grab_keyboard, 0, 1, 0 /*
1295 Grab the keyboard on the given device (defaulting to the selected one).
1296 So long as the keyboard is grabbed, all keyboard events will be delivered
1297 to emacs -- it is not possible for other X clients to eavesdrop on them.
1298 Ungrab the keyboard with `x-ungrab-keyboard' (use an unwind-protect).
1299 Returns t if the grab was successful; nil otherwise.
1300 */ )
1301 (device)
1302 Lisp_Object device;
1303 {
1304 struct device *d = decode_x_device (device);
1305 Window w = XtWindow (FRAME_X_TEXT_WIDGET (device_selected_frame (d)));
1306 Display *dpy = DEVICE_X_DISPLAY (d);
1307 Status status;
1308 XSync (dpy, False);
1309 status = XGrabKeyboard (dpy, w, True,
1310 /* I don't really understand sync-vs-async
1311 grabs, but this is what xterm does. */
1312 GrabModeAsync, GrabModeAsync,
1313 /* Use the timestamp of the last user action
1314 read by emacs proper; xterm uses CurrentTime
1315 but there's a comment that says "wrong"...
1316 (Despite the name this is the time of the
1317 last key or mouse event.) */
1318 DEVICE_X_MOUSE_TIMESTAMP (d));
1319 if (status == GrabSuccess)
1320 {
1321 /* The XUngrabKeyboard should generate a FocusIn back to this
1322 window but it doesn't unless we explicitly set focus to the
1323 window first (which should already have it. The net result
1324 is that without this call when x-ungrab-keyboard is called
1325 the selected frame ends up not having focus. */
1326 XSetInputFocus (dpy, w, RevertToParent, DEVICE_X_MOUSE_TIMESTAMP (d));
1327 return Qt;
1328 }
1329 else
1330 return Qnil;
1331 }
1332
1333 DEFUN ("x-ungrab-keyboard", Fx_ungrab_keyboard, Sx_ungrab_keyboard, 0, 1, 0 /*
1334 Release a keyboard grab made with `x-grab-keyboard'.
1335 */ )
1336 (device)
1337 Lisp_Object device;
1338 {
1339 Display *dpy = get_x_display (device);
1340 XUngrabKeyboard (dpy, CurrentTime);
1341 return Qnil;
1342 }
1343
1344
1345 /************************************************************************/
1346 /* initialization */
1347 /************************************************************************/
1348
1349 void
1350 syms_of_device_x (void)
1351 {
1352 defsubr (&Sx_debug_mode);
1353 defsubr (&Sx_get_resource);
1354 defsubr (&Sx_get_resource_prefix);
1355 defsubr (&Sx_put_resource);
1356
1357 defsubr (&Sdefault_x_device);
1358 defsubr (&Sx_display_visual_class);
1359 defsubr (&Sx_server_vendor);
1360 defsubr (&Sx_server_version);
1361 defsubr (&Sx_valid_keysym_name_p);
1362 defsubr (&Sx_keysym_on_keyboard_p);
1363
1364 defsubr (&Sx_grab_pointer);
1365 defsubr (&Sx_ungrab_pointer);
1366 defsubr (&Sx_grab_keyboard);
1367 defsubr (&Sx_ungrab_keyboard);
1368
1369 defsymbol (&Qx_error, "x-error");
1370 defsymbol (&Qinit_pre_x_win, "init-pre-x-win");
1371 defsymbol (&Qinit_post_x_win, "init-post-x-win");
1372 }
1373
1374 void
1375 console_type_create_device_x (void)
1376 {
1377 CONSOLE_HAS_METHOD (x, init_device);
1378 CONSOLE_HAS_METHOD (x, finish_init_device);
1379 CONSOLE_HAS_METHOD (x, mark_device);
1380 CONSOLE_HAS_METHOD (x, delete_device);
1381 CONSOLE_HAS_METHOD (x, device_pixel_width);
1382 CONSOLE_HAS_METHOD (x, device_pixel_height);
1383 CONSOLE_HAS_METHOD (x, device_mm_width);
1384 CONSOLE_HAS_METHOD (x, device_mm_height);
1385 CONSOLE_HAS_METHOD (x, device_bitplanes);
1386 CONSOLE_HAS_METHOD (x, device_color_cells);
1387 }
1388
1389 void
1390 vars_of_device_x (void)
1391 {
1392 DEFVAR_LISP ("x-emacs-application-class", &Vx_emacs_application_class /*
1393 The X application class of the XEmacs process.
1394 This controls, among other things, the name of the `app-defaults' file
1395 that XEmacs will use. For changes to this variable to take effect, they
1396 must be made before the connection to the X server is initialized, that is,
1397 this variable may only be changed before emacs is dumped, or by setting it
1398 in the file lisp/term/x-win.el.
1399 */ );
1400 Vx_emacs_application_class = Fpurecopy (build_string ("Emacs"));
1401
1402 DEFVAR_LISP ("x-initial-argv-list", &Vx_initial_argv_list /*
1403 You don't want to know.
1404 This is used during startup to communicate the remaining arguments in
1405 `command-line-args-left' to the C code, which passes the args to
1406 the X initialization code, which removes some args, and then the
1407 args are placed back into `x-initial-arg-list' and thence into
1408 `command-line-args-left'. Perhaps `command-line-args-left' should
1409 just reside in C.
1410 */ );
1411 Vx_initial_argv_list = Qnil;
1412
1413 Fprovide (Qx);
1414
1415 staticpro (&Vdefault_x_device);
1416 Vdefault_x_device = Qnil;
1417
1418 error_expected = 0;
1419 error_occurred = 0;
1420
1421 in_resource_setting = 0;
1422 in_specifier_change_function = 0;
1423 }