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) {
604 #ifdef HAVE_XKBKEYCODETOKEYSYM
605 ? XkbKeycodeToKeysym(dspl, code, 0, column)
607 ? XKeycodeToKeysym(dspl, code, column)
611 if (LIKELY(sym == last_sym)) {
617 /* store_modifier("Mode_switch", &mode_bit); */
618 /* handled specially here */
619 mode_bit = modifier_index;
622 /* new modifier, new luck, reset clo->old */
624 store_modifier(code, "Meta_L", clo);
629 store_modifier(code, "Meta_R", clo);
633 clo->old = super_bit;
634 store_modifier(code, "Super_L", clo);
635 super_bit = clo->old;
638 clo->old = super_bit;
639 store_modifier(code, "Super_R", clo);
640 super_bit = clo->old;
643 clo->old = hyper_bit;
644 store_modifier(code, "Hyper_L", clo);
645 hyper_bit = clo->old;
648 clo->old = hyper_bit;
649 store_modifier(code, "Hyper_R", clo);
650 hyper_bit = clo->old;
654 store_modifier(code, "Alt_L", clo);
659 store_modifier(code, "Alt_R", clo);
663 check_modifier(code, "Control_L", ControlMask, clo);
666 check_modifier(code, "Control_R", ControlMask, clo);
669 check_modifier(code, "Shift_L", ShiftMask, clo);
672 check_modifier(code, "Shift_R", ShiftMask, clo);
675 check_modifier(code, "Shift_Lock", LockMask, clo);
676 xd->lock_interpretation = XK_Shift_Lock;
679 check_modifier(code, "Caps_Lock", LockMask, clo);
680 xd->lock_interpretation = XK_Caps_Lock;
683 /* It probably doesn't make any sense for a
684 modifier bit to be assigned to a key that is
685 not one of the above, but OpenWindows assigns
686 modifier bits to a couple of random function
687 keys for no reason that I can discern, so
688 printing a warning here would be annoying. */
690 /* hope we handled everything above */
695 #undef modifier_index
706 x_reset_modifier_mapping(struct device *d)
708 #define modifier_index clo.modifier_index
709 #define modifier_key clo.modifier_key
710 #define mkpm clo.mkpm
711 Display *display = DEVICE_X_DISPLAY(d);
712 struct x_device *xd = DEVICE_X_DATA(d);
713 struct mod_clo_s clo = {
714 .warned_about_overlapping_modifiers = false,
715 .warned_about_predefined_modifiers = false,
716 .warned_about_duplicate_modifiers = false,
725 #define mode_bit clo.mode_bit
726 #define meta_bit clo.meta_bit
727 #define alt_bit clo.alt_bit
728 #define super_bit clo.super_bit
729 #define hyper_bit clo.hyper_bit
730 xd->lock_interpretation = 0;
732 if (xd->x_modifier_keymap) {
733 XFreeModifiermap(xd->x_modifier_keymap);
735 x_reset_key_mapping(d);
737 xd->x_modifier_keymap = XGetModifierMapping(display);
739 /* The call to warn_when_safe must be on the same line as the string or
740 make-msgfile won't pick it up properly (the newline doesn't confuse
741 it, but the backslash does). */
743 mkpm = xd->x_modifier_keymap->max_keypermod;
744 for (modifier_index = 0; modifier_index < 8; modifier_index++) {
745 for (modifier_key = 0; modifier_key < mkpm; modifier_key++) {
746 whatever(display, xd, &clo);
750 /* If there was no Meta key, then try using the Alt key instead.
751 If there is both a Meta key and an Alt key, then the Alt key
752 is not disturbed and remains an Alt key. */
753 if (!meta_bit && alt_bit) {
758 /* mode_bit overrides everything, since it's processed down inside of
759 XLookupString() instead of by us. If Meta and Mode_switch both
760 generate the same modifier bit (which is an error), then we don't
761 interpret that bit as Meta, because we can't make XLookupString()
762 not interpret it as Mode_switch; and interpreting it as both would
765 const char *warn = 0;
767 if (mode_bit == meta_bit) {
770 } else if (mode_bit == hyper_bit) {
773 } else if (mode_bit == super_bit) {
776 } else if (mode_bit == alt_bit) {
782 Qkey_mapping, Qwarning,
783 "SXEmacs: %s is being used for both "
784 "Mode_switch and %s.",
785 index_to_name(mode_bit), warn);
786 clo.warned_about_overlapping_modifiers = true;
790 xd->MetaMask = (meta_bit ? (1 << meta_bit) : 0);
791 xd->HyperMask = (hyper_bit ? (1 << hyper_bit) : 0);
792 xd->SuperMask = (super_bit ? (1 << super_bit) : 0);
793 xd->AltMask = (alt_bit ? (1 << alt_bit) : 0);
794 xd->ModeMask = (mode_bit ? (1 << mode_bit) : 0); /* unused */
796 if (clo.warned_about_overlapping_modifiers) {
797 warn_when_safe(Qkey_mapping, Qwarning, "%s", err_overlap_mods);
800 if (clo.warned_about_predefined_modifiers) {
801 warn_when_safe(Qkey_mapping, Qwarning, "%s", err_predef_mods);
804 /* No need to say anything more for warned_about_duplicate_modifiers. */
805 if (clo.warned_about_overlapping_modifiers ||
806 clo.warned_about_predefined_modifiers)
807 warn_when_safe(Qkey_mapping, Qwarning, "%s", err_msg_else);
808 #undef modifier_index
818 void x_init_modifier_mapping(struct device *d)
820 struct x_device *xd = DEVICE_X_DATA(d);
821 xd->x_keysym_map_hash_table = Qnil;
822 xd->x_keysym_map = NULL;
823 xd->x_modifier_keymap = NULL;
824 x_reset_modifier_mapping(d);
828 static int x_key_is_modifier_p(KeyCode keycode, struct device *d)
830 struct x_device *xd = DEVICE_X_DATA(d);
834 if (keycode < xd->x_keysym_map_min_code ||
835 keycode > xd->x_keysym_map_max_code) {
839 syms = &xd->x_keysym_map[(keycode - xd->x_keysym_map_min_code) *
840 xd->x_keysym_map_keysyms_per_code];
841 for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++) {
842 if (IsModifierKey(syms[i]) || syms[i] == XK_Mode_switch) {
843 /* why doesn't IsModifierKey count this? */
850 /* key-handling code is always ugly. It just ends up working out
853 Here are some pointers:
855 -- DOWN_MASK indicates which modifiers should be treated as "down"
856 when the corresponding upstroke happens. It gets reset for
857 a particular modifier when that modifier goes up, and reset
858 for all modifiers when a non-modifier key is pressed. Example:
860 I press Control-A-Shift and then release Control-A-Shift.
861 I want the Shift key to be sticky but not the Control key.
863 -- LAST_DOWNKEY and RELEASE_TIME are used to keep track of
864 auto-repeat -- see below.
866 -- If a modifier key is sticky, I can unstick it by pressing
867 the modifier key again. */
869 static void x_handle_sticky_modifiers(XEvent * ev, struct device *d)
876 if (!modifier_keys_are_sticky) {
877 /* Optimize for non-sticky modifiers */
881 xd = DEVICE_X_DATA(d);
882 keycode = ev->xkey.keycode;
885 if (keycode < xd->x_keysym_map_min_code ||
886 keycode > xd->x_keysym_map_max_code) {
889 key_event_p = (type == KeyPress || type == KeyRelease);
891 if (!( key_event_p && x_key_is_modifier_p(keycode, d))) {
892 /* Not a modifier key */
894 if (type == ButtonPress
896 && ((xd->last_downkey
897 && ((keycode != xd->last_downkey
898 || ev->xkey.time != xd->release_time)))
899 || (INTP(Vmodifier_keys_sticky_time)
901 > (xd->modifier_release_time
902 + XINT(Vmodifier_keys_sticky_time)))))) {
903 xd->need_to_add_mask = 0;
904 xd->last_downkey = 0;
905 } else if (type == KeyPress && !xd->last_downkey) {
906 xd->last_downkey = keycode;
908 if (type == KeyPress) {
909 xd->release_time = 0;
911 if (type == KeyPress || type == ButtonPress) {
913 xd->modifier_release_time = 0;
917 ev->xkey.state |= xd->need_to_add_mask;
919 ev->xbutton.state |= xd->need_to_add_mask;
922 if (type == KeyRelease && keycode == xd->last_downkey) {
923 /* If I hold press-and-release the Control key and then
924 press and hold down the right arrow, I want it to
925 auto-repeat Control-Right. On the other hand, if I
926 do the same but manually press the Right arrow a
927 bunch of times, I want to see one Control-Right and
928 then a bunch of Rights. This means that we need to
929 distinguish between an auto-repeated key and a key
930 pressed and released a bunch of times.
932 Naturally, the designers of the X spec didn't see fit
933 to provide an obvious way to distinguish these cases.
934 So we assume that if the release and the next press
935 occur at the same time, the key was actually auto-
936 repeated. Under Open-Windows, at least, this
938 xd->modifier_release_time = xd->release_time =
944 /* Modifier key pressed */
946 KeySym *syms = &xd->x_keysym_map[
947 (keycode - xd->x_keysym_map_min_code) *
948 xd->x_keysym_map_keysyms_per_code];
950 /* If a non-modifier key was pressed in the middle of a bunch
951 of modifiers, then it unsticks all the modifiers that were
952 previously pressed. We cannot unstick the modifiers until
953 now because we want to check for auto-repeat of the
956 if (xd->last_downkey) {
957 xd->last_downkey = 0;
958 xd->need_to_add_mask = 0;
961 if (xd->modifier_release_time
962 && INTP(Vmodifier_keys_sticky_time)
963 && (ev->xkey.time > xd->modifier_release_time +
964 XINT(Vmodifier_keys_sticky_time))) {
965 xd->need_to_add_mask = 0;
971 if (type == KeyPress) { \
972 /* If modifier key is already sticky, \
973 then unstick it. Note that we do \
974 not test down_mask to deal with the \
975 unlikely but possible case that the \
976 modifier key auto-repeats. */ \
977 if (xd->need_to_add_mask & mask) { \
978 xd->need_to_add_mask &= ~mask; \
979 xd->down_mask &= ~mask; \
981 xd->down_mask |= mask; \
984 if (xd->down_mask & mask) { \
985 xd->down_mask &= ~mask; \
986 xd->need_to_add_mask |= mask; \
989 xd->modifier_release_time = ev->xkey.time; \
992 for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++) {
1008 FROB(xd->SuperMask);
1012 FROB(xd->HyperMask);
1019 /* hope we handled everything */
1027 static void clear_sticky_modifiers(struct device *d)
1029 struct x_device *xd = DEVICE_X_DATA(d);
1031 xd->need_to_add_mask = 0;
1032 xd->last_downkey = 0;
1033 xd->release_time = 0;
1038 static int keysym_obeys_caps_lock_p(KeySym sym, struct device *d)
1040 struct x_device *xd = DEVICE_X_DATA(d);
1041 /* Eeeeevil hack. Don't apply Caps_Lock to things that aren't
1042 alphabetic characters, where "alphabetic" means something more than
1043 simply A-Z. That is, if Caps_Lock is down, typing ESC doesn't
1044 produce Shift-ESC. But if shift-lock is down, then it does. */
1045 if (xd->lock_interpretation == XK_Shift_Lock) {
1048 return ((sym >= XK_A) && (sym <= XK_Z)) ||
1049 ((sym >= XK_a) && (sym <= XK_z)) ||
1050 ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) ||
1051 ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) ||
1052 ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) ||
1053 ((sym >= XK_oslash) && (sym <= XK_thorn));
1056 /* called from EmacsFrame.c (actually from Xt itself) when a
1057 MappingNotify event is received. In its infinite wisdom, Xt
1058 decided that Xt event handlers never get MappingNotify events.
1059 O'Reilly Xt Programming Manual 9.1.2 says:
1061 MappingNotify is automatically handled by Xt, so it isn't passed
1062 to event handlers and you don't need to worry about it.
1064 Of course, we DO worry about it, so we need a special translation. */
1066 emacs_Xt_mapping_action(Widget w, XEvent * event)
1068 struct device *d = get_device_from_display(event->xany.display);
1070 if (DEVICE_X_BEING_DELETED(d)) {
1074 /* nyet. Now this is handled by Xt. */
1075 XRefreshKeyboardMapping(&event->xmapping);
1077 /* xmodmap generates about a billion MappingKeyboard events, followed by
1078 a single MappingModifier event, so it might be worthwhile to take
1079 extra MappingKeyboard events out of the queue before requesting the
1080 current keymap from the server. */
1081 switch (event->xmapping.request) {
1082 case MappingKeyboard:
1083 x_reset_key_mapping(d);
1085 case MappingModifier:
1086 x_reset_modifier_mapping(d);
1088 case MappingPointer:
1089 /* Do something here? */
1096 /************************************************************************/
1097 /* X to Emacs event conversion */
1098 /************************************************************************/
1101 x_keysym_to_emacs_keysym(KeySym keysym, int simple_p)
1104 if (keysym >= XK_exclam && keysym <= XK_asciitilde) {
1105 /* We must assume that the X keysym numbers for the ASCII
1106 graphic characters are the same as their ASCII codes. */
1107 return make_char(keysym);
1111 /* These would be handled correctly by the default case, but by
1112 special-casing them here we don't garbage a string or call
1134 /* !!#### not Mule-ized */
1135 name = XKeysymToString(keysym);
1136 if (!name || !name[0]) {
1137 /* This happens if there is a mismatch between the Xlib
1138 of SXEmacs and the Xlib of the X server...
1140 Let's hard-code in some knowledge of common keysyms
1141 introduced in recent X11 releases. Snarfed from
1144 Probably we should add some stuff here for X11R6. */
1147 return KEYSYM("kp-home");
1149 return KEYSYM("kp-left");
1151 return KEYSYM("kp-up");
1153 return KEYSYM("kp-right");
1155 return KEYSYM("kp-down");
1157 return KEYSYM("kp-prior");
1159 return KEYSYM("kp-next");
1161 return KEYSYM("kp-end");
1163 return KEYSYM("kp-begin");
1165 return KEYSYM("kp-insert");
1167 return KEYSYM("kp-delete");
1171 return KEYSYM("SunF36");
1174 return KEYSYM("SunF37");
1177 int sz = snprintf(buf, sizeof(buf),
1178 "unknown-keysym-0x%X",
1180 assert(sz>=0 && (size_t)sz < sizeof(buf));
1185 /* If it's got a one-character name, that's good enough. */
1187 return make_char(name[0]);
1189 /* If it's in the "Keyboard" character set, downcase it. The
1190 case of those keysyms is too totally random for us to force
1191 anyone to remember them. The case of the other character
1192 sets is significant, however.
1194 if ((((unsigned int)keysym) & (~0x1FF)) ==
1195 ((unsigned int)0xFE00)) {
1198 for (s1 = name, s2 = buf; *s1; s1++, s2++) {
1202 *s2 = tolower(*(unsigned char *)s1);
1208 return KEYSYM(name);
1213 x_to_emacs_keysym(XKeyPressedEvent * event, int simple_p)
1214 /* simple_p means don't try too hard (ASCII only) */
1220 /* Some implementations of XmbLookupString don't return
1221 XBufferOverflow correctly, so increase the size of the xim input
1222 buffer from 64 to the more reasonable size 513, as Emacs has done.
1223 From Kenichi Handa. */
1225 char *bufptr = buffer;
1226 int bufsiz = sizeof(buffer);
1231 x_any_window_to_frame(get_device_from_display(event->display),event->window);
1233 xic = FRAME_X_XIC(f);
1234 #endif /* XIM_XLIB */
1235 #endif /* HAVE_XIM */
1237 /* We use XLookupString if we're not using XIM, or are using
1238 XIM_XLIB but input context creation failed. */
1239 #if ! (defined (HAVE_XIM) && defined (XIM_MOTIF))
1240 #if defined (HAVE_XIM) && defined (XIM_XLIB)
1242 #endif /* XIM_XLIB */
1244 /* Apparently it's necessary to specify a dummy here (rather
1245 than passing in 0) to avoid crashes on German IRIX */
1247 XLookupString(event, dummy, 200, &keysym, 0);
1248 return (IsModifierKey(keysym) || keysym == XK_Mode_switch)
1249 ? Qnil : x_keysym_to_emacs_keysym(keysym, simple_p);
1251 #endif /* ! XIM_MOTIF */
1254 Lookup_String: /* Come-From XBufferOverflow */
1257 XmImMbLookupString(XtWindowToWidget(event->display, event->window),
1258 event, bufptr, bufsiz, &keysym, &status);
1259 #else /* XIM_XLIB */
1261 len = XmbLookupString(xic, event, bufptr, bufsiz, &keysym,
1264 #endif /* HAVE_XIM */
1266 #ifdef DEBUG_SXEMACS
1267 if (debug_x_events > 0) {
1268 stderr_out(" status=");
1269 #define print_status_when(S) if (status == S) stderr_out (#S)
1270 print_status_when(XLookupKeySym);
1271 print_status_when(XLookupBoth);
1272 print_status_when(XLookupChars);
1273 print_status_when(XLookupNone);
1274 print_status_when(XBufferOverflow);
1276 if (status == XLookupKeySym || status == XLookupBoth)
1277 stderr_out(" keysym=%s", XKeysymToString(keysym));
1278 if (status == XLookupChars || status == XLookupBoth) {
1281 stderr_out(" chars=\"");
1282 for (j = 0; j < len; j++)
1283 stderr_out("%c", bufptr[j]);
1285 } else if (bufptr[0] <= 32 || bufptr[0] >= 127) {
1286 stderr_out(" char=0x%x", bufptr[0]);
1288 stderr_out(" char=%c", bufptr[0]);
1293 #endif /* DEBUG_SXEMACS */
1298 return (IsModifierKey(keysym) || keysym == XK_Mode_switch)
1300 : x_keysym_to_emacs_keysym(keysym, simple_p);
1302 case XLookupChars: {
1303 /* Generate multiple emacs events */
1304 struct device *d = get_device_from_display(event->display);
1306 Lisp_Object instream, fb_instream;
1308 struct gcpro gcpro1, gcpro2;
1310 fb_instream = make_fixed_buffer_input_stream(bufptr, len);
1312 /* #### Use Fget_coding_system
1313 * (Vcomposed_input_coding_system) */
1314 instream = make_decoding_input_stream(XLSTREAM(fb_instream),
1318 istr = XLSTREAM(instream);
1320 GCPRO2(instream, fb_instream);
1321 while ((ch = Lstream_get_emchar(istr)) != EOF) {
1322 Lisp_Object emacs_event = Fmake_event(Qnil, Qnil);
1323 Lisp_Event *ev = XEVENT(emacs_event);
1324 ev->channel = DEVICE_CONSOLE(d);
1325 ev->event_type = key_press_event;
1326 ev->timestamp = event->time;
1327 ev->event.key.modifiers = 0;
1328 ev->event.key.keysym = make_char(ch);
1329 enqueue_Xt_dispatch_event(emacs_event);
1331 Lstream_close(istr);
1333 Lstream_delete(istr);
1334 Lstream_delete(XLSTREAM(fb_instream));
1339 case XBufferOverflow:
1340 bufptr = (char *)alloca(len + 1);
1346 return Qnil; /* not reached */
1347 #endif /* HAVE_XIM */
1351 set_last_server_timestamp(struct device *d, XEvent * x_event)
1354 switch (x_event->type) {
1357 t = x_event->xkey.time;
1361 t = x_event->xbutton.time;
1365 t = x_event->xcrossing.time;
1368 t = x_event->xmotion.time;
1370 case PropertyNotify:
1371 t = x_event->xproperty.time;
1373 case SelectionClear:
1374 t = x_event->xselectionclear.time;
1376 case SelectionRequest:
1377 t = x_event->xselectionrequest.time;
1379 case SelectionNotify:
1380 t = x_event->xselection.time;
1385 DEVICE_X_LAST_SERVER_TIMESTAMP(d) = t;
1389 x_event_to_emacs_event(XEvent * x_event, Lisp_Event * emacs_event)
1391 Display *display = x_event->xany.display;
1392 struct device *d = get_device_from_display(display);
1393 struct x_device *xd = DEVICE_X_DATA(d);
1395 if (DEVICE_X_BEING_DELETED(d)) {
1396 /* #### Uh, is this 0 correct? */
1400 set_last_server_timestamp(d, x_event);
1402 switch (x_event->type) {
1404 x_handle_sticky_modifiers(x_event, d);
1409 case ButtonRelease: {
1411 int shift_p, lock_p;
1412 Bool key_event_p = (x_event->type == KeyPress);
1413 unsigned int *state = key_event_p
1414 ? &x_event->xkey.state
1415 : &x_event->xbutton.state;
1417 /* If this is a synthetic KeyPress or Button event, and the user
1418 has expressed a disinterest in this security hole, then drop
1421 ? x_event->xkey.send_event
1422 : x_event->xbutton.send_event)
1423 #ifdef EXTERNAL_WIDGET
1424 /* ben: events get sent to an ExternalShell using
1426 This is not a perfect solution. */
1427 && !FRAME_X_EXTERNAL_WINDOW_P
1428 (x_any_window_to_frame(d, x_event->xany.window))
1430 && !x_allow_sendevents) {
1434 DEVICE_X_MOUSE_TIMESTAMP(d) =
1435 DEVICE_X_GLOBAL_MOUSE_TIMESTAMP(d) =
1437 ? x_event->xkey.time
1438 : x_event->xbutton.time;
1440 x_handle_sticky_modifiers(x_event, d);
1442 if (*state & ControlMask) {
1443 modifiers |= XEMACS_MOD_CONTROL;
1445 if (*state & xd->MetaMask) {
1446 modifiers |= XEMACS_MOD_META;
1448 if (*state & xd->SuperMask) {
1449 modifiers |= XEMACS_MOD_SUPER;
1451 if (*state & xd->HyperMask) {
1452 modifiers |= XEMACS_MOD_HYPER;
1454 if (*state & xd->AltMask) {
1455 modifiers |= XEMACS_MOD_ALT;
1458 int numero_de_botao = -1;
1461 numero_de_botao = x_event->xbutton.button;
1463 /* the button gets noted either in the button or the
1464 modifiers field, but not both. */
1465 if (numero_de_botao != 1 && (*state & Button1Mask)) {
1466 modifiers |= XEMACS_MOD_BUTTON1;
1468 if (numero_de_botao != 2 && (*state & Button2Mask)) {
1469 modifiers |= XEMACS_MOD_BUTTON2;
1471 if (numero_de_botao != 3 && (*state & Button3Mask)) {
1472 modifiers |= XEMACS_MOD_BUTTON3;
1474 if (numero_de_botao != 4 && (*state & Button4Mask)) {
1475 modifiers |= XEMACS_MOD_BUTTON4;
1477 if (numero_de_botao != 5 && (*state & Button5Mask)) {
1478 modifiers |= XEMACS_MOD_BUTTON5;
1482 /* Ignore the Caps_Lock key if:
1483 - any other modifiers are down, so that Caps_Lock doesn't
1484 turn C-x into C-X, which would suck.
1485 - the event was a mouse event. */
1486 if (modifiers || !key_event_p) {
1487 *state &= (~LockMask);
1490 shift_p = *state & ShiftMask;
1491 lock_p = *state & LockMask;
1493 if (shift_p || lock_p) {
1494 modifiers |= XEMACS_MOD_SHIFT;
1498 XKeyEvent *ev = &x_event->xkey;
1499 /* This used to compute the frame from the given X
1500 window and store it here, but we really don't care
1502 emacs_event->channel = DEVICE_CONSOLE(d);
1503 keysym = x_to_emacs_keysym(&x_event->xkey, 0);
1505 /* If the emacs keysym is nil, then that means that the
1506 X keysym was either a Modifier or NoSymbol, which
1507 probably means that we're in the midst of reading a
1508 Multi_key sequence, or a "dead" key prefix, or XIM
1509 input. Ignore it. */
1514 /* More Caps_Lock garbage: Caps_Lock should *only* add
1515 the shift modifier to two-case keys (that is, A-Z and
1516 related characters). So at this point (after looking
1517 up the keysym) if the keysym isn't a dual-case
1518 alphabetic, and if the caps lock key was down but the
1519 shift key wasn't, then turn off the shift modifier.
1521 /* #### type lossage: assuming equivalence of emacs and
1523 /* !!#### maybe fix for Mule */
1524 if (lock_p && !shift_p &&
1525 !(CHAR_OR_CHAR_INTP(keysym)
1526 && keysym_obeys_caps_lock_p(
1527 (KeySym) XCHAR_OR_CHAR_INT(keysym), d))) {
1528 modifiers &= (~XEMACS_MOD_SHIFT);
1531 /* If this key contains two distinct keysyms, that is,
1532 "shift" generates a different keysym than the
1533 non-shifted key, then don't apply the shift modifier
1534 bit: it's implicit. Otherwise, if there would be no
1535 other way to tell the difference between the shifted
1536 and unshifted version of this key, apply the shift
1537 bit. Non-graphics, like Backspace and F1 get the
1538 shift bit in the modifiers slot. Neither the
1539 characters "a", "A", "2", nor "@" normally have the
1540 shift bit set. However, "F1" normally does. */
1541 if (modifiers & XEMACS_MOD_SHIFT) {
1542 int Mode_switch_p = *state & xd->ModeMask;
1543 KeySym bot = XLookupKeysym(ev,
1546 KeySym top = XLookupKeysym(ev,
1549 if (top && bot && top != bot) {
1565 modifiers &= ~XEMACS_MOD_SHIFT;
1570 emacs_event->event_type = key_press_event;
1571 emacs_event->timestamp = ev->time;
1572 emacs_event->event.key.modifiers = modifiers;
1573 emacs_event->event.key.keysym = keysym;
1575 /* Mouse press/release event */
1576 XButtonEvent *ev = &x_event->xbutton;
1577 struct frame *frame = x_window_to_frame(d, ev->window);
1583 XSETFRAME(emacs_event->channel, frame);
1585 emacs_event->event_type = (x_event->type == ButtonPress)
1586 ? button_press_event
1587 : button_release_event;
1589 emacs_event->event.button.modifiers = modifiers;
1590 emacs_event->timestamp = ev->time;
1591 emacs_event->event.button.button = ev->button;
1592 emacs_event->event.button.x = ev->x;
1593 emacs_event->event.button.y = ev->y;
1594 /* because we don't seem to get a FocusIn event for
1595 button clicks when a widget-glyph is selected we will
1596 assume that we want the focus if a button gets
1598 if (x_event->type == ButtonPress) {
1599 handle_focus_event_1(frame, 1);
1605 case MotionNotify: {
1606 XMotionEvent *ev = &x_event->xmotion;
1607 struct frame *frame = x_window_to_frame(d, ev->window);
1609 XMotionEvent event2;
1616 /* We use MotionHintMask, so we will get only one motion event
1617 until the next time we call XQueryPointer or the user clicks
1618 the mouse. So call XQueryPointer now (meaning that the event
1619 will be in sync with the server just before Fnext_event()
1620 returns). If the mouse is still in motion, then the server
1621 will immediately generate exactly one more motion event,
1622 which will be on the queue waiting for us next time
1625 if (XQueryPointer(event2.display, event2.window,
1626 &event2.root, &event2.subwindow,
1627 &event2.x_root, &event2.y_root,
1628 &event2.x, &event2.y, &event2.state)) {
1629 /* only one structure copy */
1632 DEVICE_X_MOUSE_TIMESTAMP(d) = ev->time;
1634 XSETFRAME(emacs_event->channel, frame);
1635 emacs_event->event_type = pointer_motion_event;
1636 emacs_event->timestamp = ev->time;
1637 emacs_event->event.motion.x = ev->x;
1638 emacs_event->event.motion.y = ev->y;
1639 if (ev->state & ShiftMask) {
1640 modifiers |= XEMACS_MOD_SHIFT;
1642 if (ev->state & ControlMask) {
1643 modifiers |= XEMACS_MOD_CONTROL;
1645 if (ev->state & xd->MetaMask) {
1646 modifiers |= XEMACS_MOD_META;
1648 if (ev->state & xd->SuperMask) {
1649 modifiers |= XEMACS_MOD_SUPER;
1651 if (ev->state & xd->HyperMask) {
1652 modifiers |= XEMACS_MOD_HYPER;
1654 if (ev->state & xd->AltMask) {
1655 modifiers |= XEMACS_MOD_ALT;
1657 if (ev->state & Button1Mask) {
1658 modifiers |= XEMACS_MOD_BUTTON1;
1660 if (ev->state & Button2Mask) {
1661 modifiers |= XEMACS_MOD_BUTTON2;
1663 if (ev->state & Button3Mask) {
1664 modifiers |= XEMACS_MOD_BUTTON3;
1666 if (ev->state & Button4Mask) {
1667 modifiers |= XEMACS_MOD_BUTTON4;
1669 if (ev->state & Button5Mask) {
1670 modifiers |= XEMACS_MOD_BUTTON5;
1672 /* Currently ignores Shift_Lock but probably shouldn't
1673 (but it definitely should ignore Caps_Lock). */
1674 emacs_event->event.motion.modifiers = modifiers;
1678 case ClientMessage: {
1679 /* Patch bogus TAKE_FOCUS messages from MWM; CurrentTime is
1680 passed as the timestamp of the TAKE_FOCUS, which the ICCCM
1681 explicitly prohibits. */
1682 XClientMessageEvent *ev = &x_event->xclient;
1684 if (ev->message_type == DEVICE_XATOM_WM_PROTOCOLS(d)
1685 && (Atom) (ev->data.l[0]) ==
1686 DEVICE_XATOM_WM_TAKE_FOCUS(d)
1687 && (Atom) (ev->data.l[1]) == 0) {
1689 DEVICE_X_LAST_SERVER_TIMESTAMP(d);
1695 /* it's a magic event */
1696 struct frame *frame;
1698 XEvent *x_event_copy = &emacs_event->event.magic.
1701 #define FROB(event_member, window_member) \
1702 x_event_copy->event_member = x_event->event_member; \
1703 w = x_event->event_member.window_member
1705 switch (x_event->type) {
1706 case SelectionRequest:
1707 FROB(xselectionrequest, owner);
1709 case SelectionClear:
1710 FROB(xselectionclear, window);
1712 case SelectionNotify:
1713 FROB(xselection, requestor);
1715 case PropertyNotify:
1716 FROB(xproperty, window);
1719 FROB(xclient, window);
1721 case ConfigureNotify:
1722 FROB(xconfigure, window);
1725 case GraphicsExpose:
1726 FROB(xexpose, window);
1734 FROB(xcrossing, window);
1738 FROB(xfocus, window);
1740 case VisibilityNotify:
1741 FROB(xvisibility, window);
1744 FROB(xcreatewindow, window);
1747 w = x_event->xany.window;
1748 *x_event_copy = *x_event;
1752 frame = x_any_window_to_frame(d, w);
1757 emacs_event->event_type = magic_event;
1758 XSETFRAME(emacs_event->channel, frame);
1766 /************************************************************************/
1767 /* magic-event handling */
1768 /************************************************************************/
1770 static void handle_focus_event_1(struct frame *f, int in_p)
1772 handle_focus_event_2(XtWindow(FRAME_X_TEXT_WIDGET(f)), f, in_p);
1775 static void handle_focus_event_2(Window win, struct frame *f, int in_p)
1777 /* Although this treats focus differently for all widgets (including
1778 the frame) it seems to work ok. */
1779 Widget needs_it = XtWindowToWidget(FRAME_X_DISPLAY(f), win);
1781 #if XtSpecificationRelease > 5
1782 widget_with_focus = XtGetKeyboardFocusWidget(FRAME_X_TEXT_WIDGET(f));
1785 XIM_focus_event(f, in_p);
1786 #endif /* HAVE_XIM */
1788 /* On focus change, clear all memory of sticky modifiers
1789 to avoid non-intuitive behavior. */
1790 clear_sticky_modifiers(XDEVICE(FRAME_DEVICE(f)));
1792 /* We don't want to handle the focus change now, because we might
1793 be in an accept-process-output, sleep-for, or sit-for. So
1796 Actually, we half handle it: we handle it as far as changing the
1797 box cursor for redisplay, but we don't call any hooks or do any
1798 select-frame stuff until after the sit-for.
1800 Unfortunately native widgets break the model because they grab
1801 the keyboard focus and nothing sets it back again. I cannot find
1802 any reasonable way to do this elsewhere so we assert here that
1803 the keyboard focus is on the emacs text widget. Menus and dialogs
1804 do this in their selection callback, but we don't want that since
1805 a button having focus is legitimate. An edit field having focus
1806 is mandatory. Weirdly you get a FocusOut event when you click in
1807 a widget-glyph but you don't get a corresponding FocusIn when you
1808 click in the frame. Why is this? */
1810 #if XtSpecificationRelease > 5
1811 && needs_it != widget_with_focus
1814 lw_set_keyboard_focus(FRAME_X_SHELL_WIDGET(f), needs_it);
1817 /* If we are focusing on a native widget then record and exit. */
1818 if (needs_it != FRAME_X_TEXT_WIDGET(f)) {
1819 widget_with_focus = needs_it;
1823 /* We have the focus now. See comment in
1824 emacs_Xt_handle_widget_losing_focus (). */
1826 widget_with_focus = NULL;
1828 /* do the generic event-stream stuff. */
1832 struct gcpro gcpro1;
1835 conser = Fcons(frm, Fcons(FRAME_DEVICE(f), in_p ? Qt : Qnil));
1837 emacs_handle_focus_change_preliminary(conser);
1838 enqueue_magic_eval_event(
1839 emacs_handle_focus_change_final, conser);
1844 /* Create a synthetic X focus event. */
1846 enqueue_focus_event(Widget wants_it, Lisp_Object frame, int in_p)
1848 Lisp_Object emacs_event = Fmake_event(Qnil, Qnil);
1849 Lisp_Event *ev = XEVENT(emacs_event);
1850 XEvent *x_event = &ev->event.magic.underlying_x_event;
1852 x_event->type = in_p ? FocusIn : FocusOut;
1853 x_event->xfocus.window = XtWindow(wants_it);
1855 ev->channel = frame;
1856 ev->event_type = magic_event;
1858 enqueue_Xt_dispatch_event(emacs_event);
1861 /* The idea here is that when a widget glyph gets unmapped we don't
1862 want the focus to stay with it if it has focus - because it may
1863 well just get deleted next and then we have lost the focus until the
1864 user does something. So handle_focus_event_1 records the widget
1865 with keyboard focus when FocusOut is processed, and then, when a
1866 widget gets unmapped, it calls this function to restore focus if
1868 void emacs_Xt_handle_widget_losing_focus(struct frame *f, Widget losing_widget);
1869 void emacs_Xt_handle_widget_losing_focus(struct frame *f, Widget losing_widget)
1871 if (losing_widget == widget_with_focus) {
1872 handle_focus_event_1(f, 1);
1876 /* This is called from the external-widget code */
1878 void emacs_Xt_handle_focus_event(XEvent * event);
1879 void emacs_Xt_handle_focus_event(XEvent * event)
1881 struct device *d = get_device_from_display(event->xany.display);
1884 if (DEVICE_X_BEING_DELETED(d))
1888 * It's curious that we're using x_any_window_to_frame() instead
1889 * of x_window_to_frame(). I don't know what the impact of this is.
1891 f = x_any_window_to_frame(d, event->xfocus.window);
1893 /* focus events are sometimes generated just before
1894 a frame is destroyed. */
1896 handle_focus_event_1(f, event->type == FocusIn);
1899 /* both MapNotify and VisibilityNotify can cause this
1900 JV is_visible has the same semantics as f->visible*/
1901 static void change_frame_visibility(struct frame *f, int is_visible)
1905 XSETFRAME(frame, f);
1907 if (!FRAME_VISIBLE_P(f) && is_visible) {
1908 FRAME_VISIBLE_P(f) = is_visible;
1909 /* This improves the double flicker when uniconifying a frame
1910 some. A lot of it is not showing a buffer which has changed
1911 while the frame was iconified. To fix it further requires
1912 the good 'ol double redisplay structure. */
1913 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
1914 va_run_hook_with_args(Qmap_frame_hook, 1, frame);
1915 } else if (FRAME_VISIBLE_P(f) && !is_visible) {
1916 FRAME_VISIBLE_P(f) = 0;
1917 va_run_hook_with_args(Qunmap_frame_hook, 1, frame);
1918 } else if (FRAME_VISIBLE_P(f) * is_visible < 0) {
1919 FRAME_VISIBLE_P(f) = -FRAME_VISIBLE_P(f);
1920 if (FRAME_REPAINT_P(f))
1921 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
1922 va_run_hook_with_args(Qmap_frame_hook, 1, frame);
1926 static void handle_map_event(struct frame *f, XEvent * event)
1930 XSETFRAME(frame, f);
1931 if (event->type == MapNotify) {
1932 XWindowAttributes xwa;
1934 /* Bleagh!!!!!! Apparently some window managers (e.g. MWM)
1935 send synthetic MapNotify events when a window is first
1936 created, EVEN IF IT'S CREATED ICONIFIED OR INVISIBLE.
1937 Or something like that. We initially tried a different
1938 solution below, but that ran into a different window-
1941 It seems that the only reliable way is to treat a
1942 MapNotify event as a "hint" that the window might or
1943 might not be visible, and check explicitly. */
1945 XGetWindowAttributes(event->xany.display, event->xmap.window,
1947 if (xwa.map_state != IsViewable) {
1948 /* Calling Fframe_iconified_p is the only way we have to
1949 correctly update FRAME_ICONIFIED_P */
1950 Fframe_iconified_p(frame);
1954 FRAME_X_TOTALLY_VISIBLE_P(f) = 1;
1956 /* Bleagh again!!!! We initially tried the following hack
1957 around the MWM problem, but it turns out that TWM
1958 has a race condition when you un-iconify, where it maps
1959 the window and then tells the server that the window
1960 is un-iconified. Usually, SXEmacs wakes up between
1961 those two occurrences, and thus thinks that un-iconified
1962 windows are still iconified.
1964 Ah, the joys of X. */
1966 /* By Emacs definition, a frame that is iconified is not
1967 visible. Marking a frame as visible will automatically cause
1968 frame-iconified-p to return nil, regardless of whether the
1969 frame is actually iconified. Therefore, we have to ignore
1970 MapNotify events on iconified frames. (It's not obvious
1971 to me why these are being sent, but it happens at startup
1972 with frames that are initially iconified; perhaps they are
1973 synthetic MapNotify events coming from the window manager.)
1974 Note that `frame-iconified-p' queries the server
1975 to determine whether the frame is currently iconified,
1976 rather than consulting some internal (and likely
1977 inaccurate) state flag. Therefore, ignoring the MapNotify
1979 if (!FRAME_VISIBLE_P(f) && NILP(Fframe_iconified_p(frame)))
1981 change_frame_visibility(f, 1);
1983 FRAME_X_TOTALLY_VISIBLE_P(f) = 0;
1984 change_frame_visibility(f, 0);
1985 /* Calling Fframe_iconified_p is the only way we have to
1986 correctly update FRAME_ICONIFIED_P */
1987 Fframe_iconified_p(frame);
1991 static void handle_client_message(struct frame *f, XEvent * event)
1993 struct device *d = XDEVICE(FRAME_DEVICE(f));
1996 XSETFRAME(frame, f);
1998 if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS(d) &&
1999 (Atom) (event->xclient.data.l[0]) ==
2000 DEVICE_XATOM_WM_DELETE_WINDOW(d)) {
2001 /* WM_DELETE_WINDOW is a misc-user event, but other
2002 ClientMessages, such as WM_TAKE_FOCUS, are eval events.
2003 That's because delete-window was probably executed with a
2004 mouse click, while the others could have been sent as a
2005 result of mouse motion or some other implicit action. (Call
2006 this a "heuristic"...) The reason for caring about this is
2007 so that clicking on the close-box will make emacs prompt
2008 using a dialog box instead of the minibuffer if there are
2011 enqueue_misc_user_event(frame, Qeval,
2012 list3(Qdelete_frame, frame, Qt));
2013 } else if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS(d)
2014 && (Atom) event->xclient.data.l[0] ==
2015 DEVICE_XATOM_WM_TAKE_FOCUS(d)) {
2016 handle_focus_event_1(f, 1);
2018 /* If there is a dialog box up, focus on it.
2020 #### Actually, we're raising it too, which is wrong. We should
2021 #### just focus on it, but lwlib doesn't currently give us an
2022 #### easy way to do that. This should be fixed.
2024 unsigned long take_focus_timestamp = event->xclient.data.l[1];
2025 Widget widget = lw_raise_all_pop_up_widgets();
2027 /* kludge: raise_all returns bottommost widget, but we really
2028 want the topmost. So just raise it for now. */
2029 XMapRaised(XtDisplay(widget), XtWindow(widget));
2030 /* Grab the focus with the timestamp of the TAKE_FOCUS. */
2031 XSetInputFocus(XtDisplay(widget), XtWindow(widget),
2032 RevertToParent, take_focus_timestamp);
2038 /* #### I'm struggling to understand how the X event loop really works.
2039 Here is the problem:
2041 When widgets get mapped / changed etc the actual display updates
2042 are done asynchronously via X events being processed - this
2043 normally happens when XtAppProcessEvent() gets called. However, if
2044 we are executing lisp code or even doing redisplay we won't
2045 necessarily process X events for a very long time. This has the
2046 effect of widgets only getting updated when SXEmacs only goes into
2047 idle, or some other event causes processing of the X event queue.
2049 XtAppProcessEvent can get called from the following places:
2051 emacs_Xt_next_event () - this is normal event processing, almost
2052 any non-X event will take precedence and this means that we
2053 cannot rely on it to do the right thing at the right time for
2056 drain_X_queue () - this happens when SIGIO gets tripped,
2057 processing the event queue allows C-g to be checked for. It gets
2058 called from emacs_Xt_event_pending_p ().
2060 In order to solve this I have tried introducing a list primitive -
2061 dispatch-non-command-events - which forces processing of X events
2062 related to display. Unfortunately this has a number of problems,
2063 one is that it is possible for event_stream_event_pending_p to
2064 block for ever if there isn't actually an event. I guess this can
2065 happen if we drop the synthetic event for reason. It also relies on
2066 SIGIO processing which makes things rather fragile.
2068 People have seen behaviour whereby SXEmacs blocks until you move the
2069 mouse. This seems to indicate that dispatch-non-command-events is
2070 blocking. It may be that in a SIGIO world forcing SIGIO processing
2071 does the wrong thing.
2073 static void emacs_Xt_force_event_pending(struct frame *f)
2077 Display *dpy = DEVICE_X_DISPLAY(XDEVICE(FRAME_DEVICE(f)));
2078 event.xclient.type = ClientMessage;
2079 event.xclient.display = dpy;
2080 event.xclient.message_type = XInternAtom(dpy, "BumpQueue", False);
2081 event.xclient.format = 32;
2082 event.xclient.window = 0;
2084 /* Send the drop message */
2085 XSendEvent(dpy, XtWindow(FRAME_X_SHELL_WIDGET(f)),
2086 True, NoEventMask, &event);
2087 /* We rely on SIGIO and friends to realise we have generated an
2091 static void emacs_Xt_handle_magic_event(Lisp_Event * emacs_event)
2093 /* This function can GC */
2094 XEvent *event = &emacs_event->event.magic.underlying_x_event;
2095 struct frame *f = XFRAME(EVENT_CHANNEL(emacs_event));
2097 if (!FRAME_LIVE_P(f)
2098 || DEVICE_X_BEING_DELETED(XDEVICE(FRAME_DEVICE(f))))
2101 switch (event->type) {
2102 case SelectionRequest:
2103 x_handle_selection_request(&event->xselectionrequest);
2106 case SelectionClear:
2107 x_handle_selection_clear(&event->xselectionclear);
2110 case SelectionNotify:
2111 x_handle_selection_notify(&event->xselection);
2114 case PropertyNotify:
2115 x_handle_property_notify(&event->xproperty);
2119 if (!check_for_ignored_expose
2120 (f, event->xexpose.x, event->xexpose.y,
2121 event->xexpose.width, event->xexpose.height)
2122 && !find_matching_subwindow(f, event->xexpose.x,
2124 event->xexpose.width,
2125 event->xexpose.height))
2126 x_redraw_exposed_area(f, event->xexpose.x,
2128 event->xexpose.width,
2129 event->xexpose.height);
2132 case GraphicsExpose:
2133 /* This occurs when an XCopyArea's source area was
2134 * obscured or not available. */
2135 x_redraw_exposed_area(f, event->xexpose.x, event->xexpose.y,
2136 event->xexpose.width,
2137 event->xexpose.height);
2142 handle_map_event(f, event);
2146 if (event->xcrossing.detail != NotifyInferior) {
2149 XSETFRAME(frame, f);
2150 /* FRAME_X_MOUSE_P (f) = 1; */
2151 va_run_hook_with_args(Qmouse_enter_frame_hook, 1,
2157 if (event->xcrossing.detail != NotifyInferior) {
2160 XSETFRAME(frame, f);
2161 /* FRAME_X_MOUSE_P (f) = 0; */
2162 va_run_hook_with_args(Qmouse_leave_frame_hook, 1,
2170 #ifdef EXTERNAL_WIDGET
2171 /* External widget lossage:
2172 Ben said: YUCK. The only way to make focus changes work
2173 properly is to completely ignore all FocusIn/FocusOut events
2174 and depend only on notifications from the ExternalClient
2176 if (FRAME_X_EXTERNAL_WINDOW_P(f)) {
2180 handle_focus_event_2(event->xfocus.window, f,
2181 event->type == FocusIn);
2185 handle_client_message(f, event);
2188 case VisibilityNotify:
2189 /* window visibility has changed */
2190 if (event->xvisibility.window ==
2191 XtWindow(FRAME_X_SHELL_WIDGET(f))) {
2192 FRAME_X_TOTALLY_VISIBLE_P(f) =
2193 (event->xvisibility.state == VisibilityUnobscured);
2194 /* Note that the fvwm pager only sends VisibilityNotify
2195 when changing pages. Is this all we need to do ?
2197 /* Nope. We must at least trigger a redisplay here.
2198 Since this case seems similar to MapNotify, I've
2199 factored out some code to change_frame_visibility().
2200 This triggers the necessary redisplay and runs
2201 (un)map-frame-hook. - dkindred@cs.cmu.edu */
2202 /* Changed it again to support the tristate visibility
2204 change_frame_visibility(f, (event->xvisibility.state
2206 VisibilityFullyObscured) ? 1
2211 case ConfigureNotify:
2225 /************************************************************************/
2226 /* timeout events */
2227 /************************************************************************/
2229 static int timeout_id_tick;
2231 /* Xt interval id's might not fit into an int (they're pointers, as it
2232 happens), so we need to provide a conversion list. */
2234 /* pending_timeouts is a set (unordered), implemented as a stack.
2235 completed_timeouts* is a queue. */
2236 static struct Xt_timeout {
2238 XtIntervalId interval_id;
2239 struct Xt_timeout *next;
2240 } *pending_timeouts, *completed_timeouts_head, *completed_timeouts_tail;
2242 static struct Xt_timeout_blocktype {
2243 Blocktype_declare(struct Xt_timeout);
2244 } *the_Xt_timeout_blocktype;
2246 /* called by XtAppNextEvent() */
2247 static void Xt_timeout_callback(XtPointer closure, XtIntervalId * id)
2249 struct Xt_timeout *timeout = (struct Xt_timeout *)closure;
2250 struct Xt_timeout *t2 = pending_timeouts;
2252 /* Remove this one from the set of pending timeouts */
2253 if(timeout == NULL) {
2257 if (t2 == timeout) {
2258 pending_timeouts = pending_timeouts->next;
2260 while (t2->next && t2->next != timeout) {
2265 t2->next = t2->next->next;
2267 /* Add this one to the queue of completed timeouts */
2268 timeout->next = NULL;
2269 if (completed_timeouts_head) {
2270 completed_timeouts_tail->next = timeout;
2272 completed_timeouts_head = timeout;
2274 completed_timeouts_tail = timeout;
2277 static int emacs_Xt_add_timeout(EMACS_TIME thyme)
2279 struct Xt_timeout *timeout = Blocktype_alloc(the_Xt_timeout_blocktype);
2280 EMACS_TIME current_time;
2283 timeout->id = timeout_id_tick++;
2284 timeout->next = pending_timeouts;
2285 pending_timeouts = timeout;
2286 EMACS_GET_TIME(current_time);
2287 EMACS_SUB_TIME(thyme, thyme, current_time);
2288 milliseconds = EMACS_SECS(thyme) * 1000 + EMACS_USECS(thyme) / 1000;
2290 if (milliseconds < 1) {
2293 timeout->interval_id = XtAppAddTimeOut(Xt_app_con, milliseconds,
2294 Xt_timeout_callback,
2295 (XtPointer) timeout);
2299 #ifdef EF_USE_ASYNEQ
2300 #if 1 /* timeout based */
2301 static void Xt_watch_eq_cb(XtPointer closure, XtIntervalId *id);
2302 static int emacs_Xt_watch_event_queue(event_queue_t eq);
2303 extern void asyneq_handle_event(event_queue_t eq);
2304 extern void asyneq_handle_non_command_event(event_queue_t eq);
2307 Xt_watch_eq_cb(XtPointer closure, XtIntervalId *id)
2309 event_queue_t eq = (event_queue_t)closure;
2310 /* reestablish timeout, in case asyneq_handle_event gets to exit
2312 emacs_Xt_watch_event_queue(eq);
2313 asyneq_handle_non_command_event(eq);
2317 emacs_Xt_watch_event_queue(event_queue_t eq)
2319 int milliseconds = 10;
2320 size_t eqsz = eq_queue_size(eq)+1; /* never be 0 */
2323 while ((milliseconds*eqsz) > 100)
2329 return XtAppAddTimeOut(
2330 Xt_app_con, milliseconds, Xt_watch_eq_cb, (XtPointer)eq);
2332 #else /* work-procedure based (sets cpu on fire) */
2334 Xt_watch_eq_cb(XtPointer closure)
2336 event_queue_t eq = (event_queue_t)closure;
2337 asyneq_handle_event(eq);
2338 return FALSE; /* we never finish with this job */
2342 emacs_Xt_watch_event_queue(event_queue_t eq)
2344 return XtAppAddWorkProc(Xt_app_con, Xt_watch_eq_cb, (XtPointer)eq);
2347 #endif /* EF_USE_ASYNEQ */
2349 static void emacs_Xt_remove_timeout(int id)
2351 struct Xt_timeout *timeout, *t2;
2355 /* Find the timeout on the list of pending ones, if it's still there. */
2356 if (pending_timeouts) {
2357 if (id == pending_timeouts->id) {
2358 timeout = pending_timeouts;
2359 pending_timeouts = pending_timeouts->next;
2361 t2 = pending_timeouts;
2362 while (t2->next && t2->next->id != id)
2364 if (t2->next) { /*found it */
2366 t2->next = t2->next->next;
2369 /* if it was pending, we have removed it from the list */
2371 XtRemoveTimeOut(timeout->interval_id);
2374 /* It could be that Xt_timeout_callback was already called but we didn't
2375 convert into an Emacs event yet */
2376 if (!timeout && completed_timeouts_head) {
2377 /* Thank God for code duplication! */
2378 if (id == completed_timeouts_head->id) {
2379 timeout = completed_timeouts_head;
2380 completed_timeouts_head = completed_timeouts_head->next;
2381 /* this may not be necessary? */
2382 if (!completed_timeouts_head)
2383 completed_timeouts_tail = NULL;
2385 t2 = completed_timeouts_head;
2386 while (t2->next && t2->next->id != id)
2388 if (t2->next) { /* found it */
2390 t2->next = t2->next->next;
2392 completed_timeouts_tail = t2;
2397 /* If we found the thing on the lists of timeouts,
2398 and removed it, deallocate
2401 Blocktype_free(the_Xt_timeout_blocktype, timeout);
2406 Xt_timeout_to_emacs_event(Lisp_Event * emacs_event)
2408 struct Xt_timeout *timeout = completed_timeouts_head;
2410 completed_timeouts_head = completed_timeouts_head->next;
2411 /* probably unnecessary */
2412 if (!completed_timeouts_head) {
2413 completed_timeouts_tail = NULL;
2415 emacs_event->event_type = timeout_event;
2416 /* timeout events have nil as channel */
2417 emacs_event->timestamp = 0; /* #### wrong!! */
2418 emacs_event->event.timeout.interval_id = timeout->id;
2419 emacs_event->event.timeout.function = Qnil;
2420 emacs_event->event.timeout.object = Qnil;
2421 Blocktype_free(the_Xt_timeout_blocktype, timeout);
2424 /************************************************************************/
2425 /* process and tty events */
2426 /************************************************************************/
2428 struct what_is_ready_closure {
2434 static Lisp_Object filedesc_with_input[MAXDESC];
2435 static struct what_is_ready_closure *filedesc_to_what_closure[MAXDESC];
2437 static void init_what_input_once(void)
2442 filedesc_with_input = xnew_array(Lisp_Object, MAXDESC);
2443 filedesc_to_what_closure =
2444 xnew_array(struct what_is_ready_closure *, MAXDESC);
2447 for (i = 0; i < MAXDESC; i++) {
2448 filedesc_to_what_closure[i] = NULL;
2449 filedesc_with_input[i] = Qnil;
2452 process_events_occurred = 0;
2453 tty_events_occurred = 0;
2458 mark_what_as_being_ready(struct what_is_ready_closure *closure)
2460 if (NILP(filedesc_with_input[closure->fd])) {
2461 SELECT_TYPE temp_mask;
2462 FD_ZERO(&temp_mask);
2463 FD_SET(closure->fd, &temp_mask);
2464 /* Check to make sure there's *really* input available.
2465 Sometimes things seem to get confused and this gets called
2466 for the tty fd when there's really only input available
2467 on some process's fd. (It will subsequently get called
2468 for that process's fd, so returning without setting any
2469 flags will take care of it.) To see the problem, uncomment
2470 the stderr_out below, turn NORMAL_QUIT_CHECK_TIMEOUT_MSECS
2471 down to 25, do sh -c 'sxemacs -nw -q -f shell 2>/tmp/log'
2472 and press return repeatedly. (Seen under AIX & Linux.)
2473 -dkindred@cs.cmu.edu */
2474 if (!poll_fds_for_input(temp_mask)) {
2477 "mark_what_as_being_ready: "
2478 "no input available (fd=%d)\n",
2483 filedesc_with_input[closure->fd] = closure->what;
2484 if (PROCESSP(closure->what)) {
2485 /* Don't increment this if the current process is
2486 already marked as having input. */
2487 process_events_occurred++;
2489 tty_events_occurred++;
2496 Xt_what_callback(void *closure, int *source, XtInputId *id)
2498 /* If closure is 0, then we got a fake event from a signal handler.
2499 The only purpose of this is to make XtAppProcessEvent() stop
2502 mark_what_as_being_ready(closure);
2504 fake_event_occurred++;
2505 drain_signal_event_pipe();
2511 select_filedesc(int fd, Lisp_Object what)
2513 struct what_is_ready_closure *closure;
2515 /* If somebody is trying to select something that's already selected
2516 for, then something went wrong. The generic routines ought to
2517 detect this and error before here. */
2518 assert(!filedesc_to_what_closure[fd]);
2520 closure = xnew(struct what_is_ready_closure);
2522 closure->what = what;
2523 closure->id = XtAppAddInput(
2525 (XtPointer)(XtInputReadMask /* | XtInputExceptMask */),
2526 Xt_what_callback, closure);
2527 filedesc_to_what_closure[fd] = closure;
2532 unselect_filedesc(int fd)
2534 struct what_is_ready_closure *closure = filedesc_to_what_closure[fd];
2537 if (!NILP(filedesc_with_input[fd])) {
2538 /* We are unselecting this process before we have drained the
2539 rest of the input from it, probably from status_notify() in
2540 the command loop. This can happen like so:
2542 - We are waiting in XtAppNextEvent()
2543 - Process generates output
2544 - Process is marked as being ready
2545 - Process dies, SIGCHLD gets generated before we return (!?)
2546 It could happen I guess.
2547 - sigchld_handler() marks process as dead
2548 - Somehow we end up getting a new KeyPress event on the queue
2549 at the same time (I'm really so sure how that happens but I'm
2550 not sure it can't either so let's assume it can...).
2551 - Key events have priority so we return that
2552 instead of the proc.
2553 - Before dispatching the lisp key event we call
2555 - which deselects the process that SIGCHLD marked as dead.
2557 Thus we never remove it from _with_input and turn it into a
2558 lisp event, so we need to do it here. But this does not mean
2559 that we're throwing away the last block of output -
2560 status_notify() has already taken care of running the proc
2563 filedesc_with_input[fd] = Qnil;
2564 if (PROCESSP(closure->what)) {
2565 assert(process_events_occurred > 0);
2566 process_events_occurred--;
2568 assert(tty_events_occurred > 0);
2569 tty_events_occurred--;
2572 XtRemoveInput(closure->id);
2574 filedesc_to_what_closure[fd] = 0;
2579 emacs_Xt_select_process(Lisp_Process * p)
2581 Lisp_Object process;
2582 int infd = event_stream_unixoid_select_process(p);
2584 XSETPROCESS(process, p);
2586 select_filedesc(infd, process);
2591 emacs_Xt_unselect_process(Lisp_Process * p)
2593 int infd = event_stream_unixoid_unselect_process(p);
2596 unselect_filedesc(infd);
2601 emacs_Xt_create_stream_pair(void *inhandle, void *outhandle,
2602 Lisp_Object *instream, Lisp_Object *outstream,
2605 USID u = event_stream_unixoid_create_stream_pair(
2606 inhandle, outhandle, instream, outstream, flags);
2607 if (u != USID_ERROR) {
2614 emacs_Xt_delete_stream_pair(Lisp_Object instream, Lisp_Object outstream)
2616 event_stream_unixoid_delete_stream_pair(instream, outstream);
2617 return USID_DONTHASH;
2620 /* This is called from GC when a process object is about to be freed.
2621 If we've still got pointers to it in this file, we're gonna lose hard.
2623 void debug_process_finalization(Lisp_Process * p)
2627 Lisp_Object instr, outstr;
2629 get_process_streams(p, &instr, &outstr);
2630 /* if it still has fds, then it hasn't been killed yet. */
2631 assert(NILP(instr));
2632 assert(NILP(outstr));
2633 /* Better not still be in the "with input" table; we know it's got no fds. */
2634 for (i = 0; i < MAXDESC; i++) {
2635 Lisp_Object process = filedesc_fds_with_input[i];
2636 assert(!PROCESSP(process) || XPROCESS(process) != p);
2643 Xt_process_to_emacs_event(Lisp_Event * emacs_event)
2647 assert(process_events_occurred > 0);
2649 for (i = 0; i < MAXDESC; i++) {
2650 Lisp_Object process = filedesc_with_input[i];
2651 if (PROCESSP(process)) {
2652 filedesc_with_input[i] = Qnil;
2653 process_events_occurred--;
2654 /* process events have nil as channel */
2655 emacs_event->event_type = process_event;
2656 emacs_event->timestamp = 0; /* #### */
2657 emacs_event->event.process.process = process;
2665 emacs_Xt_select_console(struct console *con)
2667 Lisp_Object console;
2670 if (CONSOLE_X_P(con)) {
2671 /* X consoles are automatically selected for when we
2672 initialize them in Xt */
2675 infd = event_stream_unixoid_select_console(con);
2676 XSETCONSOLE(console, con);
2678 select_filedesc(infd, console);
2683 emacs_Xt_unselect_console(struct console *con)
2685 Lisp_Object console;
2688 if (CONSOLE_X_P(con)) {
2689 /* X consoles are automatically selected for when we
2690 initialize them in Xt */
2693 infd = event_stream_unixoid_unselect_console(con);
2694 XSETCONSOLE(console, con);
2696 unselect_filedesc(infd);
2700 /* read an event from a tty, if one is available. Returns non-zero
2701 if an event was available. Note that when this function is
2702 called, there should always be a tty marked as ready for input.
2703 However, the input condition might actually be EOF, so there
2704 may not really be any input available. (In this case,
2705 read_event_from_tty_or_stream_desc() will arrange for the TTY device
2709 Xt_tty_to_emacs_event(Lisp_Event * emacs_event)
2713 assert(tty_events_occurred > 0);
2714 for (i = 0; i < MAXDESC; i++) {
2715 Lisp_Object console = filedesc_with_input[i];
2716 if (CONSOLEP(console)) {
2717 assert(tty_events_occurred > 0);
2718 tty_events_occurred--;
2719 filedesc_with_input[i] = Qnil;
2720 if (read_event_from_tty_or_stream_desc(
2721 emacs_event, XCONSOLE(console), i)) {
2730 /************************************************************************/
2731 /* debugging functions to decipher an event */
2732 /************************************************************************/
2734 #ifdef DEBUG_SXEMACS
2735 #include "xintrinsicp.h" /* only describe_event() needs this */
2736 #include <X11/Xproto.h> /* only describe_event() needs this */
2738 static void describe_event_window(Window window, Display * display)
2742 stderr_out(" window: 0x%lx", (unsigned long)window);
2743 w = XtWindowToWidget(display, window);
2745 stderr_out(" %s", w->core.widget_class->core_class.class_name);
2746 f = x_any_window_to_frame(get_device_from_display(display), window);
2748 int len = XSTRING_LENGTH(f->name) + 4;
2751 int sz = snprintf(buf, len, " \"%s\"", XSTRING_DATA(f->name));
2752 assert(sz >= 0 && sz < len);
2753 write_string_to_stdio_stream(stderr, 0, (Bufbyte*)buf, 0,
2759 static const char *XEvent_mode_to_string(int mode)
2768 case NotifyWhileGrabbed:
2769 return "WhileGrabbed";
2775 static const char *XEvent_detail_to_string(int detail)
2778 case NotifyAncestor:
2780 case NotifyInferior:
2782 case NotifyNonlinear:
2784 case NotifyNonlinearVirtual:
2785 return "NonlinearVirtual";
2788 case NotifyPointerRoot:
2789 return "PointerRoot";
2790 case NotifyDetailNone:
2791 return "DetailNone";
2797 static const char *XEvent_visibility_to_string(int state)
2800 case VisibilityFullyObscured:
2801 return "FullyObscured";
2802 case VisibilityPartiallyObscured:
2803 return "PartiallyObscured";
2804 case VisibilityUnobscured:
2805 return "Unobscured";
2811 static void describe_event(XEvent * event)
2814 struct device *d = get_device_from_display(event->xany.display);
2816 int sz = snprintf(buf, sizeof(buf),
2817 "%s%s", x_event_name(event->type),
2818 event->xany.send_event ? " (send)" : "");
2819 assert(sz >= 0 && (size_t)sz < sizeof(buf));
2820 stderr_out("%-30s", buf);
2821 switch (event->type) {
2824 XFocusChangeEvent *ev = &event->xfocus;
2825 describe_event_window(ev->window, ev->display);
2826 stderr_out(" mode: %s\n",
2827 XEvent_mode_to_string(ev->mode));
2828 stderr_out(" detail: %s\n",
2829 XEvent_detail_to_string(ev->detail));
2834 XKeyEvent *ev = &event->xkey;
2835 unsigned int state = ev->state;
2837 describe_event_window(ev->window, ev->display);
2838 stderr_out(" subwindow: %ld\n", ev->subwindow);
2839 stderr_out(" state: ");
2840 /* Complete list of modifier key masks */
2841 if (state & ShiftMask)
2842 stderr_out("Shift ");
2843 if (state & LockMask)
2844 stderr_out("Lock ");
2845 if (state & ControlMask)
2846 stderr_out("Control ");
2847 if (state & Mod1Mask)
2848 stderr_out("Mod1 ");
2849 if (state & Mod2Mask)
2850 stderr_out("Mod2 ");
2851 if (state & Mod3Mask)
2852 stderr_out("Mod3 ");
2853 if (state & Mod4Mask)
2854 stderr_out("Mod4 ");
2855 if (state & Mod5Mask)
2856 stderr_out("Mod5 ");
2859 stderr_out("vanilla\n");
2862 if (x_key_is_modifier_p(ev->keycode, d))
2863 stderr_out(" Modifier key");
2864 stderr_out(" keycode: 0x%x\n", ev->keycode);
2869 if (debug_x_events > 1) {
2870 XExposeEvent *ev = &event->xexpose;
2871 describe_event_window(ev->window, ev->display);
2872 stderr_out(" region: x=%d y=%d width=%d height=%d\n",
2873 ev->x, ev->y, ev->width, ev->height);
2874 stderr_out(" count: %d\n", ev->count);
2880 case GraphicsExpose:
2881 if (debug_x_events > 1) {
2882 XGraphicsExposeEvent *ev = &event->xgraphicsexpose;
2883 describe_event_window(ev->drawable, ev->display);
2884 stderr_out(" major: %s\n",
2885 (ev->major_code == X_CopyArea ? "CopyArea" :
2887 X_CopyPlane ? "CopyPlane" : "?")));
2888 stderr_out(" region: x=%d y=%d width=%d height=%d\n",
2889 ev->x, ev->y, ev->width, ev->height);
2890 stderr_out(" count: %d\n", ev->count);
2898 if (debug_x_events > 1) {
2899 XCrossingEvent *ev = &event->xcrossing;
2900 describe_event_window(ev->window, ev->display);
2902 stderr_out(" subwindow: 0x%x\n", ev->subwindow);
2903 stderr_out(" pos: %d %d\n", ev->x, ev->y);
2904 stderr_out(" root pos: %d %d\n", ev->x_root,
2907 stderr_out(" mode: %s\n",
2908 XEvent_mode_to_string(ev->mode));
2909 stderr_out(" detail: %s\n",
2910 XEvent_detail_to_string(ev->detail));
2911 stderr_out(" focus: %d\n", ev->focus);
2913 stderr_out(" state: 0x%x\n", ev->state);
2920 case ConfigureNotify:
2921 if (debug_x_events > 1) {
2922 XConfigureEvent *ev = &event->xconfigure;
2923 describe_event_window(ev->window, ev->display);
2924 stderr_out(" above: 0x%lx\n", ev->above);
2925 stderr_out(" size: %d %d %d %d\n", ev->x, ev->y,
2926 ev->width, ev->height);
2927 stderr_out(" redirect: %d\n", ev->override_redirect);
2933 case VisibilityNotify:
2934 if (debug_x_events > 1) {
2935 XVisibilityEvent *ev = &event->xvisibility;
2936 describe_event_window(ev->window, ev->display);
2937 stderr_out(" state: %s\n",
2938 XEvent_visibility_to_string(ev->state));
2944 case ClientMessage: {
2945 XClientMessageEvent *ev = &event->xclient;
2946 char *name = XGetAtomName(ev->display, ev->message_type);
2947 stderr_out("%s", name);
2948 if (!strcmp(name, "WM_PROTOCOLS")) {
2950 XGetAtomName(ev->display, ev->data.l[0]);
2951 stderr_out("(%s)", protname);
2967 #endif /* include describe_event definition */
2969 /************************************************************************/
2970 /* get the next event from Xt */
2971 /************************************************************************/
2973 static Lisp_Object dispatch_event_queue, dispatch_event_queue_tail;
2975 void enqueue_Xt_dispatch_event(Lisp_Object event)
2977 enqueue_event(event, &dispatch_event_queue, &dispatch_event_queue_tail);
2980 static Lisp_Object dequeue_Xt_dispatch_event(void)
2982 return dequeue_event(&dispatch_event_queue, &dispatch_event_queue_tail);
2985 /* This business exists because menu events "happen" when
2986 menubar_selection_callback() is called from somewhere deep
2987 within XtAppProcessEvent in emacs_Xt_next_event(). The
2988 callback needs to terminate the modal loop in that function
2989 or else it will continue waiting until another event is
2992 Same business applies to scrollbar events. */
2995 signal_special_Xt_user_event(Lisp_Object channel, Lisp_Object function,
2998 Lisp_Object event = Fmake_event(Qnil, Qnil);
3000 XEVENT(event)->event_type = misc_user_event;
3001 XEVENT(event)->channel = channel;
3002 XEVENT(event)->event.eval.function = function;
3003 XEVENT(event)->event.eval.object = object;
3005 enqueue_Xt_dispatch_event(event);
3008 static void emacs_Xt_next_event(Lisp_Event * emacs_event)
3010 we_didnt_get_an_event:
3012 while (NILP(dispatch_event_queue) &&
3013 !completed_timeouts_head &&
3014 !fake_event_occurred &&
3015 !process_events_occurred && !tty_events_occurred) {
3017 /* Stupid logic in XtAppProcessEvent() dictates that, if process
3018 events and X events are both available, the process event
3019 gets taken first. This will cause an infinite loop if we're
3020 being called from Fdiscard_input().
3022 if (XtAppPending(Xt_app_con) & XtIMXEvent) {
3023 XtAppProcessEvent(Xt_app_con, XtIMXEvent);
3025 Lisp_Object devcons, concons;
3027 /* We're about to block. Xt has a bug in it (big
3028 surprise, there) in that it blocks using select() and
3029 doesn't flush the Xlib output buffers (XNextEvent()
3030 does this automatically before blocking). So it's
3031 necessary for us to do this ourselves. If we don't
3032 do it, then display output may not be seen until the
3033 next time an X event is received. (This happens
3034 esp. with subprocess output that gets sent to a
3037 #### The above comment may not have any validity. */
3039 DEVICE_LOOP_NO_BREAK(devcons, concons) {
3041 d = XDEVICE(XCAR(devcons));
3043 if (DEVICE_X_P(d) && DEVICE_X_DISPLAY(d)) {
3044 /* emacs may be exiting */
3045 XFlush(DEVICE_X_DISPLAY(d));
3048 XtAppProcessEvent(Xt_app_con, XtIMAll);
3052 if (!NILP(dispatch_event_queue)) {
3053 Lisp_Object event, event2;
3054 XSETEVENT(event2, emacs_event);
3055 event = dequeue_Xt_dispatch_event();
3056 Fcopy_event(event, event2);
3057 Fdeallocate_event(event);
3058 } else if (tty_events_occurred) {
3059 if (!Xt_tty_to_emacs_event(emacs_event))
3060 goto we_didnt_get_an_event;
3061 } else if (completed_timeouts_head) {
3062 Xt_timeout_to_emacs_event(emacs_event);
3063 } else if (fake_event_occurred) {
3064 /* A dummy event, so that a cycle of the command loop will occur. */
3065 fake_event_occurred = 0;
3066 /* eval events have nil as channel */
3067 emacs_event->event_type = eval_event;
3068 emacs_event->event.eval.function = Qidentity;
3069 emacs_event->event.eval.object = Qnil;
3071 /* if (process_events_occurred) */
3072 Xt_process_to_emacs_event(emacs_event);
3075 /* No need to call XFilterEvent; Xt does it for us */
3079 emacs_Xt_event_handler(Widget SXE_UNUSED(wid),
3080 XtPointer SXE_UNUSED(closure),
3082 Boolean * SXE_UNUSED(continue_to_dispatch))
3084 Lisp_Object emacs_event = Fmake_event(Qnil, Qnil);
3086 #ifdef DEBUG_SXEMACS
3087 if (debug_x_events > 0) {
3088 describe_event(event);
3090 #endif /* DEBUG_SXEMACS */
3091 if (x_event_to_emacs_event(event, XEVENT(emacs_event))) {
3092 enqueue_Xt_dispatch_event(emacs_event);
3094 Fdeallocate_event(emacs_event);
3098 /************************************************************************/
3099 /* input pending / C-g checking */
3100 /************************************************************************/
3103 quit_char_predicate(Display * display, XEvent * event, XPointer data)
3105 struct device *d = get_device_from_display(display);
3106 struct x_device *xd = DEVICE_X_DATA(d);
3108 Bool *critical = (Bool *) data;
3114 if ((event->type != KeyPress) ||
3115 (!x_any_window_to_frame(d, event->xany.window)) ||
3117 & (xd->MetaMask | xd->HyperMask | xd->SuperMask | xd->AltMask))) {
3121 /* This duplicates some code that exists elsewhere, but it's relatively
3122 fast and doesn't cons. */
3123 keysym = x_to_emacs_keysym(&event->xkey, 1);
3127 if (CHAR_OR_CHAR_INTP(keysym)) {
3128 c = XCHAR_OR_CHAR_INT(keysym);
3129 } else if (EQ(keysym, QKbackspace)) {
3130 /* Highly doubtful that these are the quit character, but... */
3132 } else if (EQ(keysym, QKtab)) {
3134 } else if (EQ(keysym, QKlinefeed)) {
3136 } else if (EQ(keysym, QKreturn)) {
3138 } else if (EQ(keysym, QKescape)) {
3140 } else if (EQ(keysym, QKspace)) {
3142 } else if (EQ(keysym, QKdelete)) {
3148 if (event->xkey.state & xd->MetaMask) {
3151 if ((event->xkey.state & ControlMask) && !(c >= 'A' && c <= 'Z')) {
3152 /* unshifted control characters */
3155 quit_char = CONSOLE_QUIT_CHAR(XCONSOLE(DEVICE_CONSOLE(d)));
3156 if (c == quit_char) {
3159 /* If we've got Control-Shift-G instead of Control-G, that means
3160 we have a critical_quit. Caps_Lock is its own modifier, so it
3161 won't cause ^G to act differently than before. */
3162 if (event->xkey.state & ControlMask) {
3165 if (c == quit_char) {
3174 /* This scans the X input queue for a KeyPress event that matches the
3175 quit character, and sets Vquit_flag. This is called from the
3176 QUIT macro to determine whether we should quit.
3178 In a SIGIO world, this won't be called unless a SIGIO has happened
3179 since the last time we checked.
3181 In a non-SIGIO world, this is called from emacs_Xt_event_pending_p
3182 (which is called from input_pending_p).
3185 x_check_for_quit_char(Display * display)
3189 Bool critical_quit = False;
3191 XEventsQueued(display, QueuedAfterReading);
3192 queued = XCheckIfEvent(display, &event,
3193 quit_char_predicate, (char *)&critical_quit);
3195 Vquit_flag = (critical_quit ? Qcritical : Qt);
3196 /* don't put the event back onto the queue. Those functions that
3197 wanted to read a ^G directly have arranged to do this. */
3202 check_for_tty_quit_char(struct device *d)
3204 SELECT_TYPE temp_mask;
3205 int infd = DEVICE_INFD(d);
3206 struct console *con = XCONSOLE(DEVICE_CONSOLE(d));
3207 Emchar quit_char = CONSOLE_QUIT_CHAR(con);
3209 FD_ZERO(&temp_mask);
3210 FD_SET(infd, &temp_mask);
3216 if (!poll_fds_for_input(temp_mask)) {
3220 event = Fmake_event(Qnil, Qnil);
3221 if (!read_event_from_tty_or_stream_desc
3222 (XEVENT(event), con, infd)) {
3223 /* EOF, or something ... */
3226 /* #### bogus. quit-char should be allowed to be any sort
3228 the_char = event_to_character(XEVENT(event), 1, 0, 0);
3229 if (the_char >= 0 && the_char == quit_char) {
3231 /* do not queue the C-g. See above. */
3235 /* queue the read event to be read for real later. */
3236 enqueue_Xt_dispatch_event(event);
3240 static void emacs_Xt_quit_p(void)
3242 Lisp_Object devcons, concons;
3243 CONSOLE_LOOP(concons) {
3244 struct console *con = XCONSOLE(XCAR(concons));
3245 if (!con->input_enabled) {
3249 CONSOLE_DEVICE_LOOP(devcons, con) {
3251 d = XDEVICE(XCAR(devcons));
3253 if (DEVICE_X_P(d) && DEVICE_X_DISPLAY(d)) {
3254 /* emacs may be exiting */
3255 x_check_for_quit_char(DEVICE_X_DISPLAY(d));
3256 } else if (DEVICE_TTY_P(d)) {
3257 check_for_tty_quit_char(d);
3263 static void drain_X_queue(void)
3265 Lisp_Object devcons, concons;
3266 CONSOLE_LOOP(concons) {
3267 struct console *con = XCONSOLE(XCAR(concons));
3268 if (!con->input_enabled) {
3272 /* sjt sez: Have you tried the loop over devices with
3273 XtAppPending(), not XEventsQueued()?
3274 Ben Sigelman sez: No.
3275 sjt sez: I'm guessing that the reason that your patch
3280 + d = XDEVICE (XCAR (devcons));
3281 + if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d)) {
3283 Ie, if the device goes down, SXEmacs detects that and deletes
3284 it. Then the if() fails (DEVICE_X_DISPLAY(d) is NULL), and
3285 we don't go into the Xlib-of-no-return. If you know
3286 different, I'd like to hear about it. ;-)
3288 These ideas haven't been tested; the code below works for
3291 CONSOLE_DEVICE_LOOP(devcons, con) {
3294 d = XDEVICE(XCAR(devcons));
3295 if (DEVICE_X_P(d) && DEVICE_X_DISPLAY(d)) {
3296 display = DEVICE_X_DISPLAY(d);
3297 while (XEventsQueued
3298 (display, QueuedAfterReading)) {
3299 XtAppProcessEvent(Xt_app_con,
3305 /* This is the old code, before Ben Sigelman's patch. */
3307 while (XtAppPending (Xt_app_con) & XtIMXEvent)
3308 XtAppProcessEvent (Xt_app_con, XtIMXEvent);
3313 emacs_Xt_event_pending_p(int user_p)
3318 /* If `user_p' is false, then this function returns whether there are any
3319 X, timeout, or fd events pending (that is, whether emacs_Xt_next_event()
3320 would return immediately without blocking).
3322 if `user_p' is true, then this function returns whether there are any
3323 *user generated* events available (that is, whether there are keyboard
3324 or mouse-click events ready to be read). This also implies that
3325 emacs_Xt_next_event() would not block.
3327 In a non-SIGIO world, this also checks whether the user has typed ^G,
3328 since this is a convenient place to do so. We don't need to do this
3329 in a SIGIO world, since input causes an interrupt.
3333 /* I don't think there's any point to this and it will nullify
3334 the speed gains achieved by the sigio_happened checking below.
3335 Its only advantage is that it may possibly make C-g response
3336 a bit faster. The C-g will be noticed within 0.25 second, anyway,
3337 even without this. */
3339 /* First check for C-g if necessary */
3344 /* This function used to simply check whether there were any X
3345 events (or if user_p was 1, it iterated over all the pending
3346 X events using XCheckIfEvent(), looking for keystrokes and
3347 button events). That worked in the old cheesoid event loop,
3348 which didn't go through XtAppDispatchEvent(), but it doesn't
3349 work any more -- X events may not result in anything. For
3350 example, a button press in a blank part of the menubar appears
3351 as an X event but will not result in any Emacs events (a
3352 button press that activates the menubar results in an Emacs
3353 event through the stop_next_event mechanism).
3355 The only accurate way of determining whether these X events
3356 translate into Emacs events is to go ahead and dispatch them
3357 until there's something on the dispatch queue. */
3359 /* See if there are any user events already on the queue. */
3360 EVENT_CHAIN_LOOP(event, dispatch_event_queue) {
3361 if (!user_p || command_event_p(event)) {
3366 /* See if there's any TTY input available.
3368 if (poll_fds_for_input(tty_only_mask)) {
3373 /* If not user_p and there are any timer or file-desc events
3374 pending, we know there will be an event so we're through. */
3375 XtInputMask pending_value;
3377 /* Note that formerly we just checked the value of
3378 XtAppPending() to determine if there was file-desc input.
3379 This doesn't work any more with the signal_event_pipe;
3380 XtAppPending() will says "yes" in this case but there isn't
3381 really any input. Another way of fixing this problem is for
3382 the signal_event_pipe to generate actual input in the form of
3383 an identity eval event or something. (#### maybe this
3384 actually happens?) */
3386 if (poll_fds_for_input(process_only_mask)) {
3389 pending_value = XtAppPending(Xt_app_con);
3391 if (pending_value & XtIMTimer) {
3396 /* XtAppPending() can be super-slow, esp. over a network connection.
3397 Quantify results have indicated that in some cases the
3398 call to detect_input_pending() completely dominates the
3399 running time of redisplay(). Fortunately, in a SIGIO world
3400 we can more quickly determine whether there are any X events:
3401 if an event has happened since the last time we checked, then
3402 a SIGIO will have happened. On a machine with broken SIGIO,
3403 we'll still be in an OK state -- the sigio_happened flag
3404 will get set at least once a second, so we'll be no more than
3405 one second behind reality. (In general it's OK if we
3406 erroneously report no input pending when input is actually
3407 pending() -- preemption is just a bit less efficient, that's
3408 all. It's bad bad bad if you err the other way -- you've
3409 promised that `next-event' won't block but it actually will,
3410 and some action might get delayed until the next time you
3414 /* quit_check_signal_tick_count is volatile so try to avoid race
3415 conditions by using a temporary variable */
3416 tick_count_val = quit_check_signal_tick_count;
3417 if (last_quit_check_signal_tick_count != tick_count_val
3418 #if !defined (SIGIO)
3419 || (XtIMXEvent & XtAppPending(Xt_app_con))
3422 last_quit_check_signal_tick_count = tick_count_val;
3424 /* We need to drain the entire queue now -- if we only
3425 drain part of it, we may later on end up with events
3426 actually pending but detect_input_pending() returning
3427 false because there wasn't another SIGIO. */
3430 EVENT_CHAIN_LOOP(event, dispatch_event_queue) {
3431 if (!user_p || command_event_p(event)) {
3441 emacs_Xt_current_event_timestamp(struct console *c)
3444 Lisp_Object devs = CONSOLE_DEVICE_LIST(c);
3449 struct device *d = XDEVICE(XCAR(devs));
3450 return DEVICE_X_LAST_SERVER_TIMESTAMP(d);
3454 /************************************************************************/
3455 /* replacement for standard string-to-pixel converter */
3456 /************************************************************************/
3458 /* This was constructed by ripping off the standard string-to-pixel
3459 converter from Converters.c in the Xt source code and modifying
3464 /* This is exported by the Xt library (at least by mine). If this
3465 isn't the case somewhere, rename this appropriately and remove
3466 the '#if 0'. Note, however, that I got "unknown structure"
3467 errors when I tried this. */
3468 XtConvertArgRec Const colorConvertArgs[] = {
3469 {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.screen),
3472 {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.colormap),
3478 #define done(type, value) \
3479 if (toVal->addr != NULL) { \
3480 if (toVal->size < sizeof(type)) { \
3481 toVal->size = sizeof(type); \
3484 *(type*)(toVal->addr) = (value); \
3486 static type static_val; \
3487 static_val = (value); \
3488 toVal->addr = (XPointer)&static_val; \
3490 toVal->size = sizeof(type); \
3491 return True /* Caller supplies `;' */
3493 /* JH: We use this because I think there's a possibility this
3494 is called before the device is properly set up, in which case
3495 I don't want to abort. */
3496 extern struct device *get_device_from_display_1(Display * dpy);
3499 Boolean EmacsXtCvtStringToPixel(Display * dpy,
3501 Cardinal * num_args,
3502 XrmValuePtr fromVal,
3503 XrmValuePtr toVal, XtPointer * closure_ret)
3505 String str = (String) fromVal->addr;
3514 Cardinal num_params = 1;
3515 XtAppContext the_app_con = XtDisplayToApplicationContext(dpy);
3517 if (*num_args != 2) {
3518 XtAppWarningMsg(the_app_con, "wrongParameters",
3519 "cvtStringToPixel", "XtToolkitError",
3520 "String to pixel conversion needs "
3521 "screen and colormap arguments",
3522 (String *) NULL, (Cardinal *) NULL);
3526 screen = *((Screen **) args[0].addr);
3527 colormap = *((Colormap *) args[1].addr);
3529 /* The original uses the private function CompareISOLatin1().
3530 Use XmuCompareISOLatin1() if you want, but I don't think it
3531 makes any difference here. */
3532 if (strcmp(str, XtDefaultBackground) == 0) {
3533 *closure_ret = False;
3534 /* This refers to the display's "*reverseVideo" resource.
3535 These display resources aren't documented anywhere that
3536 I can find, so I'm going to ignore this. */
3537 /* if (pd->rv) done(Pixel, BlackPixelOfScreen(screen)) else */
3538 done(Pixel, WhitePixelOfScreen(screen));
3540 if (strcmp(str, XtDefaultForeground) == 0) {
3541 *closure_ret = False;
3542 /* if (pd->rv) done(Pixel, WhitePixelOfScreen(screen)) else */
3543 done(Pixel, BlackPixelOfScreen(screen));
3546 /* Originally called XAllocNamedColor() here. */
3547 if ((d = get_device_from_display_1(dpy))) {
3548 visual = DEVICE_X_VISUAL(d);
3549 if (colormap != DEVICE_X_COLORMAP(d)) {
3550 XtAppWarningMsg(the_app_con, "weirdColormap",
3551 "cvtStringToPixel", "XtToolkitWarning",
3552 "The colormap passed to "
3553 "cvtStringToPixel doesn't match the "
3554 "one registered to the device.\n",
3556 status = XAllocNamedColor(dpy, colormap, (char *)str,
3557 &screenColor, &exactColor);
3559 status = XParseColor(dpy, colormap, (char *)str,
3562 status = allocate_nearest_color(
3563 dpy, colormap, visual, &screenColor);
3567 /* We haven't set up this device totally yet, so just punt */
3568 status = XAllocNamedColor(dpy, colormap, (char *)str,
3569 &screenColor, &exactColor);
3573 /* Server returns a specific error code but Xlib discards it.
3575 if (XLookupColor(DisplayOfScreen(screen), colormap, (char*)str,
3576 &exactColor, &screenColor)) {
3577 XtAppWarningMsg(the_app_con, "noColormap",
3578 "cvtStringToPixel", "XtToolkitError",
3579 "Cannot allocate colormap entry for "
3581 params, &num_params);
3584 XtAppWarningMsg(the_app_con, "badValue",
3585 "cvtStringToPixel", "XtToolkitError",
3586 "Color name \"%s\" is not defined",
3587 params, &num_params);
3590 *closure_ret = False;
3593 *closure_ret = (char *)True;
3594 done(Pixel, screenColor.pixel);
3599 static void EmacsFreePixel(XtAppContext app,
3602 XrmValuePtr args, Cardinal * num_args)
3604 if (*num_args != 2) {
3605 XtAppWarningMsg(app, "wrongParameters", "freePixel",
3607 "Freeing a pixel requires screen and "
3608 "colormap arguments",
3609 (String *) NULL, (Cardinal *) NULL);
3614 Screen *screen = *((Screen **) args[0].addr);
3615 Colormap colormap = *((Colormap *) args[1].addr);
3616 XFreeColors(DisplayOfScreen(screen), colormap,
3617 (unsigned long *)toVal->addr, 1, (unsigned long)0);
3621 /************************************************************************/
3622 /* handle focus changes for native widgets */
3623 /************************************************************************/
3625 emacs_Xt_event_widget_focus_in(Widget w,
3627 String * params, Cardinal * num_params)
3630 x_any_widget_or_parent_to_frame(get_device_from_display
3631 (event->xany.display), w);
3633 XtSetKeyboardFocus(FRAME_X_SHELL_WIDGET(f), w);
3637 emacs_Xt_event_widget_focus_out(Widget w,
3639 String * params, Cardinal * num_params)
3643 static XtActionsRec widgetActionsList[] = {
3644 {"widget-focus-in", emacs_Xt_event_widget_focus_in},
3645 {"widget-focus-out", emacs_Xt_event_widget_focus_out},
3649 emacs_Xt_event_add_widget_actions(XtAppContext ctx)
3651 XtAppAddActions(ctx, widgetActionsList, 2);
3654 /************************************************************************/
3655 /* initialization */
3656 /************************************************************************/
3657 static struct event_stream _Xt_event_stream = {
3658 .event_pending_p = emacs_Xt_event_pending_p,
3659 .force_event_pending = emacs_Xt_force_event_pending,
3660 .next_event_cb = emacs_Xt_next_event,
3661 .handle_magic_event_cb = emacs_Xt_handle_magic_event,
3662 .add_timeout_cb = emacs_Xt_add_timeout,
3663 .remove_timeout_cb = emacs_Xt_remove_timeout,
3664 .select_console_cb = emacs_Xt_select_console,
3665 .unselect_console_cb = emacs_Xt_unselect_console,
3666 .select_process_cb = emacs_Xt_select_process,
3667 .unselect_process_cb = emacs_Xt_unselect_process,
3668 .quit_p_cb = emacs_Xt_quit_p,
3669 .create_stream_pair_cb = emacs_Xt_create_stream_pair,
3670 .delete_stream_pair_cb = emacs_Xt_delete_stream_pair,
3671 .current_event_timestamp_cb = emacs_Xt_current_event_timestamp,
3674 void syms_of_event_Xt(void)
3676 defsymbol(&Qkey_mapping, "key-mapping");
3677 defsymbol(&Qsans_modifiers, "sans-modifiers");
3678 defsymbol(&Qself_insert_command, "self-insert-command");
3681 void reinit_vars_of_event_Xt(void)
3683 Xt_event_stream = &_Xt_event_stream;
3684 the_Xt_timeout_blocktype = Blocktype_new(struct Xt_timeout_blocktype);
3686 last_quit_check_signal_tick_count = 0;
3688 /* this function only makes safe calls */
3689 init_what_input_once();
3693 void vars_of_event_Xt(void)
3695 reinit_vars_of_event_Xt();
3697 dispatch_event_queue = Qnil;
3698 staticpro(&dispatch_event_queue);
3699 dispatch_event_queue_tail = Qnil;
3700 dump_add_root_object(&dispatch_event_queue_tail);
3702 DEFVAR_BOOL("x-allow-sendevents", &x_allow_sendevents /*
3703 *Non-nil means to allow synthetic events. Nil means they are ignored.
3704 Beware: allowing emacs to process SendEvents opens a big security hole.
3706 x_allow_sendevents = 0;
3708 #ifdef DEBUG_SXEMACS
3709 DEFVAR_INT("debug-x-events", &debug_x_events /*
3710 If non-zero, display debug information about X events that SXEmacs sees.
3711 Information is displayed on stderr. Currently defined values are:
3713 1 == non-verbose output
3720 /* This mess is a hack that patches the shell widget to treat visual
3721 inheritance the same as colormap and depth inheritance */
3723 static XtInitProc orig_shell_init_proc;
3726 ShellVisualPatch(Widget wanted, Widget new,
3727 ArgList args, Cardinal * num_args)
3730 ShellWidget w = (ShellWidget) new;
3732 /* first, call the original setup */
3733 (*orig_shell_init_proc) (wanted, new, args, num_args);
3735 /* if the visual isn't explicitly set, grab it from the nearest shell
3737 if (w->shell.visual == CopyFromParent) {
3739 while (p && !XtIsShell(p)) {
3743 w->shell.visual = ((ShellWidget) p)->shell.visual;
3748 void init_event_Xt_late(void)
3750 /* called when already initialized */
3751 timeout_id_tick = 1;
3752 pending_timeouts = NULL;
3753 completed_timeouts_head = NULL; /* queue is empty */
3754 completed_timeouts_tail = NULL; /* just to be picky */
3756 event_stream = Xt_event_stream;
3758 #if defined(HAVE_XIM) || defined(USE_XFONTSET)
3759 Initialize_Locale();
3760 #endif /* HAVE_XIM || USE_XFONTSET */
3762 XtToolkitInitialize();
3763 Xt_app_con = XtCreateApplicationContext();
3764 XtAppSetFallbackResources(Xt_app_con, (String*)x_fallback_resources);
3767 x_selection_timeout = (XtAppGetSelectionTimeout(Xt_app_con) / 1000);
3768 XSetErrorHandler(x_error_handler);
3769 XSetIOErrorHandler(x_IO_error_handler);
3771 XtAppAddInput(Xt_app_con, signal_event_pipe[0],
3772 (XtPointer) (XtInputReadMask /* | XtInputExceptMask */ ),
3773 Xt_what_callback, 0);
3775 XtAppSetTypeConverter(Xt_app_con, XtRString, XtRPixel,
3776 EmacsXtCvtStringToPixel,
3777 (XtConvertArgList)colorConvertArgs,
3778 2, XtCacheByDisplay, EmacsFreePixel);
3781 XtAppSetTypeConverter(Xt_app_con, XtRString, XtRXimStyles,
3782 EmacsXtCvtStringToXIMStyles,
3783 NULL, 0, XtCacheByDisplay, EmacsFreeXIMStyles);
3784 #endif /* XIM_XLIB */
3785 /* Add extra actions to native widgets to handle focus and friends. */
3786 emacs_Xt_event_add_widget_actions(Xt_app_con);
3788 /* insert the visual inheritance patch/hack described above */
3789 orig_shell_init_proc = shellClassRec.core_class.initialize;
3790 shellClassRec.core_class.initialize = ShellVisualPatch;
3792 #if defined(EF_USE_ASYNEQ)
3793 emacs_Xt_watch_event_queue(asyneq);
3797 /* event-Xt.c ends here */