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 #ifdef HAVE_X11_XKBLIB_H
62 #include <X11/XKBlib.h>
65 #include "events/events-mod.h"
67 #include "events/event-queue.h"
70 void enqueue_focus_event(Widget wants_it, Lisp_Object frame, int in_p);
71 static void handle_focus_event_1(struct frame *f, int in_p);
72 static void handle_focus_event_2(Window w, struct frame *f, int in_p);
74 static struct event_stream *Xt_event_stream;
76 /* With the new event model, all events go through XtDispatchEvent()
77 and are picked up by an event handler that is added to each frame
78 widget. (This is how it's supposed to be.) In the old method,
79 Emacs sucks out events directly from XtNextEvent() and only
80 dispatches the events that it doesn't need to deal with. This
81 old way has lots of corresponding junk that is no longer
82 necessary: lwlib extensions, synthetic XAnyEvents, unnecessary
85 /* The one and only one application context that Emacs uses. */
86 XtAppContext Xt_app_con;
88 /* Do we accept events sent by other clients? */
89 int x_allow_sendevents;
92 Fixnum debug_x_events;
95 static int process_events_occurred;
96 static int tty_events_occurred;
97 static Widget widget_with_focus;
99 /* Mask of bits indicating the descriptors that we wait for input on */
100 extern SELECT_TYPE input_wait_mask, process_only_mask, tty_only_mask;
102 static String x_fallback_resources[] = {
103 /* This file is automatically generated from the app-defaults file
104 in ../etc/Emacs.ad. These resources are consulted only if no
105 app-defaults file is found at all.
107 #include <ui/Emacs.ad.h>
111 static Lisp_Object x_keysym_to_emacs_keysym(KeySym keysym, int simple_p);
112 void emacs_Xt_mapping_action(Widget w, XEvent * event);
113 void debug_process_finalization(Lisp_Process * p);
114 void emacs_Xt_event_handler(Widget wid, XtPointer closure, XEvent * event,
115 Boolean * continue_to_dispatch);
117 static int last_quit_check_signal_tick_count;
119 Lisp_Object Qkey_mapping;
120 Lisp_Object Qsans_modifiers;
123 /************************************************************************/
124 /* keymap handling */
125 /************************************************************************/
127 /* X bogusly doesn't define the interpretations of any bits besides
128 ModControl, ModShift, and ModLock; so the Interclient Communication
129 Conventions Manual says that we have to bend over backwards to figure
130 out what the other modifier bits mean. According to ICCCM:
132 - Any keycode which is assigned ModControl is a "control" key.
134 - Any modifier bit which is assigned to a keycode which generates Meta_L
135 or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper,
138 - Any keypress event which contains ModControl in its state should be
139 interpreted as a "control" character.
141 - Any keypress event which contains a modifier bit in its state which is
142 generated by a keycode whose corresponding keysym is Meta_L or Meta_R
143 should be interpreted as a "meta" character. Likewise for Super, Hyper,
146 - It is illegal for a keysym to be associated with more than one modifier
149 This means that the only thing that emacs can reasonably interpret as a
150 "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
151 one of the modifier bits Mod1-Mod5.
153 Unfortunately, many keyboards don't have Meta keys in their default
154 configuration. So, if there are no Meta keys, but there are "Alt" keys,
155 emacs will interpret Alt as Meta. If there are both Meta and Alt keys,
156 then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to
157 mean "Symbol," but that just confused the hell out of way too many people).
159 This works with the default configurations of the 19 keyboard-types I've
162 Emacs detects keyboard configurations which violate the above rules, and
163 prints an error message on the standard-error-output. (Perhaps it should
164 use a pop-up-window instead.)
167 /* For every key on the keyboard that has a known character correspondence,
168 we define the ascii-character property of the keysym, and make the
169 default binding for the key be self-insert-command.
171 The following magic is basically intimate knowledge of X11/keysymdef.h.
172 The keysym mappings defined by X11 are based on the iso8859 standards,
173 except for Cyrillic and Greek.
175 In a non-Mule world, a user can still have a multi-lingual editor, by doing
176 (set-face-font "...-iso8859-2" (current-buffer))
177 for all their Latin-2 buffers, etc. */
179 static Lisp_Object x_keysym_to_character(KeySym keysym)
182 Lisp_Object charset = Qzero;
183 #define USE_CHARSET(var,cs) \
184 ((var) = CHARSET_BY_LEADING_BYTE (LEADING_BYTE_##cs))
186 #define USE_CHARSET(var,lb)
190 if ((keysym & 0xff) < 0xa0)
193 switch (keysym >> 8) {
194 case 0: /* ASCII + Latin1 */
195 USE_CHARSET(charset, LATIN_ISO8859_1);
196 code = keysym & 0x7f;
199 USE_CHARSET(charset, LATIN_ISO8859_2);
200 code = keysym & 0x7f;
203 USE_CHARSET(charset, LATIN_ISO8859_3);
204 code = keysym & 0x7f;
207 USE_CHARSET(charset, LATIN_ISO8859_4);
208 code = keysym & 0x7f;
210 case 4: /* Katakana */
211 USE_CHARSET(charset, KATAKANA_JISX0201);
212 if ((keysym & 0xff) > 0xa0)
213 code = keysym & 0x7f;
216 USE_CHARSET(charset, ARABIC_ISO8859_6);
217 code = keysym & 0x7f;
221 static unsigned char const cyrillic[] = /* 0x20 - 0x7f */
222 { 0x00, 0x72, 0x73, 0x71, 0x74, 0x75, 0x76, 0x77,
223 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x00, 0x7e, 0x7f,
224 0x70, 0x22, 0x23, 0x21, 0x24, 0x25, 0x26, 0x27,
225 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x00, 0x2e, 0x2f,
226 0x6e, 0x50, 0x51, 0x66, 0x54, 0x55, 0x64, 0x53,
227 0x65, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
228 0x5f, 0x6f, 0x60, 0x61, 0x62, 0x63, 0x56, 0x52,
229 0x6c, 0x6b, 0x57, 0x68, 0x6d, 0x69, 0x67, 0x6a,
230 0x4e, 0x30, 0x31, 0x46, 0x34, 0x35, 0x44, 0x33,
231 0x45, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
232 0x3f, 0x4f, 0x40, 0x41, 0x42, 0x43, 0x36, 0x32,
233 0x4c, 0x4b, 0x37, 0x48, 0x4d, 0x49, 0x47, 0x4a
235 USE_CHARSET(charset, CYRILLIC_ISO8859_5);
236 code = cyrillic[(keysym & 0x7f) - 0x20];
241 static unsigned char const greek[] = /* 0x20 - 0x7f */
242 { 0x00, 0x36, 0x38, 0x39, 0x3a, 0x5a, 0x00, 0x3c,
243 0x3e, 0x5b, 0x00, 0x3f, 0x00, 0x00, 0x35, 0x2f,
244 0x00, 0x5c, 0x5d, 0x5e, 0x5f, 0x7a, 0x40, 0x7c,
245 0x7d, 0x7b, 0x60, 0x7e, 0x00, 0x00, 0x00, 0x00,
246 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
247 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
248 0x50, 0x51, 0x53, 0x00, 0x54, 0x55, 0x56, 0x57,
249 0x58, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
251 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
252 0x70, 0x71, 0x73, 0x72, 0x74, 0x75, 0x76, 0x77,
253 0x78, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
255 USE_CHARSET(charset, GREEK_ISO8859_7);
256 code = greek[(keysym & 0x7f) - 0x20];
259 case 8: /* Technical */
261 case 9: /* Special */
263 case 10: /* Publishing */
267 case 12: /* Hebrew */
268 USE_CHARSET(charset, HEBREW_ISO8859_8);
269 code = keysym & 0x7f;
272 /* #### This needs to deal with character composition. */
273 USE_CHARSET(charset, THAI_TIS620);
274 code = keysym & 0x7f;
276 case 14: /* Korean Hangul */
278 case 19: /* Latin 9 - ISO8859-15 - unsupported charset. */
280 case 32: /* Currency */
290 return make_char(MAKE_CHAR(charset, code, 0));
292 return make_char(code + 0x80);
296 /* #### The way that keysym correspondence to characters should work:
297 - a Lisp_Event should contain a keysym AND a character slot.
298 - keybindings are tried with the keysym. If no binding can be found,
299 and there is a corresponding character, call self-insert-command.
301 #### Nuke x-iso8859-1.el.
302 #### Nuke the Qascii_character property.
303 #### Nuke Vcharacter_set_property.
306 maybe_define_x_key_as_self_inserting_character(KeySym keysym,
309 Lisp_Object character = x_keysym_to_character(keysym);
311 if (CHARP(character)) {
312 extern Lisp_Object Vcurrent_global_map;
313 extern Lisp_Object Qascii_character;
314 if (NILP(Flookup_key(Vcurrent_global_map, symbol, Qnil))) {
315 Fput(symbol, Qascii_character, character);
316 Fdefine_key(Vcurrent_global_map, symbol,
317 Qself_insert_command);
323 x_has_keysym(KeySym keysym, Lisp_Object hash_table, int with_modifiers)
325 KeySym upper_lower[2];
328 if (keysym < 0x80) /* Optimize for ASCII keysyms */
332 xmodmap -e 'keysym NN = scaron'
333 and then press (Shift scaron), X11 will return the different
334 keysym `Scaron', but `xmodmap -pke' might not even mention
335 `Scaron', so we "register" both `scaron' and `Scaron'. */
336 #ifdef HAVE_XCONVERTCASE
337 XConvertCase(keysym, &upper_lower[0], &upper_lower[1]);
339 upper_lower[0] = upper_lower[1] = keysym;
342 for (j = 0; j < (upper_lower[0] == upper_lower[1] ? 1 : 2); j++) {
344 keysym = upper_lower[j];
346 name = XKeysymToString(keysym);
348 /* X guarantees NAME to be in the Host Portable
349 Character Encoding */
350 Lisp_Object sym = x_keysym_to_emacs_keysym(keysym, 0);
351 Lisp_Object new_value = with_modifiers
352 ? Qt : Qsans_modifiers;
353 Lisp_Object old_value = Fgethash(sym, hash_table, Qnil);
355 if (!EQ(old_value, new_value)
356 && !(EQ(old_value, Qsans_modifiers) &&
357 EQ(new_value, Qt))) {
358 maybe_define_x_key_as_self_inserting_character
360 Fputhash(build_ext_string(name, Qbinary),
361 new_value, hash_table);
362 Fputhash(sym, new_value, hash_table);
369 x_reset_key_mapping(struct device *d)
371 Display *display = DEVICE_X_DISPLAY(d);
372 struct x_device *xd = DEVICE_X_DATA(d);
373 KeySym *keysym, *keysym_end;
374 Lisp_Object hash_table;
375 int key_code_count, keysyms_per_code;
377 if (xd->x_keysym_map) {
378 XFree((char *)xd->x_keysym_map);
380 XDisplayKeycodes(display,
381 &xd->x_keysym_map_min_code,
382 &xd->x_keysym_map_max_code);
384 xd->x_keysym_map_max_code - xd->x_keysym_map_min_code + 1;
386 XGetKeyboardMapping(display, xd->x_keysym_map_min_code,
388 &xd->x_keysym_map_keysyms_per_code);
390 hash_table = xd->x_keysym_map_hash_table;
391 if (HASH_TABLEP(hash_table)) {
392 Fclrhash(hash_table);
394 xd->x_keysym_map_hash_table = hash_table =
395 make_lisp_hash_table(128, HASH_TABLE_NON_WEAK,
399 for (keysym = xd->x_keysym_map,
400 keysyms_per_code = xd->x_keysym_map_keysyms_per_code,
401 keysym_end = keysym + (key_code_count * keysyms_per_code);
402 keysym < keysym_end; keysym += keysyms_per_code) {
405 if (keysym[0] == NoSymbol) {
408 x_has_keysym(keysym[0], hash_table, 0);
410 for (j = 1; j < keysyms_per_code; j++) {
411 if (keysym[j] != keysym[0] && keysym[j] != NoSymbol) {
412 x_has_keysym(keysym[j], hash_table, 1);
418 static inline const char *index_to_name(int indice)
419 __attribute__((always_inline));
420 static inline const char *index_to_name(int indice)
427 case ControlMapIndex:
444 static char *err_overlap_mods =
446 " Two distinct modifier keys (such as Meta and Hyper) cannot\n"
447 " generate the same modifier bit, because Emacs won't be able\n"
448 " to tell which modifier was actually held down when some\n"
449 " other key is pressed. It won't be able to tell Meta-x and\n"
450 " Hyper-x apart, for example. Change one of these keys to use\n"
451 " some other modifier bit. If you intend for these keys to\n"
452 " have the same behavior, then change them to have the same\n"
453 " keysym as well as the same modifier bit.";
454 static char *err_predef_mods =
456 " The semantics of the modifier bits ModShift, ModLock, and\n"
457 " ModControl are predefined. It does not make sense to assign\n"
458 " ModControl to any keysym other than Control_L or Control_R,\n"
459 " or to assign any modifier bits to the \"control\" keysyms\n"
460 " other than ModControl. You can't turn a \"control\" key\n"
461 " into a \"meta\" key (or vice versa) by simply assigning the\n"
462 " key a different modifier bit. You must also make that key\n"
463 " generate an appropriate keysym (Control_L, Meta_L, etc).";
464 static char *err_msg_else =
466 " The meanings of the modifier bits Mod1 through Mod5 are\n"
467 " determined by the keysyms used to control those bits.\n"
468 " Mod1 does NOT always mean Meta, although some\n"
469 " non-ICCCM-compliant programs assume that.";
471 /* Boy, I really wish C had local functions... */
473 unsigned int modifier_index;
474 unsigned int modifier_key;
477 /* now 32 bits of goodness */
478 bool warned_about_overlapping_modifiers:1;
479 bool warned_about_predefined_modifiers:1;
480 bool warned_about_duplicate_modifiers:1;
481 /* pad for the bools, so they end up on an 8bit boundary
482 * also store the old state */
484 /* each bit consumes 4 bits, totalling to 20 bits */
485 unsigned int meta_bit:4;
486 unsigned int hyper_bit:4;
487 unsigned int super_bit:4;
488 unsigned int alt_bit:4;
489 unsigned int mode_bit:4;
490 /* for bits left for a future modifier */
495 modbarf(KeyCode code, const char *name, const char *other,
496 struct mod_clo_s *clo)
499 Qkey_mapping, Qwarning,
500 "SXEmacs: %s (0x%x) generates %s, "
501 "which is nonsensical.",
503 clo->warned_about_predefined_modifiers = true;
508 modwarn(KeyCode code, const char *name, int old, const char *other,
509 struct mod_clo_s *clo)
511 warn_when_safe(Qkey_mapping, Qwarning,
512 "SXEmacs: %s (0x%x) generates %s, "
513 "which is generated by %s.",
514 name, code, index_to_name (old), other);
515 clo->warned_about_overlapping_modifiers = true;
520 store_modifier(KeyCode code, const char *name, struct mod_clo_s *clo)
522 #define modifier_index clo->modifier_index
523 #define modifier_key clo->modifier_key
524 #define mkpm clo->mkpm
525 if (clo->old && clo->old != modifier_index) {
527 Qkey_mapping, Qwarning,
528 "SXEmacs: %s (0x%x) generates both "
529 "%s and %s, which is nonsensical.",
530 name, code, index_to_name(clo->old),
531 index_to_name(modifier_index));
532 clo->warned_about_duplicate_modifiers = true;
534 if (modifier_index == ShiftMapIndex) {
535 modbarf(code, name, "ModShift", clo);
536 } else if (modifier_index == LockMapIndex) {
537 modbarf(code, name, "ModLock", clo);
538 } else if (modifier_index == ControlMapIndex) {
539 modbarf(code, name, "ModControl", clo);
541 } else if (sym == XK_Mode_switch) {
542 /* Mode_switch is special, see below... */
545 } else if (modifier_index == clo->meta_bit &&
546 clo->old != clo->meta_bit) {
547 modwarn(code, name, clo->meta_bit, "Meta", clo);
548 } else if (modifier_index == clo->super_bit &&
549 clo->old != clo->super_bit) {
550 modwarn(code, name, clo->super_bit, "Super", clo);
551 } else if (modifier_index == clo->hyper_bit &&
552 clo->old != clo->hyper_bit) {
553 modwarn(code, name, clo->hyper_bit, "Hyper", clo);
554 } else if (modifier_index == clo->alt_bit &&
555 clo->old != clo->alt_bit) {
556 modwarn(code, name, clo->alt_bit, "Alt", clo);
558 clo->old = modifier_index;
561 #undef modifier_index
567 check_modifier(KeyCode code, const char *name, int mask, struct mod_clo_s *clo)
569 #define modifier_index clo->modifier_index
570 #define modifier_key clo->modifier_key
571 #define mkpm clo->mkpm
572 if ((1 << modifier_index) != mask) {
574 Qkey_mapping, Qwarning,
575 "SXEmacs: %s (0x%x) generates %s, "
576 "which is nonsensical.",
578 index_to_name(modifier_index));
579 clo->warned_about_predefined_modifiers = true;
581 #undef modifier_index
588 whatever(Display *dspl, struct x_device *xd, struct mod_clo_s *clo)
590 #define modifier_index clo->modifier_index
591 #define modifier_key clo->modifier_key
592 #define mkpm clo->mkpm
593 #define mode_bit clo->mode_bit
594 #define meta_bit clo->meta_bit
595 #define alt_bit clo->alt_bit
596 #define super_bit clo->super_bit
597 #define hyper_bit clo->hyper_bit
599 KeyCode code = xd->x_modifier_keymap->modifiermap
600 [modifier_index * mkpm + modifier_key];
602 for (int column = 0; column < 4; column += 2) {
603 #ifdef HAVE_XKBKEYCODETOKEYSYM
605 ? XkbKeycodeToKeysym(dspl, code, 0, column)
608 #pragma GCC diagnostic push
609 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
611 ? XKeycodeToKeysym(dspl, code, column)
613 #pragma GCC diagnostic pop
616 if (LIKELY(sym == last_sym)) {
622 /* store_modifier("Mode_switch", &mode_bit); */
623 /* handled specially here */
624 mode_bit = modifier_index;
627 /* new modifier, new luck, reset clo->old */
629 store_modifier(code, "Meta_L", clo);
634 store_modifier(code, "Meta_R", clo);
638 clo->old = super_bit;
639 store_modifier(code, "Super_L", clo);
640 super_bit = clo->old;
643 clo->old = super_bit;
644 store_modifier(code, "Super_R", clo);
645 super_bit = clo->old;
648 clo->old = hyper_bit;
649 store_modifier(code, "Hyper_L", clo);
650 hyper_bit = clo->old;
653 clo->old = hyper_bit;
654 store_modifier(code, "Hyper_R", clo);
655 hyper_bit = clo->old;
659 store_modifier(code, "Alt_L", clo);
664 store_modifier(code, "Alt_R", clo);
668 check_modifier(code, "Control_L", ControlMask, clo);
671 check_modifier(code, "Control_R", ControlMask, clo);
674 check_modifier(code, "Shift_L", ShiftMask, clo);
677 check_modifier(code, "Shift_R", ShiftMask, clo);
680 check_modifier(code, "Shift_Lock", LockMask, clo);
681 xd->lock_interpretation = XK_Shift_Lock;
684 check_modifier(code, "Caps_Lock", LockMask, clo);
685 xd->lock_interpretation = XK_Caps_Lock;
688 /* It probably doesn't make any sense for a
689 modifier bit to be assigned to a key that is
690 not one of the above, but OpenWindows assigns
691 modifier bits to a couple of random function
692 keys for no reason that I can discern, so
693 printing a warning here would be annoying. */
695 /* hope we handled everything above */
700 #undef modifier_index
711 x_reset_modifier_mapping(struct device *d)
713 #define modifier_index clo.modifier_index
714 #define modifier_key clo.modifier_key
715 #define mkpm clo.mkpm
716 Display *display = DEVICE_X_DISPLAY(d);
717 struct x_device *xd = DEVICE_X_DATA(d);
718 struct mod_clo_s clo = {
719 .warned_about_overlapping_modifiers = false,
720 .warned_about_predefined_modifiers = false,
721 .warned_about_duplicate_modifiers = false,
730 #define mode_bit clo.mode_bit
731 #define meta_bit clo.meta_bit
732 #define alt_bit clo.alt_bit
733 #define super_bit clo.super_bit
734 #define hyper_bit clo.hyper_bit
735 xd->lock_interpretation = 0;
737 if (xd->x_modifier_keymap) {
738 XFreeModifiermap(xd->x_modifier_keymap);
740 x_reset_key_mapping(d);
742 xd->x_modifier_keymap = XGetModifierMapping(display);
744 /* The call to warn_when_safe must be on the same line as the string or
745 make-msgfile won't pick it up properly (the newline doesn't confuse
746 it, but the backslash does). */
748 mkpm = xd->x_modifier_keymap->max_keypermod;
749 for (modifier_index = 0; modifier_index < 8; modifier_index++) {
750 for (modifier_key = 0; modifier_key < mkpm; modifier_key++) {
751 whatever(display, xd, &clo);
755 /* If there was no Meta key, then try using the Alt key instead.
756 If there is both a Meta key and an Alt key, then the Alt key
757 is not disturbed and remains an Alt key. */
758 if (!meta_bit && alt_bit) {
763 /* mode_bit overrides everything, since it's processed down inside of
764 XLookupString() instead of by us. If Meta and Mode_switch both
765 generate the same modifier bit (which is an error), then we don't
766 interpret that bit as Meta, because we can't make XLookupString()
767 not interpret it as Mode_switch; and interpreting it as both would
770 const char *warn = 0;
772 if (mode_bit == meta_bit) {
775 } else if (mode_bit == hyper_bit) {
778 } else if (mode_bit == super_bit) {
781 } else if (mode_bit == alt_bit) {
787 Qkey_mapping, Qwarning,
788 "SXEmacs: %s is being used for both "
789 "Mode_switch and %s.",
790 index_to_name(mode_bit), warn);
791 clo.warned_about_overlapping_modifiers = true;
795 xd->MetaMask = (meta_bit ? (1 << meta_bit) : 0);
796 xd->HyperMask = (hyper_bit ? (1 << hyper_bit) : 0);
797 xd->SuperMask = (super_bit ? (1 << super_bit) : 0);
798 xd->AltMask = (alt_bit ? (1 << alt_bit) : 0);
799 xd->ModeMask = (mode_bit ? (1 << mode_bit) : 0); /* unused */
801 if (clo.warned_about_overlapping_modifiers) {
802 warn_when_safe(Qkey_mapping, Qwarning, "%s", err_overlap_mods);
805 if (clo.warned_about_predefined_modifiers) {
806 warn_when_safe(Qkey_mapping, Qwarning, "%s", err_predef_mods);
809 /* No need to say anything more for warned_about_duplicate_modifiers. */
810 if (clo.warned_about_overlapping_modifiers ||
811 clo.warned_about_predefined_modifiers)
812 warn_when_safe(Qkey_mapping, Qwarning, "%s", err_msg_else);
813 #undef modifier_index
823 void x_init_modifier_mapping(struct device *d)
825 struct x_device *xd = DEVICE_X_DATA(d);
826 xd->x_keysym_map_hash_table = Qnil;
827 xd->x_keysym_map = NULL;
828 xd->x_modifier_keymap = NULL;
829 x_reset_modifier_mapping(d);
833 static int x_key_is_modifier_p(KeyCode keycode, struct device *d)
835 struct x_device *xd = DEVICE_X_DATA(d);
839 if (keycode < xd->x_keysym_map_min_code ||
840 keycode > xd->x_keysym_map_max_code) {
844 syms = &xd->x_keysym_map[(keycode - xd->x_keysym_map_min_code) *
845 xd->x_keysym_map_keysyms_per_code];
846 for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++) {
847 if (IsModifierKey(syms[i]) || syms[i] == XK_Mode_switch) {
848 /* why doesn't IsModifierKey count this? */
855 /* key-handling code is always ugly. It just ends up working out
858 Here are some pointers:
860 -- DOWN_MASK indicates which modifiers should be treated as "down"
861 when the corresponding upstroke happens. It gets reset for
862 a particular modifier when that modifier goes up, and reset
863 for all modifiers when a non-modifier key is pressed. Example:
865 I press Control-A-Shift and then release Control-A-Shift.
866 I want the Shift key to be sticky but not the Control key.
868 -- LAST_DOWNKEY and RELEASE_TIME are used to keep track of
869 auto-repeat -- see below.
871 -- If a modifier key is sticky, I can unstick it by pressing
872 the modifier key again. */
874 static void x_handle_sticky_modifiers(XEvent * ev, struct device *d)
881 if (!modifier_keys_are_sticky) {
882 /* Optimize for non-sticky modifiers */
886 xd = DEVICE_X_DATA(d);
887 keycode = ev->xkey.keycode;
890 if (keycode < xd->x_keysym_map_min_code ||
891 keycode > xd->x_keysym_map_max_code) {
894 key_event_p = (type == KeyPress || type == KeyRelease);
896 if (!( key_event_p && x_key_is_modifier_p(keycode, d))) {
897 /* Not a modifier key */
899 if (type == ButtonPress
901 && ((xd->last_downkey
902 && ((keycode != xd->last_downkey
903 || ev->xkey.time != xd->release_time)))
904 || (INTP(Vmodifier_keys_sticky_time)
906 > (xd->modifier_release_time
907 + XINT(Vmodifier_keys_sticky_time)))))) {
908 xd->need_to_add_mask = 0;
909 xd->last_downkey = 0;
910 } else if (type == KeyPress && !xd->last_downkey) {
911 xd->last_downkey = keycode;
913 if (type == KeyPress) {
914 xd->release_time = 0;
916 if (type == KeyPress || type == ButtonPress) {
918 xd->modifier_release_time = 0;
922 ev->xkey.state |= xd->need_to_add_mask;
924 ev->xbutton.state |= xd->need_to_add_mask;
927 if (type == KeyRelease && keycode == xd->last_downkey) {
928 /* If I hold press-and-release the Control key and then
929 press and hold down the right arrow, I want it to
930 auto-repeat Control-Right. On the other hand, if I
931 do the same but manually press the Right arrow a
932 bunch of times, I want to see one Control-Right and
933 then a bunch of Rights. This means that we need to
934 distinguish between an auto-repeated key and a key
935 pressed and released a bunch of times.
937 Naturally, the designers of the X spec didn't see fit
938 to provide an obvious way to distinguish these cases.
939 So we assume that if the release and the next press
940 occur at the same time, the key was actually auto-
941 repeated. Under Open-Windows, at least, this
943 xd->modifier_release_time = xd->release_time =
949 /* Modifier key pressed */
951 KeySym *syms = &xd->x_keysym_map[
952 (keycode - xd->x_keysym_map_min_code) *
953 xd->x_keysym_map_keysyms_per_code];
955 /* If a non-modifier key was pressed in the middle of a bunch
956 of modifiers, then it unsticks all the modifiers that were
957 previously pressed. We cannot unstick the modifiers until
958 now because we want to check for auto-repeat of the
961 if (xd->last_downkey) {
962 xd->last_downkey = 0;
963 xd->need_to_add_mask = 0;
966 if (xd->modifier_release_time
967 && INTP(Vmodifier_keys_sticky_time)
968 && (ev->xkey.time > xd->modifier_release_time +
969 XINT(Vmodifier_keys_sticky_time))) {
970 xd->need_to_add_mask = 0;
976 if (type == KeyPress) { \
977 /* If modifier key is already sticky, \
978 then unstick it. Note that we do \
979 not test down_mask to deal with the \
980 unlikely but possible case that the \
981 modifier key auto-repeats. */ \
982 if (xd->need_to_add_mask & mask) { \
983 xd->need_to_add_mask &= ~mask; \
984 xd->down_mask &= ~mask; \
986 xd->down_mask |= mask; \
989 if (xd->down_mask & mask) { \
990 xd->down_mask &= ~mask; \
991 xd->need_to_add_mask |= mask; \
994 xd->modifier_release_time = ev->xkey.time; \
997 for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++) {
1013 FROB(xd->SuperMask);
1017 FROB(xd->HyperMask);
1024 /* hope we handled everything */
1032 static void clear_sticky_modifiers(struct device *d)
1034 struct x_device *xd = DEVICE_X_DATA(d);
1036 xd->need_to_add_mask = 0;
1037 xd->last_downkey = 0;
1038 xd->release_time = 0;
1043 static int keysym_obeys_caps_lock_p(KeySym sym, struct device *d)
1045 struct x_device *xd = DEVICE_X_DATA(d);
1046 /* Eeeeevil hack. Don't apply Caps_Lock to things that aren't
1047 alphabetic characters, where "alphabetic" means something more than
1048 simply A-Z. That is, if Caps_Lock is down, typing ESC doesn't
1049 produce Shift-ESC. But if shift-lock is down, then it does. */
1050 if (xd->lock_interpretation == XK_Shift_Lock) {
1053 return ((sym >= XK_A) && (sym <= XK_Z)) ||
1054 ((sym >= XK_a) && (sym <= XK_z)) ||
1055 ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) ||
1056 ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) ||
1057 ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) ||
1058 ((sym >= XK_oslash) && (sym <= XK_thorn));
1061 /* called from EmacsFrame.c (actually from Xt itself) when a
1062 MappingNotify event is received. In its infinite wisdom, Xt
1063 decided that Xt event handlers never get MappingNotify events.
1064 O'Reilly Xt Programming Manual 9.1.2 says:
1066 MappingNotify is automatically handled by Xt, so it isn't passed
1067 to event handlers and you don't need to worry about it.
1069 Of course, we DO worry about it, so we need a special translation. */
1071 emacs_Xt_mapping_action(Widget w, XEvent * event)
1073 struct device *d = get_device_from_display(event->xany.display);
1075 if (DEVICE_X_BEING_DELETED(d)) {
1079 /* nyet. Now this is handled by Xt. */
1080 XRefreshKeyboardMapping(&event->xmapping);
1082 /* xmodmap generates about a billion MappingKeyboard events, followed by
1083 a single MappingModifier event, so it might be worthwhile to take
1084 extra MappingKeyboard events out of the queue before requesting the
1085 current keymap from the server. */
1086 switch (event->xmapping.request) {
1087 case MappingKeyboard:
1088 x_reset_key_mapping(d);
1090 case MappingModifier:
1091 x_reset_modifier_mapping(d);
1093 case MappingPointer:
1094 /* Do something here? */
1101 /************************************************************************/
1102 /* X to Emacs event conversion */
1103 /************************************************************************/
1106 x_keysym_to_emacs_keysym(KeySym keysym, int simple_p)
1109 if (keysym >= XK_exclam && keysym <= XK_asciitilde) {
1110 /* We must assume that the X keysym numbers for the ASCII
1111 graphic characters are the same as their ASCII codes. */
1112 return make_char(keysym);
1116 /* These would be handled correctly by the default case, but by
1117 special-casing them here we don't garbage a string or call
1139 /* !!#### not Mule-ized */
1140 name = XKeysymToString(keysym);
1141 if (!name || !name[0]) {
1142 /* This happens if there is a mismatch between the Xlib
1143 of SXEmacs and the Xlib of the X server...
1145 Let's hard-code in some knowledge of common keysyms
1146 introduced in recent X11 releases. Snarfed from
1149 Probably we should add some stuff here for X11R6. */
1152 return KEYSYM("kp-home");
1154 return KEYSYM("kp-left");
1156 return KEYSYM("kp-up");
1158 return KEYSYM("kp-right");
1160 return KEYSYM("kp-down");
1162 return KEYSYM("kp-prior");
1164 return KEYSYM("kp-next");
1166 return KEYSYM("kp-end");
1168 return KEYSYM("kp-begin");
1170 return KEYSYM("kp-insert");
1172 return KEYSYM("kp-delete");
1176 return KEYSYM("SunF36");
1179 return KEYSYM("SunF37");
1182 int sz = snprintf(buf, sizeof(buf),
1183 "unknown-keysym-0x%X",
1185 assert(sz>=0 && (size_t)sz < sizeof(buf));
1190 /* If it's got a one-character name, that's good enough. */
1192 return make_char(name[0]);
1194 /* If it's in the "Keyboard" character set, downcase it. The
1195 case of those keysyms is too totally random for us to force
1196 anyone to remember them. The case of the other character
1197 sets is significant, however.
1199 if ((((unsigned int)keysym) & (~0x1FF)) ==
1200 ((unsigned int)0xFE00)) {
1203 for (s1 = name, s2 = buf; *s1; s1++, s2++) {
1207 *s2 = tolower(*(unsigned char *)s1);
1213 return KEYSYM(name);
1218 x_to_emacs_keysym(XKeyPressedEvent * event, int simple_p)
1219 /* simple_p means don't try too hard (ASCII only) */
1225 /* Some implementations of XmbLookupString don't return
1226 XBufferOverflow correctly, so increase the size of the xim input
1227 buffer from 64 to the more reasonable size 513, as Emacs has done.
1228 From Kenichi Handa. */
1230 char *bufptr = buffer;
1231 int bufsiz = sizeof(buffer);
1236 x_any_window_to_frame(get_device_from_display(event->display),event->window);
1238 xic = FRAME_X_XIC(f);
1239 #endif /* XIM_XLIB */
1240 #endif /* HAVE_XIM */
1242 /* We use XLookupString if we're not using XIM, or are using
1243 XIM_XLIB but input context creation failed. */
1244 #if ! (defined (HAVE_XIM) && defined (XIM_MOTIF))
1245 #if defined (HAVE_XIM) && defined (XIM_XLIB)
1247 #endif /* XIM_XLIB */
1249 /* Apparently it's necessary to specify a dummy here (rather
1250 than passing in 0) to avoid crashes on German IRIX */
1252 XLookupString(event, dummy, 200, &keysym, 0);
1253 return (IsModifierKey(keysym) || keysym == XK_Mode_switch)
1254 ? Qnil : x_keysym_to_emacs_keysym(keysym, simple_p);
1256 #endif /* ! XIM_MOTIF */
1259 Lookup_String: /* Come-From XBufferOverflow */
1262 XmImMbLookupString(XtWindowToWidget(event->display, event->window),
1263 event, bufptr, bufsiz, &keysym, &status);
1264 #else /* XIM_XLIB */
1266 len = XmbLookupString(xic, event, bufptr, bufsiz, &keysym,
1269 #endif /* HAVE_XIM */
1271 #ifdef DEBUG_SXEMACS
1272 if (debug_x_events > 0) {
1273 stderr_out(" status=");
1274 #define print_status_when(S) if (status == S) stderr_out (#S)
1275 print_status_when(XLookupKeySym);
1276 print_status_when(XLookupBoth);
1277 print_status_when(XLookupChars);
1278 print_status_when(XLookupNone);
1279 print_status_when(XBufferOverflow);
1281 if (status == XLookupKeySym || status == XLookupBoth)
1282 stderr_out(" keysym=%s", XKeysymToString(keysym));
1283 if (status == XLookupChars || status == XLookupBoth) {
1286 stderr_out(" chars=\"");
1287 for (j = 0; j < len; j++)
1288 stderr_out("%c", bufptr[j]);
1290 } else if (bufptr[0] <= 32 || bufptr[0] >= 127) {
1291 stderr_out(" char=0x%x", bufptr[0]);
1293 stderr_out(" char=%c", bufptr[0]);
1298 #endif /* DEBUG_SXEMACS */
1303 return (IsModifierKey(keysym) || keysym == XK_Mode_switch)
1305 : x_keysym_to_emacs_keysym(keysym, simple_p);
1307 case XLookupChars: {
1308 /* Generate multiple emacs events */
1309 struct device *d = get_device_from_display(event->display);
1311 Lisp_Object instream, fb_instream;
1313 struct gcpro gcpro1, gcpro2;
1315 fb_instream = make_fixed_buffer_input_stream(bufptr, len);
1317 /* #### Use Fget_coding_system
1318 * (Vcomposed_input_coding_system) */
1319 instream = make_decoding_input_stream(XLSTREAM(fb_instream),
1323 istr = XLSTREAM(instream);
1325 GCPRO2(instream, fb_instream);
1326 while ((ch = Lstream_get_emchar(istr)) != EOF) {
1327 Lisp_Object emacs_event = Fmake_event(Qnil, Qnil);
1328 Lisp_Event *ev = XEVENT(emacs_event);
1329 ev->channel = DEVICE_CONSOLE(d);
1330 ev->event_type = key_press_event;
1331 ev->timestamp = event->time;
1332 ev->event.key.modifiers = 0;
1333 ev->event.key.keysym = make_char(ch);
1334 enqueue_Xt_dispatch_event(emacs_event);
1336 Lstream_close(istr);
1338 Lstream_delete(istr);
1339 Lstream_delete(XLSTREAM(fb_instream));
1344 case XBufferOverflow:
1345 bufptr = (char *)alloca(len + 1);
1351 return Qnil; /* not reached */
1352 #endif /* HAVE_XIM */
1356 set_last_server_timestamp(struct device *d, XEvent * x_event)
1359 switch (x_event->type) {
1362 t = x_event->xkey.time;
1366 t = x_event->xbutton.time;
1370 t = x_event->xcrossing.time;
1373 t = x_event->xmotion.time;
1375 case PropertyNotify:
1376 t = x_event->xproperty.time;
1378 case SelectionClear:
1379 t = x_event->xselectionclear.time;
1381 case SelectionRequest:
1382 t = x_event->xselectionrequest.time;
1384 case SelectionNotify:
1385 t = x_event->xselection.time;
1390 DEVICE_X_LAST_SERVER_TIMESTAMP(d) = t;
1394 x_event_to_emacs_event(XEvent * x_event, Lisp_Event * emacs_event)
1396 Display *display = x_event->xany.display;
1397 struct device *d = get_device_from_display(display);
1398 struct x_device *xd = DEVICE_X_DATA(d);
1400 if (DEVICE_X_BEING_DELETED(d)) {
1401 /* #### Uh, is this 0 correct? */
1405 set_last_server_timestamp(d, x_event);
1407 switch (x_event->type) {
1409 x_handle_sticky_modifiers(x_event, d);
1414 case ButtonRelease: {
1416 int shift_p, lock_p;
1417 Bool key_event_p = (x_event->type == KeyPress);
1418 unsigned int *state = key_event_p
1419 ? &x_event->xkey.state
1420 : &x_event->xbutton.state;
1422 /* If this is a synthetic KeyPress or Button event, and the user
1423 has expressed a disinterest in this security hole, then drop
1426 ? x_event->xkey.send_event
1427 : x_event->xbutton.send_event)
1428 #ifdef EXTERNAL_WIDGET
1429 /* ben: events get sent to an ExternalShell using
1431 This is not a perfect solution. */
1432 && !FRAME_X_EXTERNAL_WINDOW_P
1433 (x_any_window_to_frame(d, x_event->xany.window))
1435 && !x_allow_sendevents) {
1439 DEVICE_X_MOUSE_TIMESTAMP(d) =
1440 DEVICE_X_GLOBAL_MOUSE_TIMESTAMP(d) =
1442 ? x_event->xkey.time
1443 : x_event->xbutton.time;
1445 x_handle_sticky_modifiers(x_event, d);
1447 if (*state & ControlMask) {
1448 modifiers |= XEMACS_MOD_CONTROL;
1450 if (*state & xd->MetaMask) {
1451 modifiers |= XEMACS_MOD_META;
1453 if (*state & xd->SuperMask) {
1454 modifiers |= XEMACS_MOD_SUPER;
1456 if (*state & xd->HyperMask) {
1457 modifiers |= XEMACS_MOD_HYPER;
1459 if (*state & xd->AltMask) {
1460 modifiers |= XEMACS_MOD_ALT;
1463 int numero_de_botao = -1;
1466 numero_de_botao = x_event->xbutton.button;
1468 /* the button gets noted either in the button or the
1469 modifiers field, but not both. */
1470 if (numero_de_botao != 1 && (*state & Button1Mask)) {
1471 modifiers |= XEMACS_MOD_BUTTON1;
1473 if (numero_de_botao != 2 && (*state & Button2Mask)) {
1474 modifiers |= XEMACS_MOD_BUTTON2;
1476 if (numero_de_botao != 3 && (*state & Button3Mask)) {
1477 modifiers |= XEMACS_MOD_BUTTON3;
1479 if (numero_de_botao != 4 && (*state & Button4Mask)) {
1480 modifiers |= XEMACS_MOD_BUTTON4;
1482 if (numero_de_botao != 5 && (*state & Button5Mask)) {
1483 modifiers |= XEMACS_MOD_BUTTON5;
1487 /* Ignore the Caps_Lock key if:
1488 - any other modifiers are down, so that Caps_Lock doesn't
1489 turn C-x into C-X, which would suck.
1490 - the event was a mouse event. */
1491 if (modifiers || !key_event_p) {
1492 *state &= (~LockMask);
1495 shift_p = *state & ShiftMask;
1496 lock_p = *state & LockMask;
1498 if (shift_p || lock_p) {
1499 modifiers |= XEMACS_MOD_SHIFT;
1503 XKeyEvent *ev = &x_event->xkey;
1504 /* This used to compute the frame from the given X
1505 window and store it here, but we really don't care
1507 emacs_event->channel = DEVICE_CONSOLE(d);
1508 keysym = x_to_emacs_keysym(&x_event->xkey, 0);
1510 /* If the emacs keysym is nil, then that means that the
1511 X keysym was either a Modifier or NoSymbol, which
1512 probably means that we're in the midst of reading a
1513 Multi_key sequence, or a "dead" key prefix, or XIM
1514 input. Ignore it. */
1519 /* More Caps_Lock garbage: Caps_Lock should *only* add
1520 the shift modifier to two-case keys (that is, A-Z and
1521 related characters). So at this point (after looking
1522 up the keysym) if the keysym isn't a dual-case
1523 alphabetic, and if the caps lock key was down but the
1524 shift key wasn't, then turn off the shift modifier.
1526 /* #### type lossage: assuming equivalence of emacs and
1528 /* !!#### maybe fix for Mule */
1529 if (lock_p && !shift_p &&
1530 !(CHAR_OR_CHAR_INTP(keysym)
1531 && keysym_obeys_caps_lock_p(
1532 (KeySym) XCHAR_OR_CHAR_INT(keysym), d))) {
1533 modifiers &= (~XEMACS_MOD_SHIFT);
1536 /* If this key contains two distinct keysyms, that is,
1537 "shift" generates a different keysym than the
1538 non-shifted key, then don't apply the shift modifier
1539 bit: it's implicit. Otherwise, if there would be no
1540 other way to tell the difference between the shifted
1541 and unshifted version of this key, apply the shift
1542 bit. Non-graphics, like Backspace and F1 get the
1543 shift bit in the modifiers slot. Neither the
1544 characters "a", "A", "2", nor "@" normally have the
1545 shift bit set. However, "F1" normally does. */
1546 if (modifiers & XEMACS_MOD_SHIFT) {
1547 int Mode_switch_p = *state & xd->ModeMask;
1548 KeySym bot = XLookupKeysym(ev,
1551 KeySym top = XLookupKeysym(ev,
1554 if (top && bot && top != bot) {
1570 modifiers &= ~XEMACS_MOD_SHIFT;
1575 emacs_event->event_type = key_press_event;
1576 emacs_event->timestamp = ev->time;
1577 emacs_event->event.key.modifiers = modifiers;
1578 emacs_event->event.key.keysym = keysym;
1580 /* Mouse press/release event */
1581 XButtonEvent *ev = &x_event->xbutton;
1582 struct frame *frame = x_window_to_frame(d, ev->window);
1588 XSETFRAME(emacs_event->channel, frame);
1590 emacs_event->event_type = (x_event->type == ButtonPress)
1591 ? button_press_event
1592 : button_release_event;
1594 emacs_event->event.button.modifiers = modifiers;
1595 emacs_event->timestamp = ev->time;
1596 emacs_event->event.button.button = ev->button;
1597 emacs_event->event.button.x = ev->x;
1598 emacs_event->event.button.y = ev->y;
1599 /* because we don't seem to get a FocusIn event for
1600 button clicks when a widget-glyph is selected we will
1601 assume that we want the focus if a button gets
1603 if (x_event->type == ButtonPress) {
1604 handle_focus_event_1(frame, 1);
1610 case MotionNotify: {
1611 XMotionEvent *ev = &x_event->xmotion;
1612 struct frame *frame = x_window_to_frame(d, ev->window);
1614 XMotionEvent event2;
1621 /* We use MotionHintMask, so we will get only one motion event
1622 until the next time we call XQueryPointer or the user clicks
1623 the mouse. So call XQueryPointer now (meaning that the event
1624 will be in sync with the server just before Fnext_event()
1625 returns). If the mouse is still in motion, then the server
1626 will immediately generate exactly one more motion event,
1627 which will be on the queue waiting for us next time
1630 if (XQueryPointer(event2.display, event2.window,
1631 &event2.root, &event2.subwindow,
1632 &event2.x_root, &event2.y_root,
1633 &event2.x, &event2.y, &event2.state)) {
1634 /* only one structure copy */
1637 DEVICE_X_MOUSE_TIMESTAMP(d) = ev->time;
1639 XSETFRAME(emacs_event->channel, frame);
1640 emacs_event->event_type = pointer_motion_event;
1641 emacs_event->timestamp = ev->time;
1642 emacs_event->event.motion.x = ev->x;
1643 emacs_event->event.motion.y = ev->y;
1644 if (ev->state & ShiftMask) {
1645 modifiers |= XEMACS_MOD_SHIFT;
1647 if (ev->state & ControlMask) {
1648 modifiers |= XEMACS_MOD_CONTROL;
1650 if (ev->state & xd->MetaMask) {
1651 modifiers |= XEMACS_MOD_META;
1653 if (ev->state & xd->SuperMask) {
1654 modifiers |= XEMACS_MOD_SUPER;
1656 if (ev->state & xd->HyperMask) {
1657 modifiers |= XEMACS_MOD_HYPER;
1659 if (ev->state & xd->AltMask) {
1660 modifiers |= XEMACS_MOD_ALT;
1662 if (ev->state & Button1Mask) {
1663 modifiers |= XEMACS_MOD_BUTTON1;
1665 if (ev->state & Button2Mask) {
1666 modifiers |= XEMACS_MOD_BUTTON2;
1668 if (ev->state & Button3Mask) {
1669 modifiers |= XEMACS_MOD_BUTTON3;
1671 if (ev->state & Button4Mask) {
1672 modifiers |= XEMACS_MOD_BUTTON4;
1674 if (ev->state & Button5Mask) {
1675 modifiers |= XEMACS_MOD_BUTTON5;
1677 /* Currently ignores Shift_Lock but probably shouldn't
1678 (but it definitely should ignore Caps_Lock). */
1679 emacs_event->event.motion.modifiers = modifiers;
1683 case ClientMessage: {
1684 /* Patch bogus TAKE_FOCUS messages from MWM; CurrentTime is
1685 passed as the timestamp of the TAKE_FOCUS, which the ICCCM
1686 explicitly prohibits. */
1687 XClientMessageEvent *ev = &x_event->xclient;
1689 if (ev->message_type == DEVICE_XATOM_WM_PROTOCOLS(d)
1690 && (Atom) (ev->data.l[0]) ==
1691 DEVICE_XATOM_WM_TAKE_FOCUS(d)
1692 && (Atom) (ev->data.l[1]) == 0) {
1694 DEVICE_X_LAST_SERVER_TIMESTAMP(d);
1700 /* it's a magic event */
1701 struct frame *frame;
1703 XEvent *x_event_copy = &emacs_event->event.magic.
1706 #define FROB(event_member, window_member) \
1707 x_event_copy->event_member = x_event->event_member; \
1708 w = x_event->event_member.window_member
1710 switch (x_event->type) {
1711 case SelectionRequest:
1712 FROB(xselectionrequest, owner);
1714 case SelectionClear:
1715 FROB(xselectionclear, window);
1717 case SelectionNotify:
1718 FROB(xselection, requestor);
1720 case PropertyNotify:
1721 FROB(xproperty, window);
1724 FROB(xclient, window);
1726 case ConfigureNotify:
1727 FROB(xconfigure, window);
1730 case GraphicsExpose:
1731 FROB(xexpose, window);
1739 FROB(xcrossing, window);
1743 FROB(xfocus, window);
1745 case VisibilityNotify:
1746 FROB(xvisibility, window);
1749 FROB(xcreatewindow, window);
1752 w = x_event->xany.window;
1753 *x_event_copy = *x_event;
1757 frame = x_any_window_to_frame(d, w);
1762 emacs_event->event_type = magic_event;
1763 XSETFRAME(emacs_event->channel, frame);
1771 /************************************************************************/
1772 /* magic-event handling */
1773 /************************************************************************/
1775 static void handle_focus_event_1(struct frame *f, int in_p)
1777 handle_focus_event_2(XtWindow(FRAME_X_TEXT_WIDGET(f)), f, in_p);
1780 static void handle_focus_event_2(Window win, struct frame *f, int in_p)
1782 /* Although this treats focus differently for all widgets (including
1783 the frame) it seems to work ok. */
1784 Widget needs_it = XtWindowToWidget(FRAME_X_DISPLAY(f), win);
1786 #if XtSpecificationRelease > 5
1787 widget_with_focus = XtGetKeyboardFocusWidget(FRAME_X_TEXT_WIDGET(f));
1790 XIM_focus_event(f, in_p);
1791 #endif /* HAVE_XIM */
1793 /* On focus change, clear all memory of sticky modifiers
1794 to avoid non-intuitive behavior. */
1795 clear_sticky_modifiers(XDEVICE(FRAME_DEVICE(f)));
1797 /* We don't want to handle the focus change now, because we might
1798 be in an accept-process-output, sleep-for, or sit-for. So
1801 Actually, we half handle it: we handle it as far as changing the
1802 box cursor for redisplay, but we don't call any hooks or do any
1803 select-frame stuff until after the sit-for.
1805 Unfortunately native widgets break the model because they grab
1806 the keyboard focus and nothing sets it back again. I cannot find
1807 any reasonable way to do this elsewhere so we assert here that
1808 the keyboard focus is on the emacs text widget. Menus and dialogs
1809 do this in their selection callback, but we don't want that since
1810 a button having focus is legitimate. An edit field having focus
1811 is mandatory. Weirdly you get a FocusOut event when you click in
1812 a widget-glyph but you don't get a corresponding FocusIn when you
1813 click in the frame. Why is this? */
1815 #if XtSpecificationRelease > 5
1816 && needs_it != widget_with_focus
1819 lw_set_keyboard_focus(FRAME_X_SHELL_WIDGET(f), needs_it);
1822 /* If we are focusing on a native widget then record and exit. */
1823 if (needs_it != FRAME_X_TEXT_WIDGET(f)) {
1824 widget_with_focus = needs_it;
1828 /* We have the focus now. See comment in
1829 emacs_Xt_handle_widget_losing_focus (). */
1831 widget_with_focus = NULL;
1833 /* do the generic event-stream stuff. */
1837 struct gcpro gcpro1;
1840 conser = Fcons(frm, Fcons(FRAME_DEVICE(f), in_p ? Qt : Qnil));
1842 emacs_handle_focus_change_preliminary(conser);
1843 enqueue_magic_eval_event(
1844 emacs_handle_focus_change_final, conser);
1849 /* Create a synthetic X focus event. */
1851 enqueue_focus_event(Widget wants_it, Lisp_Object frame, int in_p)
1853 Lisp_Object emacs_event = Fmake_event(Qnil, Qnil);
1854 Lisp_Event *ev = XEVENT(emacs_event);
1855 XEvent *x_event = &ev->event.magic.underlying_x_event;
1857 x_event->type = in_p ? FocusIn : FocusOut;
1858 x_event->xfocus.window = XtWindow(wants_it);
1860 ev->channel = frame;
1861 ev->event_type = magic_event;
1863 enqueue_Xt_dispatch_event(emacs_event);
1866 /* The idea here is that when a widget glyph gets unmapped we don't
1867 want the focus to stay with it if it has focus - because it may
1868 well just get deleted next and then we have lost the focus until the
1869 user does something. So handle_focus_event_1 records the widget
1870 with keyboard focus when FocusOut is processed, and then, when a
1871 widget gets unmapped, it calls this function to restore focus if
1873 void emacs_Xt_handle_widget_losing_focus(struct frame *f, Widget losing_widget);
1874 void emacs_Xt_handle_widget_losing_focus(struct frame *f, Widget losing_widget)
1876 if (losing_widget == widget_with_focus) {
1877 handle_focus_event_1(f, 1);
1881 /* This is called from the external-widget code */
1883 void emacs_Xt_handle_focus_event(XEvent * event);
1884 void emacs_Xt_handle_focus_event(XEvent * event)
1886 struct device *d = get_device_from_display(event->xany.display);
1889 if (DEVICE_X_BEING_DELETED(d))
1893 * It's curious that we're using x_any_window_to_frame() instead
1894 * of x_window_to_frame(). I don't know what the impact of this is.
1896 f = x_any_window_to_frame(d, event->xfocus.window);
1898 /* focus events are sometimes generated just before
1899 a frame is destroyed. */
1901 handle_focus_event_1(f, event->type == FocusIn);
1904 /* both MapNotify and VisibilityNotify can cause this
1905 JV is_visible has the same semantics as f->visible*/
1906 static void change_frame_visibility(struct frame *f, int is_visible)
1910 XSETFRAME(frame, f);
1912 if (!FRAME_VISIBLE_P(f) && is_visible) {
1913 FRAME_VISIBLE_P(f) = is_visible;
1914 /* This improves the double flicker when uniconifying a frame
1915 some. A lot of it is not showing a buffer which has changed
1916 while the frame was iconified. To fix it further requires
1917 the good 'ol double redisplay structure. */
1918 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
1919 va_run_hook_with_args(Qmap_frame_hook, 1, frame);
1920 } else if (FRAME_VISIBLE_P(f) && !is_visible) {
1921 FRAME_VISIBLE_P(f) = 0;
1922 va_run_hook_with_args(Qunmap_frame_hook, 1, frame);
1923 } else if (FRAME_VISIBLE_P(f) * is_visible < 0) {
1924 FRAME_VISIBLE_P(f) = -FRAME_VISIBLE_P(f);
1925 if (FRAME_REPAINT_P(f))
1926 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
1927 va_run_hook_with_args(Qmap_frame_hook, 1, frame);
1931 static void handle_map_event(struct frame *f, XEvent * event)
1935 XSETFRAME(frame, f);
1936 if (event->type == MapNotify) {
1937 XWindowAttributes xwa;
1939 /* Bleagh!!!!!! Apparently some window managers (e.g. MWM)
1940 send synthetic MapNotify events when a window is first
1941 created, EVEN IF IT'S CREATED ICONIFIED OR INVISIBLE.
1942 Or something like that. We initially tried a different
1943 solution below, but that ran into a different window-
1946 It seems that the only reliable way is to treat a
1947 MapNotify event as a "hint" that the window might or
1948 might not be visible, and check explicitly. */
1950 XGetWindowAttributes(event->xany.display, event->xmap.window,
1952 if (xwa.map_state != IsViewable) {
1953 /* Calling Fframe_iconified_p is the only way we have to
1954 correctly update FRAME_ICONIFIED_P */
1955 Fframe_iconified_p(frame);
1959 FRAME_X_TOTALLY_VISIBLE_P(f) = 1;
1961 /* Bleagh again!!!! We initially tried the following hack
1962 around the MWM problem, but it turns out that TWM
1963 has a race condition when you un-iconify, where it maps
1964 the window and then tells the server that the window
1965 is un-iconified. Usually, SXEmacs wakes up between
1966 those two occurrences, and thus thinks that un-iconified
1967 windows are still iconified.
1969 Ah, the joys of X. */
1971 /* By Emacs definition, a frame that is iconified is not
1972 visible. Marking a frame as visible will automatically cause
1973 frame-iconified-p to return nil, regardless of whether the
1974 frame is actually iconified. Therefore, we have to ignore
1975 MapNotify events on iconified frames. (It's not obvious
1976 to me why these are being sent, but it happens at startup
1977 with frames that are initially iconified; perhaps they are
1978 synthetic MapNotify events coming from the window manager.)
1979 Note that `frame-iconified-p' queries the server
1980 to determine whether the frame is currently iconified,
1981 rather than consulting some internal (and likely
1982 inaccurate) state flag. Therefore, ignoring the MapNotify
1984 if (!FRAME_VISIBLE_P(f) && NILP(Fframe_iconified_p(frame)))
1986 change_frame_visibility(f, 1);
1988 FRAME_X_TOTALLY_VISIBLE_P(f) = 0;
1989 change_frame_visibility(f, 0);
1990 /* Calling Fframe_iconified_p is the only way we have to
1991 correctly update FRAME_ICONIFIED_P */
1992 Fframe_iconified_p(frame);
1996 static void handle_client_message(struct frame *f, XEvent * event)
1998 struct device *d = XDEVICE(FRAME_DEVICE(f));
2001 XSETFRAME(frame, f);
2003 if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS(d) &&
2004 (Atom) (event->xclient.data.l[0]) ==
2005 DEVICE_XATOM_WM_DELETE_WINDOW(d)) {
2006 /* WM_DELETE_WINDOW is a misc-user event, but other
2007 ClientMessages, such as WM_TAKE_FOCUS, are eval events.
2008 That's because delete-window was probably executed with a
2009 mouse click, while the others could have been sent as a
2010 result of mouse motion or some other implicit action. (Call
2011 this a "heuristic"...) The reason for caring about this is
2012 so that clicking on the close-box will make emacs prompt
2013 using a dialog box instead of the minibuffer if there are
2016 enqueue_misc_user_event(frame, Qeval,
2017 list3(Qdelete_frame, frame, Qt));
2018 } else if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS(d)
2019 && (Atom) event->xclient.data.l[0] ==
2020 DEVICE_XATOM_WM_TAKE_FOCUS(d)) {
2021 handle_focus_event_1(f, 1);
2023 /* If there is a dialog box up, focus on it.
2025 #### Actually, we're raising it too, which is wrong. We should
2026 #### just focus on it, but lwlib doesn't currently give us an
2027 #### easy way to do that. This should be fixed.
2029 unsigned long take_focus_timestamp = event->xclient.data.l[1];
2030 Widget widget = lw_raise_all_pop_up_widgets();
2032 /* kludge: raise_all returns bottommost widget, but we really
2033 want the topmost. So just raise it for now. */
2034 XMapRaised(XtDisplay(widget), XtWindow(widget));
2035 /* Grab the focus with the timestamp of the TAKE_FOCUS. */
2036 XSetInputFocus(XtDisplay(widget), XtWindow(widget),
2037 RevertToParent, take_focus_timestamp);
2043 /* #### I'm struggling to understand how the X event loop really works.
2044 Here is the problem:
2046 When widgets get mapped / changed etc the actual display updates
2047 are done asynchronously via X events being processed - this
2048 normally happens when XtAppProcessEvent() gets called. However, if
2049 we are executing lisp code or even doing redisplay we won't
2050 necessarily process X events for a very long time. This has the
2051 effect of widgets only getting updated when SXEmacs only goes into
2052 idle, or some other event causes processing of the X event queue.
2054 XtAppProcessEvent can get called from the following places:
2056 emacs_Xt_next_event () - this is normal event processing, almost
2057 any non-X event will take precedence and this means that we
2058 cannot rely on it to do the right thing at the right time for
2061 drain_X_queue () - this happens when SIGIO gets tripped,
2062 processing the event queue allows C-g to be checked for. It gets
2063 called from emacs_Xt_event_pending_p ().
2065 In order to solve this I have tried introducing a list primitive -
2066 dispatch-non-command-events - which forces processing of X events
2067 related to display. Unfortunately this has a number of problems,
2068 one is that it is possible for event_stream_event_pending_p to
2069 block for ever if there isn't actually an event. I guess this can
2070 happen if we drop the synthetic event for reason. It also relies on
2071 SIGIO processing which makes things rather fragile.
2073 People have seen behaviour whereby SXEmacs blocks until you move the
2074 mouse. This seems to indicate that dispatch-non-command-events is
2075 blocking. It may be that in a SIGIO world forcing SIGIO processing
2076 does the wrong thing.
2078 static void emacs_Xt_force_event_pending(struct frame *f)
2082 Display *dpy = DEVICE_X_DISPLAY(XDEVICE(FRAME_DEVICE(f)));
2083 event.xclient.type = ClientMessage;
2084 event.xclient.display = dpy;
2085 event.xclient.message_type = XInternAtom(dpy, "BumpQueue", False);
2086 event.xclient.format = 32;
2087 event.xclient.window = 0;
2089 /* Send the drop message */
2090 XSendEvent(dpy, XtWindow(FRAME_X_SHELL_WIDGET(f)),
2091 True, NoEventMask, &event);
2092 /* We rely on SIGIO and friends to realise we have generated an
2096 static void emacs_Xt_handle_magic_event(Lisp_Event * emacs_event)
2098 /* This function can GC */
2099 XEvent *event = &emacs_event->event.magic.underlying_x_event;
2100 struct frame *f = XFRAME(EVENT_CHANNEL(emacs_event));
2102 if (!FRAME_LIVE_P(f)
2103 || DEVICE_X_BEING_DELETED(XDEVICE(FRAME_DEVICE(f))))
2106 switch (event->type) {
2107 case SelectionRequest:
2108 x_handle_selection_request(&event->xselectionrequest);
2111 case SelectionClear:
2112 x_handle_selection_clear(&event->xselectionclear);
2115 case SelectionNotify:
2116 x_handle_selection_notify(&event->xselection);
2119 case PropertyNotify:
2120 x_handle_property_notify(&event->xproperty);
2124 if (!check_for_ignored_expose
2125 (f, event->xexpose.x, event->xexpose.y,
2126 event->xexpose.width, event->xexpose.height)
2127 && !find_matching_subwindow(f, event->xexpose.x,
2129 event->xexpose.width,
2130 event->xexpose.height))
2131 x_redraw_exposed_area(f, event->xexpose.x,
2133 event->xexpose.width,
2134 event->xexpose.height);
2137 case GraphicsExpose:
2138 /* This occurs when an XCopyArea's source area was
2139 * obscured or not available. */
2140 x_redraw_exposed_area(f, event->xexpose.x, event->xexpose.y,
2141 event->xexpose.width,
2142 event->xexpose.height);
2147 handle_map_event(f, event);
2151 if (event->xcrossing.detail != NotifyInferior) {
2154 XSETFRAME(frame, f);
2155 /* FRAME_X_MOUSE_P (f) = 1; */
2156 va_run_hook_with_args(Qmouse_enter_frame_hook, 1,
2162 if (event->xcrossing.detail != NotifyInferior) {
2165 XSETFRAME(frame, f);
2166 /* FRAME_X_MOUSE_P (f) = 0; */
2167 va_run_hook_with_args(Qmouse_leave_frame_hook, 1,
2175 #ifdef EXTERNAL_WIDGET
2176 /* External widget lossage:
2177 Ben said: YUCK. The only way to make focus changes work
2178 properly is to completely ignore all FocusIn/FocusOut events
2179 and depend only on notifications from the ExternalClient
2181 if (FRAME_X_EXTERNAL_WINDOW_P(f)) {
2185 handle_focus_event_2(event->xfocus.window, f,
2186 event->type == FocusIn);
2190 handle_client_message(f, event);
2193 case VisibilityNotify:
2194 /* window visibility has changed */
2195 if (event->xvisibility.window ==
2196 XtWindow(FRAME_X_SHELL_WIDGET(f))) {
2197 FRAME_X_TOTALLY_VISIBLE_P(f) =
2198 (event->xvisibility.state == VisibilityUnobscured);
2199 /* Note that the fvwm pager only sends VisibilityNotify
2200 when changing pages. Is this all we need to do ?
2202 /* Nope. We must at least trigger a redisplay here.
2203 Since this case seems similar to MapNotify, I've
2204 factored out some code to change_frame_visibility().
2205 This triggers the necessary redisplay and runs
2206 (un)map-frame-hook. - dkindred@cs.cmu.edu */
2207 /* Changed it again to support the tristate visibility
2209 change_frame_visibility(f, (event->xvisibility.state
2211 VisibilityFullyObscured) ? 1
2216 case ConfigureNotify:
2230 /************************************************************************/
2231 /* timeout events */
2232 /************************************************************************/
2234 static int timeout_id_tick;
2236 /* Xt interval id's might not fit into an int (they're pointers, as it
2237 happens), so we need to provide a conversion list. */
2239 /* pending_timeouts is a set (unordered), implemented as a stack.
2240 completed_timeouts* is a queue. */
2241 static struct Xt_timeout {
2243 XtIntervalId interval_id;
2244 struct Xt_timeout *next;
2245 } *pending_timeouts, *completed_timeouts_head, *completed_timeouts_tail;
2247 static struct Xt_timeout_blocktype {
2248 Blocktype_declare(struct Xt_timeout);
2249 } *the_Xt_timeout_blocktype;
2251 /* called by XtAppNextEvent() */
2252 static void Xt_timeout_callback(XtPointer closure, XtIntervalId * id)
2254 struct Xt_timeout *timeout = (struct Xt_timeout *)closure;
2255 struct Xt_timeout *t2 = pending_timeouts;
2257 /* Remove this one from the set of pending timeouts */
2258 if(timeout == NULL) {
2262 if (t2 == timeout) {
2263 pending_timeouts = pending_timeouts->next;
2265 while (t2->next && t2->next != timeout) {
2270 t2->next = t2->next->next;
2272 /* Add this one to the queue of completed timeouts */
2273 timeout->next = NULL;
2274 if (completed_timeouts_head) {
2275 completed_timeouts_tail->next = timeout;
2277 completed_timeouts_head = timeout;
2279 completed_timeouts_tail = timeout;
2282 static int emacs_Xt_add_timeout(EMACS_TIME thyme)
2284 struct Xt_timeout *timeout = Blocktype_alloc(the_Xt_timeout_blocktype);
2285 EMACS_TIME current_time;
2288 timeout->id = timeout_id_tick++;
2289 timeout->next = pending_timeouts;
2290 pending_timeouts = timeout;
2291 EMACS_GET_TIME(current_time);
2292 EMACS_SUB_TIME(thyme, thyme, current_time);
2293 milliseconds = EMACS_SECS(thyme) * 1000 + EMACS_USECS(thyme) / 1000;
2295 if (milliseconds < 1) {
2298 timeout->interval_id = XtAppAddTimeOut(Xt_app_con, milliseconds,
2299 Xt_timeout_callback,
2300 (XtPointer) timeout);
2304 #ifdef EF_USE_ASYNEQ
2305 #if 1 /* timeout based */
2306 static void Xt_watch_eq_cb(XtPointer closure, XtIntervalId *id);
2307 static int emacs_Xt_watch_event_queue(event_queue_t eq);
2308 extern void asyneq_handle_event(event_queue_t eq);
2309 extern void asyneq_handle_non_command_event(event_queue_t eq);
2312 Xt_watch_eq_cb(XtPointer closure, XtIntervalId *id)
2314 event_queue_t eq = (event_queue_t)closure;
2315 /* reestablish timeout, in case asyneq_handle_event gets to exit
2317 emacs_Xt_watch_event_queue(eq);
2318 asyneq_handle_non_command_event(eq);
2322 emacs_Xt_watch_event_queue(event_queue_t eq)
2324 int milliseconds = 10;
2325 size_t eqsz = eq_queue_size(eq)+1; /* never be 0 */
2328 while ((milliseconds*eqsz) > 100)
2334 return XtAppAddTimeOut(
2335 Xt_app_con, milliseconds, Xt_watch_eq_cb, (XtPointer)eq);
2337 #else /* work-procedure based (sets cpu on fire) */
2339 Xt_watch_eq_cb(XtPointer closure)
2341 event_queue_t eq = (event_queue_t)closure;
2342 asyneq_handle_event(eq);
2343 return FALSE; /* we never finish with this job */
2347 emacs_Xt_watch_event_queue(event_queue_t eq)
2349 return XtAppAddWorkProc(Xt_app_con, Xt_watch_eq_cb, (XtPointer)eq);
2352 #endif /* EF_USE_ASYNEQ */
2354 static void emacs_Xt_remove_timeout(int id)
2356 struct Xt_timeout *timeout, *t2;
2360 /* Find the timeout on the list of pending ones, if it's still there. */
2361 if (pending_timeouts) {
2362 if (id == pending_timeouts->id) {
2363 timeout = pending_timeouts;
2364 pending_timeouts = pending_timeouts->next;
2366 t2 = pending_timeouts;
2367 while (t2->next && t2->next->id != id)
2369 if (t2->next) { /*found it */
2371 t2->next = t2->next->next;
2374 /* if it was pending, we have removed it from the list */
2376 XtRemoveTimeOut(timeout->interval_id);
2379 /* It could be that Xt_timeout_callback was already called but we didn't
2380 convert into an Emacs event yet */
2381 if (!timeout && completed_timeouts_head) {
2382 /* Thank God for code duplication! */
2383 if (id == completed_timeouts_head->id) {
2384 timeout = completed_timeouts_head;
2385 completed_timeouts_head = completed_timeouts_head->next;
2386 /* this may not be necessary? */
2387 if (!completed_timeouts_head)
2388 completed_timeouts_tail = NULL;
2390 t2 = completed_timeouts_head;
2391 while (t2->next && t2->next->id != id)
2393 if (t2->next) { /* found it */
2395 t2->next = t2->next->next;
2397 completed_timeouts_tail = t2;
2402 /* If we found the thing on the lists of timeouts,
2403 and removed it, deallocate
2406 Blocktype_free(the_Xt_timeout_blocktype, timeout);
2411 Xt_timeout_to_emacs_event(Lisp_Event * emacs_event)
2413 struct Xt_timeout *timeout = completed_timeouts_head;
2415 completed_timeouts_head = completed_timeouts_head->next;
2416 /* probably unnecessary */
2417 if (!completed_timeouts_head) {
2418 completed_timeouts_tail = NULL;
2420 emacs_event->event_type = timeout_event;
2421 /* timeout events have nil as channel */
2422 emacs_event->timestamp = 0; /* #### wrong!! */
2423 emacs_event->event.timeout.interval_id = timeout->id;
2424 emacs_event->event.timeout.function = Qnil;
2425 emacs_event->event.timeout.object = Qnil;
2426 Blocktype_free(the_Xt_timeout_blocktype, timeout);
2429 /************************************************************************/
2430 /* process and tty events */
2431 /************************************************************************/
2433 struct what_is_ready_closure {
2439 static Lisp_Object filedesc_with_input[MAXDESC];
2440 static struct what_is_ready_closure *filedesc_to_what_closure[MAXDESC];
2442 static void init_what_input_once(void)
2447 filedesc_with_input = xnew_array(Lisp_Object, MAXDESC);
2448 filedesc_to_what_closure =
2449 xnew_array(struct what_is_ready_closure *, MAXDESC);
2452 for (i = 0; i < MAXDESC; i++) {
2453 filedesc_to_what_closure[i] = NULL;
2454 filedesc_with_input[i] = Qnil;
2457 process_events_occurred = 0;
2458 tty_events_occurred = 0;
2463 mark_what_as_being_ready(struct what_is_ready_closure *closure)
2465 if (NILP(filedesc_with_input[closure->fd])) {
2466 SELECT_TYPE temp_mask;
2467 FD_ZERO(&temp_mask);
2468 FD_SET(closure->fd, &temp_mask);
2469 /* Check to make sure there's *really* input available.
2470 Sometimes things seem to get confused and this gets called
2471 for the tty fd when there's really only input available
2472 on some process's fd. (It will subsequently get called
2473 for that process's fd, so returning without setting any
2474 flags will take care of it.) To see the problem, uncomment
2475 the stderr_out below, turn NORMAL_QUIT_CHECK_TIMEOUT_MSECS
2476 down to 25, do sh -c 'sxemacs -nw -q -f shell 2>/tmp/log'
2477 and press return repeatedly. (Seen under AIX & Linux.)
2478 -dkindred@cs.cmu.edu */
2479 if (!poll_fds_for_input(temp_mask)) {
2482 "mark_what_as_being_ready: "
2483 "no input available (fd=%d)\n",
2488 filedesc_with_input[closure->fd] = closure->what;
2489 if (PROCESSP(closure->what)) {
2490 /* Don't increment this if the current process is
2491 already marked as having input. */
2492 process_events_occurred++;
2494 tty_events_occurred++;
2501 Xt_what_callback(void *closure, int *source, XtInputId *id)
2503 /* If closure is 0, then we got a fake event from a signal handler.
2504 The only purpose of this is to make XtAppProcessEvent() stop
2507 mark_what_as_being_ready(closure);
2509 fake_event_occurred++;
2510 drain_signal_event_pipe();
2516 select_filedesc(int fd, Lisp_Object what)
2518 struct what_is_ready_closure *closure;
2520 /* If somebody is trying to select something that's already selected
2521 for, then something went wrong. The generic routines ought to
2522 detect this and error before here. */
2523 assert(!filedesc_to_what_closure[fd]);
2525 closure = xnew(struct what_is_ready_closure);
2527 closure->what = what;
2528 closure->id = XtAppAddInput(
2530 (XtPointer)(XtInputReadMask /* | XtInputExceptMask */),
2531 Xt_what_callback, closure);
2532 filedesc_to_what_closure[fd] = closure;
2537 unselect_filedesc(int fd)
2539 struct what_is_ready_closure *closure = filedesc_to_what_closure[fd];
2542 if (!NILP(filedesc_with_input[fd])) {
2543 /* We are unselecting this process before we have drained the
2544 rest of the input from it, probably from status_notify() in
2545 the command loop. This can happen like so:
2547 - We are waiting in XtAppNextEvent()
2548 - Process generates output
2549 - Process is marked as being ready
2550 - Process dies, SIGCHLD gets generated before we return (!?)
2551 It could happen I guess.
2552 - sigchld_handler() marks process as dead
2553 - Somehow we end up getting a new KeyPress event on the queue
2554 at the same time (I'm really so sure how that happens but I'm
2555 not sure it can't either so let's assume it can...).
2556 - Key events have priority so we return that
2557 instead of the proc.
2558 - Before dispatching the lisp key event we call
2560 - which deselects the process that SIGCHLD marked as dead.
2562 Thus we never remove it from _with_input and turn it into a
2563 lisp event, so we need to do it here. But this does not mean
2564 that we're throwing away the last block of output -
2565 status_notify() has already taken care of running the proc
2568 filedesc_with_input[fd] = Qnil;
2569 if (PROCESSP(closure->what)) {
2570 assert(process_events_occurred > 0);
2571 process_events_occurred--;
2573 assert(tty_events_occurred > 0);
2574 tty_events_occurred--;
2577 XtRemoveInput(closure->id);
2579 filedesc_to_what_closure[fd] = 0;
2584 emacs_Xt_select_process(Lisp_Process * p)
2586 Lisp_Object process;
2587 int infd = event_stream_unixoid_select_process(p);
2589 XSETPROCESS(process, p);
2591 select_filedesc(infd, process);
2596 emacs_Xt_unselect_process(Lisp_Process * p)
2598 int infd = event_stream_unixoid_unselect_process(p);
2601 unselect_filedesc(infd);
2606 emacs_Xt_create_stream_pair(void *inhandle, void *outhandle,
2607 Lisp_Object *instream, Lisp_Object *outstream,
2610 USID u = event_stream_unixoid_create_stream_pair(
2611 inhandle, outhandle, instream, outstream, flags);
2612 if (u != USID_ERROR) {
2619 emacs_Xt_delete_stream_pair(Lisp_Object instream, Lisp_Object outstream)
2621 event_stream_unixoid_delete_stream_pair(instream, outstream);
2622 return USID_DONTHASH;
2625 /* This is called from GC when a process object is about to be freed.
2626 If we've still got pointers to it in this file, we're gonna lose hard.
2628 void debug_process_finalization(Lisp_Process * p)
2632 Lisp_Object instr, outstr;
2634 get_process_streams(p, &instr, &outstr);
2635 /* if it still has fds, then it hasn't been killed yet. */
2636 assert(NILP(instr));
2637 assert(NILP(outstr));
2638 /* Better not still be in the "with input" table; we know it's got no fds. */
2639 for (i = 0; i < MAXDESC; i++) {
2640 Lisp_Object process = filedesc_fds_with_input[i];
2641 assert(!PROCESSP(process) || XPROCESS(process) != p);
2648 Xt_process_to_emacs_event(Lisp_Event * emacs_event)
2652 assert(process_events_occurred > 0);
2654 for (i = 0; i < MAXDESC; i++) {
2655 Lisp_Object process = filedesc_with_input[i];
2656 if (PROCESSP(process)) {
2657 filedesc_with_input[i] = Qnil;
2658 process_events_occurred--;
2659 /* process events have nil as channel */
2660 emacs_event->event_type = process_event;
2661 emacs_event->timestamp = 0; /* #### */
2662 emacs_event->event.process.process = process;
2670 emacs_Xt_select_console(struct console *con)
2672 Lisp_Object console;
2675 if (CONSOLE_X_P(con)) {
2676 /* X consoles are automatically selected for when we
2677 initialize them in Xt */
2680 infd = event_stream_unixoid_select_console(con);
2681 XSETCONSOLE(console, con);
2683 select_filedesc(infd, console);
2688 emacs_Xt_unselect_console(struct console *con)
2690 Lisp_Object console;
2693 if (CONSOLE_X_P(con)) {
2694 /* X consoles are automatically selected for when we
2695 initialize them in Xt */
2698 infd = event_stream_unixoid_unselect_console(con);
2699 XSETCONSOLE(console, con);
2701 unselect_filedesc(infd);
2705 /* read an event from a tty, if one is available. Returns non-zero
2706 if an event was available. Note that when this function is
2707 called, there should always be a tty marked as ready for input.
2708 However, the input condition might actually be EOF, so there
2709 may not really be any input available. (In this case,
2710 read_event_from_tty_or_stream_desc() will arrange for the TTY device
2714 Xt_tty_to_emacs_event(Lisp_Event * emacs_event)
2718 assert(tty_events_occurred > 0);
2719 for (i = 0; i < MAXDESC; i++) {
2720 Lisp_Object console = filedesc_with_input[i];
2721 if (CONSOLEP(console)) {
2722 assert(tty_events_occurred > 0);
2723 tty_events_occurred--;
2724 filedesc_with_input[i] = Qnil;
2725 if (read_event_from_tty_or_stream_desc(
2726 emacs_event, XCONSOLE(console), i)) {
2735 /************************************************************************/
2736 /* debugging functions to decipher an event */
2737 /************************************************************************/
2739 #ifdef DEBUG_SXEMACS
2740 #include "xintrinsicp.h" /* only describe_event() needs this */
2741 #include <X11/Xproto.h> /* only describe_event() needs this */
2743 static void describe_event_window(Window window, Display * display)
2747 stderr_out(" window: 0x%lx", (unsigned long)window);
2748 w = XtWindowToWidget(display, window);
2750 stderr_out(" %s", w->core.widget_class->core_class.class_name);
2751 f = x_any_window_to_frame(get_device_from_display(display), window);
2753 int len = XSTRING_LENGTH(f->name) + 4;
2756 int sz = snprintf(buf, len, " \"%s\"", XSTRING_DATA(f->name));
2757 assert(sz >= 0 && sz < len);
2758 write_string_to_stdio_stream(stderr, 0, (Bufbyte*)buf, 0,
2764 static const char *XEvent_mode_to_string(int mode)
2773 case NotifyWhileGrabbed:
2774 return "WhileGrabbed";
2780 static const char *XEvent_detail_to_string(int detail)
2783 case NotifyAncestor:
2785 case NotifyInferior:
2787 case NotifyNonlinear:
2789 case NotifyNonlinearVirtual:
2790 return "NonlinearVirtual";
2793 case NotifyPointerRoot:
2794 return "PointerRoot";
2795 case NotifyDetailNone:
2796 return "DetailNone";
2802 static const char *XEvent_visibility_to_string(int state)
2805 case VisibilityFullyObscured:
2806 return "FullyObscured";
2807 case VisibilityPartiallyObscured:
2808 return "PartiallyObscured";
2809 case VisibilityUnobscured:
2810 return "Unobscured";
2816 static void describe_event(XEvent * event)
2819 struct device *d = get_device_from_display(event->xany.display);
2821 int sz = snprintf(buf, sizeof(buf),
2822 "%s%s", x_event_name(event->type),
2823 event->xany.send_event ? " (send)" : "");
2824 assert(sz >= 0 && (size_t)sz < sizeof(buf));
2825 stderr_out("%-30s", buf);
2826 switch (event->type) {
2829 XFocusChangeEvent *ev = &event->xfocus;
2830 describe_event_window(ev->window, ev->display);
2831 stderr_out(" mode: %s\n",
2832 XEvent_mode_to_string(ev->mode));
2833 stderr_out(" detail: %s\n",
2834 XEvent_detail_to_string(ev->detail));
2839 XKeyEvent *ev = &event->xkey;
2840 unsigned int state = ev->state;
2842 describe_event_window(ev->window, ev->display);
2843 stderr_out(" subwindow: %ld\n", ev->subwindow);
2844 stderr_out(" state: ");
2845 /* Complete list of modifier key masks */
2846 if (state & ShiftMask)
2847 stderr_out("Shift ");
2848 if (state & LockMask)
2849 stderr_out("Lock ");
2850 if (state & ControlMask)
2851 stderr_out("Control ");
2852 if (state & Mod1Mask)
2853 stderr_out("Mod1 ");
2854 if (state & Mod2Mask)
2855 stderr_out("Mod2 ");
2856 if (state & Mod3Mask)
2857 stderr_out("Mod3 ");
2858 if (state & Mod4Mask)
2859 stderr_out("Mod4 ");
2860 if (state & Mod5Mask)
2861 stderr_out("Mod5 ");
2864 stderr_out("vanilla\n");
2867 if (x_key_is_modifier_p(ev->keycode, d))
2868 stderr_out(" Modifier key");
2869 stderr_out(" keycode: 0x%x\n", ev->keycode);
2874 if (debug_x_events > 1) {
2875 XExposeEvent *ev = &event->xexpose;
2876 describe_event_window(ev->window, ev->display);
2877 stderr_out(" region: x=%d y=%d width=%d height=%d\n",
2878 ev->x, ev->y, ev->width, ev->height);
2879 stderr_out(" count: %d\n", ev->count);
2885 case GraphicsExpose:
2886 if (debug_x_events > 1) {
2887 XGraphicsExposeEvent *ev = &event->xgraphicsexpose;
2888 describe_event_window(ev->drawable, ev->display);
2889 stderr_out(" major: %s\n",
2890 (ev->major_code == X_CopyArea ? "CopyArea" :
2892 X_CopyPlane ? "CopyPlane" : "?")));
2893 stderr_out(" region: x=%d y=%d width=%d height=%d\n",
2894 ev->x, ev->y, ev->width, ev->height);
2895 stderr_out(" count: %d\n", ev->count);
2903 if (debug_x_events > 1) {
2904 XCrossingEvent *ev = &event->xcrossing;
2905 describe_event_window(ev->window, ev->display);
2907 stderr_out(" subwindow: 0x%x\n", ev->subwindow);
2908 stderr_out(" pos: %d %d\n", ev->x, ev->y);
2909 stderr_out(" root pos: %d %d\n", ev->x_root,
2912 stderr_out(" mode: %s\n",
2913 XEvent_mode_to_string(ev->mode));
2914 stderr_out(" detail: %s\n",
2915 XEvent_detail_to_string(ev->detail));
2916 stderr_out(" focus: %d\n", ev->focus);
2918 stderr_out(" state: 0x%x\n", ev->state);
2925 case ConfigureNotify:
2926 if (debug_x_events > 1) {
2927 XConfigureEvent *ev = &event->xconfigure;
2928 describe_event_window(ev->window, ev->display);
2929 stderr_out(" above: 0x%lx\n", ev->above);
2930 stderr_out(" size: %d %d %d %d\n", ev->x, ev->y,
2931 ev->width, ev->height);
2932 stderr_out(" redirect: %d\n", ev->override_redirect);
2938 case VisibilityNotify:
2939 if (debug_x_events > 1) {
2940 XVisibilityEvent *ev = &event->xvisibility;
2941 describe_event_window(ev->window, ev->display);
2942 stderr_out(" state: %s\n",
2943 XEvent_visibility_to_string(ev->state));
2949 case ClientMessage: {
2950 XClientMessageEvent *ev = &event->xclient;
2951 char *name = XGetAtomName(ev->display, ev->message_type);
2952 stderr_out("%s", name);
2953 if (!strcmp(name, "WM_PROTOCOLS")) {
2955 XGetAtomName(ev->display, ev->data.l[0]);
2956 stderr_out("(%s)", protname);
2972 #endif /* include describe_event definition */
2974 /************************************************************************/
2975 /* get the next event from Xt */
2976 /************************************************************************/
2978 static Lisp_Object dispatch_event_queue, dispatch_event_queue_tail;
2980 void enqueue_Xt_dispatch_event(Lisp_Object event)
2982 enqueue_event(event, &dispatch_event_queue, &dispatch_event_queue_tail);
2985 static Lisp_Object dequeue_Xt_dispatch_event(void)
2987 return dequeue_event(&dispatch_event_queue, &dispatch_event_queue_tail);
2990 /* This business exists because menu events "happen" when
2991 menubar_selection_callback() is called from somewhere deep
2992 within XtAppProcessEvent in emacs_Xt_next_event(). The
2993 callback needs to terminate the modal loop in that function
2994 or else it will continue waiting until another event is
2997 Same business applies to scrollbar events. */
3000 signal_special_Xt_user_event(Lisp_Object channel, Lisp_Object function,
3003 Lisp_Object event = Fmake_event(Qnil, Qnil);
3005 XEVENT(event)->event_type = misc_user_event;
3006 XEVENT(event)->channel = channel;
3007 XEVENT(event)->event.eval.function = function;
3008 XEVENT(event)->event.eval.object = object;
3010 enqueue_Xt_dispatch_event(event);
3013 static void emacs_Xt_next_event(Lisp_Event * emacs_event)
3015 we_didnt_get_an_event:
3017 while (NILP(dispatch_event_queue) &&
3018 !completed_timeouts_head &&
3019 !fake_event_occurred &&
3020 !process_events_occurred && !tty_events_occurred) {
3022 /* Stupid logic in XtAppProcessEvent() dictates that, if process
3023 events and X events are both available, the process event
3024 gets taken first. This will cause an infinite loop if we're
3025 being called from Fdiscard_input().
3027 if (XtAppPending(Xt_app_con) & XtIMXEvent) {
3028 XtAppProcessEvent(Xt_app_con, XtIMXEvent);
3030 Lisp_Object devcons, concons;
3032 /* We're about to block. Xt has a bug in it (big
3033 surprise, there) in that it blocks using select() and
3034 doesn't flush the Xlib output buffers (XNextEvent()
3035 does this automatically before blocking). So it's
3036 necessary for us to do this ourselves. If we don't
3037 do it, then display output may not be seen until the
3038 next time an X event is received. (This happens
3039 esp. with subprocess output that gets sent to a
3042 #### The above comment may not have any validity. */
3044 DEVICE_LOOP_NO_BREAK(devcons, concons) {
3046 d = XDEVICE(XCAR(devcons));
3048 if (DEVICE_X_P(d) && DEVICE_X_DISPLAY(d)) {
3049 /* emacs may be exiting */
3050 XFlush(DEVICE_X_DISPLAY(d));
3053 XtAppProcessEvent(Xt_app_con, XtIMAll);
3057 if (!NILP(dispatch_event_queue)) {
3058 Lisp_Object event, event2;
3059 XSETEVENT(event2, emacs_event);
3060 event = dequeue_Xt_dispatch_event();
3061 Fcopy_event(event, event2);
3062 Fdeallocate_event(event);
3063 } else if (tty_events_occurred) {
3064 if (!Xt_tty_to_emacs_event(emacs_event))
3065 goto we_didnt_get_an_event;
3066 } else if (completed_timeouts_head) {
3067 Xt_timeout_to_emacs_event(emacs_event);
3068 } else if (fake_event_occurred) {
3069 /* A dummy event, so that a cycle of the command loop will occur. */
3070 fake_event_occurred = 0;
3071 /* eval events have nil as channel */
3072 emacs_event->event_type = eval_event;
3073 emacs_event->event.eval.function = Qidentity;
3074 emacs_event->event.eval.object = Qnil;
3076 /* if (process_events_occurred) */
3077 Xt_process_to_emacs_event(emacs_event);
3080 /* No need to call XFilterEvent; Xt does it for us */
3084 emacs_Xt_event_handler(Widget SXE_UNUSED(wid),
3085 XtPointer SXE_UNUSED(closure),
3087 Boolean * SXE_UNUSED(continue_to_dispatch))
3089 Lisp_Object emacs_event = Fmake_event(Qnil, Qnil);
3091 #ifdef DEBUG_SXEMACS
3092 if (debug_x_events > 0) {
3093 describe_event(event);
3095 #endif /* DEBUG_SXEMACS */
3096 if (x_event_to_emacs_event(event, XEVENT(emacs_event))) {
3097 enqueue_Xt_dispatch_event(emacs_event);
3099 Fdeallocate_event(emacs_event);
3103 /************************************************************************/
3104 /* input pending / C-g checking */
3105 /************************************************************************/
3108 quit_char_predicate(Display * display, XEvent * event, XPointer data)
3110 struct device *d = get_device_from_display(display);
3111 struct x_device *xd = DEVICE_X_DATA(d);
3113 Bool *critical = (Bool *) data;
3119 if ((event->type != KeyPress) ||
3120 (!x_any_window_to_frame(d, event->xany.window)) ||
3122 & (xd->MetaMask | xd->HyperMask | xd->SuperMask | xd->AltMask))) {
3126 /* This duplicates some code that exists elsewhere, but it's relatively
3127 fast and doesn't cons. */
3128 keysym = x_to_emacs_keysym(&event->xkey, 1);
3132 if (CHAR_OR_CHAR_INTP(keysym)) {
3133 c = XCHAR_OR_CHAR_INT(keysym);
3134 } else if (EQ(keysym, QKbackspace)) {
3135 /* Highly doubtful that these are the quit character, but... */
3137 } else if (EQ(keysym, QKtab)) {
3139 } else if (EQ(keysym, QKlinefeed)) {
3141 } else if (EQ(keysym, QKreturn)) {
3143 } else if (EQ(keysym, QKescape)) {
3145 } else if (EQ(keysym, QKspace)) {
3147 } else if (EQ(keysym, QKdelete)) {
3153 if (event->xkey.state & xd->MetaMask) {
3156 if ((event->xkey.state & ControlMask) && !(c >= 'A' && c <= 'Z')) {
3157 /* unshifted control characters */
3160 quit_char = CONSOLE_QUIT_CHAR(XCONSOLE(DEVICE_CONSOLE(d)));
3161 if (c == quit_char) {
3164 /* If we've got Control-Shift-G instead of Control-G, that means
3165 we have a critical_quit. Caps_Lock is its own modifier, so it
3166 won't cause ^G to act differently than before. */
3167 if (event->xkey.state & ControlMask) {
3170 if (c == quit_char) {
3179 /* This scans the X input queue for a KeyPress event that matches the
3180 quit character, and sets Vquit_flag. This is called from the
3181 QUIT macro to determine whether we should quit.
3183 In a SIGIO world, this won't be called unless a SIGIO has happened
3184 since the last time we checked.
3186 In a non-SIGIO world, this is called from emacs_Xt_event_pending_p
3187 (which is called from input_pending_p).
3190 x_check_for_quit_char(Display * display)
3194 Bool critical_quit = False;
3196 XEventsQueued(display, QueuedAfterReading);
3197 queued = XCheckIfEvent(display, &event,
3198 quit_char_predicate, (char *)&critical_quit);
3200 Vquit_flag = (critical_quit ? Qcritical : Qt);
3201 /* don't put the event back onto the queue. Those functions that
3202 wanted to read a ^G directly have arranged to do this. */
3207 check_for_tty_quit_char(struct device *d)
3209 SELECT_TYPE temp_mask;
3210 int infd = DEVICE_INFD(d);
3211 struct console *con = XCONSOLE(DEVICE_CONSOLE(d));
3212 Emchar quit_char = CONSOLE_QUIT_CHAR(con);
3214 FD_ZERO(&temp_mask);
3215 FD_SET(infd, &temp_mask);
3221 if (!poll_fds_for_input(temp_mask)) {
3225 event = Fmake_event(Qnil, Qnil);
3226 if (!read_event_from_tty_or_stream_desc
3227 (XEVENT(event), con, infd)) {
3228 /* EOF, or something ... */
3231 /* #### bogus. quit-char should be allowed to be any sort
3233 the_char = event_to_character(XEVENT(event), 1, 0, 0);
3234 if (the_char >= 0 && the_char == quit_char) {
3236 /* do not queue the C-g. See above. */
3240 /* queue the read event to be read for real later. */
3241 enqueue_Xt_dispatch_event(event);
3245 static void emacs_Xt_quit_p(void)
3247 Lisp_Object devcons, concons;
3248 CONSOLE_LOOP(concons) {
3249 struct console *con = XCONSOLE(XCAR(concons));
3250 if (!con->input_enabled) {
3254 CONSOLE_DEVICE_LOOP(devcons, con) {
3256 d = XDEVICE(XCAR(devcons));
3258 if (DEVICE_X_P(d) && DEVICE_X_DISPLAY(d)) {
3259 /* emacs may be exiting */
3260 x_check_for_quit_char(DEVICE_X_DISPLAY(d));
3261 } else if (DEVICE_TTY_P(d)) {
3262 check_for_tty_quit_char(d);
3268 static void drain_X_queue(void)
3270 Lisp_Object devcons, concons;
3271 CONSOLE_LOOP(concons) {
3272 struct console *con = XCONSOLE(XCAR(concons));
3273 if (!con->input_enabled) {
3277 /* sjt sez: Have you tried the loop over devices with
3278 XtAppPending(), not XEventsQueued()?
3279 Ben Sigelman sez: No.
3280 sjt sez: I'm guessing that the reason that your patch
3285 + d = XDEVICE (XCAR (devcons));
3286 + if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d)) {
3288 Ie, if the device goes down, SXEmacs detects that and deletes
3289 it. Then the if() fails (DEVICE_X_DISPLAY(d) is NULL), and
3290 we don't go into the Xlib-of-no-return. If you know
3291 different, I'd like to hear about it. ;-)
3293 These ideas haven't been tested; the code below works for
3296 CONSOLE_DEVICE_LOOP(devcons, con) {
3299 d = XDEVICE(XCAR(devcons));
3300 if (DEVICE_X_P(d) && DEVICE_X_DISPLAY(d)) {
3301 display = DEVICE_X_DISPLAY(d);
3302 while (XEventsQueued
3303 (display, QueuedAfterReading)) {
3304 XtAppProcessEvent(Xt_app_con,
3310 /* This is the old code, before Ben Sigelman's patch. */
3312 while (XtAppPending (Xt_app_con) & XtIMXEvent)
3313 XtAppProcessEvent (Xt_app_con, XtIMXEvent);
3318 emacs_Xt_event_pending_p(int user_p)
3323 /* If `user_p' is false, then this function returns whether there are any
3324 X, timeout, or fd events pending (that is, whether emacs_Xt_next_event()
3325 would return immediately without blocking).
3327 if `user_p' is true, then this function returns whether there are any
3328 *user generated* events available (that is, whether there are keyboard
3329 or mouse-click events ready to be read). This also implies that
3330 emacs_Xt_next_event() would not block.
3332 In a non-SIGIO world, this also checks whether the user has typed ^G,
3333 since this is a convenient place to do so. We don't need to do this
3334 in a SIGIO world, since input causes an interrupt.
3338 /* I don't think there's any point to this and it will nullify
3339 the speed gains achieved by the sigio_happened checking below.
3340 Its only advantage is that it may possibly make C-g response
3341 a bit faster. The C-g will be noticed within 0.25 second, anyway,
3342 even without this. */
3344 /* First check for C-g if necessary */
3349 /* This function used to simply check whether there were any X
3350 events (or if user_p was 1, it iterated over all the pending
3351 X events using XCheckIfEvent(), looking for keystrokes and
3352 button events). That worked in the old cheesoid event loop,
3353 which didn't go through XtAppDispatchEvent(), but it doesn't
3354 work any more -- X events may not result in anything. For
3355 example, a button press in a blank part of the menubar appears
3356 as an X event but will not result in any Emacs events (a
3357 button press that activates the menubar results in an Emacs
3358 event through the stop_next_event mechanism).
3360 The only accurate way of determining whether these X events
3361 translate into Emacs events is to go ahead and dispatch them
3362 until there's something on the dispatch queue. */
3364 /* See if there are any user events already on the queue. */
3365 EVENT_CHAIN_LOOP(event, dispatch_event_queue) {
3366 if (!user_p || command_event_p(event)) {
3371 /* See if there's any TTY input available.
3373 if (poll_fds_for_input(tty_only_mask)) {
3378 /* If not user_p and there are any timer or file-desc events
3379 pending, we know there will be an event so we're through. */
3380 XtInputMask pending_value;
3382 /* Note that formerly we just checked the value of
3383 XtAppPending() to determine if there was file-desc input.
3384 This doesn't work any more with the signal_event_pipe;
3385 XtAppPending() will says "yes" in this case but there isn't
3386 really any input. Another way of fixing this problem is for
3387 the signal_event_pipe to generate actual input in the form of
3388 an identity eval event or something. (#### maybe this
3389 actually happens?) */
3391 if (poll_fds_for_input(process_only_mask)) {
3394 pending_value = XtAppPending(Xt_app_con);
3396 if (pending_value & XtIMTimer) {
3401 /* XtAppPending() can be super-slow, esp. over a network connection.
3402 Quantify results have indicated that in some cases the
3403 call to detect_input_pending() completely dominates the
3404 running time of redisplay(). Fortunately, in a SIGIO world
3405 we can more quickly determine whether there are any X events:
3406 if an event has happened since the last time we checked, then
3407 a SIGIO will have happened. On a machine with broken SIGIO,
3408 we'll still be in an OK state -- the sigio_happened flag
3409 will get set at least once a second, so we'll be no more than
3410 one second behind reality. (In general it's OK if we
3411 erroneously report no input pending when input is actually
3412 pending() -- preemption is just a bit less efficient, that's
3413 all. It's bad bad bad if you err the other way -- you've
3414 promised that `next-event' won't block but it actually will,
3415 and some action might get delayed until the next time you
3419 /* quit_check_signal_tick_count is volatile so try to avoid race
3420 conditions by using a temporary variable */
3421 tick_count_val = quit_check_signal_tick_count;
3422 if (last_quit_check_signal_tick_count != tick_count_val
3423 #if !defined (SIGIO)
3424 || (XtIMXEvent & XtAppPending(Xt_app_con))
3427 last_quit_check_signal_tick_count = tick_count_val;
3429 /* We need to drain the entire queue now -- if we only
3430 drain part of it, we may later on end up with events
3431 actually pending but detect_input_pending() returning
3432 false because there wasn't another SIGIO. */
3435 EVENT_CHAIN_LOOP(event, dispatch_event_queue) {
3436 if (!user_p || command_event_p(event)) {
3446 emacs_Xt_current_event_timestamp(struct console *c)
3449 Lisp_Object devs = CONSOLE_DEVICE_LIST(c);
3454 struct device *d = XDEVICE(XCAR(devs));
3455 return DEVICE_X_LAST_SERVER_TIMESTAMP(d);
3459 /************************************************************************/
3460 /* replacement for standard string-to-pixel converter */
3461 /************************************************************************/
3463 /* This was constructed by ripping off the standard string-to-pixel
3464 converter from Converters.c in the Xt source code and modifying
3469 /* This is exported by the Xt library (at least by mine). If this
3470 isn't the case somewhere, rename this appropriately and remove
3471 the '#if 0'. Note, however, that I got "unknown structure"
3472 errors when I tried this. */
3473 XtConvertArgRec Const colorConvertArgs[] = {
3474 {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.screen),
3477 {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.colormap),
3483 #define done(type, value) \
3484 if (toVal->addr != NULL) { \
3485 if (toVal->size < sizeof(type)) { \
3486 toVal->size = sizeof(type); \
3489 *(type*)(toVal->addr) = (value); \
3491 static type static_val; \
3492 static_val = (value); \
3493 toVal->addr = (XPointer)&static_val; \
3495 toVal->size = sizeof(type); \
3496 return True /* Caller supplies `;' */
3498 /* JH: We use this because I think there's a possibility this
3499 is called before the device is properly set up, in which case
3500 I don't want to abort. */
3501 extern struct device *get_device_from_display_1(Display * dpy);
3504 Boolean EmacsXtCvtStringToPixel(Display * dpy,
3506 Cardinal * num_args,
3507 XrmValuePtr fromVal,
3508 XrmValuePtr toVal, XtPointer * closure_ret)
3510 String str = (String) fromVal->addr;
3519 Cardinal num_params = 1;
3520 XtAppContext the_app_con = XtDisplayToApplicationContext(dpy);
3522 if (*num_args != 2) {
3523 XtAppWarningMsg(the_app_con, "wrongParameters",
3524 "cvtStringToPixel", "XtToolkitError",
3525 "String to pixel conversion needs "
3526 "screen and colormap arguments",
3527 (String *) NULL, (Cardinal *) NULL);
3531 screen = *((Screen **) args[0].addr);
3532 colormap = *((Colormap *) args[1].addr);
3534 /* The original uses the private function CompareISOLatin1().
3535 Use XmuCompareISOLatin1() if you want, but I don't think it
3536 makes any difference here. */
3537 if (strcmp(str, XtDefaultBackground) == 0) {
3538 *closure_ret = False;
3539 /* This refers to the display's "*reverseVideo" resource.
3540 These display resources aren't documented anywhere that
3541 I can find, so I'm going to ignore this. */
3542 /* if (pd->rv) done(Pixel, BlackPixelOfScreen(screen)) else */
3543 done(Pixel, WhitePixelOfScreen(screen));
3545 if (strcmp(str, XtDefaultForeground) == 0) {
3546 *closure_ret = False;
3547 /* if (pd->rv) done(Pixel, WhitePixelOfScreen(screen)) else */
3548 done(Pixel, BlackPixelOfScreen(screen));
3551 /* Originally called XAllocNamedColor() here. */
3552 if ((d = get_device_from_display_1(dpy))) {
3553 visual = DEVICE_X_VISUAL(d);
3554 if (colormap != DEVICE_X_COLORMAP(d)) {
3555 XtAppWarningMsg(the_app_con, "weirdColormap",
3556 "cvtStringToPixel", "XtToolkitWarning",
3557 "The colormap passed to "
3558 "cvtStringToPixel doesn't match the "
3559 "one registered to the device.\n",
3561 status = XAllocNamedColor(dpy, colormap, (char *)str,
3562 &screenColor, &exactColor);
3564 status = XParseColor(dpy, colormap, (char *)str,
3567 status = allocate_nearest_color(
3568 dpy, colormap, visual, &screenColor);
3572 /* We haven't set up this device totally yet, so just punt */
3573 status = XAllocNamedColor(dpy, colormap, (char *)str,
3574 &screenColor, &exactColor);
3578 /* Server returns a specific error code but Xlib discards it.
3580 if (XLookupColor(DisplayOfScreen(screen), colormap, (char*)str,
3581 &exactColor, &screenColor)) {
3582 XtAppWarningMsg(the_app_con, "noColormap",
3583 "cvtStringToPixel", "XtToolkitError",
3584 "Cannot allocate colormap entry for "
3586 params, &num_params);
3589 XtAppWarningMsg(the_app_con, "badValue",
3590 "cvtStringToPixel", "XtToolkitError",
3591 "Color name \"%s\" is not defined",
3592 params, &num_params);
3595 *closure_ret = False;
3598 *closure_ret = (char *)True;
3599 done(Pixel, screenColor.pixel);
3604 static void EmacsFreePixel(XtAppContext app,
3607 XrmValuePtr args, Cardinal * num_args)
3609 if (*num_args != 2) {
3610 XtAppWarningMsg(app, "wrongParameters", "freePixel",
3612 "Freeing a pixel requires screen and "
3613 "colormap arguments",
3614 (String *) NULL, (Cardinal *) NULL);
3619 Screen *screen = *((Screen **) args[0].addr);
3620 Colormap colormap = *((Colormap *) args[1].addr);
3621 XFreeColors(DisplayOfScreen(screen), colormap,
3622 (unsigned long *)toVal->addr, 1, (unsigned long)0);
3626 /************************************************************************/
3627 /* handle focus changes for native widgets */
3628 /************************************************************************/
3630 emacs_Xt_event_widget_focus_in(Widget w,
3632 String * params, Cardinal * num_params)
3635 x_any_widget_or_parent_to_frame(get_device_from_display
3636 (event->xany.display), w);
3638 XtSetKeyboardFocus(FRAME_X_SHELL_WIDGET(f), w);
3642 emacs_Xt_event_widget_focus_out(Widget w,
3644 String * params, Cardinal * num_params)
3648 static XtActionsRec widgetActionsList[] = {
3649 {"widget-focus-in", emacs_Xt_event_widget_focus_in},
3650 {"widget-focus-out", emacs_Xt_event_widget_focus_out},
3654 emacs_Xt_event_add_widget_actions(XtAppContext ctx)
3656 XtAppAddActions(ctx, widgetActionsList, 2);
3659 /************************************************************************/
3660 /* initialization */
3661 /************************************************************************/
3662 static struct event_stream _Xt_event_stream = {
3663 .event_pending_p = emacs_Xt_event_pending_p,
3664 .force_event_pending = emacs_Xt_force_event_pending,
3665 .next_event_cb = emacs_Xt_next_event,
3666 .handle_magic_event_cb = emacs_Xt_handle_magic_event,
3667 .add_timeout_cb = emacs_Xt_add_timeout,
3668 .remove_timeout_cb = emacs_Xt_remove_timeout,
3669 .select_console_cb = emacs_Xt_select_console,
3670 .unselect_console_cb = emacs_Xt_unselect_console,
3671 .select_process_cb = emacs_Xt_select_process,
3672 .unselect_process_cb = emacs_Xt_unselect_process,
3673 .quit_p_cb = emacs_Xt_quit_p,
3674 .create_stream_pair_cb = emacs_Xt_create_stream_pair,
3675 .delete_stream_pair_cb = emacs_Xt_delete_stream_pair,
3676 .current_event_timestamp_cb = emacs_Xt_current_event_timestamp,
3679 void syms_of_event_Xt(void)
3681 defsymbol(&Qkey_mapping, "key-mapping");
3682 defsymbol(&Qsans_modifiers, "sans-modifiers");
3683 defsymbol(&Qself_insert_command, "self-insert-command");
3686 void reinit_vars_of_event_Xt(void)
3688 Xt_event_stream = &_Xt_event_stream;
3689 the_Xt_timeout_blocktype = Blocktype_new(struct Xt_timeout_blocktype);
3691 last_quit_check_signal_tick_count = 0;
3693 /* this function only makes safe calls */
3694 init_what_input_once();
3698 void vars_of_event_Xt(void)
3700 reinit_vars_of_event_Xt();
3702 dispatch_event_queue = Qnil;
3703 staticpro(&dispatch_event_queue);
3704 dispatch_event_queue_tail = Qnil;
3705 dump_add_root_object(&dispatch_event_queue_tail);
3707 DEFVAR_BOOL("x-allow-sendevents", &x_allow_sendevents /*
3708 *Non-nil means to allow synthetic events. Nil means they are ignored.
3709 Beware: allowing emacs to process SendEvents opens a big security hole.
3711 x_allow_sendevents = 0;
3713 #ifdef DEBUG_SXEMACS
3714 DEFVAR_INT("debug-x-events", &debug_x_events /*
3715 If non-zero, display debug information about X events that SXEmacs sees.
3716 Information is displayed on stderr. Currently defined values are:
3718 1 == non-verbose output
3725 /* This mess is a hack that patches the shell widget to treat visual
3726 inheritance the same as colormap and depth inheritance */
3728 static XtInitProc orig_shell_init_proc;
3731 ShellVisualPatch(Widget wanted, Widget new,
3732 ArgList args, Cardinal * num_args)
3735 ShellWidget w = (ShellWidget) new;
3737 /* first, call the original setup */
3738 (*orig_shell_init_proc) (wanted, new, args, num_args);
3740 /* if the visual isn't explicitly set, grab it from the nearest shell
3742 if (w->shell.visual == CopyFromParent) {
3744 while (p && !XtIsShell(p)) {
3748 w->shell.visual = ((ShellWidget) p)->shell.visual;
3753 void init_event_Xt_late(void)
3755 /* called when already initialized */
3756 timeout_id_tick = 1;
3757 pending_timeouts = NULL;
3758 completed_timeouts_head = NULL; /* queue is empty */
3759 completed_timeouts_tail = NULL; /* just to be picky */
3761 event_stream = Xt_event_stream;
3763 #if defined(HAVE_XIM) || defined(USE_XFONTSET)
3764 Initialize_Locale();
3765 #endif /* HAVE_XIM || USE_XFONTSET */
3767 XtToolkitInitialize();
3768 Xt_app_con = XtCreateApplicationContext();
3769 XtAppSetFallbackResources(Xt_app_con, (String*)x_fallback_resources);
3772 x_selection_timeout = (XtAppGetSelectionTimeout(Xt_app_con) / 1000);
3773 XSetErrorHandler(x_error_handler);
3774 XSetIOErrorHandler(x_IO_error_handler);
3776 XtAppAddInput(Xt_app_con, signal_event_pipe[0],
3777 (XtPointer) (XtInputReadMask /* | XtInputExceptMask */ ),
3778 Xt_what_callback, 0);
3780 XtAppSetTypeConverter(Xt_app_con, XtRString, XtRPixel,
3781 EmacsXtCvtStringToPixel,
3782 (XtConvertArgList)colorConvertArgs,
3783 2, XtCacheByDisplay, EmacsFreePixel);
3786 XtAppSetTypeConverter(Xt_app_con, XtRString, XtRXimStyles,
3787 EmacsXtCvtStringToXIMStyles,
3788 NULL, 0, XtCacheByDisplay, EmacsFreeXIMStyles);
3789 #endif /* XIM_XLIB */
3790 /* Add extra actions to native widgets to handle focus and friends. */
3791 emacs_Xt_event_add_widget_actions(Xt_app_con);
3793 /* insert the visual inheritance patch/hack described above */
3794 orig_shell_init_proc = shellClassRec.core_class.initialize;
3795 shellClassRec.core_class.initialize = ShellVisualPatch;
3797 #if defined(EF_USE_ASYNEQ)
3798 emacs_Xt_watch_event_queue(asyneq);
3802 /* event-Xt.c ends here */