1 /* The event_stream interface for X11 with Xt, and/or tty frames.
2 Copyright (C) 1991-5, 1997 Free Software Foundation, Inc.
3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 1996 Ben Wing.
6 This file is part of SXEmacs
8 SXEmacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 SXEmacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 /* Synched up with: Not in FSF. */
27 #include "console-x.h"
28 #include "ui/lwlib/lwlib.h"
29 #include "EmacsFrame.h"
31 #include "mem/blocktype.h"
33 #include "ui/console.h"
34 /* #include "ui/TTY/console-tty.h"
36 #define INCLUDE_EVENTS_H_PRIVATE_SPHERE
37 #include "events/events.h"
39 #include "objects-x.h"
41 #include "ui/redisplay.h"
45 #include "sysproc.h" /* for MAXDESC */
47 #include "xintrinsicp.h" /* CoreP.h needs this */
48 #include <X11/CoreP.h> /* Numerous places access the fields of
49 a core widget directly. We could
50 use XtGetValues(), but ... */
51 #include <X11/ShellP.h>
58 #include "mule/file-coding.h"
61 #include "events/events-mod.h"
63 #include "events/event-queue.h"
66 void enqueue_focus_event(Widget wants_it, Lisp_Object frame, int in_p);
67 static void handle_focus_event_1(struct frame *f, int in_p);
68 static void handle_focus_event_2(Window w, struct frame *f, int in_p);
70 static struct event_stream *Xt_event_stream;
72 /* With the new event model, all events go through XtDispatchEvent()
73 and are picked up by an event handler that is added to each frame
74 widget. (This is how it's supposed to be.) In the old method,
75 Emacs sucks out events directly from XtNextEvent() and only
76 dispatches the events that it doesn't need to deal with. This
77 old way has lots of corresponding junk that is no longer
78 necessary: lwlib extensions, synthetic XAnyEvents, unnecessary
81 /* The one and only one application context that Emacs uses. */
82 XtAppContext Xt_app_con;
84 /* Do we accept events sent by other clients? */
85 int x_allow_sendevents;
88 Fixnum debug_x_events;
91 static int process_events_occurred;
92 static int tty_events_occurred;
93 static Widget widget_with_focus;
95 /* Mask of bits indicating the descriptors that we wait for input on */
96 extern SELECT_TYPE input_wait_mask, process_only_mask, tty_only_mask;
98 static String x_fallback_resources[] = {
99 /* This file is automatically generated from the app-defaults file
100 in ../etc/Emacs.ad. These resources are consulted only if no
101 app-defaults file is found at all.
103 #include <ui/Emacs.ad.h>
107 static Lisp_Object x_keysym_to_emacs_keysym(KeySym keysym, int simple_p);
108 void emacs_Xt_mapping_action(Widget w, XEvent * event);
109 void debug_process_finalization(Lisp_Process * p);
110 void emacs_Xt_event_handler(Widget wid, XtPointer closure, XEvent * event,
111 Boolean * continue_to_dispatch);
113 static int last_quit_check_signal_tick_count;
115 Lisp_Object Qkey_mapping;
116 Lisp_Object Qsans_modifiers;
119 /************************************************************************/
120 /* keymap handling */
121 /************************************************************************/
123 /* X bogusly doesn't define the interpretations of any bits besides
124 ModControl, ModShift, and ModLock; so the Interclient Communication
125 Conventions Manual says that we have to bend over backwards to figure
126 out what the other modifier bits mean. According to ICCCM:
128 - Any keycode which is assigned ModControl is a "control" key.
130 - Any modifier bit which is assigned to a keycode which generates Meta_L
131 or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper,
134 - Any keypress event which contains ModControl in its state should be
135 interpreted as a "control" character.
137 - Any keypress event which contains a modifier bit in its state which is
138 generated by a keycode whose corresponding keysym is Meta_L or Meta_R
139 should be interpreted as a "meta" character. Likewise for Super, Hyper,
142 - It is illegal for a keysym to be associated with more than one modifier
145 This means that the only thing that emacs can reasonably interpret as a
146 "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
147 one of the modifier bits Mod1-Mod5.
149 Unfortunately, many keyboards don't have Meta keys in their default
150 configuration. So, if there are no Meta keys, but there are "Alt" keys,
151 emacs will interpret Alt as Meta. If there are both Meta and Alt keys,
152 then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to
153 mean "Symbol," but that just confused the hell out of way too many people).
155 This works with the default configurations of the 19 keyboard-types I've
158 Emacs detects keyboard configurations which violate the above rules, and
159 prints an error message on the standard-error-output. (Perhaps it should
160 use a pop-up-window instead.)
163 /* For every key on the keyboard that has a known character correspondence,
164 we define the ascii-character property of the keysym, and make the
165 default binding for the key be self-insert-command.
167 The following magic is basically intimate knowledge of X11/keysymdef.h.
168 The keysym mappings defined by X11 are based on the iso8859 standards,
169 except for Cyrillic and Greek.
171 In a non-Mule world, a user can still have a multi-lingual editor, by doing
172 (set-face-font "...-iso8859-2" (current-buffer))
173 for all their Latin-2 buffers, etc. */
175 static Lisp_Object x_keysym_to_character(KeySym keysym)
178 Lisp_Object charset = Qzero;
179 #define USE_CHARSET(var,cs) \
180 ((var) = CHARSET_BY_LEADING_BYTE (LEADING_BYTE_##cs))
182 #define USE_CHARSET(var,lb)
186 if ((keysym & 0xff) < 0xa0)
189 switch (keysym >> 8) {
190 case 0: /* ASCII + Latin1 */
191 USE_CHARSET(charset, LATIN_ISO8859_1);
192 code = keysym & 0x7f;
195 USE_CHARSET(charset, LATIN_ISO8859_2);
196 code = keysym & 0x7f;
199 USE_CHARSET(charset, LATIN_ISO8859_3);
200 code = keysym & 0x7f;
203 USE_CHARSET(charset, LATIN_ISO8859_4);
204 code = keysym & 0x7f;
206 case 4: /* Katakana */
207 USE_CHARSET(charset, KATAKANA_JISX0201);
208 if ((keysym & 0xff) > 0xa0)
209 code = keysym & 0x7f;
212 USE_CHARSET(charset, ARABIC_ISO8859_6);
213 code = keysym & 0x7f;
217 static unsigned char const cyrillic[] = /* 0x20 - 0x7f */
218 { 0x00, 0x72, 0x73, 0x71, 0x74, 0x75, 0x76, 0x77,
219 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x00, 0x7e, 0x7f,
220 0x70, 0x22, 0x23, 0x21, 0x24, 0x25, 0x26, 0x27,
221 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x00, 0x2e, 0x2f,
222 0x6e, 0x50, 0x51, 0x66, 0x54, 0x55, 0x64, 0x53,
223 0x65, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
224 0x5f, 0x6f, 0x60, 0x61, 0x62, 0x63, 0x56, 0x52,
225 0x6c, 0x6b, 0x57, 0x68, 0x6d, 0x69, 0x67, 0x6a,
226 0x4e, 0x30, 0x31, 0x46, 0x34, 0x35, 0x44, 0x33,
227 0x45, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
228 0x3f, 0x4f, 0x40, 0x41, 0x42, 0x43, 0x36, 0x32,
229 0x4c, 0x4b, 0x37, 0x48, 0x4d, 0x49, 0x47, 0x4a
231 USE_CHARSET(charset, CYRILLIC_ISO8859_5);
232 code = cyrillic[(keysym & 0x7f) - 0x20];
237 static unsigned char const greek[] = /* 0x20 - 0x7f */
238 { 0x00, 0x36, 0x38, 0x39, 0x3a, 0x5a, 0x00, 0x3c,
239 0x3e, 0x5b, 0x00, 0x3f, 0x00, 0x00, 0x35, 0x2f,
240 0x00, 0x5c, 0x5d, 0x5e, 0x5f, 0x7a, 0x40, 0x7c,
241 0x7d, 0x7b, 0x60, 0x7e, 0x00, 0x00, 0x00, 0x00,
242 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
243 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
244 0x50, 0x51, 0x53, 0x00, 0x54, 0x55, 0x56, 0x57,
245 0x58, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
247 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
248 0x70, 0x71, 0x73, 0x72, 0x74, 0x75, 0x76, 0x77,
249 0x78, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
251 USE_CHARSET(charset, GREEK_ISO8859_7);
252 code = greek[(keysym & 0x7f) - 0x20];
255 case 8: /* Technical */
257 case 9: /* Special */
259 case 10: /* Publishing */
263 case 12: /* Hebrew */
264 USE_CHARSET(charset, HEBREW_ISO8859_8);
265 code = keysym & 0x7f;
268 /* #### This needs to deal with character composition. */
269 USE_CHARSET(charset, THAI_TIS620);
270 code = keysym & 0x7f;
272 case 14: /* Korean Hangul */
274 case 19: /* Latin 9 - ISO8859-15 - unsupported charset. */
276 case 32: /* Currency */
286 return make_char(MAKE_CHAR(charset, code, 0));
288 return make_char(code + 0x80);
292 /* #### The way that keysym correspondence to characters should work:
293 - a Lisp_Event should contain a keysym AND a character slot.
294 - keybindings are tried with the keysym. If no binding can be found,
295 and there is a corresponding character, call self-insert-command.
297 #### Nuke x-iso8859-1.el.
298 #### Nuke the Qascii_character property.
299 #### Nuke Vcharacter_set_property.
302 maybe_define_x_key_as_self_inserting_character(KeySym keysym,
305 Lisp_Object character = x_keysym_to_character(keysym);
307 if (CHARP(character)) {
308 extern Lisp_Object Vcurrent_global_map;
309 extern Lisp_Object Qascii_character;
310 if (NILP(Flookup_key(Vcurrent_global_map, symbol, Qnil))) {
311 Fput(symbol, Qascii_character, character);
312 Fdefine_key(Vcurrent_global_map, symbol,
313 Qself_insert_command);
319 x_has_keysym(KeySym keysym, Lisp_Object hash_table, int with_modifiers)
321 KeySym upper_lower[2];
324 if (keysym < 0x80) /* Optimize for ASCII keysyms */
328 xmodmap -e 'keysym NN = scaron'
329 and then press (Shift scaron), X11 will return the different
330 keysym `Scaron', but `xmodmap -pke' might not even mention
331 `Scaron', so we "register" both `scaron' and `Scaron'. */
332 #ifdef HAVE_XCONVERTCASE
333 XConvertCase(keysym, &upper_lower[0], &upper_lower[1]);
335 upper_lower[0] = upper_lower[1] = keysym;
338 for (j = 0; j < (upper_lower[0] == upper_lower[1] ? 1 : 2); j++) {
340 keysym = upper_lower[j];
342 name = XKeysymToString(keysym);
344 /* X guarantees NAME to be in the Host Portable
345 Character Encoding */
346 Lisp_Object sym = x_keysym_to_emacs_keysym(keysym, 0);
347 Lisp_Object new_value = with_modifiers
348 ? Qt : Qsans_modifiers;
349 Lisp_Object old_value = Fgethash(sym, hash_table, Qnil);
351 if (!EQ(old_value, new_value)
352 && !(EQ(old_value, Qsans_modifiers) &&
353 EQ(new_value, Qt))) {
354 maybe_define_x_key_as_self_inserting_character
356 Fputhash(build_ext_string(name, Qbinary),
357 new_value, hash_table);
358 Fputhash(sym, new_value, hash_table);
365 x_reset_key_mapping(struct device *d)
367 Display *display = DEVICE_X_DISPLAY(d);
368 struct x_device *xd = DEVICE_X_DATA(d);
369 KeySym *keysym, *keysym_end;
370 Lisp_Object hash_table;
371 int key_code_count, keysyms_per_code;
373 if (xd->x_keysym_map) {
374 XFree((char *)xd->x_keysym_map);
376 XDisplayKeycodes(display,
377 &xd->x_keysym_map_min_code,
378 &xd->x_keysym_map_max_code);
380 xd->x_keysym_map_max_code - xd->x_keysym_map_min_code + 1;
382 XGetKeyboardMapping(display, xd->x_keysym_map_min_code,
384 &xd->x_keysym_map_keysyms_per_code);
386 hash_table = xd->x_keysym_map_hash_table;
387 if (HASH_TABLEP(hash_table)) {
388 Fclrhash(hash_table);
390 xd->x_keysym_map_hash_table = hash_table =
391 make_lisp_hash_table(128, HASH_TABLE_NON_WEAK,
395 for (keysym = xd->x_keysym_map,
396 keysyms_per_code = xd->x_keysym_map_keysyms_per_code,
397 keysym_end = keysym + (key_code_count * keysyms_per_code);
398 keysym < keysym_end; keysym += keysyms_per_code) {
401 if (keysym[0] == NoSymbol) {
404 x_has_keysym(keysym[0], hash_table, 0);
406 for (j = 1; j < keysyms_per_code; j++) {
407 if (keysym[j] != keysym[0] && keysym[j] != NoSymbol) {
408 x_has_keysym(keysym[j], hash_table, 1);
414 static inline const char *index_to_name(int indice)
415 __attribute__((always_inline));
416 static inline const char *index_to_name(int indice)
423 case ControlMapIndex:
440 static char *err_overlap_mods =
442 " Two distinct modifier keys (such as Meta and Hyper) cannot\n"
443 " generate the same modifier bit, because Emacs won't be able\n"
444 " to tell which modifier was actually held down when some\n"
445 " other key is pressed. It won't be able to tell Meta-x and\n"
446 " Hyper-x apart, for example. Change one of these keys to use\n"
447 " some other modifier bit. If you intend for these keys to\n"
448 " have the same behavior, then change them to have the same\n"
449 " keysym as well as the same modifier bit.";
450 static char *err_predef_mods =
452 " The semantics of the modifier bits ModShift, ModLock, and\n"
453 " ModControl are predefined. It does not make sense to assign\n"
454 " ModControl to any keysym other than Control_L or Control_R,\n"
455 " or to assign any modifier bits to the \"control\" keysyms\n"
456 " other than ModControl. You can't turn a \"control\" key\n"
457 " into a \"meta\" key (or vice versa) by simply assigning the\n"
458 " key a different modifier bit. You must also make that key\n"
459 " generate an appropriate keysym (Control_L, Meta_L, etc).";
460 static char *err_msg_else =
462 " The meanings of the modifier bits Mod1 through Mod5 are\n"
463 " determined by the keysyms used to control those bits.\n"
464 " Mod1 does NOT always mean Meta, although some\n"
465 " non-ICCCM-compliant programs assume that.";
467 /* Boy, I really wish C had local functions... */
469 unsigned int modifier_index;
470 unsigned int modifier_key;
473 /* now 32 bits of goodness */
474 bool warned_about_overlapping_modifiers:1;
475 bool warned_about_predefined_modifiers:1;
476 bool warned_about_duplicate_modifiers:1;
477 /* pad for the bools, so they end up on an 8bit boundary
478 * also store the old state */
480 /* each bit consumes 4 bits, totalling to 20 bits */
481 unsigned int meta_bit:4;
482 unsigned int hyper_bit:4;
483 unsigned int super_bit:4;
484 unsigned int alt_bit:4;
485 unsigned int mode_bit:4;
486 /* for bits left for a future modifier */
491 modbarf(KeyCode code, const char *name, const char *other,
492 struct mod_clo_s *clo)
495 Qkey_mapping, Qwarning,
496 "SXEmacs: %s (0x%x) generates %s, "
497 "which is nonsensical.",
499 clo->warned_about_predefined_modifiers = true;
504 modwarn(KeyCode code, const char *name, int old, const char *other,
505 struct mod_clo_s *clo)
507 warn_when_safe(Qkey_mapping, Qwarning,
508 "SXEmacs: %s (0x%x) generates %s, "
509 "which is generated by %s.",
510 name, code, index_to_name (old), other);
511 clo->warned_about_overlapping_modifiers = true;
516 store_modifier(KeyCode code, const char *name, struct mod_clo_s *clo)
518 #define modifier_index clo->modifier_index
519 #define modifier_key clo->modifier_key
520 #define mkpm clo->mkpm
521 if (clo->old && clo->old != modifier_index) {
523 Qkey_mapping, Qwarning,
524 "SXEmacs: %s (0x%x) generates both "
525 "%s and %s, which is nonsensical.",
526 name, code, index_to_name(clo->old),
527 index_to_name(modifier_index));
528 clo->warned_about_duplicate_modifiers = true;
530 if (modifier_index == ShiftMapIndex) {
531 modbarf(code, name, "ModShift", clo);
532 } else if (modifier_index == LockMapIndex) {
533 modbarf(code, name, "ModLock", clo);
534 } else if (modifier_index == ControlMapIndex) {
535 modbarf(code, name, "ModControl", clo);
537 } else if (sym == XK_Mode_switch) {
538 /* Mode_switch is special, see below... */
541 } else if (modifier_index == clo->meta_bit &&
542 clo->old != clo->meta_bit) {
543 modwarn(code, name, clo->meta_bit, "Meta", clo);
544 } else if (modifier_index == clo->super_bit &&
545 clo->old != clo->super_bit) {
546 modwarn(code, name, clo->super_bit, "Super", clo);
547 } else if (modifier_index == clo->hyper_bit &&
548 clo->old != clo->hyper_bit) {
549 modwarn(code, name, clo->hyper_bit, "Hyper", clo);
550 } else if (modifier_index == clo->alt_bit &&
551 clo->old != clo->alt_bit) {
552 modwarn(code, name, clo->alt_bit, "Alt", clo);
554 clo->old = modifier_index;
557 #undef modifier_index
563 check_modifier(KeyCode code, const char *name, int mask, struct mod_clo_s *clo)
565 #define modifier_index clo->modifier_index
566 #define modifier_key clo->modifier_key
567 #define mkpm clo->mkpm
568 if ((1 << modifier_index) != mask) {
570 Qkey_mapping, Qwarning,
571 "SXEmacs: %s (0x%x) generates %s, "
572 "which is nonsensical.",
574 index_to_name(modifier_index));
575 clo->warned_about_predefined_modifiers = true;
577 #undef modifier_index
584 whatever(Display *dspl, struct x_device *xd, struct mod_clo_s *clo)
586 #define modifier_index clo->modifier_index
587 #define modifier_key clo->modifier_key
588 #define mkpm clo->mkpm
589 #define mode_bit clo->mode_bit
590 #define meta_bit clo->meta_bit
591 #define alt_bit clo->alt_bit
592 #define super_bit clo->super_bit
593 #define hyper_bit clo->hyper_bit
595 KeyCode code = xd->x_modifier_keymap->modifiermap
596 [modifier_index * mkpm + modifier_key];
598 for (int column = 0; column < 4; column += 2) {
600 ? XKeycodeToKeysym(dspl, code, column)
603 if (LIKELY(sym == last_sym)) {
609 /* store_modifier("Mode_switch", &mode_bit); */
610 /* handled specially here */
611 mode_bit = modifier_index;
614 /* new modifier, new luck, reset clo->old */
616 store_modifier(code, "Meta_L", clo);
621 store_modifier(code, "Meta_R", clo);
625 clo->old = super_bit;
626 store_modifier(code, "Super_L", clo);
627 super_bit = clo->old;
630 clo->old = super_bit;
631 store_modifier(code, "Super_R", clo);
632 super_bit = clo->old;
635 clo->old = hyper_bit;
636 store_modifier(code, "Hyper_L", clo);
637 hyper_bit = clo->old;
640 clo->old = hyper_bit;
641 store_modifier(code, "Hyper_R", clo);
642 hyper_bit = clo->old;
646 store_modifier(code, "Alt_L", clo);
651 store_modifier(code, "Alt_R", clo);
655 check_modifier(code, "Control_L", ControlMask, clo);
658 check_modifier(code, "Control_R", ControlMask, clo);
661 check_modifier(code, "Shift_L", ShiftMask, clo);
664 check_modifier(code, "Shift_R", ShiftMask, clo);
667 check_modifier(code, "Shift_Lock", LockMask, clo);
668 xd->lock_interpretation = XK_Shift_Lock;
671 check_modifier(code, "Caps_Lock", LockMask, clo);
672 xd->lock_interpretation = XK_Caps_Lock;
675 /* It probably doesn't make any sense for a
676 modifier bit to be assigned to a key that is
677 not one of the above, but OpenWindows assigns
678 modifier bits to a couple of random function
679 keys for no reason that I can discern, so
680 printing a warning here would be annoying. */
682 /* hope we handled everything above */
687 #undef modifier_index
698 x_reset_modifier_mapping(struct device *d)
700 #define modifier_index clo.modifier_index
701 #define modifier_key clo.modifier_key
702 #define mkpm clo.mkpm
703 Display *display = DEVICE_X_DISPLAY(d);
704 struct x_device *xd = DEVICE_X_DATA(d);
705 struct mod_clo_s clo = {
706 .warned_about_overlapping_modifiers = false,
707 .warned_about_predefined_modifiers = false,
708 .warned_about_duplicate_modifiers = false,
717 #define mode_bit clo.mode_bit
718 #define meta_bit clo.meta_bit
719 #define alt_bit clo.alt_bit
720 #define super_bit clo.super_bit
721 #define hyper_bit clo.hyper_bit
722 xd->lock_interpretation = 0;
724 if (xd->x_modifier_keymap) {
725 XFreeModifiermap(xd->x_modifier_keymap);
727 x_reset_key_mapping(d);
729 xd->x_modifier_keymap = XGetModifierMapping(display);
731 /* The call to warn_when_safe must be on the same line as the string or
732 make-msgfile won't pick it up properly (the newline doesn't confuse
733 it, but the backslash does). */
735 mkpm = xd->x_modifier_keymap->max_keypermod;
736 for (modifier_index = 0; modifier_index < 8; modifier_index++) {
737 for (modifier_key = 0; modifier_key < mkpm; modifier_key++) {
738 whatever(display, xd, &clo);
742 /* If there was no Meta key, then try using the Alt key instead.
743 If there is both a Meta key and an Alt key, then the Alt key
744 is not disturbed and remains an Alt key. */
745 if (!meta_bit && alt_bit) {
750 /* mode_bit overrides everything, since it's processed down inside of
751 XLookupString() instead of by us. If Meta and Mode_switch both
752 generate the same modifier bit (which is an error), then we don't
753 interpret that bit as Meta, because we can't make XLookupString()
754 not interpret it as Mode_switch; and interpreting it as both would
757 const char *warn = 0;
759 if (mode_bit == meta_bit) {
762 } else if (mode_bit == hyper_bit) {
765 } else if (mode_bit == super_bit) {
768 } else if (mode_bit == alt_bit) {
774 Qkey_mapping, Qwarning,
775 "SXEmacs: %s is being used for both "
776 "Mode_switch and %s.",
777 index_to_name(mode_bit), warn);
778 clo.warned_about_overlapping_modifiers = true;
782 xd->MetaMask = (meta_bit ? (1 << meta_bit) : 0);
783 xd->HyperMask = (hyper_bit ? (1 << hyper_bit) : 0);
784 xd->SuperMask = (super_bit ? (1 << super_bit) : 0);
785 xd->AltMask = (alt_bit ? (1 << alt_bit) : 0);
786 xd->ModeMask = (mode_bit ? (1 << mode_bit) : 0); /* unused */
788 if (clo.warned_about_overlapping_modifiers) {
789 warn_when_safe(Qkey_mapping, Qwarning, "%s", err_overlap_mods);
792 if (clo.warned_about_predefined_modifiers) {
793 warn_when_safe(Qkey_mapping, Qwarning, "%s", err_predef_mods);
796 /* No need to say anything more for warned_about_duplicate_modifiers. */
797 if (clo.warned_about_overlapping_modifiers ||
798 clo.warned_about_predefined_modifiers)
799 warn_when_safe(Qkey_mapping, Qwarning, "%s", err_msg_else);
800 #undef modifier_index
810 void x_init_modifier_mapping(struct device *d)
812 struct x_device *xd = DEVICE_X_DATA(d);
813 xd->x_keysym_map_hash_table = Qnil;
814 xd->x_keysym_map = NULL;
815 xd->x_modifier_keymap = NULL;
816 x_reset_modifier_mapping(d);
820 static int x_key_is_modifier_p(KeyCode keycode, struct device *d)
822 struct x_device *xd = DEVICE_X_DATA(d);
826 if (keycode < xd->x_keysym_map_min_code ||
827 keycode > xd->x_keysym_map_max_code) {
831 syms = &xd->x_keysym_map[(keycode - xd->x_keysym_map_min_code) *
832 xd->x_keysym_map_keysyms_per_code];
833 for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++) {
834 if (IsModifierKey(syms[i]) || syms[i] == XK_Mode_switch) {
835 /* why doesn't IsModifierKey count this? */
842 /* key-handling code is always ugly. It just ends up working out
845 Here are some pointers:
847 -- DOWN_MASK indicates which modifiers should be treated as "down"
848 when the corresponding upstroke happens. It gets reset for
849 a particular modifier when that modifier goes up, and reset
850 for all modifiers when a non-modifier key is pressed. Example:
852 I press Control-A-Shift and then release Control-A-Shift.
853 I want the Shift key to be sticky but not the Control key.
855 -- LAST_DOWNKEY and RELEASE_TIME are used to keep track of
856 auto-repeat -- see below.
858 -- If a modifier key is sticky, I can unstick it by pressing
859 the modifier key again. */
861 static void x_handle_sticky_modifiers(XEvent * ev, struct device *d)
867 if (!modifier_keys_are_sticky) {
868 /* Optimize for non-sticky modifiers */
872 xd = DEVICE_X_DATA(d);
873 keycode = ev->xkey.keycode;
876 if (keycode < xd->x_keysym_map_min_code ||
877 keycode > xd->x_keysym_map_max_code) {
881 if (!((type == KeyPress || type == KeyRelease) &&
882 x_key_is_modifier_p(keycode, d))) {
883 /* Not a modifier key */
884 bool key_event_p = (type == KeyPress || type == KeyRelease);
886 if (type == ButtonPress
888 && ((xd->last_downkey
889 && ((keycode != xd->last_downkey
890 || ev->xkey.time != xd->release_time)))
891 || (INTP(Vmodifier_keys_sticky_time)
893 > (xd->modifier_release_time
894 + XINT(Vmodifier_keys_sticky_time)))))) {
895 xd->need_to_add_mask = 0;
896 xd->last_downkey = 0;
897 } else if (type == KeyPress && !xd->last_downkey) {
898 xd->last_downkey = keycode;
900 if (type == KeyPress) {
901 xd->release_time = 0;
903 if (type == KeyPress || type == ButtonPress) {
905 xd->modifier_release_time = 0;
909 ev->xkey.state |= xd->need_to_add_mask;
911 ev->xbutton.state |= xd->need_to_add_mask;
914 if (type == KeyRelease && keycode == xd->last_downkey) {
915 /* If I hold press-and-release the Control key and then
916 press and hold down the right arrow, I want it to
917 auto-repeat Control-Right. On the other hand, if I
918 do the same but manually press the Right arrow a
919 bunch of times, I want to see one Control-Right and
920 then a bunch of Rights. This means that we need to
921 distinguish between an auto-repeated key and a key
922 pressed and released a bunch of times.
924 Naturally, the designers of the X spec didn't see fit
925 to provide an obvious way to distinguish these cases.
926 So we assume that if the release and the next press
927 occur at the same time, the key was actually auto-
928 repeated. Under Open-Windows, at least, this
930 xd->modifier_release_time = xd->release_time =
936 /* Modifier key pressed */
938 KeySym *syms = &xd->x_keysym_map[
939 (keycode - xd->x_keysym_map_min_code) *
940 xd->x_keysym_map_keysyms_per_code];
942 /* If a non-modifier key was pressed in the middle of a bunch
943 of modifiers, then it unsticks all the modifiers that were
944 previously pressed. We cannot unstick the modifiers until
945 now because we want to check for auto-repeat of the
948 if (xd->last_downkey) {
949 xd->last_downkey = 0;
950 xd->need_to_add_mask = 0;
953 if (xd->modifier_release_time
954 && INTP(Vmodifier_keys_sticky_time)
955 && (ev->xkey.time > xd->modifier_release_time +
956 XINT(Vmodifier_keys_sticky_time))) {
957 xd->need_to_add_mask = 0;
963 if (type == KeyPress) { \
964 /* If modifier key is already sticky, \
965 then unstick it. Note that we do \
966 not test down_mask to deal with the \
967 unlikely but possible case that the \
968 modifier key auto-repeats. */ \
969 if (xd->need_to_add_mask & mask) { \
970 xd->need_to_add_mask &= ~mask; \
971 xd->down_mask &= ~mask; \
973 xd->down_mask |= mask; \
976 if (xd->down_mask & mask) { \
977 xd->down_mask &= ~mask; \
978 xd->need_to_add_mask |= mask; \
981 xd->modifier_release_time = ev->xkey.time; \
984 for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++) {
1000 FROB(xd->SuperMask);
1004 FROB(xd->HyperMask);
1011 /* hope we handled everything */
1019 static void clear_sticky_modifiers(struct device *d)
1021 struct x_device *xd = DEVICE_X_DATA(d);
1023 xd->need_to_add_mask = 0;
1024 xd->last_downkey = 0;
1025 xd->release_time = 0;
1030 static int keysym_obeys_caps_lock_p(KeySym sym, struct device *d)
1032 struct x_device *xd = DEVICE_X_DATA(d);
1033 /* Eeeeevil hack. Don't apply Caps_Lock to things that aren't
1034 alphabetic characters, where "alphabetic" means something more than
1035 simply A-Z. That is, if Caps_Lock is down, typing ESC doesn't
1036 produce Shift-ESC. But if shift-lock is down, then it does. */
1037 if (xd->lock_interpretation == XK_Shift_Lock) {
1040 return ((sym >= XK_A) && (sym <= XK_Z)) ||
1041 ((sym >= XK_a) && (sym <= XK_z)) ||
1042 ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) ||
1043 ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) ||
1044 ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) ||
1045 ((sym >= XK_oslash) && (sym <= XK_thorn));
1048 /* called from EmacsFrame.c (actually from Xt itself) when a
1049 MappingNotify event is received. In its infinite wisdom, Xt
1050 decided that Xt event handlers never get MappingNotify events.
1051 O'Reilly Xt Programming Manual 9.1.2 says:
1053 MappingNotify is automatically handled by Xt, so it isn't passed
1054 to event handlers and you don't need to worry about it.
1056 Of course, we DO worry about it, so we need a special translation. */
1058 emacs_Xt_mapping_action(Widget w, XEvent * event)
1060 struct device *d = get_device_from_display(event->xany.display);
1062 if (DEVICE_X_BEING_DELETED(d)) {
1066 /* nyet. Now this is handled by Xt. */
1067 XRefreshKeyboardMapping(&event->xmapping);
1069 /* xmodmap generates about a billion MappingKeyboard events, followed by
1070 a single MappingModifier event, so it might be worthwhile to take
1071 extra MappingKeyboard events out of the queue before requesting the
1072 current keymap from the server. */
1073 switch (event->xmapping.request) {
1074 case MappingKeyboard:
1075 x_reset_key_mapping(d);
1077 case MappingModifier:
1078 x_reset_modifier_mapping(d);
1080 case MappingPointer:
1081 /* Do something here? */
1088 /************************************************************************/
1089 /* X to Emacs event conversion */
1090 /************************************************************************/
1093 x_keysym_to_emacs_keysym(KeySym keysym, int simple_p)
1096 if (keysym >= XK_exclam && keysym <= XK_asciitilde) {
1097 /* We must assume that the X keysym numbers for the ASCII
1098 graphic characters are the same as their ASCII codes. */
1099 return make_char(keysym);
1103 /* These would be handled correctly by the default case, but by
1104 special-casing them here we don't garbage a string or call
1126 /* !!#### not Mule-ized */
1127 name = XKeysymToString(keysym);
1128 if (!name || !name[0]) {
1129 /* This happens if there is a mismatch between the Xlib
1130 of SXEmacs and the Xlib of the X server...
1132 Let's hard-code in some knowledge of common keysyms
1133 introduced in recent X11 releases. Snarfed from
1136 Probably we should add some stuff here for X11R6. */
1139 return KEYSYM("kp-home");
1141 return KEYSYM("kp-left");
1143 return KEYSYM("kp-up");
1145 return KEYSYM("kp-right");
1147 return KEYSYM("kp-down");
1149 return KEYSYM("kp-prior");
1151 return KEYSYM("kp-next");
1153 return KEYSYM("kp-end");
1155 return KEYSYM("kp-begin");
1157 return KEYSYM("kp-insert");
1159 return KEYSYM("kp-delete");
1163 return KEYSYM("SunF36");
1166 return KEYSYM("SunF37");
1169 int sz = snprintf(buf, sizeof(buf),
1170 "unknown-keysym-0x%X",
1172 assert(sz>=0 && (size_t)sz < sizeof(buf));
1177 /* If it's got a one-character name, that's good enough. */
1179 return make_char(name[0]);
1181 /* If it's in the "Keyboard" character set, downcase it. The
1182 case of those keysyms is too totally random for us to force
1183 anyone to remember them. The case of the other character
1184 sets is significant, however.
1186 if ((((unsigned int)keysym) & (~0x1FF)) ==
1187 ((unsigned int)0xFE00)) {
1190 for (s1 = name, s2 = buf; *s1; s1++, s2++) {
1194 *s2 = tolower(*(unsigned char *)s1);
1200 return KEYSYM(name);
1205 x_to_emacs_keysym(XKeyPressedEvent * event, int simple_p)
1206 /* simple_p means don't try too hard (ASCII only) */
1212 /* Some implementations of XmbLookupString don't return
1213 XBufferOverflow correctly, so increase the size of the xim input
1214 buffer from 64 to the more reasonable size 513, as Emacs has done.
1215 From Kenichi Handa. */
1217 char *bufptr = buffer;
1218 int bufsiz = sizeof(buffer);
1223 x_any_window_to_frame(get_device_from_display(event->display),event->window);
1225 xic = FRAME_X_XIC(f);
1226 #endif /* XIM_XLIB */
1227 #endif /* HAVE_XIM */
1229 /* We use XLookupString if we're not using XIM, or are using
1230 XIM_XLIB but input context creation failed. */
1231 #if ! (defined (HAVE_XIM) && defined (XIM_MOTIF))
1232 #if defined (HAVE_XIM) && defined (XIM_XLIB)
1234 #endif /* XIM_XLIB */
1236 /* Apparently it's necessary to specify a dummy here (rather
1237 than passing in 0) to avoid crashes on German IRIX */
1239 XLookupString(event, dummy, 200, &keysym, 0);
1240 return (IsModifierKey(keysym) || keysym == XK_Mode_switch)
1241 ? Qnil : x_keysym_to_emacs_keysym(keysym, simple_p);
1243 #endif /* ! XIM_MOTIF */
1246 Lookup_String: /* Come-From XBufferOverflow */
1249 XmImMbLookupString(XtWindowToWidget(event->display, event->window),
1250 event, bufptr, bufsiz, &keysym, &status);
1251 #else /* XIM_XLIB */
1253 len = XmbLookupString(xic, event, bufptr, bufsiz, &keysym,
1256 #endif /* HAVE_XIM */
1258 #ifdef DEBUG_SXEMACS
1259 if (debug_x_events > 0) {
1260 stderr_out(" status=");
1261 #define print_status_when(S) if (status == S) stderr_out (#S)
1262 print_status_when(XLookupKeySym);
1263 print_status_when(XLookupBoth);
1264 print_status_when(XLookupChars);
1265 print_status_when(XLookupNone);
1266 print_status_when(XBufferOverflow);
1268 if (status == XLookupKeySym || status == XLookupBoth)
1269 stderr_out(" keysym=%s", XKeysymToString(keysym));
1270 if (status == XLookupChars || status == XLookupBoth) {
1273 stderr_out(" chars=\"");
1274 for (j = 0; j < len; j++)
1275 stderr_out("%c", bufptr[j]);
1277 } else if (bufptr[0] <= 32 || bufptr[0] >= 127) {
1278 stderr_out(" char=0x%x", bufptr[0]);
1280 stderr_out(" char=%c", bufptr[0]);
1285 #endif /* DEBUG_SXEMACS */
1290 return (IsModifierKey(keysym) || keysym == XK_Mode_switch)
1292 : x_keysym_to_emacs_keysym(keysym, simple_p);
1294 case XLookupChars: {
1295 /* Generate multiple emacs events */
1296 struct device *d = get_device_from_display(event->display);
1298 Lisp_Object instream, fb_instream;
1300 struct gcpro gcpro1, gcpro2;
1302 fb_instream = make_fixed_buffer_input_stream(bufptr, len);
1304 /* #### Use Fget_coding_system
1305 * (Vcomposed_input_coding_system) */
1306 instream = make_decoding_input_stream(XLSTREAM(fb_instream),
1310 istr = XLSTREAM(instream);
1312 GCPRO2(instream, fb_instream);
1313 while ((ch = Lstream_get_emchar(istr)) != EOF) {
1314 Lisp_Object emacs_event = Fmake_event(Qnil, Qnil);
1315 Lisp_Event *ev = XEVENT(emacs_event);
1316 ev->channel = DEVICE_CONSOLE(d);
1317 ev->event_type = key_press_event;
1318 ev->timestamp = event->time;
1319 ev->event.key.modifiers = 0;
1320 ev->event.key.keysym = make_char(ch);
1321 enqueue_Xt_dispatch_event(emacs_event);
1323 Lstream_close(istr);
1325 Lstream_delete(istr);
1326 Lstream_delete(XLSTREAM(fb_instream));
1331 case XBufferOverflow:
1332 bufptr = (char *)alloca(len + 1);
1338 return Qnil; /* not reached */
1339 #endif /* HAVE_XIM */
1343 set_last_server_timestamp(struct device *d, XEvent * x_event)
1346 switch (x_event->type) {
1349 t = x_event->xkey.time;
1353 t = x_event->xbutton.time;
1357 t = x_event->xcrossing.time;
1360 t = x_event->xmotion.time;
1362 case PropertyNotify:
1363 t = x_event->xproperty.time;
1365 case SelectionClear:
1366 t = x_event->xselectionclear.time;
1368 case SelectionRequest:
1369 t = x_event->xselectionrequest.time;
1371 case SelectionNotify:
1372 t = x_event->xselection.time;
1377 DEVICE_X_LAST_SERVER_TIMESTAMP(d) = t;
1381 x_event_to_emacs_event(XEvent * x_event, Lisp_Event * emacs_event)
1383 Display *display = x_event->xany.display;
1384 struct device *d = get_device_from_display(display);
1385 struct x_device *xd = DEVICE_X_DATA(d);
1387 if (DEVICE_X_BEING_DELETED(d)) {
1388 /* #### Uh, is this 0 correct? */
1392 set_last_server_timestamp(d, x_event);
1394 switch (x_event->type) {
1396 x_handle_sticky_modifiers(x_event, d);
1401 case ButtonRelease: {
1403 int shift_p, lock_p;
1404 Bool key_event_p = (x_event->type == KeyPress);
1405 unsigned int *state = key_event_p
1406 ? &x_event->xkey.state
1407 : &x_event->xbutton.state;
1409 /* If this is a synthetic KeyPress or Button event, and the user
1410 has expressed a disinterest in this security hole, then drop
1413 ? x_event->xkey.send_event
1414 : x_event->xbutton.send_event)
1415 #ifdef EXTERNAL_WIDGET
1416 /* ben: events get sent to an ExternalShell using
1418 This is not a perfect solution. */
1419 && !FRAME_X_EXTERNAL_WINDOW_P
1420 (x_any_window_to_frame(d, x_event->xany.window))
1422 && !x_allow_sendevents) {
1426 DEVICE_X_MOUSE_TIMESTAMP(d) =
1427 DEVICE_X_GLOBAL_MOUSE_TIMESTAMP(d) =
1429 ? x_event->xkey.time
1430 : x_event->xbutton.time;
1432 x_handle_sticky_modifiers(x_event, d);
1434 if (*state & ControlMask) {
1435 modifiers |= XEMACS_MOD_CONTROL;
1437 if (*state & xd->MetaMask) {
1438 modifiers |= XEMACS_MOD_META;
1440 if (*state & xd->SuperMask) {
1441 modifiers |= XEMACS_MOD_SUPER;
1443 if (*state & xd->HyperMask) {
1444 modifiers |= XEMACS_MOD_HYPER;
1446 if (*state & xd->AltMask) {
1447 modifiers |= XEMACS_MOD_ALT;
1450 int numero_de_botao = -1;
1453 numero_de_botao = x_event->xbutton.button;
1455 /* the button gets noted either in the button or the
1456 modifiers field, but not both. */
1457 if (numero_de_botao != 1 && (*state & Button1Mask)) {
1458 modifiers |= XEMACS_MOD_BUTTON1;
1460 if (numero_de_botao != 2 && (*state & Button2Mask)) {
1461 modifiers |= XEMACS_MOD_BUTTON2;
1463 if (numero_de_botao != 3 && (*state & Button3Mask)) {
1464 modifiers |= XEMACS_MOD_BUTTON3;
1466 if (numero_de_botao != 4 && (*state & Button4Mask)) {
1467 modifiers |= XEMACS_MOD_BUTTON4;
1469 if (numero_de_botao != 5 && (*state & Button5Mask)) {
1470 modifiers |= XEMACS_MOD_BUTTON5;
1474 /* Ignore the Caps_Lock key if:
1475 - any other modifiers are down, so that Caps_Lock doesn't
1476 turn C-x into C-X, which would suck.
1477 - the event was a mouse event. */
1478 if (modifiers || !key_event_p) {
1479 *state &= (~LockMask);
1482 shift_p = *state & ShiftMask;
1483 lock_p = *state & LockMask;
1485 if (shift_p || lock_p) {
1486 modifiers |= XEMACS_MOD_SHIFT;
1490 XKeyEvent *ev = &x_event->xkey;
1491 /* This used to compute the frame from the given X
1492 window and store it here, but we really don't care
1494 emacs_event->channel = DEVICE_CONSOLE(d);
1495 keysym = x_to_emacs_keysym(&x_event->xkey, 0);
1497 /* If the emacs keysym is nil, then that means that the
1498 X keysym was either a Modifier or NoSymbol, which
1499 probably means that we're in the midst of reading a
1500 Multi_key sequence, or a "dead" key prefix, or XIM
1501 input. Ignore it. */
1506 /* More Caps_Lock garbage: Caps_Lock should *only* add
1507 the shift modifier to two-case keys (that is, A-Z and
1508 related characters). So at this point (after looking
1509 up the keysym) if the keysym isn't a dual-case
1510 alphabetic, and if the caps lock key was down but the
1511 shift key wasn't, then turn off the shift modifier.
1513 /* #### type lossage: assuming equivalence of emacs and
1515 /* !!#### maybe fix for Mule */
1516 if (lock_p && !shift_p &&
1517 !(CHAR_OR_CHAR_INTP(keysym)
1518 && keysym_obeys_caps_lock_p(
1519 (KeySym) XCHAR_OR_CHAR_INT(keysym), d))) {
1520 modifiers &= (~XEMACS_MOD_SHIFT);
1523 /* If this key contains two distinct keysyms, that is,
1524 "shift" generates a different keysym than the
1525 non-shifted key, then don't apply the shift modifier
1526 bit: it's implicit. Otherwise, if there would be no
1527 other way to tell the difference between the shifted
1528 and unshifted version of this key, apply the shift
1529 bit. Non-graphics, like Backspace and F1 get the
1530 shift bit in the modifiers slot. Neither the
1531 characters "a", "A", "2", nor "@" normally have the
1532 shift bit set. However, "F1" normally does. */
1533 if (modifiers & XEMACS_MOD_SHIFT) {
1534 int Mode_switch_p = *state & xd->ModeMask;
1535 KeySym bot = XLookupKeysym(ev,
1538 KeySym top = XLookupKeysym(ev,
1541 if (top && bot && top != bot) {
1557 modifiers &= ~XEMACS_MOD_SHIFT;
1562 emacs_event->event_type = key_press_event;
1563 emacs_event->timestamp = ev->time;
1564 emacs_event->event.key.modifiers = modifiers;
1565 emacs_event->event.key.keysym = keysym;
1567 /* Mouse press/release event */
1568 XButtonEvent *ev = &x_event->xbutton;
1569 struct frame *frame = x_window_to_frame(d, ev->window);
1575 XSETFRAME(emacs_event->channel, frame);
1577 emacs_event->event_type = (x_event->type == ButtonPress)
1578 ? button_press_event
1579 : button_release_event;
1581 emacs_event->event.button.modifiers = modifiers;
1582 emacs_event->timestamp = ev->time;
1583 emacs_event->event.button.button = ev->button;
1584 emacs_event->event.button.x = ev->x;
1585 emacs_event->event.button.y = ev->y;
1586 /* because we don't seem to get a FocusIn event for
1587 button clicks when a widget-glyph is selected we will
1588 assume that we want the focus if a button gets
1590 if (x_event->type == ButtonPress) {
1591 handle_focus_event_1(frame, 1);
1597 case MotionNotify: {
1598 XMotionEvent *ev = &x_event->xmotion;
1599 struct frame *frame = x_window_to_frame(d, ev->window);
1601 XMotionEvent event2;
1608 /* We use MotionHintMask, so we will get only one motion event
1609 until the next time we call XQueryPointer or the user clicks
1610 the mouse. So call XQueryPointer now (meaning that the event
1611 will be in sync with the server just before Fnext_event()
1612 returns). If the mouse is still in motion, then the server
1613 will immediately generate exactly one more motion event,
1614 which will be on the queue waiting for us next time
1617 if (XQueryPointer(event2.display, event2.window,
1618 &event2.root, &event2.subwindow,
1619 &event2.x_root, &event2.y_root,
1620 &event2.x, &event2.y, &event2.state)) {
1621 /* only one structure copy */
1624 DEVICE_X_MOUSE_TIMESTAMP(d) = ev->time;
1626 XSETFRAME(emacs_event->channel, frame);
1627 emacs_event->event_type = pointer_motion_event;
1628 emacs_event->timestamp = ev->time;
1629 emacs_event->event.motion.x = ev->x;
1630 emacs_event->event.motion.y = ev->y;
1631 if (ev->state & ShiftMask) {
1632 modifiers |= XEMACS_MOD_SHIFT;
1634 if (ev->state & ControlMask) {
1635 modifiers |= XEMACS_MOD_CONTROL;
1637 if (ev->state & xd->MetaMask) {
1638 modifiers |= XEMACS_MOD_META;
1640 if (ev->state & xd->SuperMask) {
1641 modifiers |= XEMACS_MOD_SUPER;
1643 if (ev->state & xd->HyperMask) {
1644 modifiers |= XEMACS_MOD_HYPER;
1646 if (ev->state & xd->AltMask) {
1647 modifiers |= XEMACS_MOD_ALT;
1649 if (ev->state & Button1Mask) {
1650 modifiers |= XEMACS_MOD_BUTTON1;
1652 if (ev->state & Button2Mask) {
1653 modifiers |= XEMACS_MOD_BUTTON2;
1655 if (ev->state & Button3Mask) {
1656 modifiers |= XEMACS_MOD_BUTTON3;
1658 if (ev->state & Button4Mask) {
1659 modifiers |= XEMACS_MOD_BUTTON4;
1661 if (ev->state & Button5Mask) {
1662 modifiers |= XEMACS_MOD_BUTTON5;
1664 /* Currently ignores Shift_Lock but probably shouldn't
1665 (but it definitely should ignore Caps_Lock). */
1666 emacs_event->event.motion.modifiers = modifiers;
1670 case ClientMessage: {
1671 /* Patch bogus TAKE_FOCUS messages from MWM; CurrentTime is
1672 passed as the timestamp of the TAKE_FOCUS, which the ICCCM
1673 explicitly prohibits. */
1674 XClientMessageEvent *ev = &x_event->xclient;
1676 if (ev->message_type == DEVICE_XATOM_WM_PROTOCOLS(d)
1677 && (Atom) (ev->data.l[0]) ==
1678 DEVICE_XATOM_WM_TAKE_FOCUS(d)
1679 && (Atom) (ev->data.l[1]) == 0) {
1681 DEVICE_X_LAST_SERVER_TIMESTAMP(d);
1687 /* it's a magic event */
1688 struct frame *frame;
1690 XEvent *x_event_copy = &emacs_event->event.magic.
1693 #define FROB(event_member, window_member) \
1694 x_event_copy->event_member = x_event->event_member; \
1695 w = x_event->event_member.window_member
1697 switch (x_event->type) {
1698 case SelectionRequest:
1699 FROB(xselectionrequest, owner);
1701 case SelectionClear:
1702 FROB(xselectionclear, window);
1704 case SelectionNotify:
1705 FROB(xselection, requestor);
1707 case PropertyNotify:
1708 FROB(xproperty, window);
1711 FROB(xclient, window);
1713 case ConfigureNotify:
1714 FROB(xconfigure, window);
1717 case GraphicsExpose:
1718 FROB(xexpose, window);
1726 FROB(xcrossing, window);
1730 FROB(xfocus, window);
1732 case VisibilityNotify:
1733 FROB(xvisibility, window);
1736 FROB(xcreatewindow, window);
1739 w = x_event->xany.window;
1740 *x_event_copy = *x_event;
1744 frame = x_any_window_to_frame(d, w);
1749 emacs_event->event_type = magic_event;
1750 XSETFRAME(emacs_event->channel, frame);
1758 /************************************************************************/
1759 /* magic-event handling */
1760 /************************************************************************/
1762 static void handle_focus_event_1(struct frame *f, int in_p)
1764 handle_focus_event_2(XtWindow(FRAME_X_TEXT_WIDGET(f)), f, in_p);
1767 static void handle_focus_event_2(Window win, struct frame *f, int in_p)
1769 /* Although this treats focus differently for all widgets (including
1770 the frame) it seems to work ok. */
1771 Widget needs_it = XtWindowToWidget(FRAME_X_DISPLAY(f), win);
1773 #if XtSpecificationRelease > 5
1774 widget_with_focus = XtGetKeyboardFocusWidget(FRAME_X_TEXT_WIDGET(f));
1777 XIM_focus_event(f, in_p);
1778 #endif /* HAVE_XIM */
1780 /* On focus change, clear all memory of sticky modifiers
1781 to avoid non-intuitive behavior. */
1782 clear_sticky_modifiers(XDEVICE(FRAME_DEVICE(f)));
1784 /* We don't want to handle the focus change now, because we might
1785 be in an accept-process-output, sleep-for, or sit-for. So
1788 Actually, we half handle it: we handle it as far as changing the
1789 box cursor for redisplay, but we don't call any hooks or do any
1790 select-frame stuff until after the sit-for.
1792 Unfortunately native widgets break the model because they grab
1793 the keyboard focus and nothing sets it back again. I cannot find
1794 any reasonable way to do this elsewhere so we assert here that
1795 the keyboard focus is on the emacs text widget. Menus and dialogs
1796 do this in their selection callback, but we don't want that since
1797 a button having focus is legitimate. An edit field having focus
1798 is mandatory. Weirdly you get a FocusOut event when you click in
1799 a widget-glyph but you don't get a corresponding FocusIn when you
1800 click in the frame. Why is this? */
1802 #if XtSpecificationRelease > 5
1803 && needs_it != widget_with_focus
1806 lw_set_keyboard_focus(FRAME_X_SHELL_WIDGET(f), needs_it);
1809 /* If we are focusing on a native widget then record and exit. */
1810 if (needs_it != FRAME_X_TEXT_WIDGET(f)) {
1811 widget_with_focus = needs_it;
1815 /* We have the focus now. See comment in
1816 emacs_Xt_handle_widget_losing_focus (). */
1818 widget_with_focus = NULL;
1820 /* do the generic event-stream stuff. */
1824 struct gcpro gcpro1;
1827 conser = Fcons(frm, Fcons(FRAME_DEVICE(f), in_p ? Qt : Qnil));
1829 emacs_handle_focus_change_preliminary(conser);
1830 enqueue_magic_eval_event(
1831 emacs_handle_focus_change_final, conser);
1836 /* Create a synthetic X focus event. */
1838 enqueue_focus_event(Widget wants_it, Lisp_Object frame, int in_p)
1840 Lisp_Object emacs_event = Fmake_event(Qnil, Qnil);
1841 Lisp_Event *ev = XEVENT(emacs_event);
1842 XEvent *x_event = &ev->event.magic.underlying_x_event;
1844 x_event->type = in_p ? FocusIn : FocusOut;
1845 x_event->xfocus.window = XtWindow(wants_it);
1847 ev->channel = frame;
1848 ev->event_type = magic_event;
1850 enqueue_Xt_dispatch_event(emacs_event);
1853 /* The idea here is that when a widget glyph gets unmapped we don't
1854 want the focus to stay with it if it has focus - because it may
1855 well just get deleted next and then we have lost the focus until the
1856 user does something. So handle_focus_event_1 records the widget
1857 with keyboard focus when FocusOut is processed, and then, when a
1858 widget gets unmapped, it calls this function to restore focus if
1860 void emacs_Xt_handle_widget_losing_focus(struct frame *f, Widget losing_widget);
1861 void emacs_Xt_handle_widget_losing_focus(struct frame *f, Widget losing_widget)
1863 if (losing_widget == widget_with_focus) {
1864 handle_focus_event_1(f, 1);
1868 /* This is called from the external-widget code */
1870 void emacs_Xt_handle_focus_event(XEvent * event);
1871 void emacs_Xt_handle_focus_event(XEvent * event)
1873 struct device *d = get_device_from_display(event->xany.display);
1876 if (DEVICE_X_BEING_DELETED(d))
1880 * It's curious that we're using x_any_window_to_frame() instead
1881 * of x_window_to_frame(). I don't know what the impact of this is.
1883 f = x_any_window_to_frame(d, event->xfocus.window);
1885 /* focus events are sometimes generated just before
1886 a frame is destroyed. */
1888 handle_focus_event_1(f, event->type == FocusIn);
1891 /* both MapNotify and VisibilityNotify can cause this
1892 JV is_visible has the same semantics as f->visible*/
1893 static void change_frame_visibility(struct frame *f, int is_visible)
1897 XSETFRAME(frame, f);
1899 if (!FRAME_VISIBLE_P(f) && is_visible) {
1900 FRAME_VISIBLE_P(f) = is_visible;
1901 /* This improves the double flicker when uniconifying a frame
1902 some. A lot of it is not showing a buffer which has changed
1903 while the frame was iconified. To fix it further requires
1904 the good 'ol double redisplay structure. */
1905 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
1906 va_run_hook_with_args(Qmap_frame_hook, 1, frame);
1907 } else if (FRAME_VISIBLE_P(f) && !is_visible) {
1908 FRAME_VISIBLE_P(f) = 0;
1909 va_run_hook_with_args(Qunmap_frame_hook, 1, frame);
1910 } else if (FRAME_VISIBLE_P(f) * is_visible < 0) {
1911 FRAME_VISIBLE_P(f) = -FRAME_VISIBLE_P(f);
1912 if (FRAME_REPAINT_P(f))
1913 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
1914 va_run_hook_with_args(Qmap_frame_hook, 1, frame);
1918 static void handle_map_event(struct frame *f, XEvent * event)
1922 XSETFRAME(frame, f);
1923 if (event->type == MapNotify) {
1924 XWindowAttributes xwa;
1926 /* Bleagh!!!!!! Apparently some window managers (e.g. MWM)
1927 send synthetic MapNotify events when a window is first
1928 created, EVEN IF IT'S CREATED ICONIFIED OR INVISIBLE.
1929 Or something like that. We initially tried a different
1930 solution below, but that ran into a different window-
1933 It seems that the only reliable way is to treat a
1934 MapNotify event as a "hint" that the window might or
1935 might not be visible, and check explicitly. */
1937 XGetWindowAttributes(event->xany.display, event->xmap.window,
1939 if (xwa.map_state != IsViewable) {
1940 /* Calling Fframe_iconified_p is the only way we have to
1941 correctly update FRAME_ICONIFIED_P */
1942 Fframe_iconified_p(frame);
1946 FRAME_X_TOTALLY_VISIBLE_P(f) = 1;
1948 /* Bleagh again!!!! We initially tried the following hack
1949 around the MWM problem, but it turns out that TWM
1950 has a race condition when you un-iconify, where it maps
1951 the window and then tells the server that the window
1952 is un-iconified. Usually, SXEmacs wakes up between
1953 those two occurrences, and thus thinks that un-iconified
1954 windows are still iconified.
1956 Ah, the joys of X. */
1958 /* By Emacs definition, a frame that is iconified is not
1959 visible. Marking a frame as visible will automatically cause
1960 frame-iconified-p to return nil, regardless of whether the
1961 frame is actually iconified. Therefore, we have to ignore
1962 MapNotify events on iconified frames. (It's not obvious
1963 to me why these are being sent, but it happens at startup
1964 with frames that are initially iconified; perhaps they are
1965 synthetic MapNotify events coming from the window manager.)
1966 Note that `frame-iconified-p' queries the server
1967 to determine whether the frame is currently iconified,
1968 rather than consulting some internal (and likely
1969 inaccurate) state flag. Therefore, ignoring the MapNotify
1971 if (!FRAME_VISIBLE_P(f) && NILP(Fframe_iconified_p(frame)))
1973 change_frame_visibility(f, 1);
1975 FRAME_X_TOTALLY_VISIBLE_P(f) = 0;
1976 change_frame_visibility(f, 0);
1977 /* Calling Fframe_iconified_p is the only way we have to
1978 correctly update FRAME_ICONIFIED_P */
1979 Fframe_iconified_p(frame);
1983 static void handle_client_message(struct frame *f, XEvent * event)
1985 struct device *d = XDEVICE(FRAME_DEVICE(f));
1988 XSETFRAME(frame, f);
1990 if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS(d) &&
1991 (Atom) (event->xclient.data.l[0]) ==
1992 DEVICE_XATOM_WM_DELETE_WINDOW(d)) {
1993 /* WM_DELETE_WINDOW is a misc-user event, but other
1994 ClientMessages, such as WM_TAKE_FOCUS, are eval events.
1995 That's because delete-window was probably executed with a
1996 mouse click, while the others could have been sent as a
1997 result of mouse motion or some other implicit action. (Call
1998 this a "heuristic"...) The reason for caring about this is
1999 so that clicking on the close-box will make emacs prompt
2000 using a dialog box instead of the minibuffer if there are
2003 enqueue_misc_user_event(frame, Qeval,
2004 list3(Qdelete_frame, frame, Qt));
2005 } else if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS(d)
2006 && (Atom) event->xclient.data.l[0] ==
2007 DEVICE_XATOM_WM_TAKE_FOCUS(d)) {
2008 handle_focus_event_1(f, 1);
2010 /* If there is a dialog box up, focus on it.
2012 #### Actually, we're raising it too, which is wrong. We should
2013 #### just focus on it, but lwlib doesn't currently give us an
2014 #### easy way to do that. This should be fixed.
2016 unsigned long take_focus_timestamp = event->xclient.data.l[1];
2017 Widget widget = lw_raise_all_pop_up_widgets();
2019 /* kludge: raise_all returns bottommost widget, but we really
2020 want the topmost. So just raise it for now. */
2021 XMapRaised(XtDisplay(widget), XtWindow(widget));
2022 /* Grab the focus with the timestamp of the TAKE_FOCUS. */
2023 XSetInputFocus(XtDisplay(widget), XtWindow(widget),
2024 RevertToParent, take_focus_timestamp);
2030 /* #### I'm struggling to understand how the X event loop really works.
2031 Here is the problem:
2033 When widgets get mapped / changed etc the actual display updates
2034 are done asynchronously via X events being processed - this
2035 normally happens when XtAppProcessEvent() gets called. However, if
2036 we are executing lisp code or even doing redisplay we won't
2037 necessarily process X events for a very long time. This has the
2038 effect of widgets only getting updated when SXEmacs only goes into
2039 idle, or some other event causes processing of the X event queue.
2041 XtAppProcessEvent can get called from the following places:
2043 emacs_Xt_next_event () - this is normal event processing, almost
2044 any non-X event will take precedence and this means that we
2045 cannot rely on it to do the right thing at the right time for
2048 drain_X_queue () - this happens when SIGIO gets tripped,
2049 processing the event queue allows C-g to be checked for. It gets
2050 called from emacs_Xt_event_pending_p ().
2052 In order to solve this I have tried introducing a list primitive -
2053 dispatch-non-command-events - which forces processing of X events
2054 related to display. Unfortunately this has a number of problems,
2055 one is that it is possible for event_stream_event_pending_p to
2056 block for ever if there isn't actually an event. I guess this can
2057 happen if we drop the synthetic event for reason. It also relies on
2058 SIGIO processing which makes things rather fragile.
2060 People have seen behaviour whereby SXEmacs blocks until you move the
2061 mouse. This seems to indicate that dispatch-non-command-events is
2062 blocking. It may be that in a SIGIO world forcing SIGIO processing
2063 does the wrong thing.
2065 static void emacs_Xt_force_event_pending(struct frame *f)
2069 Display *dpy = DEVICE_X_DISPLAY(XDEVICE(FRAME_DEVICE(f)));
2070 event.xclient.type = ClientMessage;
2071 event.xclient.display = dpy;
2072 event.xclient.message_type = XInternAtom(dpy, "BumpQueue", False);
2073 event.xclient.format = 32;
2074 event.xclient.window = 0;
2076 /* Send the drop message */
2077 XSendEvent(dpy, XtWindow(FRAME_X_SHELL_WIDGET(f)),
2078 True, NoEventMask, &event);
2079 /* We rely on SIGIO and friends to realise we have generated an
2083 static void emacs_Xt_handle_magic_event(Lisp_Event * emacs_event)
2085 /* This function can GC */
2086 XEvent *event = &emacs_event->event.magic.underlying_x_event;
2087 struct frame *f = XFRAME(EVENT_CHANNEL(emacs_event));
2089 if (!FRAME_LIVE_P(f)
2090 || DEVICE_X_BEING_DELETED(XDEVICE(FRAME_DEVICE(f))))
2093 switch (event->type) {
2094 case SelectionRequest:
2095 x_handle_selection_request(&event->xselectionrequest);
2098 case SelectionClear:
2099 x_handle_selection_clear(&event->xselectionclear);
2102 case SelectionNotify:
2103 x_handle_selection_notify(&event->xselection);
2106 case PropertyNotify:
2107 x_handle_property_notify(&event->xproperty);
2111 if (!check_for_ignored_expose
2112 (f, event->xexpose.x, event->xexpose.y,
2113 event->xexpose.width, event->xexpose.height)
2114 && !find_matching_subwindow(f, event->xexpose.x,
2116 event->xexpose.width,
2117 event->xexpose.height))
2118 x_redraw_exposed_area(f, event->xexpose.x,
2120 event->xexpose.width,
2121 event->xexpose.height);
2124 case GraphicsExpose:
2125 /* This occurs when an XCopyArea's source area was
2126 * obscured or not available. */
2127 x_redraw_exposed_area(f, event->xexpose.x, event->xexpose.y,
2128 event->xexpose.width,
2129 event->xexpose.height);
2134 handle_map_event(f, event);
2138 if (event->xcrossing.detail != NotifyInferior) {
2141 XSETFRAME(frame, f);
2142 /* FRAME_X_MOUSE_P (f) = 1; */
2143 va_run_hook_with_args(Qmouse_enter_frame_hook, 1,
2149 if (event->xcrossing.detail != NotifyInferior) {
2152 XSETFRAME(frame, f);
2153 /* FRAME_X_MOUSE_P (f) = 0; */
2154 va_run_hook_with_args(Qmouse_leave_frame_hook, 1,
2162 #ifdef EXTERNAL_WIDGET
2163 /* External widget lossage:
2164 Ben said: YUCK. The only way to make focus changes work
2165 properly is to completely ignore all FocusIn/FocusOut events
2166 and depend only on notifications from the ExternalClient
2168 if (FRAME_X_EXTERNAL_WINDOW_P(f)) {
2172 handle_focus_event_2(event->xfocus.window, f,
2173 event->type == FocusIn);
2177 handle_client_message(f, event);
2180 case VisibilityNotify:
2181 /* window visibility has changed */
2182 if (event->xvisibility.window ==
2183 XtWindow(FRAME_X_SHELL_WIDGET(f))) {
2184 FRAME_X_TOTALLY_VISIBLE_P(f) =
2185 (event->xvisibility.state == VisibilityUnobscured);
2186 /* Note that the fvwm pager only sends VisibilityNotify
2187 when changing pages. Is this all we need to do ?
2189 /* Nope. We must at least trigger a redisplay here.
2190 Since this case seems similar to MapNotify, I've
2191 factored out some code to change_frame_visibility().
2192 This triggers the necessary redisplay and runs
2193 (un)map-frame-hook. - dkindred@cs.cmu.edu */
2194 /* Changed it again to support the tristate visibility
2196 change_frame_visibility(f, (event->xvisibility.state
2198 VisibilityFullyObscured) ? 1
2203 case ConfigureNotify:
2217 /************************************************************************/
2218 /* timeout events */
2219 /************************************************************************/
2221 static int timeout_id_tick;
2223 /* Xt interval id's might not fit into an int (they're pointers, as it
2224 happens), so we need to provide a conversion list. */
2226 /* pending_timeouts is a set (unordered), implemented as a stack.
2227 completed_timeouts* is a queue. */
2228 static struct Xt_timeout {
2230 XtIntervalId interval_id;
2231 struct Xt_timeout *next;
2232 } *pending_timeouts, *completed_timeouts_head, *completed_timeouts_tail;
2234 static struct Xt_timeout_blocktype {
2235 Blocktype_declare(struct Xt_timeout);
2236 } *the_Xt_timeout_blocktype;
2238 /* called by XtAppNextEvent() */
2239 static void Xt_timeout_callback(XtPointer closure, XtIntervalId * id)
2241 struct Xt_timeout *timeout = (struct Xt_timeout *)closure;
2242 struct Xt_timeout *t2 = pending_timeouts;
2244 /* Remove this one from the set of pending timeouts */
2245 if(timeout == NULL) {
2249 if (t2 == timeout) {
2250 pending_timeouts = pending_timeouts->next;
2252 while (t2->next && t2->next != timeout) {
2257 t2->next = t2->next->next;
2259 /* Add this one to the queue of completed timeouts */
2260 timeout->next = NULL;
2261 if (completed_timeouts_head) {
2262 completed_timeouts_tail->next = timeout;
2264 completed_timeouts_head = timeout;
2266 completed_timeouts_tail = timeout;
2269 static int emacs_Xt_add_timeout(EMACS_TIME thyme)
2271 struct Xt_timeout *timeout = Blocktype_alloc(the_Xt_timeout_blocktype);
2272 EMACS_TIME current_time;
2275 timeout->id = timeout_id_tick++;
2276 timeout->next = pending_timeouts;
2277 pending_timeouts = timeout;
2278 EMACS_GET_TIME(current_time);
2279 EMACS_SUB_TIME(thyme, thyme, current_time);
2280 milliseconds = EMACS_SECS(thyme) * 1000 + EMACS_USECS(thyme) / 1000;
2282 if (milliseconds < 1) {
2285 timeout->interval_id = XtAppAddTimeOut(Xt_app_con, milliseconds,
2286 Xt_timeout_callback,
2287 (XtPointer) timeout);
2291 #ifdef EF_USE_ASYNEQ
2292 #if 1 /* timeout based */
2293 static void Xt_watch_eq_cb(XtPointer closure, XtIntervalId *id);
2294 static int emacs_Xt_watch_event_queue(event_queue_t eq);
2295 extern void asyneq_handle_event(event_queue_t eq);
2296 extern void asyneq_handle_non_command_event(event_queue_t eq);
2299 Xt_watch_eq_cb(XtPointer closure, XtIntervalId *id)
2301 event_queue_t eq = (event_queue_t)closure;
2302 /* reestablish timeout, in case asyneq_handle_event gets to exit
2304 emacs_Xt_watch_event_queue(eq);
2305 asyneq_handle_non_command_event(eq);
2309 emacs_Xt_watch_event_queue(event_queue_t eq)
2311 int milliseconds = 10;
2312 size_t eqsz = eq_queue_size(eq)+1; /* never be 0 */
2315 while ((milliseconds*eqsz) > 100)
2321 return XtAppAddTimeOut(
2322 Xt_app_con, milliseconds, Xt_watch_eq_cb, (XtPointer)eq);
2324 #else /* work-procedure based (sets cpu on fire) */
2326 Xt_watch_eq_cb(XtPointer closure)
2328 event_queue_t eq = (event_queue_t)closure;
2329 asyneq_handle_event(eq);
2330 return FALSE; /* we never finish with this job */
2334 emacs_Xt_watch_event_queue(event_queue_t eq)
2336 return XtAppAddWorkProc(Xt_app_con, Xt_watch_eq_cb, (XtPointer)eq);
2339 #endif /* EF_USE_ASYNEQ */
2341 static void emacs_Xt_remove_timeout(int id)
2343 struct Xt_timeout *timeout, *t2;
2347 /* Find the timeout on the list of pending ones, if it's still there. */
2348 if (pending_timeouts) {
2349 if (id == pending_timeouts->id) {
2350 timeout = pending_timeouts;
2351 pending_timeouts = pending_timeouts->next;
2353 t2 = pending_timeouts;
2354 while (t2->next && t2->next->id != id)
2356 if (t2->next) { /*found it */
2358 t2->next = t2->next->next;
2361 /* if it was pending, we have removed it from the list */
2363 XtRemoveTimeOut(timeout->interval_id);
2366 /* It could be that Xt_timeout_callback was already called but we didn't
2367 convert into an Emacs event yet */
2368 if (!timeout && completed_timeouts_head) {
2369 /* Thank God for code duplication! */
2370 if (id == completed_timeouts_head->id) {
2371 timeout = completed_timeouts_head;
2372 completed_timeouts_head = completed_timeouts_head->next;
2373 /* this may not be necessary? */
2374 if (!completed_timeouts_head)
2375 completed_timeouts_tail = NULL;
2377 t2 = completed_timeouts_head;
2378 while (t2->next && t2->next->id != id)
2380 if (t2->next) { /* found it */
2382 t2->next = t2->next->next;
2384 completed_timeouts_tail = t2;
2389 /* If we found the thing on the lists of timeouts,
2390 and removed it, deallocate
2393 Blocktype_free(the_Xt_timeout_blocktype, timeout);
2398 Xt_timeout_to_emacs_event(Lisp_Event * emacs_event)
2400 struct Xt_timeout *timeout = completed_timeouts_head;
2402 completed_timeouts_head = completed_timeouts_head->next;
2403 /* probably unnecessary */
2404 if (!completed_timeouts_head) {
2405 completed_timeouts_tail = NULL;
2407 emacs_event->event_type = timeout_event;
2408 /* timeout events have nil as channel */
2409 emacs_event->timestamp = 0; /* #### wrong!! */
2410 emacs_event->event.timeout.interval_id = timeout->id;
2411 emacs_event->event.timeout.function = Qnil;
2412 emacs_event->event.timeout.object = Qnil;
2413 Blocktype_free(the_Xt_timeout_blocktype, timeout);
2416 /************************************************************************/
2417 /* process and tty events */
2418 /************************************************************************/
2420 struct what_is_ready_closure {
2426 static Lisp_Object filedesc_with_input[MAXDESC];
2427 static struct what_is_ready_closure *filedesc_to_what_closure[MAXDESC];
2429 static void init_what_input_once(void)
2434 filedesc_with_input = xnew_array(Lisp_Object, MAXDESC);
2435 filedesc_to_what_closure =
2436 xnew_array(struct what_is_ready_closure *, MAXDESC);
2439 for (i = 0; i < MAXDESC; i++) {
2440 filedesc_to_what_closure[i] = NULL;
2441 filedesc_with_input[i] = Qnil;
2444 process_events_occurred = 0;
2445 tty_events_occurred = 0;
2450 mark_what_as_being_ready(struct what_is_ready_closure *closure)
2452 if (NILP(filedesc_with_input[closure->fd])) {
2453 SELECT_TYPE temp_mask;
2454 FD_ZERO(&temp_mask);
2455 FD_SET(closure->fd, &temp_mask);
2456 /* Check to make sure there's *really* input available.
2457 Sometimes things seem to get confused and this gets called
2458 for the tty fd when there's really only input available
2459 on some process's fd. (It will subsequently get called
2460 for that process's fd, so returning without setting any
2461 flags will take care of it.) To see the problem, uncomment
2462 the stderr_out below, turn NORMAL_QUIT_CHECK_TIMEOUT_MSECS
2463 down to 25, do sh -c 'sxemacs -nw -q -f shell 2>/tmp/log'
2464 and press return repeatedly. (Seen under AIX & Linux.)
2465 -dkindred@cs.cmu.edu */
2466 if (!poll_fds_for_input(temp_mask)) {
2469 "mark_what_as_being_ready: "
2470 "no input available (fd=%d)\n",
2475 filedesc_with_input[closure->fd] = closure->what;
2476 if (PROCESSP(closure->what)) {
2477 /* Don't increment this if the current process is
2478 already marked as having input. */
2479 process_events_occurred++;
2481 tty_events_occurred++;
2488 Xt_what_callback(void *closure, int *source, XtInputId *id)
2490 /* If closure is 0, then we got a fake event from a signal handler.
2491 The only purpose of this is to make XtAppProcessEvent() stop
2494 mark_what_as_being_ready(closure);
2496 fake_event_occurred++;
2497 drain_signal_event_pipe();
2503 select_filedesc(int fd, Lisp_Object what)
2505 struct what_is_ready_closure *closure;
2507 /* If somebody is trying to select something that's already selected
2508 for, then something went wrong. The generic routines ought to
2509 detect this and error before here. */
2510 assert(!filedesc_to_what_closure[fd]);
2512 closure = xnew(struct what_is_ready_closure);
2514 closure->what = what;
2515 closure->id = XtAppAddInput(
2517 (XtPointer)(XtInputReadMask /* | XtInputExceptMask */),
2518 Xt_what_callback, closure);
2519 filedesc_to_what_closure[fd] = closure;
2524 unselect_filedesc(int fd)
2526 struct what_is_ready_closure *closure = filedesc_to_what_closure[fd];
2529 if (!NILP(filedesc_with_input[fd])) {
2530 /* We are unselecting this process before we have drained the
2531 rest of the input from it, probably from status_notify() in
2532 the command loop. This can happen like so:
2534 - We are waiting in XtAppNextEvent()
2535 - Process generates output
2536 - Process is marked as being ready
2537 - Process dies, SIGCHLD gets generated before we return (!?)
2538 It could happen I guess.
2539 - sigchld_handler() marks process as dead
2540 - Somehow we end up getting a new KeyPress event on the queue
2541 at the same time (I'm really so sure how that happens but I'm
2542 not sure it can't either so let's assume it can...).
2543 - Key events have priority so we return that
2544 instead of the proc.
2545 - Before dispatching the lisp key event we call
2547 - which deselects the process that SIGCHLD marked as dead.
2549 Thus we never remove it from _with_input and turn it into a
2550 lisp event, so we need to do it here. But this does not mean
2551 that we're throwing away the last block of output -
2552 status_notify() has already taken care of running the proc
2555 filedesc_with_input[fd] = Qnil;
2556 if (PROCESSP(closure->what)) {
2557 assert(process_events_occurred > 0);
2558 process_events_occurred--;
2560 assert(tty_events_occurred > 0);
2561 tty_events_occurred--;
2564 XtRemoveInput(closure->id);
2566 filedesc_to_what_closure[fd] = 0;
2571 emacs_Xt_select_process(Lisp_Process * p)
2573 Lisp_Object process;
2574 int infd = event_stream_unixoid_select_process(p);
2576 XSETPROCESS(process, p);
2578 select_filedesc(infd, process);
2583 emacs_Xt_unselect_process(Lisp_Process * p)
2585 int infd = event_stream_unixoid_unselect_process(p);
2588 unselect_filedesc(infd);
2593 emacs_Xt_create_stream_pair(void *inhandle, void *outhandle,
2594 Lisp_Object *instream, Lisp_Object *outstream,
2597 USID u = event_stream_unixoid_create_stream_pair(
2598 inhandle, outhandle, instream, outstream, flags);
2599 if (u != USID_ERROR) {
2606 emacs_Xt_delete_stream_pair(Lisp_Object instream, Lisp_Object outstream)
2608 event_stream_unixoid_delete_stream_pair(instream, outstream);
2609 return USID_DONTHASH;
2612 /* This is called from GC when a process object is about to be freed.
2613 If we've still got pointers to it in this file, we're gonna lose hard.
2615 void debug_process_finalization(Lisp_Process * p)
2619 Lisp_Object instr, outstr;
2621 get_process_streams(p, &instr, &outstr);
2622 /* if it still has fds, then it hasn't been killed yet. */
2623 assert(NILP(instr));
2624 assert(NILP(outstr));
2625 /* Better not still be in the "with input" table; we know it's got no fds. */
2626 for (i = 0; i < MAXDESC; i++) {
2627 Lisp_Object process = filedesc_fds_with_input[i];
2628 assert(!PROCESSP(process) || XPROCESS(process) != p);
2635 Xt_process_to_emacs_event(Lisp_Event * emacs_event)
2639 assert(process_events_occurred > 0);
2641 for (i = 0; i < MAXDESC; i++) {
2642 Lisp_Object process = filedesc_with_input[i];
2643 if (PROCESSP(process)) {
2644 filedesc_with_input[i] = Qnil;
2645 process_events_occurred--;
2646 /* process events have nil as channel */
2647 emacs_event->event_type = process_event;
2648 emacs_event->timestamp = 0; /* #### */
2649 emacs_event->event.process.process = process;
2657 emacs_Xt_select_console(struct console *con)
2659 Lisp_Object console;
2662 if (CONSOLE_X_P(con)) {
2663 /* X consoles are automatically selected for when we
2664 initialize them in Xt */
2667 infd = event_stream_unixoid_select_console(con);
2668 XSETCONSOLE(console, con);
2670 select_filedesc(infd, console);
2675 emacs_Xt_unselect_console(struct console *con)
2677 Lisp_Object console;
2680 if (CONSOLE_X_P(con)) {
2681 /* X consoles are automatically selected for when we
2682 initialize them in Xt */
2685 infd = event_stream_unixoid_unselect_console(con);
2686 XSETCONSOLE(console, con);
2688 unselect_filedesc(infd);
2692 /* read an event from a tty, if one is available. Returns non-zero
2693 if an event was available. Note that when this function is
2694 called, there should always be a tty marked as ready for input.
2695 However, the input condition might actually be EOF, so there
2696 may not really be any input available. (In this case,
2697 read_event_from_tty_or_stream_desc() will arrange for the TTY device
2701 Xt_tty_to_emacs_event(Lisp_Event * emacs_event)
2705 assert(tty_events_occurred > 0);
2706 for (i = 0; i < MAXDESC; i++) {
2707 Lisp_Object console = filedesc_with_input[i];
2708 if (CONSOLEP(console)) {
2709 assert(tty_events_occurred > 0);
2710 tty_events_occurred--;
2711 filedesc_with_input[i] = Qnil;
2712 if (read_event_from_tty_or_stream_desc(
2713 emacs_event, XCONSOLE(console), i)) {
2722 /************************************************************************/
2723 /* debugging functions to decipher an event */
2724 /************************************************************************/
2726 #ifdef DEBUG_SXEMACS
2727 #include "xintrinsicp.h" /* only describe_event() needs this */
2728 #include <X11/Xproto.h> /* only describe_event() needs this */
2730 static void describe_event_window(Window window, Display * display)
2734 stderr_out(" window: 0x%lx", (unsigned long)window);
2735 w = XtWindowToWidget(display, window);
2737 stderr_out(" %s", w->core.widget_class->core_class.class_name);
2738 f = x_any_window_to_frame(get_device_from_display(display), window);
2740 int len = XSTRING_LENGTH(f->name) + 4;
2743 int sz = snprintf(buf, len, " \"%s\"", XSTRING_DATA(f->name));
2744 assert(sz >= 0 && sz < len);
2745 write_string_to_stdio_stream(stderr, 0, (Bufbyte*)buf, 0,
2751 static const char *XEvent_mode_to_string(int mode)
2760 case NotifyWhileGrabbed:
2761 return "WhileGrabbed";
2767 static const char *XEvent_detail_to_string(int detail)
2770 case NotifyAncestor:
2772 case NotifyInferior:
2774 case NotifyNonlinear:
2776 case NotifyNonlinearVirtual:
2777 return "NonlinearVirtual";
2780 case NotifyPointerRoot:
2781 return "PointerRoot";
2782 case NotifyDetailNone:
2783 return "DetailNone";
2789 static const char *XEvent_visibility_to_string(int state)
2792 case VisibilityFullyObscured:
2793 return "FullyObscured";
2794 case VisibilityPartiallyObscured:
2795 return "PartiallyObscured";
2796 case VisibilityUnobscured:
2797 return "Unobscured";
2803 static void describe_event(XEvent * event)
2806 struct device *d = get_device_from_display(event->xany.display);
2808 int sz = snprintf(buf, sizeof(buf),
2809 "%s%s", x_event_name(event->type),
2810 event->xany.send_event ? " (send)" : "");
2811 assert(sz >= 0 && (size_t)sz < sizeof(buf));
2812 stderr_out("%-30s", buf);
2813 switch (event->type) {
2816 XFocusChangeEvent *ev = &event->xfocus;
2817 describe_event_window(ev->window, ev->display);
2818 stderr_out(" mode: %s\n",
2819 XEvent_mode_to_string(ev->mode));
2820 stderr_out(" detail: %s\n",
2821 XEvent_detail_to_string(ev->detail));
2826 XKeyEvent *ev = &event->xkey;
2827 unsigned int state = ev->state;
2829 describe_event_window(ev->window, ev->display);
2830 stderr_out(" subwindow: %ld\n", ev->subwindow);
2831 stderr_out(" state: ");
2832 /* Complete list of modifier key masks */
2833 if (state & ShiftMask)
2834 stderr_out("Shift ");
2835 if (state & LockMask)
2836 stderr_out("Lock ");
2837 if (state & ControlMask)
2838 stderr_out("Control ");
2839 if (state & Mod1Mask)
2840 stderr_out("Mod1 ");
2841 if (state & Mod2Mask)
2842 stderr_out("Mod2 ");
2843 if (state & Mod3Mask)
2844 stderr_out("Mod3 ");
2845 if (state & Mod4Mask)
2846 stderr_out("Mod4 ");
2847 if (state & Mod5Mask)
2848 stderr_out("Mod5 ");
2851 stderr_out("vanilla\n");
2854 if (x_key_is_modifier_p(ev->keycode, d))
2855 stderr_out(" Modifier key");
2856 stderr_out(" keycode: 0x%x\n", ev->keycode);
2861 if (debug_x_events > 1) {
2862 XExposeEvent *ev = &event->xexpose;
2863 describe_event_window(ev->window, ev->display);
2864 stderr_out(" region: x=%d y=%d width=%d height=%d\n",
2865 ev->x, ev->y, ev->width, ev->height);
2866 stderr_out(" count: %d\n", ev->count);
2872 case GraphicsExpose:
2873 if (debug_x_events > 1) {
2874 XGraphicsExposeEvent *ev = &event->xgraphicsexpose;
2875 describe_event_window(ev->drawable, ev->display);
2876 stderr_out(" major: %s\n",
2877 (ev->major_code == X_CopyArea ? "CopyArea" :
2879 X_CopyPlane ? "CopyPlane" : "?")));
2880 stderr_out(" region: x=%d y=%d width=%d height=%d\n",
2881 ev->x, ev->y, ev->width, ev->height);
2882 stderr_out(" count: %d\n", ev->count);
2890 if (debug_x_events > 1) {
2891 XCrossingEvent *ev = &event->xcrossing;
2892 describe_event_window(ev->window, ev->display);
2894 stderr_out(" subwindow: 0x%x\n", ev->subwindow);
2895 stderr_out(" pos: %d %d\n", ev->x, ev->y);
2896 stderr_out(" root pos: %d %d\n", ev->x_root,
2899 stderr_out(" mode: %s\n",
2900 XEvent_mode_to_string(ev->mode));
2901 stderr_out(" detail: %s\n",
2902 XEvent_detail_to_string(ev->detail));
2903 stderr_out(" focus: %d\n", ev->focus);
2905 stderr_out(" state: 0x%x\n", ev->state);
2912 case ConfigureNotify:
2913 if (debug_x_events > 1) {
2914 XConfigureEvent *ev = &event->xconfigure;
2915 describe_event_window(ev->window, ev->display);
2916 stderr_out(" above: 0x%lx\n", ev->above);
2917 stderr_out(" size: %d %d %d %d\n", ev->x, ev->y,
2918 ev->width, ev->height);
2919 stderr_out(" redirect: %d\n", ev->override_redirect);
2925 case VisibilityNotify:
2926 if (debug_x_events > 1) {
2927 XVisibilityEvent *ev = &event->xvisibility;
2928 describe_event_window(ev->window, ev->display);
2929 stderr_out(" state: %s\n",
2930 XEvent_visibility_to_string(ev->state));
2936 case ClientMessage: {
2937 XClientMessageEvent *ev = &event->xclient;
2938 char *name = XGetAtomName(ev->display, ev->message_type);
2939 stderr_out("%s", name);
2940 if (!strcmp(name, "WM_PROTOCOLS")) {
2942 XGetAtomName(ev->display, ev->data.l[0]);
2943 stderr_out("(%s)", protname);
2959 #endif /* include describe_event definition */
2961 /************************************************************************/
2962 /* get the next event from Xt */
2963 /************************************************************************/
2965 static Lisp_Object dispatch_event_queue, dispatch_event_queue_tail;
2967 void enqueue_Xt_dispatch_event(Lisp_Object event)
2969 enqueue_event(event, &dispatch_event_queue, &dispatch_event_queue_tail);
2972 static Lisp_Object dequeue_Xt_dispatch_event(void)
2974 return dequeue_event(&dispatch_event_queue, &dispatch_event_queue_tail);
2977 /* This business exists because menu events "happen" when
2978 menubar_selection_callback() is called from somewhere deep
2979 within XtAppProcessEvent in emacs_Xt_next_event(). The
2980 callback needs to terminate the modal loop in that function
2981 or else it will continue waiting until another event is
2984 Same business applies to scrollbar events. */
2987 signal_special_Xt_user_event(Lisp_Object channel, Lisp_Object function,
2990 Lisp_Object event = Fmake_event(Qnil, Qnil);
2992 XEVENT(event)->event_type = misc_user_event;
2993 XEVENT(event)->channel = channel;
2994 XEVENT(event)->event.eval.function = function;
2995 XEVENT(event)->event.eval.object = object;
2997 enqueue_Xt_dispatch_event(event);
3000 static void emacs_Xt_next_event(Lisp_Event * emacs_event)
3002 we_didnt_get_an_event:
3004 while (NILP(dispatch_event_queue) &&
3005 !completed_timeouts_head &&
3006 !fake_event_occurred &&
3007 !process_events_occurred && !tty_events_occurred) {
3009 /* Stupid logic in XtAppProcessEvent() dictates that, if process
3010 events and X events are both available, the process event
3011 gets taken first. This will cause an infinite loop if we're
3012 being called from Fdiscard_input().
3014 if (XtAppPending(Xt_app_con) & XtIMXEvent) {
3015 XtAppProcessEvent(Xt_app_con, XtIMXEvent);
3017 Lisp_Object devcons, concons;
3019 /* We're about to block. Xt has a bug in it (big
3020 surprise, there) in that it blocks using select() and
3021 doesn't flush the Xlib output buffers (XNextEvent()
3022 does this automatically before blocking). So it's
3023 necessary for us to do this ourselves. If we don't
3024 do it, then display output may not be seen until the
3025 next time an X event is received. (This happens
3026 esp. with subprocess output that gets sent to a
3029 #### The above comment may not have any validity. */
3031 DEVICE_LOOP_NO_BREAK(devcons, concons) {
3033 d = XDEVICE(XCAR(devcons));
3035 if (DEVICE_X_P(d) && DEVICE_X_DISPLAY(d)) {
3036 /* emacs may be exiting */
3037 XFlush(DEVICE_X_DISPLAY(d));
3040 XtAppProcessEvent(Xt_app_con, XtIMAll);
3044 if (!NILP(dispatch_event_queue)) {
3045 Lisp_Object event, event2;
3046 XSETEVENT(event2, emacs_event);
3047 event = dequeue_Xt_dispatch_event();
3048 Fcopy_event(event, event2);
3049 Fdeallocate_event(event);
3050 } else if (tty_events_occurred) {
3051 if (!Xt_tty_to_emacs_event(emacs_event))
3052 goto we_didnt_get_an_event;
3053 } else if (completed_timeouts_head) {
3054 Xt_timeout_to_emacs_event(emacs_event);
3055 } else if (fake_event_occurred) {
3056 /* A dummy event, so that a cycle of the command loop will occur. */
3057 fake_event_occurred = 0;
3058 /* eval events have nil as channel */
3059 emacs_event->event_type = eval_event;
3060 emacs_event->event.eval.function = Qidentity;
3061 emacs_event->event.eval.object = Qnil;
3063 /* if (process_events_occurred) */
3064 Xt_process_to_emacs_event(emacs_event);
3067 /* No need to call XFilterEvent; Xt does it for us */
3071 emacs_Xt_event_handler(Widget SXE_UNUSED(wid),
3072 XtPointer SXE_UNUSED(closure),
3074 Boolean * SXE_UNUSED(continue_to_dispatch))
3076 Lisp_Object emacs_event = Fmake_event(Qnil, Qnil);
3078 #ifdef DEBUG_SXEMACS
3079 if (debug_x_events > 0) {
3080 describe_event(event);
3082 #endif /* DEBUG_SXEMACS */
3083 if (x_event_to_emacs_event(event, XEVENT(emacs_event))) {
3084 enqueue_Xt_dispatch_event(emacs_event);
3086 Fdeallocate_event(emacs_event);
3090 /************************************************************************/
3091 /* input pending / C-g checking */
3092 /************************************************************************/
3095 quit_char_predicate(Display * display, XEvent * event, XPointer data)
3097 struct device *d = get_device_from_display(display);
3098 struct x_device *xd = DEVICE_X_DATA(d);
3100 Bool *critical = (Bool *) data;
3106 if ((event->type != KeyPress) ||
3107 (!x_any_window_to_frame(d, event->xany.window)) ||
3109 & (xd->MetaMask | xd->HyperMask | xd->SuperMask | xd->AltMask))) {
3113 /* This duplicates some code that exists elsewhere, but it's relatively
3114 fast and doesn't cons. */
3115 keysym = x_to_emacs_keysym(&event->xkey, 1);
3119 if (CHAR_OR_CHAR_INTP(keysym)) {
3120 c = XCHAR_OR_CHAR_INT(keysym);
3121 } else if (EQ(keysym, QKbackspace)) {
3122 /* Highly doubtful that these are the quit character, but... */
3124 } else if (EQ(keysym, QKtab)) {
3126 } else if (EQ(keysym, QKlinefeed)) {
3128 } else if (EQ(keysym, QKreturn)) {
3130 } else if (EQ(keysym, QKescape)) {
3132 } else if (EQ(keysym, QKspace)) {
3134 } else if (EQ(keysym, QKdelete)) {
3140 if (event->xkey.state & xd->MetaMask) {
3143 if ((event->xkey.state & ControlMask) && !(c >= 'A' && c <= 'Z')) {
3144 /* unshifted control characters */
3147 quit_char = CONSOLE_QUIT_CHAR(XCONSOLE(DEVICE_CONSOLE(d)));
3148 if (c == quit_char) {
3151 /* If we've got Control-Shift-G instead of Control-G, that means
3152 we have a critical_quit. Caps_Lock is its own modifier, so it
3153 won't cause ^G to act differently than before. */
3154 if (event->xkey.state & ControlMask) {
3157 if (c == quit_char) {
3166 /* This scans the X input queue for a KeyPress event that matches the
3167 quit character, and sets Vquit_flag. This is called from the
3168 QUIT macro to determine whether we should quit.
3170 In a SIGIO world, this won't be called unless a SIGIO has happened
3171 since the last time we checked.
3173 In a non-SIGIO world, this is called from emacs_Xt_event_pending_p
3174 (which is called from input_pending_p).
3177 x_check_for_quit_char(Display * display)
3181 Bool critical_quit = False;
3183 XEventsQueued(display, QueuedAfterReading);
3184 queued = XCheckIfEvent(display, &event,
3185 quit_char_predicate, (char *)&critical_quit);
3187 Vquit_flag = (critical_quit ? Qcritical : Qt);
3188 /* don't put the event back onto the queue. Those functions that
3189 wanted to read a ^G directly have arranged to do this. */
3194 check_for_tty_quit_char(struct device *d)
3196 SELECT_TYPE temp_mask;
3197 int infd = DEVICE_INFD(d);
3198 struct console *con = XCONSOLE(DEVICE_CONSOLE(d));
3199 Emchar quit_char = CONSOLE_QUIT_CHAR(con);
3201 FD_ZERO(&temp_mask);
3202 FD_SET(infd, &temp_mask);
3208 if (!poll_fds_for_input(temp_mask)) {
3212 event = Fmake_event(Qnil, Qnil);
3213 if (!read_event_from_tty_or_stream_desc
3214 (XEVENT(event), con, infd)) {
3215 /* EOF, or something ... */
3218 /* #### bogus. quit-char should be allowed to be any sort
3220 the_char = event_to_character(XEVENT(event), 1, 0, 0);
3221 if (the_char >= 0 && the_char == quit_char) {
3223 /* do not queue the C-g. See above. */
3227 /* queue the read event to be read for real later. */
3228 enqueue_Xt_dispatch_event(event);
3232 static void emacs_Xt_quit_p(void)
3234 Lisp_Object devcons, concons;
3235 CONSOLE_LOOP(concons) {
3236 struct console *con = XCONSOLE(XCAR(concons));
3237 if (!con->input_enabled) {
3241 CONSOLE_DEVICE_LOOP(devcons, con) {
3243 d = XDEVICE(XCAR(devcons));
3245 if (DEVICE_X_P(d) && DEVICE_X_DISPLAY(d)) {
3246 /* emacs may be exiting */
3247 x_check_for_quit_char(DEVICE_X_DISPLAY(d));
3248 } else if (DEVICE_TTY_P(d)) {
3249 check_for_tty_quit_char(d);
3255 static void drain_X_queue(void)
3257 Lisp_Object devcons, concons;
3258 CONSOLE_LOOP(concons) {
3259 struct console *con = XCONSOLE(XCAR(concons));
3260 if (!con->input_enabled) {
3264 /* sjt sez: Have you tried the loop over devices with
3265 XtAppPending(), not XEventsQueued()?
3266 Ben Sigelman sez: No.
3267 sjt sez: I'm guessing that the reason that your patch
3272 + d = XDEVICE (XCAR (devcons));
3273 + if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d)) {
3275 Ie, if the device goes down, SXEmacs detects that and deletes
3276 it. Then the if() fails (DEVICE_X_DISPLAY(d) is NULL), and
3277 we don't go into the Xlib-of-no-return. If you know
3278 different, I'd like to hear about it. ;-)
3280 These ideas haven't been tested; the code below works for
3283 CONSOLE_DEVICE_LOOP(devcons, con) {
3286 d = XDEVICE(XCAR(devcons));
3287 if (DEVICE_X_P(d) && DEVICE_X_DISPLAY(d)) {
3288 display = DEVICE_X_DISPLAY(d);
3289 while (XEventsQueued
3290 (display, QueuedAfterReading)) {
3291 XtAppProcessEvent(Xt_app_con,
3297 /* This is the old code, before Ben Sigelman's patch. */
3299 while (XtAppPending (Xt_app_con) & XtIMXEvent)
3300 XtAppProcessEvent (Xt_app_con, XtIMXEvent);
3305 emacs_Xt_event_pending_p(int user_p)
3310 /* If `user_p' is false, then this function returns whether there are any
3311 X, timeout, or fd events pending (that is, whether emacs_Xt_next_event()
3312 would return immediately without blocking).
3314 if `user_p' is true, then this function returns whether there are any
3315 *user generated* events available (that is, whether there are keyboard
3316 or mouse-click events ready to be read). This also implies that
3317 emacs_Xt_next_event() would not block.
3319 In a non-SIGIO world, this also checks whether the user has typed ^G,
3320 since this is a convenient place to do so. We don't need to do this
3321 in a SIGIO world, since input causes an interrupt.
3325 /* I don't think there's any point to this and it will nullify
3326 the speed gains achieved by the sigio_happened checking below.
3327 Its only advantage is that it may possibly make C-g response
3328 a bit faster. The C-g will be noticed within 0.25 second, anyway,
3329 even without this. */
3331 /* First check for C-g if necessary */
3336 /* This function used to simply check whether there were any X
3337 events (or if user_p was 1, it iterated over all the pending
3338 X events using XCheckIfEvent(), looking for keystrokes and
3339 button events). That worked in the old cheesoid event loop,
3340 which didn't go through XtAppDispatchEvent(), but it doesn't
3341 work any more -- X events may not result in anything. For
3342 example, a button press in a blank part of the menubar appears
3343 as an X event but will not result in any Emacs events (a
3344 button press that activates the menubar results in an Emacs
3345 event through the stop_next_event mechanism).
3347 The only accurate way of determining whether these X events
3348 translate into Emacs events is to go ahead and dispatch them
3349 until there's something on the dispatch queue. */
3351 /* See if there are any user events already on the queue. */
3352 EVENT_CHAIN_LOOP(event, dispatch_event_queue) {
3353 if (!user_p || command_event_p(event)) {
3358 /* See if there's any TTY input available.
3360 if (poll_fds_for_input(tty_only_mask)) {
3365 /* If not user_p and there are any timer or file-desc events
3366 pending, we know there will be an event so we're through. */
3367 XtInputMask pending_value;
3369 /* Note that formerly we just checked the value of
3370 XtAppPending() to determine if there was file-desc input.
3371 This doesn't work any more with the signal_event_pipe;
3372 XtAppPending() will says "yes" in this case but there isn't
3373 really any input. Another way of fixing this problem is for
3374 the signal_event_pipe to generate actual input in the form of
3375 an identity eval event or something. (#### maybe this
3376 actually happens?) */
3378 if (poll_fds_for_input(process_only_mask)) {
3381 pending_value = XtAppPending(Xt_app_con);
3383 if (pending_value & XtIMTimer) {
3388 /* XtAppPending() can be super-slow, esp. over a network connection.
3389 Quantify results have indicated that in some cases the
3390 call to detect_input_pending() completely dominates the
3391 running time of redisplay(). Fortunately, in a SIGIO world
3392 we can more quickly determine whether there are any X events:
3393 if an event has happened since the last time we checked, then
3394 a SIGIO will have happened. On a machine with broken SIGIO,
3395 we'll still be in an OK state -- the sigio_happened flag
3396 will get set at least once a second, so we'll be no more than
3397 one second behind reality. (In general it's OK if we
3398 erroneously report no input pending when input is actually
3399 pending() -- preemption is just a bit less efficient, that's
3400 all. It's bad bad bad if you err the other way -- you've
3401 promised that `next-event' won't block but it actually will,
3402 and some action might get delayed until the next time you
3406 /* quit_check_signal_tick_count is volatile so try to avoid race
3407 conditions by using a temporary variable */
3408 tick_count_val = quit_check_signal_tick_count;
3409 if (last_quit_check_signal_tick_count != tick_count_val
3410 #if !defined (SIGIO)
3411 || (XtIMXEvent & XtAppPending(Xt_app_con))
3414 last_quit_check_signal_tick_count = tick_count_val;
3416 /* We need to drain the entire queue now -- if we only
3417 drain part of it, we may later on end up with events
3418 actually pending but detect_input_pending() returning
3419 false because there wasn't another SIGIO. */
3422 EVENT_CHAIN_LOOP(event, dispatch_event_queue) {
3423 if (!user_p || command_event_p(event)) {
3433 emacs_Xt_current_event_timestamp(struct console *c)
3436 Lisp_Object devs = CONSOLE_DEVICE_LIST(c);
3441 struct device *d = XDEVICE(XCAR(devs));
3442 return DEVICE_X_LAST_SERVER_TIMESTAMP(d);
3446 /************************************************************************/
3447 /* replacement for standard string-to-pixel converter */
3448 /************************************************************************/
3450 /* This was constructed by ripping off the standard string-to-pixel
3451 converter from Converters.c in the Xt source code and modifying
3456 /* This is exported by the Xt library (at least by mine). If this
3457 isn't the case somewhere, rename this appropriately and remove
3458 the '#if 0'. Note, however, that I got "unknown structure"
3459 errors when I tried this. */
3460 XtConvertArgRec Const colorConvertArgs[] = {
3461 {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.screen),
3464 {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.colormap),
3470 #define done(type, value) \
3471 if (toVal->addr != NULL) { \
3472 if (toVal->size < sizeof(type)) { \
3473 toVal->size = sizeof(type); \
3476 *(type*)(toVal->addr) = (value); \
3478 static type static_val; \
3479 static_val = (value); \
3480 toVal->addr = (XPointer)&static_val; \
3482 toVal->size = sizeof(type); \
3483 return True /* Caller supplies `;' */
3485 /* JH: We use this because I think there's a possibility this
3486 is called before the device is properly set up, in which case
3487 I don't want to abort. */
3488 extern struct device *get_device_from_display_1(Display * dpy);
3491 Boolean EmacsXtCvtStringToPixel(Display * dpy,
3493 Cardinal * num_args,
3494 XrmValuePtr fromVal,
3495 XrmValuePtr toVal, XtPointer * closure_ret)
3497 String str = (String) fromVal->addr;
3506 Cardinal num_params = 1;
3507 XtAppContext the_app_con = XtDisplayToApplicationContext(dpy);
3509 if (*num_args != 2) {
3510 XtAppWarningMsg(the_app_con, "wrongParameters",
3511 "cvtStringToPixel", "XtToolkitError",
3512 "String to pixel conversion needs "
3513 "screen and colormap arguments",
3514 (String *) NULL, (Cardinal *) NULL);
3518 screen = *((Screen **) args[0].addr);
3519 colormap = *((Colormap *) args[1].addr);
3521 /* The original uses the private function CompareISOLatin1().
3522 Use XmuCompareISOLatin1() if you want, but I don't think it
3523 makes any difference here. */
3524 if (strcmp(str, XtDefaultBackground) == 0) {
3525 *closure_ret = False;
3526 /* This refers to the display's "*reverseVideo" resource.
3527 These display resources aren't documented anywhere that
3528 I can find, so I'm going to ignore this. */
3529 /* if (pd->rv) done(Pixel, BlackPixelOfScreen(screen)) else */
3530 done(Pixel, WhitePixelOfScreen(screen));
3532 if (strcmp(str, XtDefaultForeground) == 0) {
3533 *closure_ret = False;
3534 /* if (pd->rv) done(Pixel, WhitePixelOfScreen(screen)) else */
3535 done(Pixel, BlackPixelOfScreen(screen));
3538 /* Originally called XAllocNamedColor() here. */
3539 if ((d = get_device_from_display_1(dpy))) {
3540 visual = DEVICE_X_VISUAL(d);
3541 if (colormap != DEVICE_X_COLORMAP(d)) {
3542 XtAppWarningMsg(the_app_con, "weirdColormap",
3543 "cvtStringToPixel", "XtToolkitWarning",
3544 "The colormap passed to "
3545 "cvtStringToPixel doesn't match the "
3546 "one registered to the device.\n",
3548 status = XAllocNamedColor(dpy, colormap, (char *)str,
3549 &screenColor, &exactColor);
3551 status = XParseColor(dpy, colormap, (char *)str,
3554 status = allocate_nearest_color(
3555 dpy, colormap, visual, &screenColor);
3559 /* We haven't set up this device totally yet, so just punt */
3560 status = XAllocNamedColor(dpy, colormap, (char *)str,
3561 &screenColor, &exactColor);
3565 /* Server returns a specific error code but Xlib discards it.
3567 if (XLookupColor(DisplayOfScreen(screen), colormap, (char*)str,
3568 &exactColor, &screenColor)) {
3569 XtAppWarningMsg(the_app_con, "noColormap",
3570 "cvtStringToPixel", "XtToolkitError",
3571 "Cannot allocate colormap entry for "
3573 params, &num_params);
3576 XtAppWarningMsg(the_app_con, "badValue",
3577 "cvtStringToPixel", "XtToolkitError",
3578 "Color name \"%s\" is not defined",
3579 params, &num_params);
3582 *closure_ret = False;
3585 *closure_ret = (char *)True;
3586 done(Pixel, screenColor.pixel);
3591 static void EmacsFreePixel(XtAppContext app,
3594 XrmValuePtr args, Cardinal * num_args)
3596 if (*num_args != 2) {
3597 XtAppWarningMsg(app, "wrongParameters", "freePixel",
3599 "Freeing a pixel requires screen and "
3600 "colormap arguments",
3601 (String *) NULL, (Cardinal *) NULL);
3606 Screen *screen = *((Screen **) args[0].addr);
3607 Colormap colormap = *((Colormap *) args[1].addr);
3608 XFreeColors(DisplayOfScreen(screen), colormap,
3609 (unsigned long *)toVal->addr, 1, (unsigned long)0);
3613 /************************************************************************/
3614 /* handle focus changes for native widgets */
3615 /************************************************************************/
3617 emacs_Xt_event_widget_focus_in(Widget w,
3619 String * params, Cardinal * num_params)
3622 x_any_widget_or_parent_to_frame(get_device_from_display
3623 (event->xany.display), w);
3625 XtSetKeyboardFocus(FRAME_X_SHELL_WIDGET(f), w);
3629 emacs_Xt_event_widget_focus_out(Widget w,
3631 String * params, Cardinal * num_params)
3635 static XtActionsRec widgetActionsList[] = {
3636 {"widget-focus-in", emacs_Xt_event_widget_focus_in},
3637 {"widget-focus-out", emacs_Xt_event_widget_focus_out},
3641 emacs_Xt_event_add_widget_actions(XtAppContext ctx)
3643 XtAppAddActions(ctx, widgetActionsList, 2);
3646 /************************************************************************/
3647 /* initialization */
3648 /************************************************************************/
3649 static struct event_stream _Xt_event_stream = {
3650 .event_pending_p = emacs_Xt_event_pending_p,
3651 .force_event_pending = emacs_Xt_force_event_pending,
3652 .next_event_cb = emacs_Xt_next_event,
3653 .handle_magic_event_cb = emacs_Xt_handle_magic_event,
3654 .add_timeout_cb = emacs_Xt_add_timeout,
3655 .remove_timeout_cb = emacs_Xt_remove_timeout,
3656 .select_console_cb = emacs_Xt_select_console,
3657 .unselect_console_cb = emacs_Xt_unselect_console,
3658 .select_process_cb = emacs_Xt_select_process,
3659 .unselect_process_cb = emacs_Xt_unselect_process,
3660 .quit_p_cb = emacs_Xt_quit_p,
3661 .create_stream_pair_cb = emacs_Xt_create_stream_pair,
3662 .delete_stream_pair_cb = emacs_Xt_delete_stream_pair,
3663 .current_event_timestamp_cb = emacs_Xt_current_event_timestamp,
3666 void syms_of_event_Xt(void)
3668 defsymbol(&Qkey_mapping, "key-mapping");
3669 defsymbol(&Qsans_modifiers, "sans-modifiers");
3670 defsymbol(&Qself_insert_command, "self-insert-command");
3673 void reinit_vars_of_event_Xt(void)
3675 Xt_event_stream = &_Xt_event_stream;
3676 the_Xt_timeout_blocktype = Blocktype_new(struct Xt_timeout_blocktype);
3678 last_quit_check_signal_tick_count = 0;
3680 /* this function only makes safe calls */
3681 init_what_input_once();
3685 void vars_of_event_Xt(void)
3687 reinit_vars_of_event_Xt();
3689 dispatch_event_queue = Qnil;
3690 staticpro(&dispatch_event_queue);
3691 dispatch_event_queue_tail = Qnil;
3692 dump_add_root_object(&dispatch_event_queue_tail);
3694 DEFVAR_BOOL("x-allow-sendevents", &x_allow_sendevents /*
3695 *Non-nil means to allow synthetic events. Nil means they are ignored.
3696 Beware: allowing emacs to process SendEvents opens a big security hole.
3698 x_allow_sendevents = 0;
3700 #ifdef DEBUG_SXEMACS
3701 DEFVAR_INT("debug-x-events", &debug_x_events /*
3702 If non-zero, display debug information about X events that SXEmacs sees.
3703 Information is displayed on stderr. Currently defined values are:
3705 1 == non-verbose output
3712 /* This mess is a hack that patches the shell widget to treat visual
3713 inheritance the same as colormap and depth inheritance */
3715 static XtInitProc orig_shell_init_proc;
3718 ShellVisualPatch(Widget wanted, Widget new,
3719 ArgList args, Cardinal * num_args)
3722 ShellWidget w = (ShellWidget) new;
3724 /* first, call the original setup */
3725 (*orig_shell_init_proc) (wanted, new, args, num_args);
3727 /* if the visual isn't explicitly set, grab it from the nearest shell
3729 if (w->shell.visual == CopyFromParent) {
3731 while (p && !XtIsShell(p)) {
3735 w->shell.visual = ((ShellWidget) p)->shell.visual;
3740 void init_event_Xt_late(void)
3742 /* called when already initialized */
3743 timeout_id_tick = 1;
3744 pending_timeouts = NULL;
3745 completed_timeouts_head = NULL; /* queue is empty */
3746 completed_timeouts_tail = NULL; /* just to be picky */
3748 event_stream = Xt_event_stream;
3750 #if defined(HAVE_XIM) || defined(USE_XFONTSET)
3751 Initialize_Locale();
3752 #endif /* HAVE_XIM || USE_XFONTSET */
3754 XtToolkitInitialize();
3755 Xt_app_con = XtCreateApplicationContext();
3756 XtAppSetFallbackResources(Xt_app_con, (String*)x_fallback_resources);
3759 x_selection_timeout = (XtAppGetSelectionTimeout(Xt_app_con) / 1000);
3760 XSetErrorHandler(x_error_handler);
3761 XSetIOErrorHandler(x_IO_error_handler);
3763 XtAppAddInput(Xt_app_con, signal_event_pipe[0],
3764 (XtPointer) (XtInputReadMask /* | XtInputExceptMask */ ),
3765 Xt_what_callback, 0);
3767 XtAppSetTypeConverter(Xt_app_con, XtRString, XtRPixel,
3768 EmacsXtCvtStringToPixel,
3769 (XtConvertArgList)colorConvertArgs,
3770 2, XtCacheByDisplay, EmacsFreePixel);
3773 XtAppSetTypeConverter(Xt_app_con, XtRString, XtRXimStyles,
3774 EmacsXtCvtStringToXIMStyles,
3775 NULL, 0, XtCacheByDisplay, EmacsFreeXIMStyles);
3776 #endif /* XIM_XLIB */
3777 /* Add extra actions to native widgets to handle focus and friends. */
3778 emacs_Xt_event_add_widget_actions(Xt_app_con);
3780 /* insert the visual inheritance patch/hack described above */
3781 orig_shell_init_proc = shellClassRec.core_class.initialize;
3782 shellClassRec.core_class.initialize = ShellVisualPatch;
3784 #if defined(EF_USE_ASYNEQ)
3785 emacs_Xt_watch_event_queue(asyneq);
3789 /* event-Xt.c ends here */