comparison src/event-Xt.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 /* The event_stream interface for X11 with Xt, and/or tty frames.
2 Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 1996 Ben Wing.
5
6 This file is part of XEmacs.
7
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
22
23 /* Synched up with: Not in FSF. */
24
25 #include <config.h>
26 #include "lisp.h"
27
28 #include "console-x.h"
29 #include "lwlib.h"
30 #include "EmacsFrame.h"
31
32 #include "blocktype.h"
33 #include "buffer.h"
34 #include "commands.h"
35 #include "console.h"
36 #include "console-tty.h"
37 #include "events.h"
38 #include "frame.h"
39 #include "objects-x.h"
40 #include "process.h"
41 #include "redisplay.h"
42
43 #include "systime.h"
44 #include "sysproc.h" /* for MAXDESC */
45
46 #include "xintrinsicp.h" /* CoreP.h needs this */
47 #include <X11/CoreP.h> /* Numerous places access the fields of
48 a core widget directly. We could
49 use XtVaGetValues(), but ... */
50
51 static struct event_stream *Xt_event_stream;
52
53 /* With the new event model, all events go through XtDispatchEvent()
54 and are picked up by an event handler that is added to each frame
55 widget. (This is how it's supposed to be.) In the old method,
56 Emacs sucks out events directly from XtNextEvent() and only
57 dispatches the events that it doesn't need to deal with. This
58 old way has lots of corresponding junk that is no longer
59 necessary: lwlib extensions, synthetic XAnyEvents, unnecessary
60 magic events, etc. */
61
62 /* The one and only one application context that Emacs uses. */
63 XtAppContext Xt_app_con;
64
65 /* Do we accept events sent by other clients? */
66 int x_allow_sendevents;
67
68 int modifier_keys_are_sticky;
69
70 #ifdef DEBUG_XEMACS
71 int x_debug_events;
72 #endif
73
74 static int process_events_occurred;
75 static int tty_events_occurred;
76
77 /* Mask of bits indicating the descriptors that we wait for input on */
78 extern SELECT_TYPE input_wait_mask, process_only_mask, tty_only_mask;
79
80 static CONST String x_fallback_resources[] =
81 {
82 /* This file is automatically generated from the app-defaults file
83 in ../etc/Emacs.ad. These resources are consulted only if no
84 app-defaults file is found at all.
85 */
86 #include "Emacs.ad.h"
87 0
88 };
89
90 void emacs_Xt_mapping_action (Widget w, XEvent *event);
91 void debug_process_finalization (struct Lisp_Process *p);
92 Lisp_Object dequeue_Xt_dispatch_event (void);
93 void emacs_Xt_event_handler (Widget wid, XtPointer closure, XEvent *event,
94 Boolean *continue_to_dispatch);
95
96 #ifdef EPOCH
97 void dispatch_epoch_event (struct frame *f, XEvent *event, Lisp_Object type);
98 #endif
99
100 static int last_quit_check_signal_tick_count;
101
102 Lisp_Object Qkey_mapping;
103
104
105 /************************************************************************/
106 /* keymap handling */
107 /************************************************************************/
108
109 /* X bogusly doesn't define the interpretations of any bits besides
110 ModControl, ModShift, and ModLock; so the Interclient Communication
111 Conventions Manual says that we have to bend over backwards to figure
112 out what the other modifier bits mean. According to ICCCM:
113
114 - Any keycode which is assigned ModControl is a "control" key.
115
116 - Any modifier bit which is assigned to a keycode which generates Meta_L
117 or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper,
118 etc.
119
120 - Any keypress event which contains ModControl in its state should be
121 interpreted as a "control" character.
122
123 - Any keypress event which contains a modifier bit in its state which is
124 generated by a keycode whose corresponding keysym is Meta_L or Meta_R
125 should be interpreted as a "meta" character. Likewise for Super, Hyper,
126 etc.
127
128 - It is illegal for a keysym to be associated with more than one modifier
129 bit.
130
131 This means that the only thing that emacs can reasonably interpret as a
132 "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
133 one of the modifier bits Mod1-Mod5.
134
135 Unfortunately, many keyboards don't have Meta keys in their default
136 configuration. So, if there are no Meta keys, but there are "Alt" keys,
137 emacs will interpret Alt as Meta. If there are both Meta and Alt keys,
138 then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to
139 mean "Symbol," but that just confused the hell out of way too many people).
140
141 This works with the default configurations of the 19 keyboard-types I've
142 checked.
143
144 Emacs detects keyboard configurations which violate the above rules, and
145 prints an error message on the standard-error-output. (Perhaps it should
146 use a pop-up-window instead.)
147 */
148
149 static void
150 x_reset_key_mapping (struct device *d)
151 {
152 Display *display = DEVICE_X_DISPLAY (d);
153 struct x_device *xd = DEVICE_X_DATA (d);
154 int max_code;
155 if (xd->x_keysym_map)
156 XFree ((char *) xd->x_keysym_map);
157 XDisplayKeycodes (display, &xd->x_keysym_map_min_code,
158 &max_code);
159 xd->x_keysym_map =
160 XGetKeyboardMapping (display, xd->x_keysym_map_min_code,
161 max_code - xd->x_keysym_map_min_code + 1,
162 &xd->x_keysym_map_keysyms_per_code);
163 }
164
165 static CONST char *
166 index_to_name (int indice)
167 {
168 return ((indice == ShiftMapIndex ? "ModShift"
169 : (indice == LockMapIndex ? "ModLock"
170 : (indice == ControlMapIndex ? "ModControl"
171 : (indice == Mod1MapIndex ? "Mod1"
172 : (indice == Mod2MapIndex ? "Mod2"
173 : (indice == Mod3MapIndex ? "Mod3"
174 : (indice == Mod4MapIndex ? "Mod4"
175 : (indice == Mod5MapIndex ? "Mod5"
176 : "???")))))))));
177 }
178
179 /* Boy, I really wish C had local functions... */
180 struct c_doesnt_have_closures /* #### not yet used */
181 {
182 int warned_about_overlapping_modifiers;
183 int warned_about_predefined_modifiers;
184 int warned_about_duplicate_modifiers;
185 int meta_bit;
186 int hyper_bit;
187 int super_bit;
188 int alt_bit;
189 int mode_bit;
190 };
191
192 static void
193 x_reset_modifier_mapping (struct device *d)
194 {
195 Display *display = DEVICE_X_DISPLAY (d);
196 struct x_device *xd = DEVICE_X_DATA (d);
197 int modifier_index, modifier_key, column, mkpm;
198 int warned_about_overlapping_modifiers = 0;
199 int warned_about_predefined_modifiers = 0;
200 int warned_about_duplicate_modifiers = 0;
201 int meta_bit = 0;
202 int hyper_bit = 0;
203 int super_bit = 0;
204 int alt_bit = 0;
205 int mode_bit = 0;
206
207 xd->lock_interpretation = 0;
208
209 if (xd->x_modifier_keymap)
210 XFreeModifiermap (xd->x_modifier_keymap);
211
212 x_reset_key_mapping (d);
213
214 xd->x_modifier_keymap = XGetModifierMapping (display);
215
216 /* Boy, I really wish C had local functions...
217 */
218
219 /* The call to warn_when_safe must be on the same line as the string or
220 make-msgfile won't pick it up properly (the newline doesn't confuse
221 it, but the backslash does). */
222
223 #define modwarn(name,old,other) \
224 warn_when_safe (Qkey_mapping, Qwarning, "XEmacs: %s (0x%x) generates %s, which is generated by %s.", \
225 name, code, index_to_name (old), other), \
226 warned_about_overlapping_modifiers = 1
227
228 #define modbarf(name,other) \
229 warn_when_safe (Qkey_mapping, Qwarning, "XEmacs: %s (0x%x) generates %s, which is nonsensical.", \
230 name, code, other), \
231 warned_about_predefined_modifiers = 1
232
233 #define check_modifier(name,mask) \
234 if ((1<<modifier_index) != mask) \
235 warn_when_safe (Qkey_mapping, Qwarning, "XEmacs: %s (0x%x) generates %s, which is nonsensical.", \
236 name, code, index_to_name (modifier_index)), \
237 warned_about_predefined_modifiers = 1
238
239 #define store_modifier(name,old) \
240 if (old && old != modifier_index) \
241 warn_when_safe (Qkey_mapping, Qwarning, "XEmacs: %s (0x%x) generates both %s and %s, which is nonsensical.",\
242 name, code, index_to_name (old), \
243 index_to_name (modifier_index)), \
244 warned_about_duplicate_modifiers = 1; \
245 if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift"); \
246 else if (modifier_index == LockMapIndex) modbarf (name,"ModLock"); \
247 else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \
248 else if (sym == XK_Mode_switch) \
249 mode_bit = modifier_index; /* Mode_switch is special, see below... */ \
250 else if (modifier_index == meta_bit && old != meta_bit) \
251 modwarn (name, meta_bit, "Meta"); \
252 else if (modifier_index == super_bit && old != super_bit) \
253 modwarn (name, super_bit, "Super"); \
254 else if (modifier_index == hyper_bit && old != hyper_bit) \
255 modwarn (name, hyper_bit, "Hyper"); \
256 else if (modifier_index == alt_bit && old != alt_bit) \
257 modwarn (name, alt_bit, "Alt"); \
258 else \
259 old = modifier_index;
260
261 mkpm = xd->x_modifier_keymap->max_keypermod;
262 for (modifier_index = 0; modifier_index < 8; modifier_index++)
263 for (modifier_key = 0; modifier_key < mkpm; modifier_key++) {
264 KeySym last_sym = 0;
265 for (column = 0; column < 4; column += 2) {
266 KeyCode code = xd->x_modifier_keymap->modifiermap[modifier_index * mkpm
267 + modifier_key];
268 KeySym sym = (code ? XKeycodeToKeysym (display, code, column) : 0);
269 if (sym == last_sym) continue;
270 last_sym = sym;
271 switch (sym) {
272 case XK_Mode_switch:store_modifier ("Mode_switch", mode_bit); break;
273 case XK_Meta_L: store_modifier ("Meta_L", meta_bit); break;
274 case XK_Meta_R: store_modifier ("Meta_R", meta_bit); break;
275 case XK_Super_L: store_modifier ("Super_L", super_bit); break;
276 case XK_Super_R: store_modifier ("Super_R", super_bit); break;
277 case XK_Hyper_L: store_modifier ("Hyper_L", hyper_bit); break;
278 case XK_Hyper_R: store_modifier ("Hyper_R", hyper_bit); break;
279 case XK_Alt_L: store_modifier ("Alt_L", alt_bit); break;
280 case XK_Alt_R: store_modifier ("Alt_R", alt_bit); break;
281 case XK_Control_L: check_modifier ("Control_L", ControlMask); break;
282 case XK_Control_R: check_modifier ("Control_R", ControlMask); break;
283 case XK_Shift_L: check_modifier ("Shift_L", ShiftMask); break;
284 case XK_Shift_R: check_modifier ("Shift_R", ShiftMask); break;
285 case XK_Shift_Lock: check_modifier ("Shift_Lock", LockMask);
286 xd->lock_interpretation = XK_Shift_Lock; break;
287 case XK_Caps_Lock: check_modifier ("Caps_Lock", LockMask);
288 xd->lock_interpretation = XK_Caps_Lock; break;
289
290 /* It probably doesn't make any sense for a modifier bit to be
291 assigned to a key that is not one of the above, but OpenWindows
292 assigns modifier bits to a couple of random function keys for
293 no reason that I can discern, so printing a warning here would
294 be annoying.
295 */
296 }
297 }
298 }
299 #undef store_modifier
300 #undef check_modifier
301 #undef modwarn
302 #undef modbarf
303
304 /* If there was no Meta key, then try using the Alt key instead.
305 If there is both a Meta key and an Alt key, then the Alt key
306 is not disturbed and remains an Alt key.
307 */
308 if (! meta_bit && alt_bit)
309 meta_bit = alt_bit, alt_bit = 0;
310
311 /* mode_bit overrides everything, since it's processed down inside of
312 XLookupString() instead of by us. If Meta and Mode_switch both
313 generate the same modifier bit (which is an error), then we don't
314 interpret that bit as Meta, because we can't make XLookupString()
315 not interpret it as Mode_switch; and interpreting it as both would
316 be totally wrong.
317 */
318 if (mode_bit)
319 {
320 CONST char *warn = 0;
321 if (mode_bit == meta_bit) warn = "Meta", meta_bit = 0;
322 else if (mode_bit == hyper_bit) warn = "Hyper", hyper_bit = 0;
323 else if (mode_bit == super_bit) warn = "Super", super_bit = 0;
324 else if (mode_bit == alt_bit) warn = "Alt", alt_bit = 0;
325 if (warn)
326 {
327 warn_when_safe
328 (Qkey_mapping, Qwarning,
329 "XEmacs: %s is being used for both Mode_switch and %s.",
330 index_to_name (mode_bit), warn),
331 warned_about_overlapping_modifiers = 1;
332 }
333 }
334 #undef index_to_name
335
336 xd->MetaMask = (meta_bit ? (1 << meta_bit) : 0);
337 xd->HyperMask = (hyper_bit ? (1 << hyper_bit) : 0);
338 xd->SuperMask = (super_bit ? (1 << super_bit) : 0);
339 xd->AltMask = (alt_bit ? (1 << alt_bit) : 0);
340 xd->ModeMask = (mode_bit ? (1 << mode_bit) : 0); /* unused */
341
342
343 if (warned_about_overlapping_modifiers)
344 warn_when_safe (Qkey_mapping, Qwarning, "\n"
345 " Two distinct modifier keys (such as Meta and Hyper) cannot generate\n"
346 " the same modifier bit, because Emacs won't be able to tell which\n"
347 " modifier was actually held down when some other key is pressed. It\n"
348 " won't be able to tell Meta-x and Hyper-x apart, for example. Change\n"
349 " one of these keys to use some other modifier bit. If you intend for\n"
350 " these keys to have the same behavior, then change them to have the\n"
351 " same keysym as well as the same modifier bit.");
352
353 if (warned_about_predefined_modifiers)
354 warn_when_safe (Qkey_mapping, Qwarning, "\n"
355 " The semantics of the modifier bits ModShift, ModLock, and ModControl\n"
356 " are predefined. It does not make sense to assign ModControl to any\n"
357 " keysym other than Control_L or Control_R, or to assign any modifier\n"
358 " bits to the \"control\" keysyms other than ModControl. You can't\n"
359 " turn a \"control\" key into a \"meta\" key (or vice versa) by simply\n"
360 " assigning the key a different modifier bit. You must also make that\n"
361 " key generate an appropriate keysym (Control_L, Meta_L, etc).");
362
363 /* Don\'t need to say anything more for warned_about_duplicate_modifiers. */
364
365 if (warned_about_overlapping_modifiers || warned_about_predefined_modifiers)
366 warn_when_safe (Qkey_mapping, Qwarning, "\n"
367 " The meanings of the modifier bits Mod1 through Mod5 are determined\n"
368 " by the keysyms used to control those bits. Mod1 does NOT always\n"
369 " mean Meta, although some non-ICCCM-compliant programs assume that.");
370 }
371
372 void
373 x_init_modifier_mapping (struct device *d)
374 {
375 DEVICE_X_DATA (d)->x_keysym_map = 0;
376 DEVICE_X_DATA (d)->x_modifier_keymap = 0;
377 x_reset_modifier_mapping (d);
378 }
379
380 static int
381 x_key_is_modifier_p (KeyCode keycode, struct device *d)
382 {
383 struct x_device *xd = DEVICE_X_DATA (d);
384 KeySym *syms = &xd->x_keysym_map [(keycode - xd->x_keysym_map_min_code) *
385 xd->x_keysym_map_keysyms_per_code];
386 int i;
387 for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++)
388 if (IsModifierKey (syms [i]) ||
389 syms [i] == XK_Mode_switch) /* why doesn't IsModifierKey count this? */
390 return 1;
391 return 0;
392 }
393
394 /* key-handling code is always ugly. It just ends up working out
395 that way.
396
397 Here are some pointers:
398
399 -- DOWN_MASK indicates which modifiers should be treated as "down"
400 when the corresponding upstroke happens. It gets reset for
401 a particular modifier when that modifier goes up, and reset
402 for all modifiers when a non-modifier key is pressed. Example:
403
404 I press Control-A-Shift and then release Control-A-Shift.
405 I want the Shift key to be sticky but not the Control key.
406
407 -- LAST_DOWNKEY and RELEASE_TIME are used to keep track of
408 auto-repeat -- see below.
409
410 -- If a modifier key is sticky, I can unstick it by pressing
411 the modifier key again. */
412
413 static void
414 x_handle_sticky_modifiers (XEvent *ev, struct device *d)
415 {
416 struct x_device *xd = DEVICE_X_DATA (d);
417 KeyCode keycode = ev->xkey.keycode;
418 int type = ev->xany.type;
419 int is_modifier =
420 (type == KeyPress || type == KeyRelease) &&
421 x_key_is_modifier_p (keycode, d);
422
423 if (!modifier_keys_are_sticky)
424 return;
425
426 if (!is_modifier)
427 {
428 if (type == KeyPress && !xd->last_downkey)
429 xd->last_downkey = keycode;
430 else if (type == ButtonPress ||
431 (type == KeyPress && xd->last_downkey &&
432 (keycode != xd->last_downkey ||
433 ev->xkey.time != xd->release_time)))
434 {
435 xd->need_to_add_mask = 0;
436 xd->last_downkey = 0;
437 }
438 if (type == KeyPress)
439 xd->release_time = 0;
440 if (type == KeyPress || type == ButtonPress)
441 xd->down_mask = 0;
442
443 ev->xkey.state |= xd->need_to_add_mask;
444
445 if (type == KeyRelease && keycode == xd->last_downkey)
446 /* If I hold press-and-release the Control key and then press
447 and hold down the right arrow, I want it to auto-repeat
448 Control-Right. On the other hand, if I do the same but
449 manually press the Right arrow a bunch of times, I want
450 to see one Control-Right and then a bunch of Rights.
451 This means that we need to distinguish between an
452 auto-repeated key and a key pressed and released a bunch
453 of times.
454
455 Naturally, the designers of the X spec didn't see fit
456 to provide an obvious way to distinguish these cases.
457 So we assume that if the release and the next press
458 occur at the same time, the key was actually auto-
459 repeated. Under Open-Windows, at least, this works.
460 */
461 xd->release_time = ev->xkey.time;
462 }
463 else
464 {
465 KeySym *syms = &xd->x_keysym_map [(keycode - xd->x_keysym_map_min_code) *
466 xd->x_keysym_map_keysyms_per_code];
467 int i;
468
469 #define FROB(mask) \
470 do { \
471 if (type == KeyPress) \
472 { \
473 /* If modifier key is already sticky, \
474 then unstick it. Note that we do \
475 not test down_mask to deal with the \
476 unlikely but possible case that the \
477 modifier key auto-repeats. */ \
478 if (xd->need_to_add_mask & mask) \
479 { \
480 xd->need_to_add_mask &= ~mask; \
481 xd->down_mask &= ~mask; \
482 } \
483 else \
484 xd->down_mask |= mask; \
485 } \
486 else \
487 { \
488 if (xd->down_mask & mask) \
489 { \
490 xd->down_mask &= ~mask; \
491 xd->need_to_add_mask |= mask; \
492 } \
493 } \
494 } while (0)
495
496 /* If a non-modifier key was pressed in the middle of a bunch
497 of modifiers, then it unsticks all the modifiers that were
498 previously pressed. We cannot unstick the modifiers until
499 now because we want to check for auto-repeat of the
500 non-modifier key. */
501
502 if (xd->last_downkey)
503 {
504 xd->last_downkey = 0;
505 xd->need_to_add_mask = 0;
506 }
507
508 for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++)
509 {
510 if (syms[i] == XK_Control_L || syms[i] == XK_Control_R)
511 FROB (ControlMask);
512 if (syms[i] == XK_Shift_L || syms[i] == XK_Shift_R)
513 FROB (ShiftMask);
514 if (syms[i] == XK_Meta_L || syms[i] == XK_Meta_R)
515 FROB (xd->MetaMask);
516 if (syms[i] == XK_Super_L || syms[i] == XK_Super_R)
517 FROB (xd->SuperMask);
518 if (syms[i] == XK_Hyper_L || syms[i] == XK_Hyper_R)
519 FROB (xd->HyperMask);
520 if (syms[i] == XK_Alt_L || syms[i] == XK_Alt_R)
521 FROB (xd->AltMask);
522 }
523 }
524 #undef FROB
525 }
526
527 static void
528 clear_sticky_modifiers (struct device *d)
529 {
530 struct x_device *xd = DEVICE_X_DATA (d);
531
532 xd->need_to_add_mask = 0;
533 xd->last_downkey = 0;
534 xd->release_time = 0;
535 xd->down_mask = 0;
536 }
537
538 static int
539 keysym_obeys_caps_lock_p (KeySym sym, struct device *d)
540 {
541 struct x_device *xd = DEVICE_X_DATA (d);
542 /* Eeeeevil hack. Don't apply caps-lock to things that aren't alphabetic
543 characters, where "alphabetic" means something more than simply A-Z.
544 That is, if caps-lock is down, typing ESC doesn't produce Shift-ESC.
545 But if shift-lock is down, then it does.
546 */
547 if (xd->lock_interpretation == XK_Shift_Lock)
548 return 1;
549 if (((sym >= XK_A) && (sym <= XK_Z)) ||
550 ((sym >= XK_a) && (sym <= XK_z)) ||
551 ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) ||
552 ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) ||
553 ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) ||
554 ((sym >= XK_oslash) && (sym <= XK_thorn)))
555 return 1;
556 else
557 return 0;
558 }
559
560 /* called from EmacsFrame.c (actually from Xt itself) when a
561 MappingNotify event is received. For non-obvious reasons,
562 our event handler does not see these events, so we need a
563 special translation. */
564 void
565 emacs_Xt_mapping_action (Widget w, XEvent* event)
566 {
567 struct device *d = get_device_from_display (event->xany.display);
568 #if 0
569 /* nyet. Now this is handled by Xt. */
570 XRefreshKeyboardMapping (&event->xmapping);
571 #endif
572 /* xmodmap generates about a billion MappingKeyboard events, followed
573 by a single MappingModifier event, so it might be worthwhile to
574 take extra MappingKeyboard events out of the queue before requesting
575 the current keymap from the server.
576 */
577 if (event->xmapping.request == MappingKeyboard)
578 x_reset_key_mapping (d);
579 else if (event->xmapping.request == MappingModifier)
580 x_reset_modifier_mapping (d);
581 }
582
583
584 /************************************************************************/
585 /* X to Emacs event conversion */
586 /************************************************************************/
587
588 #if (defined(sun) || defined(__sun)) && defined(__GNUC__)
589 # define SUNOS_GCC_L0_BUG
590 #endif
591
592 #ifdef SUNOS_GCC_L0_BUG
593 static void
594 x_to_emacs_keysym_sunos_bug (Lisp_Object *return_value_sunos_bug, /* #### */
595 XEvent *event, int simple_p)
596 #else /* !SUNOS_GCC_L0_BUG */
597 static Lisp_Object
598 x_to_emacs_keysym (XEvent *event, int simple_p)
599 #endif /* !SUNOS_GCC_L0_BUG */
600 /* simple_p means don't try too hard (ASCII only) */
601 {
602 char *name;
603 KeySym keysym = 0;
604 struct device *d = get_device_from_display (event->xany.display);
605 /* Apparently it's necessary to specify a dummy here (rather than
606 passing in 0) to avoid crashes on German IRIX */
607 char dummy[256];
608
609 #ifdef SUNOS_GCC_L0_BUG
610 # define return(lose) \
611 do {*return_value_sunos_bug = (lose); goto return_it; } while (0)
612 #endif
613
614 /* ### FIX this by replacing with calls to XmbLookupString.
615 XLookupString should never be called. --mrb */
616 XLookupString (&event->xkey, dummy, 200, &keysym, 0);
617
618 /* &DEVICE_X_X_COMPOSE_STATUS (d)); */
619
620 if (keysym >= XK_exclam && keysym <= XK_asciitilde)
621 /* We must assume that the X keysym numbers for the ASCII graphic
622 characters are the same as their ASCII codes. */
623 return (make_char (keysym));
624
625 switch (keysym)
626 {
627 /* These would be handled correctly by the default case, but by
628 special-casing them here we don't garbage a string or call intern().
629 */
630 case XK_BackSpace: return (QKbackspace);
631 case XK_Tab: return (QKtab);
632 case XK_Linefeed: return (QKlinefeed);
633 case XK_Return: return (QKreturn);
634 case XK_Escape: return (QKescape);
635 case XK_space: return (QKspace);
636 case XK_Delete: return (QKdelete);
637 case 0: return (Qnil);
638 /* This kludge prevents bogus Xlib compose conversions.
639 Don't ask why. The following case must be removed when we
640 switch to using XmbLookupString */
641 case XK_Multi_key: XLookupString (&event->xkey, dummy, 200, &keysym, 0);
642 /* Fallthrough!! */
643 default:
644 if (simple_p) return (Qnil);
645 /* #### without return_value_sunos_bug, %l0 (GCC struct return pointer)
646 * #### gets roached (top 8 bits cleared) around this call.
647 */
648 /* !!#### not Mule-ized */
649 name = XKeysymToString (keysym);
650 if (!name || !name[0]) /* this shouldn't happen... */
651 {
652 char buf [255];
653 sprintf (buf, "unknown_keysym_0x%X", (int) keysym);
654 return (KEYSYM (buf));
655 }
656 /* If it's got a one-character name, that's good enough. */
657 if (!name[1]) return (make_char (name[0]));
658
659 /* If it's in the "Keyboard" character set, downcase it.
660 The case of those keysyms is too totally random for us to
661 force anyone to remember them.
662 The case of the other character sets is significant, however.
663 */
664 if ((((unsigned int) keysym) & (~0xFF)) == ((unsigned int) 0xFF00))
665 {
666 char buf [255];
667 char *s1, *s2;
668 for (s1 = name, s2 = buf; *s1; s1++, s2++)
669 *s2 = tolower (* (unsigned char *) s1);
670 *s2 = 0;
671 return (KEYSYM (buf));
672 }
673 return (KEYSYM (name));
674 }
675 #ifdef SUNOS_GCC_L0_BUG
676 # undef return
677 return_it:
678 return;
679 #endif
680 }
681
682 #ifdef SUNOS_GCC_L0_BUG
683 /* #### */
684 static Lisp_Object
685 x_to_emacs_keysym (XEvent *event, int simple_p)
686 {
687 Lisp_Object return_value_sunos_bug;
688 x_to_emacs_keysym_sunos_bug (&return_value_sunos_bug, event, simple_p);
689 return (return_value_sunos_bug);
690 }
691 #endif
692
693 static void
694 set_last_server_timestamp (struct device *d, XEvent *x_event)
695 {
696 switch (x_event->xany.type)
697 {
698 case KeyPress:
699 case KeyRelease:
700 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = x_event->xkey.time;
701 break;
702
703 case ButtonPress:
704 case ButtonRelease:
705 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = x_event->xbutton.time;
706 break;
707
708 case MotionNotify:
709 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = x_event->xmotion.time;
710 break;
711
712 case EnterNotify:
713 case LeaveNotify:
714 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = x_event->xcrossing.time;
715 break;
716
717 case PropertyNotify:
718 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = x_event->xproperty.time;
719 break;
720
721 case SelectionClear:
722 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = x_event->xselectionclear.time;
723 break;
724
725 case SelectionRequest:
726 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = x_event->xselectionrequest.time;
727 break;
728
729 case SelectionNotify:
730 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = x_event->xselection.time;
731 break;
732 }
733 }
734
735 static int
736 x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
737 {
738 Display *display = x_event->xany.display;
739 struct device *d = get_device_from_display (display);
740 struct x_device *xd = DEVICE_X_DATA (d);
741
742 set_last_server_timestamp (d, x_event);
743
744 switch (x_event->xany.type)
745 {
746 case KeyRelease:
747 x_handle_sticky_modifiers (x_event, d);
748 return 0;
749
750 case KeyPress:
751 case ButtonPress:
752 case ButtonRelease:
753 {
754 unsigned int modifiers = 0;
755 int shift_p;
756 int lock_p;
757 #ifdef EXTERNAL_WIDGET
758 struct frame *f = x_any_window_to_frame (d, x_event->xany.window);
759 #endif
760
761 /* If this is a synthetic KeyPress or Button event, and the user
762 has expressed a disinterest in this security hole, then drop
763 it on the floor.
764 */
765 if (((x_event->xany.type == KeyPress)
766 ? x_event->xkey.send_event
767 : x_event->xbutton.send_event)
768 #ifdef EXTERNAL_WIDGET
769 /* ben: events get sent to an ExternalShell using XSendEvent.
770 This is not a perfect solution. */
771 && !FRAME_X_EXTERNAL_WINDOW_P (f)
772 #endif
773 && !x_allow_sendevents)
774 return 0;
775
776 x_handle_sticky_modifiers (x_event, d);
777
778 shift_p = x_event->xkey.state & ShiftMask;
779 lock_p = x_event->xkey.state & LockMask;
780
781 if (x_event->xany.type == KeyPress)
782 DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d) = x_event->xkey.time;
783 else
784 DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d) = x_event->xbutton.time;
785
786 /* Ignore the caps-lock key w.r.t. mouse presses and releases. */
787 if (x_event->xany.type != KeyPress)
788 lock_p = 0;
789
790 if (x_event->xkey.state & ControlMask) modifiers |= MOD_CONTROL;
791 if (x_event->xkey.state & xd->MetaMask) modifiers |= MOD_META;
792 if (x_event->xkey.state & xd->SuperMask) modifiers |= MOD_SUPER;
793 if (x_event->xkey.state & xd->HyperMask) modifiers |= MOD_HYPER;
794 if (x_event->xkey.state & xd->AltMask) modifiers |= MOD_ALT;
795
796 /* Ignore the caps-lock key if any other modifiers are down; this is
797 so that Caps doesn't turn C-x into C-X, which would suck. */
798 if (modifiers)
799 {
800 x_event->xkey.state &= (~LockMask);
801 lock_p = 0;
802 }
803
804 if (shift_p || lock_p)
805 modifiers |= MOD_SHIFT;
806
807 DEVICE_X_MOUSE_TIMESTAMP (d) = DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d);
808
809 switch (x_event->xany.type)
810 {
811 case KeyPress:
812 {
813 Lisp_Object keysym;
814 KeyCode keycode = x_event->xkey.keycode;
815
816 if (x_key_is_modifier_p (keycode, d)) /* it's a modifier key */
817 return 0;
818
819 /* This used to compute the frame from the given X window
820 and store it here, but we really don't care about the
821 frame. */
822 emacs_event->channel = DEVICE_CONSOLE (d);
823 keysym = x_to_emacs_keysym (x_event, 0);
824
825 /* If the emacs keysym is nil, then that means that the
826 X keysym was NoSymbol, which probably means that
827 we're in the midst of reading a Multi_key sequence,
828 or a "dead" key prefix. Ignore it. */
829 if (NILP (keysym))
830 return 0;
831
832 /* More caps-lock garbage: caps-lock should *only* add
833 the shift modifier to two-case keys (that is, A-Z and
834 related characters). So at this point (after looking
835 up the keysym) if the keysym isn't a dual-case
836 alphabetic, and if the caps lock key was down but the
837 shift key wasn't, then turn off the shift modifier.
838 Gag barf retch. */
839 /* #### type lossage: assuming equivalence of emacs and
840 X keysyms */
841 /* !!#### maybe fix for Mule */
842 if (! (CHAR_OR_CHAR_INTP (keysym)
843 && keysym_obeys_caps_lock_p
844 ((KeySym) XCHAR_OR_CHAR_INT (keysym), d))
845 && lock_p
846 && !shift_p)
847 modifiers &= (~MOD_SHIFT);
848
849 /* If this key contains two distinct keysyms, that is,
850 "shift" generates a different keysym than the
851 non-shifted key, then don't apply the shift modifier
852 bit: it's implicit. Otherwise, if there would be no
853 other way to tell the difference between the shifted
854 and unshifted version of this key, apply the shift
855 bit. Non-graphics, like Backspace and F1 get the
856 shift bit in the modifiers slot. Neither the
857 characters "a", "A", "2", nor "@" normally have the
858 shift bit set. However, "F1" normally does. */
859 if (modifiers & MOD_SHIFT)
860 {
861 KeySym top, bot;
862 if (x_event->xkey.state & xd->ModeMask)
863 bot = XLookupKeysym (&x_event->xkey, 2),
864 top = XLookupKeysym (&x_event->xkey, 3);
865 else
866 bot = XLookupKeysym (&x_event->xkey, 0),
867 top = XLookupKeysym (&x_event->xkey, 1);
868 if (top && bot && top != bot)
869 modifiers &= ~MOD_SHIFT;
870 }
871 emacs_event->event_type = key_press_event;
872 emacs_event->timestamp = x_event->xkey.time;
873 emacs_event->event.key.modifiers = modifiers;
874 emacs_event->event.key.keysym = keysym;
875 break;
876 }
877 case ButtonPress:
878 case ButtonRelease:
879 {
880 struct frame *frame =
881 x_window_to_frame (d, x_event->xbutton.window);
882 if (! frame)
883 return 0; /* not for us */
884 XSETFRAME (emacs_event->channel, frame);
885 }
886
887 if (x_event->type == ButtonPress)
888 emacs_event->event_type = button_press_event;
889 else emacs_event->event_type = button_release_event;
890 emacs_event->timestamp = x_event->xbutton.time;
891 emacs_event->event.button.modifiers = modifiers;
892 emacs_event->event.button.button = x_event->xbutton.button;
893 emacs_event->event.button.x = x_event->xbutton.x;
894 emacs_event->event.button.y = x_event->xbutton.y;
895 break;
896 }
897 }
898 break;
899
900 case MotionNotify:
901 {
902 Window w = x_event->xmotion.window;
903 struct frame *frame = x_window_to_frame (d, w);
904 XEvent event2;
905
906 if (! frame)
907 return 0; /* not for us */
908
909 /* We use MotionHintMask, so we will get only one motion event
910 until the next time we call XQueryPointer or the user clicks
911 the mouse. So call XQueryPointer now (meaning that the event
912 will be in sync with the server just before Fnext_event()
913 returns). If the mouse is still in motion, then the server
914 will immediately generate exactly one more motion event, which
915 will be on the queue waiting for us next time around.
916 */
917 event2 = *x_event;
918 if (XQueryPointer (x_event->xmotion.display, event2.xmotion.window,
919 &event2.xmotion.root, &event2.xmotion.subwindow,
920 &event2.xmotion.x_root, &event2.xmotion.y_root,
921 &event2.xmotion.x, &event2.xmotion.y,
922 &event2.xmotion.state))
923 *x_event = event2;
924
925 DEVICE_X_MOUSE_TIMESTAMP (d) = x_event->xmotion.time;
926
927 XSETFRAME (emacs_event->channel, frame);
928 emacs_event->event_type = pointer_motion_event;
929 emacs_event->timestamp = x_event->xmotion.time;
930 emacs_event->event.motion.x = x_event->xmotion.x;
931 emacs_event->event.motion.y = x_event->xmotion.y;
932 {
933 unsigned int modifiers = 0;
934 if (x_event->xmotion.state & ShiftMask) modifiers |= MOD_SHIFT;
935 if (x_event->xmotion.state & ControlMask) modifiers |= MOD_CONTROL;
936 if (x_event->xmotion.state & xd->MetaMask) modifiers |= MOD_META;
937 if (x_event->xmotion.state & xd->SuperMask) modifiers |= MOD_SUPER;
938 if (x_event->xmotion.state & xd->HyperMask) modifiers |= MOD_HYPER;
939 if (x_event->xmotion.state & xd->AltMask) modifiers |= MOD_ALT;
940 /* Currently ignores Shift_Lock but probably shouldn't
941 (but it definitely should ignore Caps_Lock). */
942 emacs_event->event.motion.modifiers = modifiers;
943 }
944 }
945 break;
946
947 case ClientMessage:
948 /* Patch bogus TAKE_FOCUS messages from MWM; CurrentTime is passed as the
949 timestamp of the TAKE_FOCUS, which the ICCCM explicitly prohibits. */
950 if (x_event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS (d)
951 && x_event->xclient.data.l[0] == DEVICE_XATOM_WM_TAKE_FOCUS (d)
952 && x_event->xclient.data.l[1] == 0)
953 {
954 x_event->xclient.data.l[1] = DEVICE_X_LAST_SERVER_TIMESTAMP (d);
955 }
956 /* fall through */
957
958 default: /* it's a magic event */
959 {
960 struct frame *f;
961
962 switch (x_event->type)
963 {
964 /* Note: the number of cases could be reduced to two or
965 three by using xany.window, but it's perhaps clearer
966 and potentially more robust this way */
967 case SelectionRequest:
968 f = x_window_to_frame (d, x_event->xselectionrequest.owner);
969 break;
970
971 case SelectionClear:
972 f = x_window_to_frame (d, x_event->xselectionclear.window);
973 break;
974
975 case SelectionNotify:
976 f = x_window_to_frame (d, x_event->xselection.requestor);
977 break;
978
979 case PropertyNotify:
980 f = x_window_to_frame (d, x_event->xproperty.window);
981 break;
982
983 case Expose:
984 case GraphicsExpose:
985 f = x_window_to_frame (d, x_event->xexpose.window);
986 break;
987
988 case MapNotify:
989 case UnmapNotify:
990 f = x_any_window_to_frame (d, x_event->xmap.window);
991 break;
992
993 case EnterNotify:
994 case LeaveNotify:
995 f = x_any_window_to_frame (d, x_event->xcrossing.window);
996 break;
997
998 case FocusIn:
999 case FocusOut:
1000 /* It's curious that we're using x_any_window_to_frame()
1001 here. I don't know if this causes problems. */
1002 f = x_any_window_to_frame (d, x_event->xfocus.window);
1003
1004 case ClientMessage:
1005 f = x_any_window_to_frame (d, x_event->xclient.window);
1006 break;
1007
1008 case MappingNotify:
1009 case VisibilityNotify:
1010 f = x_any_window_to_frame (d, x_event->xvisibility.window);
1011 break;
1012
1013 case ConfigureNotify:
1014 f = x_any_window_to_frame (d, x_event->xconfigure.window);
1015 break;
1016
1017 default:
1018 f = x_any_window_to_frame (d, x_event->xany.window);
1019 break;
1020 }
1021
1022 if (!f)
1023 return 0;
1024
1025 emacs_event->event_type = magic_event;
1026 XSETFRAME (emacs_event->channel, f);
1027 memcpy ((char *) &emacs_event->event.magic.underlying_x_event,
1028 (char *) x_event,
1029 sizeof (XEvent));
1030 break;
1031 }
1032 }
1033 return 1;
1034 }
1035
1036
1037 /************************************************************************/
1038 /* magic-event handling */
1039 /************************************************************************/
1040
1041 static void
1042 handle_focus_event_1 (struct frame *f, int in_p)
1043 {
1044 /* On focus change, clear all memory of sticky modifiers
1045 to avoid non-intuitive behavior. */
1046 clear_sticky_modifiers (XDEVICE (FRAME_DEVICE (f)));
1047
1048 /* We don't want to handle the focus change now, because we might
1049 be in an accept-process-output, sleep-for, or sit-for. So
1050 we enqueue it.
1051
1052 Actually, we half handle it: we handle it as far as changing the
1053 box cursor for redisplay, but we don't call any hooks or do any
1054 select-frame stuff until after the sit-for.
1055 */
1056 {
1057 Lisp_Object frm;
1058 Lisp_Object conser;
1059 struct gcpro gcpro1;
1060
1061 XSETFRAME (frm, f);
1062 conser = Fcons (frm, Fcons (FRAME_DEVICE (f), in_p ? Qt : Qnil));
1063 GCPRO1 (conser);
1064 emacs_handle_focus_change_preliminary (conser);
1065 enqueue_magic_eval_event (emacs_handle_focus_change_final,
1066 conser);
1067 UNGCPRO;
1068 }
1069 }
1070
1071 /* This is called from the external-widget code */
1072
1073 void emacs_Xt_handle_focus_event (XEvent *event);
1074 void
1075 emacs_Xt_handle_focus_event (XEvent *event)
1076 {
1077 /*
1078 * It's curious that we're using x_any_window_to_frame() instead
1079 * of x_window_to_frame(). I don't know what the impact of this is.
1080 */
1081
1082 struct frame *f =
1083 x_any_window_to_frame (get_device_from_display (event->xany.display),
1084 event->xfocus.window);
1085 if (!f)
1086 /* focus events are sometimes generated just before
1087 a frame is destroyed. */
1088 return;
1089 handle_focus_event_1 (f, event->xany.type == FocusIn);
1090 }
1091
1092 static void
1093 handle_map_event (struct frame *f, XEvent *event)
1094 {
1095 Lisp_Object frame = Qnil;
1096
1097 XSETFRAME (frame, f);
1098 if (event->xany.type == MapNotify)
1099 {
1100 XWindowAttributes xwa;
1101
1102 /* Bleagh!!!!!! Apparently some window managers (e.g. MWM)
1103 send synthetic MapNotify events when a window is first
1104 created, EVENT IF IT'S CREATED ICONIFIED OR INVISIBLE.
1105 Or something like that. We initially tried a different
1106 solution below, but that ran into a different window-
1107 manager bug.
1108
1109 It seems that the only reliable way is to treat a
1110 MapNotify event as a "hint" that the window might or
1111 might not be visible, and check explicitly. */
1112
1113 XGetWindowAttributes (event->xany.display, event->xmap.window,
1114 &xwa);
1115 if (xwa.map_state != IsViewable)
1116 {
1117 /* Calling Fframe_iconified_p is the only way we have to
1118 correctly update FRAME_ICONIFIED_P */
1119 Fframe_iconified_p (frame);
1120 return;
1121 }
1122
1123 FRAME_X_TOTALLY_VISIBLE_P (f) = 1;
1124 #if 0
1125 /* Bleagh again!!!! We initially tried the following hack
1126 around the MWM problem, but it turns out that TWM
1127 has a race condition when you un-iconify, where it maps
1128 the window and then tells the server that the window
1129 is un-iconified. Usually, XEmacs wakes up between
1130 those two occurrences, and thus thinks that un-iconified
1131 windows are still iconified.
1132
1133 Ah, the joys of X. */
1134
1135 /* By Emacs definition, a frame that is iconified is not
1136 visible. Marking a frame as visible will automatically cause
1137 frame-iconified-p to return nil, regardless of whether the
1138 frame is actually iconified. Therefore, we have to ignore
1139 MapNotify events on iconified frames. (It's not obvious
1140 to me why these are being sent, but it happens at startup
1141 with frames that are initially iconified; perhaps they are
1142 synthetic MapNotify events coming from the window manager.)
1143 Note that `frame-iconified-p' queries the server
1144 to determine whether the frame is currently iconified,
1145 rather than consulting some internal (and likely
1146 inaccurate) state flag. Therefore, ignoring the MapNotify
1147 is correct. */
1148 if (!f->visible && NILP (Fframe_iconified_p (frame)))
1149 #endif
1150 if (!f->visible)
1151 {
1152 f->visible = 1;
1153 /* This improves the double flicker when uniconifying a frame
1154 some. A lot of it is not showing a buffer which has changed
1155 while the frame was iconified. To fix it further requires
1156 the good 'ol double redisplay structure. */
1157 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
1158 va_run_hook_with_args (Qmap_frame_hook, 1, frame);
1159 #ifdef EPOCH
1160 dispatch_epoch_event (f, event, Qx_map);
1161 #endif
1162 }
1163 }
1164 else
1165 {
1166 FRAME_X_TOTALLY_VISIBLE_P (f) = 0;
1167 if (f->visible)
1168 {
1169 f->visible = 0;
1170 va_run_hook_with_args (Qunmap_frame_hook, 1, frame);
1171 #ifdef EPOCH
1172 dispatch_epoch_event (f, event, Qx_unmap);
1173 #endif
1174 }
1175
1176 /* Calling Fframe_iconified_p is the only way we have to
1177 correctly update FRAME_ICONIFIED_P */
1178 Fframe_iconified_p (frame);
1179 }
1180 }
1181
1182 static void
1183 handle_client_message (struct frame *f, XEvent *event)
1184 {
1185 struct device *d = XDEVICE (FRAME_DEVICE (f));
1186 Lisp_Object frame = Qnil;
1187
1188 XSETFRAME (frame, f);
1189
1190 if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS (d) &&
1191 event->xclient.data.l[0] == DEVICE_XATOM_WM_DELETE_WINDOW (d))
1192 {
1193 /* WM_DELETE_WINDOW is a misc-user event, but other ClientMessages,
1194 such as WM_TAKE_FOCUS, are eval events. That's because delete-window
1195 was probably executed with a mouse click, while the others could
1196 have been sent as a result of mouse motion or some other implicit
1197 action. (Call this a "heuristic"...) The reason for caring about
1198 this is so that clicking on the close-box will make emacs prompt
1199 using a dialog box instead of the minibuffer if there are unsaved
1200 buffers.
1201 */
1202 enqueue_misc_user_event (frame, Qeval,
1203 list3 (Qdelete_frame, frame, Qt));
1204 }
1205 else if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS (d) &&
1206 event->xclient.data.l[0] == DEVICE_XATOM_WM_TAKE_FOCUS (d))
1207 {
1208 handle_focus_event_1 (f, 1);
1209 #if 0
1210 /* If there is a dialog box up, focus on it.
1211
1212 #### Actually, we're raising it too, which is wrong. We should
1213 #### just focus on it, but lwlib doesn't currently give us an
1214 #### easy way to do that. This should be fixed.
1215 */
1216 unsigned long take_focus_timestamp = event->xclient.data.l[1];
1217 Widget widget = lw_raise_all_pop_up_widgets ();
1218 if (widget)
1219 {
1220 /* kludge: raise_all returns bottommost widget, but we really
1221 want the topmost. So just raise it for now. */
1222 XMapRaised (XtDisplay (widget), XtWindow (widget));
1223 /* Grab the focus with the timestamp of the TAKE_FOCUS. */
1224 XSetInputFocus (XtDisplay (widget), XtWindow (widget),
1225 RevertToParent, take_focus_timestamp);
1226 }
1227 #endif
1228 }
1229 #ifdef EPOCH
1230 dispatch_epoch_event (f, event, Qx_client_message);
1231 #endif
1232 }
1233
1234 static void
1235 emacs_Xt_handle_magic_event (struct Lisp_Event *emacs_event)
1236 {
1237 /* This function can GC */
1238 XEvent *event = (XEvent *) &emacs_event->event.magic.underlying_x_event;
1239 struct frame *f = XFRAME (EVENT_CHANNEL (emacs_event));
1240
1241 if (!FRAME_LIVE_P (f))
1242 return;
1243
1244 switch (event->type)
1245 {
1246 case SelectionRequest:
1247 x_handle_selection_request (&event->xselectionrequest);
1248 break;
1249
1250 case SelectionClear:
1251 x_handle_selection_clear (&event->xselectionclear);
1252 break;
1253
1254 case SelectionNotify:
1255 x_handle_selection_notify (&event->xselection);
1256 break;
1257
1258 case PropertyNotify:
1259 x_handle_property_notify (&event->xproperty);
1260 #ifdef EPOCH
1261 dispatch_epoch_event (f, event, Qx_property_change);
1262 #endif
1263 break;
1264
1265 case Expose:
1266 x_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y,
1267 event->xexpose.width, event->xexpose.height);
1268 break;
1269
1270 case GraphicsExpose: /* This occurs when an XCopyArea's source area was
1271 obscured or not available. */
1272 x_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y,
1273 event->xexpose.width, event->xexpose.height);
1274 break;
1275
1276 case MapNotify:
1277 case UnmapNotify:
1278 handle_map_event (f, event);
1279 break;
1280
1281 case EnterNotify:
1282 if (event->xcrossing.detail != NotifyInferior)
1283 {
1284 Lisp_Object frame;
1285
1286 XSETFRAME (frame, f);
1287 /* FRAME_X_MOUSE_P (f) = 1; */
1288 va_run_hook_with_args (Qmouse_enter_frame_hook, 1, frame);
1289 }
1290 break;
1291
1292 case LeaveNotify:
1293 if (event->xcrossing.detail != NotifyInferior)
1294 {
1295 Lisp_Object frame;
1296
1297 XSETFRAME (frame, f);
1298 /* FRAME_X_MOUSE_P (f) = 0; */
1299 va_run_hook_with_args (Qmouse_leave_frame_hook, 1, frame);
1300 }
1301 break;
1302
1303 case FocusIn:
1304 case FocusOut:
1305 #ifdef EXTERNAL_WIDGET
1306 /* External widget lossage: Ben said:
1307 YUCK. The only way to make focus changes work properly is to
1308 completely ignore all FocusIn/FocusOut events and depend only
1309 on notifications from the ExternalClient widget. */
1310 if (FRAME_X_EXTERNAL_WINDOW_P (f))
1311 break;
1312 #endif
1313 handle_focus_event_1 (f, event->xany.type == FocusIn);
1314 break;
1315
1316 case ClientMessage:
1317 handle_client_message (f, event);
1318 break;
1319
1320 #if 0
1321 /* this is where we ought to be handling this event, but
1322 we don't see it here. --ben */
1323 case MappingNotify: /* The user has run xmodmap */
1324 #endif
1325
1326 case VisibilityNotify: /* window visiblity has changed */
1327 if (event->xvisibility.state == VisibilityUnobscured)
1328 FRAME_X_TOTALLY_VISIBLE_P (f) = 1;
1329 else
1330 FRAME_X_TOTALLY_VISIBLE_P (f) = 0;
1331 break;
1332
1333 case ConfigureNotify:
1334 if (event->xconfigure.window != XtWindow (FRAME_X_SHELL_WIDGET (f)))
1335 break;
1336 FRAME_X_SHELL_WIDGET (f)->core.x = event->xconfigure.x;
1337 FRAME_X_SHELL_WIDGET (f)->core.y = event->xconfigure.y;
1338 break;
1339
1340 default:
1341 break;
1342 }
1343 }
1344
1345
1346 /************************************************************************/
1347 /* timeout events */
1348 /************************************************************************/
1349
1350 static int timeout_id_tick;
1351
1352 /* Xt interval id's might not fit into an int (they're pointers, as it
1353 happens), so we need to provide a conversion list. */
1354
1355 struct Xt_timeout
1356 {
1357 int id;
1358 XtIntervalId interval_id;
1359 struct Xt_timeout *next;
1360 } *pending_timeouts, *completed_timeouts;
1361
1362 struct Xt_timeout_blocktype
1363 {
1364 Blocktype_declare (struct Xt_timeout);
1365 } *the_Xt_timeout_blocktype;
1366
1367 /* called by XtAppNextEvent() */
1368 static void
1369 Xt_timeout_callback (XtPointer closure, XtIntervalId *id)
1370 {
1371 struct Xt_timeout *timeout = (struct Xt_timeout *) closure;
1372 struct Xt_timeout *t2 = pending_timeouts;
1373 /* Remove this one from the list of pending timeouts */
1374 if (t2 == timeout)
1375 pending_timeouts = pending_timeouts->next;
1376 else
1377 {
1378 while (t2->next && t2->next != timeout) t2 = t2->next;
1379 assert (t2->next);
1380 t2->next = t2->next->next;
1381 }
1382 /* Add this one to the list of completed timeouts */
1383 timeout->next = completed_timeouts;
1384 completed_timeouts = timeout;
1385 }
1386
1387 static int
1388 emacs_Xt_add_timeout (EMACS_TIME thyme)
1389 {
1390 struct Xt_timeout *timeout = Blocktype_alloc (the_Xt_timeout_blocktype);
1391 EMACS_TIME current_time;
1392 int milliseconds;
1393
1394 timeout->id = timeout_id_tick++;
1395 timeout->next = pending_timeouts;
1396 pending_timeouts = timeout;
1397 EMACS_GET_TIME (current_time);
1398 EMACS_SUB_TIME (thyme, thyme, current_time);
1399 milliseconds = EMACS_SECS (thyme) * 1000 +
1400 EMACS_USECS (thyme) / 1000;
1401 if (milliseconds < 1)
1402 milliseconds = 1;
1403 timeout->interval_id = XtAppAddTimeOut (Xt_app_con, milliseconds,
1404 Xt_timeout_callback,
1405 (XtPointer) timeout);
1406 return timeout->id;
1407 }
1408
1409 static void
1410 emacs_Xt_remove_timeout (int id)
1411 {
1412 struct Xt_timeout *timeout, *t2;
1413
1414 /* Find the timeout on the list of pending ones, if it's still there. */
1415 if (!pending_timeouts) return;
1416 if (id == pending_timeouts->id)
1417 {
1418 timeout = pending_timeouts;
1419 pending_timeouts = pending_timeouts->next;
1420 }
1421 else
1422 {
1423 t2 = pending_timeouts;
1424 while (t2->next && t2->next->id != id) t2 = t2->next;
1425 if (! t2->next) return;
1426 timeout = t2->next;
1427 t2->next = t2->next->next;
1428 }
1429
1430 /* At this point, we've found the thing on the list of pending timeouts,
1431 and removed it.
1432 */
1433
1434 XtRemoveTimeOut (timeout->interval_id);
1435 Blocktype_free (the_Xt_timeout_blocktype, timeout);
1436 }
1437
1438 static void
1439 Xt_timeout_to_emacs_event (struct Lisp_Event *emacs_event)
1440 {
1441 struct Xt_timeout *timeout = completed_timeouts;
1442 assert (timeout);
1443 completed_timeouts = completed_timeouts->next;
1444 emacs_event->event_type = timeout_event;
1445 /* timeout events have nil as channel */
1446 emacs_event->timestamp = 0; /* #### wrong!! */
1447 emacs_event->event.timeout.interval_id = timeout->id;
1448 Blocktype_free (the_Xt_timeout_blocktype, timeout);
1449 }
1450
1451
1452 /************************************************************************/
1453 /* process and tty events */
1454 /************************************************************************/
1455
1456 struct what_is_ready_closure
1457 {
1458 int fd;
1459 Lisp_Object what;
1460 XtInputId id;
1461 };
1462
1463 static Lisp_Object *filedesc_with_input;
1464 static struct what_is_ready_closure **filedesc_to_what_closure;
1465
1466 static void
1467 init_what_input_once (void)
1468 {
1469 int i;
1470
1471 filedesc_with_input = (Lisp_Object *)
1472 xmalloc (MAXDESC * sizeof (Lisp_Object));
1473 filedesc_to_what_closure = (struct what_is_ready_closure **)
1474 xmalloc (MAXDESC * sizeof (struct what_is_ready_closure *));
1475
1476 for (i = 0; i < MAXDESC; i++)
1477 {
1478 filedesc_to_what_closure[i] = 0;
1479 filedesc_with_input[i] = Qnil;
1480 }
1481
1482 process_events_occurred = 0;
1483 tty_events_occurred = 0;
1484 }
1485
1486 static void
1487 mark_what_as_being_ready (struct what_is_ready_closure *closure)
1488 {
1489 if (NILP (filedesc_with_input[closure->fd]))
1490 {
1491 SELECT_TYPE temp_mask;
1492 FD_ZERO (&temp_mask);
1493 FD_SET (closure->fd, &temp_mask);
1494 /* Check to make sure there's *really* input available.
1495 Sometimes things seem to get confused and this gets called
1496 for the tty fd when there's really only input available
1497 on some process's fd. (It will subsequently get called
1498 for that process's fd, so returning without setting any
1499 flags will take care of it.) To see the problem, uncomment
1500 the stderr_out below, turn NORMAL_QUIT_CHECK_TIMEOUT_MSECS
1501 down to 25, do sh -c 'xemacs -nw -q -f shell 2>/tmp/log'
1502 and press return repeatedly. (Seen under AIX & Linux.)
1503 -dkindred@cs.cmu.edu */
1504 if (!poll_fds_for_input (temp_mask))
1505 {
1506 #if 0
1507 stderr_out ("mark_what_as_being_ready: no input available (fd=%d)\n",
1508 closure->fd);
1509 #endif
1510 return;
1511 }
1512 filedesc_with_input[closure->fd] = closure->what;
1513 if (PROCESSP (closure->what))
1514 /* Don't increment this if the current process is already marked
1515 * as having input. */
1516 process_events_occurred++;
1517 else
1518 tty_events_occurred++;
1519 }
1520 }
1521
1522 static void
1523 Xt_what_callback (void *closure, int *source, XtInputId *id)
1524 {
1525 /* If closure is 0, then we got a fake event from a signal handler.
1526 The only purpose of this is to make XtAppProcessEvent() stop
1527 blocking. */
1528 if (closure)
1529 mark_what_as_being_ready ((struct what_is_ready_closure *) closure);
1530 else
1531 {
1532 fake_event_occurred++;
1533 drain_signal_event_pipe ();
1534 }
1535 }
1536
1537 static void
1538 select_filedesc (int fd, Lisp_Object what)
1539 {
1540 struct what_is_ready_closure *closure;
1541
1542 /* If somebody is trying to select something that's already selected
1543 for, then something went wrong. The generic routines ought to
1544 detect this and error before here. */
1545 assert (!filedesc_to_what_closure[fd]);
1546
1547 closure = (struct what_is_ready_closure *) xmalloc (sizeof (*closure));
1548 closure->fd = fd;
1549 closure->what = what;
1550 closure->id =
1551 XtAppAddInput (Xt_app_con, fd,
1552 (XtPointer) (XtInputReadMask /* | XtInputExceptMask */),
1553 Xt_what_callback, closure);
1554 filedesc_to_what_closure[fd] = closure;
1555 }
1556
1557 static void
1558 unselect_filedesc (int fd)
1559 {
1560 struct what_is_ready_closure *closure = filedesc_to_what_closure[fd];
1561
1562 assert (closure);
1563 if (!NILP (filedesc_with_input[fd]))
1564 {
1565 /* We are unselecting this process before we have drained the rest of
1566 the input from it, probably from status_notify() in the command loop.
1567 This can happen like so:
1568
1569 - We are waiting in XtAppNextEvent()
1570 - Process generates output
1571 - Process is marked as being ready
1572 - Process dies, SIGCHLD gets generated before we return (!?)
1573 It could happen I guess.
1574 - sigchld_handler() marks process as dead
1575 - Somehow we end up getting a new KeyPress event on the queue
1576 at the same time (I'm really so sure how that happens but I'm
1577 not sure it can't either so let's assume it can...).
1578 - Key events have priority so we return that instead of the proc.
1579 - Before dispatching the lisp key event we call status_notify()
1580 - Which deselects the process that SIGCHLD marked as dead.
1581
1582 Thus we never remove it from _with_input and turn it into a lisp
1583 event, so we need to do it here. But this does not mean that we're
1584 throwing away the last block of output - status_notify() has already
1585 taken care of running the proc filter or whatever.
1586 */
1587 filedesc_with_input[fd] = Qnil;
1588 if (PROCESSP (closure->what))
1589 {
1590 assert (process_events_occurred > 0);
1591 process_events_occurred--;
1592 }
1593 else
1594 {
1595 assert (tty_events_occurred > 0);
1596 tty_events_occurred--;
1597 }
1598 }
1599 XtRemoveInput (closure->id);
1600 xfree (closure);
1601 filedesc_to_what_closure[fd] = 0;
1602 }
1603
1604 static void
1605 emacs_Xt_select_process (struct Lisp_Process *p)
1606 {
1607 int infd;
1608 Lisp_Object process;
1609
1610 infd = event_stream_unixoid_select_process (p);
1611
1612 XSETPROCESS (process, p);
1613 select_filedesc (infd, process);
1614 }
1615
1616 static void
1617 emacs_Xt_unselect_process (struct Lisp_Process *p)
1618 {
1619 int infd;
1620
1621 infd = event_stream_unixoid_unselect_process (p);
1622
1623 unselect_filedesc (infd);
1624 }
1625
1626 /* This is called from GC when a process object is about to be freed.
1627 If we've still got pointers to it in this file, we're gonna lose hard.
1628 */
1629 void
1630 debug_process_finalization (struct Lisp_Process *p)
1631 {
1632 #if 0 /* #### */
1633 int i;
1634 int infd, outfd;
1635 get_process_file_descriptors (p, &infd, &outfd);
1636 /* if it still has fds, then it hasn't been killed yet. */
1637 assert (infd < 0);
1638 assert (outfd < 0);
1639 /* Better not still be in the "with input" table; we know it's got no fds. */
1640 for (i = 0; i < MAXDESC; i++)
1641 {
1642 Lisp_Object process = filedesc_fds_with_input [i];
1643 assert (!PROCESSP (process) || XPROCESS (process) != p);
1644 }
1645 #endif
1646 }
1647
1648 static void
1649 Xt_process_to_emacs_event (struct Lisp_Event *emacs_event)
1650 {
1651 int i;
1652 Lisp_Object process;
1653
1654 assert (process_events_occurred > 0);
1655 for (i = 0; i < MAXDESC; i++)
1656 {
1657 process = filedesc_with_input[i];
1658 if (PROCESSP (process))
1659 break;
1660 }
1661 assert (i < MAXDESC);
1662 filedesc_with_input[i] = Qnil;
1663 process_events_occurred--;
1664 /* process events have nil as channel */
1665 emacs_event->event_type = process_event;
1666 emacs_event->timestamp = 0; /* #### */
1667 emacs_event->event.process.process = process;
1668 }
1669
1670 static void
1671 emacs_Xt_select_console (struct console *con)
1672 {
1673 Lisp_Object console = Qnil;
1674 int infd;
1675
1676 if (CONSOLE_X_P (con))
1677 return; /* X consoles are automatically selected for when we
1678 initialize them in Xt */
1679 infd = event_stream_unixoid_select_console (con);
1680 XSETCONSOLE (console, con);
1681 select_filedesc (infd, console);
1682 }
1683
1684 static void
1685 emacs_Xt_unselect_console (struct console *con)
1686 {
1687 Lisp_Object console = Qnil;
1688 int infd;
1689
1690 if (CONSOLE_X_P (con))
1691 return; /* X consoles are automatically selected for when we
1692 initialize them in Xt */
1693 infd = event_stream_unixoid_unselect_console (con);
1694 XSETCONSOLE (console, con);
1695 unselect_filedesc (infd);
1696 }
1697
1698 /* read an event from a tty, if one is available. Returns non-zero
1699 if an event was available. Note that when this function is
1700 called, there should always be a tty marked as ready for input.
1701 However, the input condition might actually be EOF, so there
1702 may not really be any input available. (In this case,
1703 read_event_from_tty_or_stream_desc() will arrange for the TTY device
1704 to be deleted.) */
1705
1706 static int
1707 Xt_tty_to_emacs_event (struct Lisp_Event *emacs_event)
1708 {
1709 int i;
1710
1711 assert (tty_events_occurred > 0);
1712 for (i = 0; i < MAXDESC; i++)
1713 {
1714 Lisp_Object console = filedesc_with_input[i];
1715 if (CONSOLEP (console))
1716 {
1717 assert (tty_events_occurred > 0);
1718 tty_events_occurred--;
1719 filedesc_with_input[i] = Qnil;
1720 if (read_event_from_tty_or_stream_desc
1721 (emacs_event, XCONSOLE (console), i))
1722 return 1;
1723 }
1724 }
1725
1726 return 0;
1727 }
1728
1729
1730 /************************************************************************/
1731 /* debugging functions to decipher an event */
1732 /************************************************************************/
1733
1734 #ifdef DEBUG_XEMACS
1735 #include "xintrinsicp.h" /* only describe_event() needs this */
1736 #include <X11/Xproto.h> /* only describe_event() needs this */
1737
1738 static void
1739 describe_event_window (Window window, Display *display)
1740 {
1741 struct frame *f;
1742 Widget w;
1743 stderr_out (" window: 0x%x", (int) window);
1744 w = XtWindowToWidget (display, window);
1745 if (w)
1746 stderr_out (" %s", w->core.widget_class->core_class.class_name);
1747 f = x_any_window_to_frame (get_device_from_display (display), window);
1748 if (f) {
1749 char buf[500];
1750 sprintf (buf, " \"%s\"", string_data (XSTRING (f->name)));
1751 write_string_to_stdio_stream (stderr, 0, (Bufbyte *) buf, 0, strlen (buf),
1752 FORMAT_DISPLAY);
1753 }
1754 stderr_out ("\n");
1755 }
1756
1757 static CONST char *
1758 XEvent_mode_to_string (int mode)
1759 {
1760 switch (mode)
1761 {
1762 case NotifyNormal: return "Normal";
1763 case NotifyGrab: return "Grab";
1764 case NotifyUngrab: return "Ungrab";
1765 case NotifyWhileGrabbed: return "WhileGrabbed";
1766 default:
1767 return "???";
1768 }
1769 }
1770
1771 static CONST char *
1772 XEvent_detail_to_string (int detail)
1773 {
1774 switch (detail)
1775 {
1776 case NotifyAncestor: return "Ancestor";
1777 case NotifyInferior: return "Inferior";
1778 case NotifyNonlinear: return "Nonlinear";
1779 case NotifyNonlinearVirtual: return "NonlinearVirtual";
1780 case NotifyPointer: return "Pointer";
1781 case NotifyPointerRoot: return "PointerRoot";
1782 case NotifyDetailNone: return "DetailNone";
1783 default:
1784 return "???";
1785 }
1786 }
1787
1788 static CONST char *
1789 XEvent_visibility_to_string (int state)
1790 {
1791 switch (state)
1792 {
1793 case VisibilityFullyObscured: return "FullyObscured";
1794 case VisibilityPartiallyObscured: return "PartiallyObscured";
1795 case VisibilityUnobscured: return "Unobscured";
1796 default:
1797 return "???";
1798 }
1799 }
1800
1801 static void
1802 describe_event (XEvent *event)
1803 {
1804 char buf[100];
1805 struct device *d = get_device_from_display (event->xany.display);
1806
1807 sprintf (buf, "%s%s", x_event_name (event->type),
1808 event->xany.send_event ? " (send)" : "");
1809 stderr_out ("%-30s", buf);
1810 switch (event->type)
1811 {
1812 case FocusIn:
1813 case FocusOut:
1814 {
1815 XFocusChangeEvent *ev = &event->xfocus;
1816 describe_event_window (ev->window, ev->display);
1817 stderr_out (" mode: %s\n", XEvent_mode_to_string (ev->mode));
1818 stderr_out (" detail: %s\n", XEvent_detail_to_string(ev->detail));
1819 break;
1820 }
1821
1822 case KeyPress:
1823 {
1824 Lisp_Object keysym;
1825 XKeyEvent *ev = &event->xkey;
1826 unsigned int state = ev->state;
1827
1828 describe_event_window (ev->window, ev->display);
1829 stderr_out (" subwindow: %ld\n", ev->subwindow);
1830 stderr_out (" state: ");
1831 if (state & ShiftMask) stderr_out ("Shift ");
1832 if (state & LockMask) stderr_out ("Lock ");
1833 if (state & ControlMask) stderr_out ("Control ");
1834 if (state & Mod1Mask) stderr_out ("Mod1 ");
1835 if (state & Mod2Mask) stderr_out ("Mod2 ");
1836 if (state & Mod3Mask) stderr_out ("Mod3 ");
1837 if (state & Mod4Mask) stderr_out ("Mod4 ");
1838 if (state & Mod5Mask) stderr_out ("Mod5 ");
1839 #if 0 /* Apparently these don't exist? */
1840 if (state & MetaMask) stderr_out ("Meta ");
1841 if (state & SuperMask) stderr_out ("Super ");
1842 if (state & HyperMask) stderr_out ("Hyper ");
1843 if (state & AltMask) stderr_out ("Alt ");
1844 if (state & ModeMask) stderr_out ("Mode_switch ");
1845 #endif
1846
1847 if (! state)
1848 stderr_out ("vanilla\n");
1849 else
1850 stderr_out ("\n");
1851 if (x_key_is_modifier_p (ev->keycode, d))
1852 stderr_out (" Modifier key");
1853 stderr_out (" keycode: 0x%x\n", ev->keycode);
1854 keysym = x_to_emacs_keysym (event, 0);
1855 if (CHAR_OR_CHAR_INTP (keysym))
1856 {
1857 if (XCHAR_OR_CHAR_INT (keysym) > 32
1858 && XCHAR_OR_CHAR_INT (keysym) < 127)
1859 stderr_out (" keysym: %c\n", XCHAR_OR_CHAR_INT (keysym));
1860 else
1861 stderr_out (" keysym: %d\n", XCHAR_OR_CHAR_INT (keysym));
1862 }
1863 else
1864 stderr_out (" keysym: %s\n", string_data (XSYMBOL (keysym)->name));
1865 }
1866 break;
1867
1868 case Expose:
1869 if (x_debug_events > 1)
1870 {
1871 XExposeEvent *ev = &event->xexpose;
1872 describe_event_window (ev->window, ev->display);
1873 stderr_out (" region: %d %d %d %d\n", ev->x, ev->y,
1874 ev->width, ev->height);
1875 stderr_out (" count: %d\n", ev->count);
1876 }
1877 else
1878 stderr_out ("\n");
1879 break;
1880
1881 case GraphicsExpose:
1882 if (x_debug_events > 1)
1883 {
1884 XGraphicsExposeEvent *ev = &event->xgraphicsexpose;
1885 describe_event_window (ev->drawable, ev->display);
1886 stderr_out (" major: %s\n",
1887 (ev ->major_code == X_CopyArea ? "CopyArea" :
1888 (ev->major_code == X_CopyPlane ? "CopyPlane" : "?")));
1889 stderr_out (" region: %d %d %d %d\n", ev->x, ev->y,
1890 ev->width, ev->height);
1891 stderr_out (" count: %d\n", ev->count);
1892 }
1893 else
1894 stderr_out ("\n");
1895 break;
1896
1897 case EnterNotify:
1898 case LeaveNotify:
1899 if (x_debug_events > 1)
1900 {
1901 XCrossingEvent *ev = &event->xcrossing;
1902 describe_event_window (ev->window, ev->display);
1903 #if 0
1904 stderr_out(" subwindow: 0x%x\n", ev->subwindow);
1905 stderr_out(" pos: %d %d\n", ev->x, ev->y);
1906 stderr_out(" root pos: %d %d\n", ev->x_root, ev->y_root);
1907 #endif
1908 stderr_out(" mode: %s\n", XEvent_mode_to_string(ev->mode));
1909 stderr_out(" detail: %s\n", XEvent_detail_to_string(ev->detail));
1910 stderr_out(" focus: %d\n", ev->focus);
1911 #if 0
1912 stderr_out(" state: 0x%x\n", ev->state);
1913 #endif
1914 }
1915 else
1916 stderr_out("\n");
1917 break;
1918
1919 case ConfigureNotify:
1920 if (x_debug_events > 1)
1921 {
1922 XConfigureEvent *ev = &event->xconfigure;
1923 describe_event_window (ev->window, ev->display);
1924 stderr_out(" above: 0x%lx\n", ev->above);
1925 stderr_out(" size: %d %d %d %d\n", ev->x, ev->y,
1926 ev->width, ev->height);
1927 stderr_out(" redirect: %d\n", ev->override_redirect);
1928 }
1929 else
1930 stderr_out("\n");
1931 break;
1932
1933 case VisibilityNotify:
1934 if (x_debug_events > 1)
1935 {
1936 XVisibilityEvent *ev = &event->xvisibility;
1937 describe_event_window (ev->window, ev->display);
1938 stderr_out(" state: %s\n", XEvent_visibility_to_string(ev->state));
1939 }
1940 else
1941 stderr_out ("\n");
1942 break;
1943
1944 case ClientMessage:
1945 {
1946 XClientMessageEvent *ev = &event->xclient;
1947 char *name = XGetAtomName (ev->display, ev->message_type);
1948 stderr_out ("%s", name);
1949 if (!strcmp (name, "WM_PROTOCOLS")) {
1950 char *protname = XGetAtomName (ev->display, ev->data.l[0]);
1951 stderr_out ("(%s)", protname);
1952 XFree (protname);
1953 }
1954 XFree (name);
1955 stderr_out ("\n");
1956 break;
1957 }
1958
1959 default:
1960 stderr_out ("\n");
1961 break;
1962 }
1963
1964 fflush (stdout);
1965 }
1966
1967 #endif /* include describe_event definition */
1968
1969
1970 /************************************************************************/
1971 /* get the next event from Xt */
1972 /************************************************************************/
1973
1974 static Lisp_Object dispatch_event_queue, dispatch_event_queue_tail;
1975
1976 static void
1977 enqueue_Xt_dispatch_event (Lisp_Object event)
1978 {
1979 enqueue_event (event, &dispatch_event_queue, &dispatch_event_queue_tail);
1980 }
1981
1982 Lisp_Object
1983 dequeue_Xt_dispatch_event (void)
1984 {
1985 return dequeue_event (&dispatch_event_queue, &dispatch_event_queue_tail);
1986 }
1987
1988 /* This business exists because menu events "happen" when
1989 menubar_selection_callback() is called from somewhere deep
1990 within XtAppProcessEvent in emacs_Xt_next_event(). The
1991 callback needs to terminate the modal loop in that function
1992 or else it will continue waiting until another event is
1993 received.
1994
1995 Same business applies to scrollbar events. */
1996
1997 void
1998 signal_special_Xt_user_event (Lisp_Object channel, Lisp_Object function,
1999 Lisp_Object object)
2000 {
2001 Lisp_Object event;
2002
2003 event = Fmake_event ();
2004
2005 XEVENT (event)->event_type = misc_user_event;
2006 XEVENT (event)->channel = channel;
2007 XEVENT (event)->event.eval.function = function;
2008 XEVENT (event)->event.eval.object = object;
2009
2010 enqueue_Xt_dispatch_event (event);
2011 }
2012
2013 static void
2014 emacs_Xt_next_event (struct Lisp_Event *emacs_event)
2015 {
2016 we_didnt_get_an_event:
2017
2018 while (NILP (dispatch_event_queue) &&
2019 !completed_timeouts &&
2020 !fake_event_occurred &&
2021 !process_events_occurred &&
2022 !tty_events_occurred)
2023 {
2024
2025 /* Stupid logic in XtAppProcessEvent() dictates that, if process
2026 events and X events are both available, the process event gets
2027 taken first. This will cause an infinite loop if we're being
2028 called from Fdiscard_input().
2029 */
2030 if (XtAppPending (Xt_app_con) & XtIMXEvent)
2031 XtAppProcessEvent (Xt_app_con, XtIMXEvent);
2032 else
2033 {
2034 Lisp_Object devcons, concons;
2035
2036 /* We're about to block. Xt has a bug in it (big surprise,
2037 there) in that it blocks using select() and doesn't
2038 flush the Xlib output buffers (XNextEvent() does this
2039 automatically before blocking). So it's necessary
2040 for us to do this ourselves. If we don't do it, then
2041 display output may not be seen until the next time
2042 an X event is received. (This happens esp. with
2043 subprocess output that gets sent to a visible buffer.)
2044
2045 #### The above comment may not have any validity. */
2046
2047 DEVICE_LOOP_NO_BREAK (devcons, concons)
2048 {
2049 struct device *d;
2050 d = XDEVICE (XCAR (devcons));
2051
2052 if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d))
2053 /* emacs may be exiting */
2054 XFlush (DEVICE_X_DISPLAY (d));
2055 }
2056 XtAppProcessEvent (Xt_app_con, XtIMAll);
2057 }
2058 }
2059
2060 if (!NILP (dispatch_event_queue))
2061 {
2062 Lisp_Object event, event2;
2063 XSETEVENT (event2, emacs_event);
2064 event = dequeue_Xt_dispatch_event ();
2065 Fcopy_event (event, event2);
2066 Fdeallocate_event (event);
2067 }
2068 else if (tty_events_occurred)
2069 {
2070 if (!Xt_tty_to_emacs_event (emacs_event))
2071 goto we_didnt_get_an_event;
2072 }
2073 else if (completed_timeouts)
2074 Xt_timeout_to_emacs_event (emacs_event);
2075 else if (fake_event_occurred)
2076 {
2077 /* A dummy event, so that a cycle of the command loop will
2078 occur. */
2079 fake_event_occurred = 0;
2080 /* eval events have nil as channel */
2081 emacs_event->event_type = eval_event;
2082 emacs_event->event.eval.function = Qidentity;
2083 emacs_event->event.eval.object = Qnil;
2084 }
2085 else /* if (process_events_occurred) */
2086 Xt_process_to_emacs_event (emacs_event);
2087
2088 /* No need to call XFilterEvent; Xt does it for us */
2089 }
2090
2091 void
2092 emacs_Xt_event_handler (Widget wid /* unused */,
2093 XtPointer closure /* unused */,
2094 XEvent *event,
2095 Boolean *continue_to_dispatch /* unused */)
2096 {
2097 Lisp_Object emacs_event = Fmake_event ();
2098
2099 #ifdef DEBUG_XEMACS
2100 if (x_debug_events > 0)
2101 {
2102 describe_event (event);
2103 }
2104 #endif /* DEBUG_XEMACS */
2105 if (x_event_to_emacs_event (event, XEVENT (emacs_event)))
2106 enqueue_Xt_dispatch_event (emacs_event);
2107 else
2108 Fdeallocate_event (emacs_event);
2109 }
2110
2111
2112 /************************************************************************/
2113 /* input pending / C-g checking */
2114 /************************************************************************/
2115
2116 static Bool
2117 quit_char_predicate (Display *display, XEvent *event, XPointer data)
2118 {
2119 struct device *d = get_device_from_display (display);
2120 struct x_device *xd = DEVICE_X_DATA (d);
2121 char c, quit_char;
2122 Bool *critical = (Bool *) data;
2123 Lisp_Object keysym;
2124
2125 if (critical) *critical = False;
2126 if (event->type != KeyPress) return 0;
2127 if (! x_any_window_to_frame (d, event->xany.window)) return 0;
2128 if (event->xkey.state
2129 & (xd->MetaMask | xd->HyperMask | xd->SuperMask | xd->AltMask))
2130 return 0;
2131
2132 /* This duplicates some code that exists elsewhere, but it's relatively
2133 fast and doesn't cons.
2134 */
2135 keysym = x_to_emacs_keysym (event, 1);
2136 if (NILP (keysym)) return 0;
2137 if (CHAR_OR_CHAR_INTP (keysym))
2138 c = XCHAR_OR_CHAR_INT (keysym);
2139 /* Highly doubtful that these are the quit character, but... */
2140 else if (EQ (keysym, QKbackspace)) c = '\b';
2141 else if (EQ (keysym, QKtab)) c = '\t';
2142 else if (EQ (keysym, QKlinefeed)) c = '\n';
2143 else if (EQ (keysym, QKreturn)) c = '\r';
2144 else if (EQ (keysym, QKescape)) c = 27;
2145 else if (EQ (keysym, QKspace)) c = ' ';
2146 else if (EQ (keysym, QKdelete)) c = 127;
2147 else return 0;
2148
2149 if (event->xkey.state & xd->MetaMask) c |= 0x80;
2150 if ((event->xkey.state & ControlMask) && !(c >= 'A' && c <= 'Z'))
2151 c &= 0x1F; /* unshifted control characters */
2152 quit_char = CONSOLE_QUIT_CHAR (XCONSOLE (DEVICE_CONSOLE (d)));
2153 if (c == quit_char)
2154 return True;
2155 /* If we've got Control-Shift-G instead of Control-G, that means
2156 we have a critical_quit. Caps_Lock is its own modifier, so it
2157 won't cause ^G to act differently than before. */
2158 if (event->xkey.state & ControlMask) c &= 0x1F;
2159 if (c == quit_char)
2160 {
2161 if (critical) *critical = True;
2162 return True;
2163 }
2164 return False;
2165 }
2166
2167 /* This scans the X input queue for a KeyPress event that matches the
2168 quit character, and sets Vquit_flag. This is called from the
2169 QUIT macro to determine whether we should quit.
2170
2171 In a SIGIO world, this won't be called unless a SIGIO has happened
2172 since the last time we checked.
2173
2174 In a non-SIGIO world, this is called from emacs_Xt_event_pending_p
2175 (which is called from input_pending_p).
2176 */
2177 static void
2178 x_check_for_quit_char (Display *display)
2179 {
2180 XEvent event;
2181 int queued;
2182 Bool critical_quit = False;
2183 XEventsQueued (display, QueuedAfterReading);
2184 queued = XCheckIfEvent (display, &event,
2185 quit_char_predicate,
2186 (XtPointer)&critical_quit);
2187 if (queued)
2188 {
2189 Vquit_flag = (critical_quit ? Qcritical : Qt);
2190 /* don't put the event back onto the queue. Those functions that
2191 wanted to read a ^G directly have arranged to do this. */
2192 }
2193 }
2194
2195 static void
2196 check_for_tty_quit_char (struct device *d)
2197 {
2198 SELECT_TYPE temp_mask;
2199 int infd = DEVICE_INFD (d);
2200 struct console *con = XCONSOLE (DEVICE_CONSOLE (d));
2201 Emchar quit_char = CONSOLE_QUIT_CHAR (con);
2202
2203 FD_ZERO (&temp_mask);
2204 FD_SET (infd, &temp_mask);
2205
2206 while (1)
2207 {
2208 Lisp_Object event;
2209 Emchar the_char;
2210
2211 if (!poll_fds_for_input (temp_mask))
2212 return;
2213
2214 event = Fmake_event ();
2215 if (!read_event_from_tty_or_stream_desc (XEVENT (event), con, infd))
2216 /* EOF, or something ... */
2217 return;
2218 /* #### bogus. quit-char should be allowed to be any sort
2219 of event. */
2220 the_char = event_to_character (XEVENT (event), 1, 0, 0);
2221 if (the_char >= 0 && the_char == quit_char)
2222 {
2223 Vquit_flag = Qt;
2224 /* do not queue the C-g. See above. */
2225 return;
2226 }
2227
2228 /* queue the read event to be read for real later. */
2229 enqueue_Xt_dispatch_event (event);
2230 }
2231 }
2232
2233 static void
2234 emacs_Xt_quit_p (void)
2235 {
2236 Lisp_Object devcons, concons;
2237 CONSOLE_LOOP (concons)
2238 {
2239 struct console *con = XCONSOLE (XCAR (concons));
2240 if (!con->input_enabled)
2241 continue;
2242
2243 CONSOLE_DEVICE_LOOP (devcons, con)
2244 {
2245 struct device *d;
2246 d = XDEVICE (XCAR (devcons));
2247
2248 if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d))
2249 /* emacs may be exiting */
2250 x_check_for_quit_char (DEVICE_X_DISPLAY (d));
2251 else if (DEVICE_TTY_P (d))
2252 check_for_tty_quit_char (d);
2253 }
2254 }
2255 }
2256
2257 static void
2258 drain_X_queue (void)
2259 {
2260 while (XtAppPending (Xt_app_con) & XtIMXEvent)
2261 XtAppProcessEvent (Xt_app_con, XtIMXEvent);
2262 }
2263
2264 static int
2265 emacs_Xt_event_pending_p (int user_p)
2266 {
2267 Lisp_Object event;
2268 int tick_count_val;
2269
2270 /* If `user_p' is false, then this function returns whether there are any
2271 X, timeout, or fd events pending (that is, whether emacs_Xt_next_event()
2272 would return immediately without blocking).
2273
2274 if `user_p' is true, then this function returns whether there are any
2275 *user generated* events available (that is, whether there are keyboard
2276 or mouse-click events ready to be read). This also implies that
2277 emacs_Xt_next_event() would not block.
2278
2279 In a non-SIGIO world, this also checks whether the user has typed ^G,
2280 since this is a convenient place to do so. We don't need to do this
2281 in a SIGIO world, since input causes an interrupt.
2282 */
2283
2284 #if 0
2285 /* I don't think there's any point to this and it will nullify
2286 the speed gains achieved by the sigio_happened checking below.
2287 Its only advantage is that it may possibly make C-g response
2288 a bit faster. The C-g will be noticed within 0.25 second, anyway,
2289 even without this. */
2290 #ifndef SIGIO
2291 /* First check for C-g if necessary */
2292 emacs_Xt_quit_p ();
2293 #endif
2294 #endif
2295
2296 /* This function used to simply check whether there were any X
2297 events (or is user_p was 1, it iterated over all the pending
2298 X events using XCheckIfEvent(), looking for keystrokes and
2299 button events). That worked in the old cheesoid event loop,
2300 which didn't go through XtAppDispatchEvent(), but it doesn't
2301 work any more -- X events may not result in anything. For
2302 example, a button press in a blank part of the menubar appears
2303 as an X event but will not result in any Emacs events (a
2304 button press that activates the menubar results in an Emacs
2305 event through the stop_next_event mechanism).
2306
2307 The only accurate way of determining whether these X events
2308 translate into Emacs events is to go ahead and dispatch them
2309 until there's something on the dispatch queue. */
2310
2311 /* See if there are any user events already on the queue. */
2312 EVENT_CHAIN_LOOP (event, dispatch_event_queue)
2313 if (!user_p || command_event_p (event))
2314 return 1;
2315
2316 /* See if there's any TTY input available.
2317 */
2318 if (poll_fds_for_input (tty_only_mask))
2319 return 1;
2320
2321 if (!user_p)
2322 {
2323 /* If not user_p and there are any timer or file-desc events
2324 pending, we know there will be an event so we're through. */
2325 XtInputMask pending_value;
2326
2327 /* Note that formerly we just checked the value of XtAppPending()
2328 to determine if there was file-desc input. This doesn't
2329 work any more with the signal_event_pipe; XtAppPending()
2330 will says "yes" in this case but there isn't really any
2331 input. Another way of fixing this problem is for the
2332 signal_event_pipe to generate actual input in the form
2333 of an identity eval event or something. (#### maybe this
2334 actually happens?) */
2335
2336 if (poll_fds_for_input (process_only_mask))
2337 return 1;
2338
2339 pending_value = XtAppPending (Xt_app_con);
2340
2341 if (pending_value & XtIMTimer)
2342 return 1;
2343 }
2344
2345 /* XtAppPending() can be super-slow, esp. over a network connection.
2346 Quantify results have indicated that in some cases the
2347 call to detect_input_pending() completely dominates the
2348 running time of redisplay(). Fortunately, in a SIGIO world
2349 we can more quickly determine whether there are any X events:
2350 if an event has happened since the last time we checked, then
2351 a SIGIO will have happened. On a machine with broken SIGIO,
2352 we'll still be in an OK state -- the sigio_happened flag
2353 will get set at least once a second, so we'll be no more than
2354 one second behind reality. (In general it's OK if we
2355 erroneously report no input pending when input is actually
2356 pending() -- preemption is just a bit less efficient, that's
2357 all. It's bad bad bad if you err the other way -- you've
2358 promised that `next-event' won't block but it actually will,
2359 and some action might get delayed until the next time you
2360 hit a key.)
2361 */
2362
2363 /* quit_check_signal_tick_count is volatile so try to avoid race conditions
2364 by using a temporary variable */
2365 tick_count_val = quit_check_signal_tick_count;
2366 if (last_quit_check_signal_tick_count != tick_count_val)
2367 {
2368 last_quit_check_signal_tick_count = tick_count_val;
2369
2370 /* We need to drain the entire queue now -- if we only
2371 drain part of it, we may later on end up with events
2372 actually pending but detect_input_pending() returning
2373 false because there wasn't another SIGIO. */
2374 drain_X_queue ();
2375
2376 EVENT_CHAIN_LOOP (event, dispatch_event_queue)
2377 if (!user_p || command_event_p (event))
2378 return 1;
2379 }
2380
2381 return 0;
2382 }
2383
2384
2385 /************************************************************************/
2386 /* replacement for standard string-to-pixel converter */
2387 /************************************************************************/
2388
2389 /* This was constructed by ripping off the standard string-to-pixel
2390 converter from Converters.c in the Xt source code and modifying
2391 appropriately. */
2392
2393 #if 0
2394
2395 /* This is exported by the Xt library (at least by mine). If this
2396 isn't the case somewhere, rename this appropriately and remove
2397 the '#if 0'. Note, however, that I got "unknown structure"
2398 errors when I tried this. */
2399 XtConvertArgRec Const colorConvertArgs[] = {
2400 {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
2401 sizeof(Screen *)},
2402 {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
2403 sizeof(Colormap)}
2404 };
2405
2406 #endif
2407
2408 #define done(type, value) \
2409 if (toVal->addr != NULL) { \
2410 if (toVal->size < sizeof(type)) { \
2411 toVal->size = sizeof(type); \
2412 return False; \
2413 } \
2414 *(type*)(toVal->addr) = (value); \
2415 } else { \
2416 static type static_val; \
2417 static_val = (value); \
2418 toVal->addr = (XPointer)&static_val; \
2419 } \
2420 toVal->size = sizeof(type); \
2421 return True /* Caller supplies `;' */
2422
2423 static
2424 Boolean EmacsXtCvtStringToPixel (
2425 Display *dpy,
2426 XrmValuePtr args,
2427 Cardinal *num_args,
2428 XrmValuePtr fromVal,
2429 XrmValuePtr toVal,
2430 XtPointer *closure_ret)
2431 {
2432 String str = (String)fromVal->addr;
2433 XColor screenColor;
2434 XColor exactColor;
2435 Screen *screen;
2436 Colormap colormap;
2437 Status status;
2438 String params[1];
2439 Cardinal num_params = 1;
2440 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
2441
2442 if (*num_args != 2) {
2443 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToPixel",
2444 "XtToolkitError",
2445 "String to pixel conversion needs screen and colormap arguments",
2446 (String *)NULL, (Cardinal *)NULL);
2447 return False;
2448 }
2449
2450 screen = *((Screen **) args[0].addr);
2451 colormap = *((Colormap *) args[1].addr);
2452
2453 /* The original uses the private function CompareISOLatin1().
2454 Use XmuCompareISOLatin1() if you want, but I don't think it
2455 makes any difference here. */
2456 if (strcmp(str, XtDefaultBackground) == 0) {
2457 *closure_ret = False;
2458 /* This refers to the display's "*reverseVideo" resource.
2459 These display resources aren't documented anywhere that
2460 I can find, so I'm going to ignore this. */
2461 /* if (pd->rv) done(Pixel, BlackPixelOfScreen(screen)) else */
2462 done(Pixel, WhitePixelOfScreen(screen));
2463 }
2464 if (strcmp(str, XtDefaultForeground) == 0) {
2465 *closure_ret = False;
2466 /* if (pd->rv) done(Pixel, WhitePixelOfScreen(screen)) else */
2467 done(Pixel, BlackPixelOfScreen(screen));
2468 }
2469
2470 /* Originally called XAllocNamedColor() here. */
2471 status = XParseColor (DisplayOfScreen(screen), colormap, (char*)str,
2472 &screenColor);
2473 if (status) {
2474 status = allocate_nearest_color (DisplayOfScreen(screen), colormap,
2475 &screenColor);
2476 }
2477
2478 if (status == 0) {
2479 params[0] = str;
2480 /* Server returns a specific error code but Xlib discards it. Ugh */
2481 if (XLookupColor(DisplayOfScreen(screen), colormap, (char*)str,
2482 &exactColor, &screenColor)) {
2483 XtAppWarningMsg(the_app_con, "noColormap", "cvtStringToPixel",
2484 "XtToolkitError",
2485 "Cannot allocate colormap entry for \"%s\"",
2486 params, &num_params);
2487
2488 } else {
2489 XtAppWarningMsg(the_app_con, "badValue", "cvtStringToPixel",
2490 "XtToolkitError",
2491 "Color name \"%s\" is not defined", params, &num_params);
2492 }
2493
2494 *closure_ret = False;
2495 return False;
2496 } else {
2497 *closure_ret = (char*)True;
2498 done(Pixel, screenColor.pixel);
2499 }
2500 }
2501
2502 /* ARGSUSED */
2503 static void EmacsFreePixel (
2504 XtAppContext app,
2505 XrmValuePtr toVal,
2506 XtPointer closure,
2507 XrmValuePtr args,
2508 Cardinal *num_args)
2509 {
2510 if (*num_args != 2) {
2511 XtAppWarningMsg(app, "wrongParameters","freePixel","XtToolkitError",
2512 "Freeing a pixel requires screen and colormap arguments",
2513 (String *)NULL, (Cardinal *)NULL);
2514 return;
2515 }
2516
2517 if (closure) {
2518 Screen *screen = *((Screen **) args[0].addr);
2519 Colormap colormap = *((Colormap *) args[1].addr);
2520 XFreeColors(DisplayOfScreen(screen), colormap,
2521 (unsigned long*)toVal->addr, 1, (unsigned long)0);
2522 }
2523 }
2524
2525
2526 /************************************************************************/
2527 /* initialization */
2528 /************************************************************************/
2529
2530 void
2531 syms_of_event_Xt (void)
2532 {
2533 defsymbol (&Qkey_mapping, "key-mapping");
2534 }
2535
2536 void
2537 vars_of_event_Xt (void)
2538 {
2539 dispatch_event_queue = Qnil;
2540 staticpro (&dispatch_event_queue);
2541 dispatch_event_queue_tail = Qnil;
2542
2543 /* this function only makes safe calls */
2544 init_what_input_once ();
2545
2546 Xt_event_stream =
2547 (struct event_stream *) xmalloc (sizeof (struct event_stream));
2548 Xt_event_stream->event_pending_p = emacs_Xt_event_pending_p;
2549 Xt_event_stream->next_event_cb = emacs_Xt_next_event;
2550 Xt_event_stream->handle_magic_event_cb= emacs_Xt_handle_magic_event;
2551 Xt_event_stream->add_timeout_cb = emacs_Xt_add_timeout;
2552 Xt_event_stream->remove_timeout_cb = emacs_Xt_remove_timeout;
2553 Xt_event_stream->select_console_cb = emacs_Xt_select_console;
2554 Xt_event_stream->unselect_console_cb = emacs_Xt_unselect_console;
2555 Xt_event_stream->select_process_cb = emacs_Xt_select_process;
2556 Xt_event_stream->unselect_process_cb = emacs_Xt_unselect_process;
2557 Xt_event_stream->quit_p_cb = emacs_Xt_quit_p;
2558
2559 DEFVAR_BOOL ("modifier-keys-are-sticky", &modifier_keys_are_sticky /*
2560 *Non-nil makes modifier keys sticky.
2561 This means that you can release the modifier key before pressing down
2562 the key that you wish to be modified. Although this is non-standard
2563 behavior, it is recommended because it reduces the strain on your hand,
2564 thus reducing the incidence of the dreaded Emacs-pinky syndrome.
2565 */ );
2566 modifier_keys_are_sticky = 0;
2567
2568 DEFVAR_BOOL ("x-allow-sendevents", &x_allow_sendevents /*
2569 *Non-nil means to allow synthetic events. Nil means they are ignored.
2570 Beware: allowing emacs to process SendEvents opens a big security hole.
2571 */ );
2572 x_allow_sendevents = 0;
2573
2574 #ifdef DEBUG_XEMACS
2575 DEFVAR_INT ("x-debug-events", &x_debug_events /*
2576 If non-zero, display debug information about X events that XEmacs sees.
2577 Information is displayed on stderr. Currently defined values are:
2578
2579 1 == non-verbose output
2580 2 == verbose output
2581 */ );
2582 x_debug_events = 0;
2583 #endif
2584
2585 the_Xt_timeout_blocktype = Blocktype_new (struct Xt_timeout_blocktype);
2586
2587 last_quit_check_signal_tick_count = 0;
2588 }
2589
2590 void
2591 init_event_Xt_late (void) /* called when already initialized */
2592 {
2593 timeout_id_tick = 1;
2594 pending_timeouts = 0;
2595 completed_timeouts = 0;
2596
2597 event_stream = Xt_event_stream;
2598 XtToolkitInitialize ();
2599 Xt_app_con = XtCreateApplicationContext ();
2600 XtAppSetFallbackResources (Xt_app_con, (String *) x_fallback_resources);
2601
2602 /* In xselect.c */
2603 x_selection_timeout = (XtAppGetSelectionTimeout (Xt_app_con) / 1000);
2604 XSetErrorHandler (x_error_handler);
2605 XSetIOErrorHandler (x_IO_error_handler);
2606
2607 XtAppAddInput (Xt_app_con, signal_event_pipe[0],
2608 (XtPointer) (XtInputReadMask /* | XtInputExceptMask */),
2609 Xt_what_callback, 0);
2610
2611 XtAppSetTypeConverter (Xt_app_con, XtRString, XtRPixel,
2612 EmacsXtCvtStringToPixel,
2613 (XtConvertArgList) colorConvertArgs,
2614 2, XtCacheByDisplay, EmacsFreePixel);
2615 }