1 /* The event_stream interface for X11 with Xt, and/or tty frames.
2 Copyright (C) 1991-5, 1997 Free Software Foundation, Inc.
3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 1996 Ben Wing.
6 This file is part of SXEmacs
8 SXEmacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 SXEmacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 /* Synched up with: Not in FSF. */
27 #include "console-x.h"
28 #include "ui/lwlib/lwlib.h"
29 #include "EmacsFrame.h"
31 #include "mem/blocktype.h"
33 #include "ui/console.h"
34 /* #include "ui/TTY/console-tty.h"
36 #define INCLUDE_EVENTS_H_PRIVATE_SPHERE
37 #include "events/events.h"
39 #include "objects-x.h"
41 #include "ui/redisplay.h"
45 #include "sysproc.h" /* for MAXDESC */
47 #include "xintrinsicp.h" /* CoreP.h needs this */
48 #include <X11/CoreP.h> /* Numerous places access the fields of
49 a core widget directly. We could
50 use XtGetValues(), but ... */
51 #include <X11/ShellP.h>
58 #include "mule/file-coding.h"
61 #include "events/events-mod.h"
63 #include "events/event-queue.h"
66 void enqueue_focus_event(Widget wants_it, Lisp_Object frame, int in_p);
67 static void handle_focus_event_1(struct frame *f, int in_p);
68 static void handle_focus_event_2(Window w, struct frame *f, int in_p);
70 static struct event_stream *Xt_event_stream;
72 /* With the new event model, all events go through XtDispatchEvent()
73 and are picked up by an event handler that is added to each frame
74 widget. (This is how it's supposed to be.) In the old method,
75 Emacs sucks out events directly from XtNextEvent() and only
76 dispatches the events that it doesn't need to deal with. This
77 old way has lots of corresponding junk that is no longer
78 necessary: lwlib extensions, synthetic XAnyEvents, unnecessary
81 /* The one and only one application context that Emacs uses. */
82 XtAppContext Xt_app_con;
84 /* Do we accept events sent by other clients? */
85 int x_allow_sendevents;
88 Fixnum debug_x_events;
91 static int process_events_occurred;
92 static int tty_events_occurred;
93 static Widget widget_with_focus;
95 /* Mask of bits indicating the descriptors that we wait for input on */
96 extern SELECT_TYPE input_wait_mask, process_only_mask, tty_only_mask;
98 static String x_fallback_resources[] = {
99 /* This file is automatically generated from the app-defaults file
100 in ../etc/Emacs.ad. These resources are consulted only if no
101 app-defaults file is found at all.
103 #include <ui/Emacs.ad.h>
107 static Lisp_Object x_keysym_to_emacs_keysym(KeySym keysym, int simple_p);
108 void emacs_Xt_mapping_action(Widget w, XEvent * event);
109 void debug_process_finalization(Lisp_Process * p);
110 void emacs_Xt_event_handler(Widget wid, XtPointer closure, XEvent * event,
111 Boolean * continue_to_dispatch);
113 static int last_quit_check_signal_tick_count;
115 Lisp_Object Qkey_mapping;
116 Lisp_Object Qsans_modifiers;
119 /************************************************************************/
120 /* keymap handling */
121 /************************************************************************/
123 /* X bogusly doesn't define the interpretations of any bits besides
124 ModControl, ModShift, and ModLock; so the Interclient Communication
125 Conventions Manual says that we have to bend over backwards to figure
126 out what the other modifier bits mean. According to ICCCM:
128 - Any keycode which is assigned ModControl is a "control" key.
130 - Any modifier bit which is assigned to a keycode which generates Meta_L
131 or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper,
134 - Any keypress event which contains ModControl in its state should be
135 interpreted as a "control" character.
137 - Any keypress event which contains a modifier bit in its state which is
138 generated by a keycode whose corresponding keysym is Meta_L or Meta_R
139 should be interpreted as a "meta" character. Likewise for Super, Hyper,
142 - It is illegal for a keysym to be associated with more than one modifier
145 This means that the only thing that emacs can reasonably interpret as a
146 "meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
147 one of the modifier bits Mod1-Mod5.
149 Unfortunately, many keyboards don't have Meta keys in their default
150 configuration. So, if there are no Meta keys, but there are "Alt" keys,
151 emacs will interpret Alt as Meta. If there are both Meta and Alt keys,
152 then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to
153 mean "Symbol," but that just confused the hell out of way too many people).
155 This works with the default configurations of the 19 keyboard-types I've
158 Emacs detects keyboard configurations which violate the above rules, and
159 prints an error message on the standard-error-output. (Perhaps it should
160 use a pop-up-window instead.)
163 /* For every key on the keyboard that has a known character correspondence,
164 we define the ascii-character property of the keysym, and make the
165 default binding for the key be self-insert-command.
167 The following magic is basically intimate knowledge of X11/keysymdef.h.
168 The keysym mappings defined by X11 are based on the iso8859 standards,
169 except for Cyrillic and Greek.
171 In a non-Mule world, a user can still have a multi-lingual editor, by doing
172 (set-face-font "...-iso8859-2" (current-buffer))
173 for all their Latin-2 buffers, etc. */
175 static Lisp_Object x_keysym_to_character(KeySym keysym)
178 Lisp_Object charset = Qzero;
179 #define USE_CHARSET(var,cs) \
180 ((var) = CHARSET_BY_LEADING_BYTE (LEADING_BYTE_##cs))
182 #define USE_CHARSET(var,lb)
186 if ((keysym & 0xff) < 0xa0)
189 switch (keysym >> 8) {
190 case 0: /* ASCII + Latin1 */
191 USE_CHARSET(charset, LATIN_ISO8859_1);
192 code = keysym & 0x7f;
195 USE_CHARSET(charset, LATIN_ISO8859_2);
196 code = keysym & 0x7f;
199 USE_CHARSET(charset, LATIN_ISO8859_3);
200 code = keysym & 0x7f;
203 USE_CHARSET(charset, LATIN_ISO8859_4);
204 code = keysym & 0x7f;
206 case 4: /* Katakana */
207 USE_CHARSET(charset, KATAKANA_JISX0201);
208 if ((keysym & 0xff) > 0xa0)
209 code = keysym & 0x7f;
212 USE_CHARSET(charset, ARABIC_ISO8859_6);
213 code = keysym & 0x7f;
217 static unsigned char const cyrillic[] = /* 0x20 - 0x7f */
218 { 0x00, 0x72, 0x73, 0x71, 0x74, 0x75, 0x76, 0x77,
219 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x00, 0x7e, 0x7f,
220 0x70, 0x22, 0x23, 0x21, 0x24, 0x25, 0x26, 0x27,
221 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x00, 0x2e, 0x2f,
222 0x6e, 0x50, 0x51, 0x66, 0x54, 0x55, 0x64, 0x53,
223 0x65, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
224 0x5f, 0x6f, 0x60, 0x61, 0x62, 0x63, 0x56, 0x52,
225 0x6c, 0x6b, 0x57, 0x68, 0x6d, 0x69, 0x67, 0x6a,
226 0x4e, 0x30, 0x31, 0x46, 0x34, 0x35, 0x44, 0x33,
227 0x45, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
228 0x3f, 0x4f, 0x40, 0x41, 0x42, 0x43, 0x36, 0x32,
229 0x4c, 0x4b, 0x37, 0x48, 0x4d, 0x49, 0x47, 0x4a
231 USE_CHARSET(charset, CYRILLIC_ISO8859_5);
232 code = cyrillic[(keysym & 0x7f) - 0x20];
237 static unsigned char const greek[] = /* 0x20 - 0x7f */
238 { 0x00, 0x36, 0x38, 0x39, 0x3a, 0x5a, 0x00, 0x3c,
239 0x3e, 0x5b, 0x00, 0x3f, 0x00, 0x00, 0x35, 0x2f,
240 0x00, 0x5c, 0x5d, 0x5e, 0x5f, 0x7a, 0x40, 0x7c,
241 0x7d, 0x7b, 0x60, 0x7e, 0x00, 0x00, 0x00, 0x00,
242 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
243 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
244 0x50, 0x51, 0x53, 0x00, 0x54, 0x55, 0x56, 0x57,
245 0x58, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
247 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
248 0x70, 0x71, 0x73, 0x72, 0x74, 0x75, 0x76, 0x77,
249 0x78, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
251 USE_CHARSET(charset, GREEK_ISO8859_7);
252 code = greek[(keysym & 0x7f) - 0x20];
255 case 8: /* Technical */
257 case 9: /* Special */
259 case 10: /* Publishing */
263 case 12: /* Hebrew */
264 USE_CHARSET(charset, HEBREW_ISO8859_8);
265 code = keysym & 0x7f;
268 /* #### This needs to deal with character composition. */
269 USE_CHARSET(charset, THAI_TIS620);
270 code = keysym & 0x7f;
272 case 14: /* Korean Hangul */
274 case 19: /* Latin 9 - ISO8859-15 - unsupported charset. */
276 case 32: /* Currency */
286 return make_char(MAKE_CHAR(charset, code, 0));
288 return make_char(code + 0x80);
292 /* #### The way that keysym correspondence to characters should work:
293 - a Lisp_Event should contain a keysym AND a character slot.
294 - keybindings are tried with the keysym. If no binding can be found,
295 and there is a corresponding character, call self-insert-command.
297 #### Nuke x-iso8859-1.el.
298 #### Nuke the Qascii_character property.
299 #### Nuke Vcharacter_set_property.
302 maybe_define_x_key_as_self_inserting_character(KeySym keysym,
305 Lisp_Object character = x_keysym_to_character(keysym);
307 if (CHARP(character)) {
308 extern Lisp_Object Vcurrent_global_map;
309 extern Lisp_Object Qascii_character;
310 if (NILP(Flookup_key(Vcurrent_global_map, symbol, Qnil))) {
311 Fput(symbol, Qascii_character, character);
312 Fdefine_key(Vcurrent_global_map, symbol,
313 Qself_insert_command);
319 x_has_keysym(KeySym keysym, Lisp_Object hash_table, int with_modifiers)
321 KeySym upper_lower[2];
324 if (keysym < 0x80) /* Optimize for ASCII keysyms */
328 xmodmap -e 'keysym NN = scaron'
329 and then press (Shift scaron), X11 will return the different
330 keysym `Scaron', but `xmodmap -pke' might not even mention
331 `Scaron', so we "register" both `scaron' and `Scaron'. */
332 #ifdef HAVE_XCONVERTCASE
333 XConvertCase(keysym, &upper_lower[0], &upper_lower[1]);
335 upper_lower[0] = upper_lower[1] = keysym;
338 for (j = 0; j < (upper_lower[0] == upper_lower[1] ? 1 : 2); j++) {
340 keysym = upper_lower[j];
342 name = XKeysymToString(keysym);
344 /* X guarantees NAME to be in the Host Portable
345 Character Encoding */
346 Lisp_Object sym = x_keysym_to_emacs_keysym(keysym, 0);
347 Lisp_Object new_value = with_modifiers
348 ? Qt : Qsans_modifiers;
349 Lisp_Object old_value = Fgethash(sym, hash_table, Qnil);
351 if (!EQ(old_value, new_value)
352 && !(EQ(old_value, Qsans_modifiers) &&
353 EQ(new_value, Qt))) {
354 maybe_define_x_key_as_self_inserting_character
356 Fputhash(build_ext_string(name, Qbinary),
357 new_value, hash_table);
358 Fputhash(sym, new_value, hash_table);
365 x_reset_key_mapping(struct device *d)
367 Display *display = DEVICE_X_DISPLAY(d);
368 struct x_device *xd = DEVICE_X_DATA(d);
369 KeySym *keysym, *keysym_end;
370 Lisp_Object hash_table;
371 int key_code_count, keysyms_per_code;
373 if (xd->x_keysym_map) {
374 XFree((char *)xd->x_keysym_map);
376 XDisplayKeycodes(display,
377 &xd->x_keysym_map_min_code,
378 &xd->x_keysym_map_max_code);
380 xd->x_keysym_map_max_code - xd->x_keysym_map_min_code + 1;
382 XGetKeyboardMapping(display, xd->x_keysym_map_min_code,
384 &xd->x_keysym_map_keysyms_per_code);
386 hash_table = xd->x_keysym_map_hash_table;
387 if (HASH_TABLEP(hash_table)) {
388 Fclrhash(hash_table);
390 xd->x_keysym_map_hash_table = hash_table =
391 make_lisp_hash_table(128, HASH_TABLE_NON_WEAK,
395 for (keysym = xd->x_keysym_map,
396 keysyms_per_code = xd->x_keysym_map_keysyms_per_code,
397 keysym_end = keysym + (key_code_count * keysyms_per_code);
398 keysym < keysym_end; keysym += keysyms_per_code) {
401 if (keysym[0] == NoSymbol) {
404 x_has_keysym(keysym[0], hash_table, 0);
406 for (j = 1; j < keysyms_per_code; j++) {
407 if (keysym[j] != keysym[0] && keysym[j] != NoSymbol) {
408 x_has_keysym(keysym[j], hash_table, 1);
414 static inline const char *index_to_name(int indice)
415 __attribute__((always_inline));
416 static inline const char *index_to_name(int indice)
423 case ControlMapIndex:
441 /* Boy, I really wish C had local functions... */
442 /* yeah? look closer, mate! */
443 struct c_doesnt_have_closures { /* #### not yet used */
444 bool warned_about_overlapping_modifiers;
445 bool warned_about_predefined_modifiers;
446 bool warned_about_duplicate_modifiers;
455 static char *err_overlap_mods =
457 " Two distinct modifier keys (such as Meta and Hyper) cannot\n"
458 " generate the same modifier bit, because Emacs won't be able\n"
459 " to tell which modifier was actually held down when some\n"
460 " other key is pressed. It won't be able to tell Meta-x and\n"
461 " Hyper-x apart, for example. Change one of these keys to use\n"
462 " some other modifier bit. If you intend for these keys to\n"
463 " have the same behavior, then change them to have the same\n"
464 " keysym as well as the same modifier bit.";
465 static char *err_predef_mods =
467 " The semantics of the modifier bits ModShift, ModLock, and\n"
468 " ModControl are predefined. It does not make sense to assign\n"
469 " ModControl to any keysym other than Control_L or Control_R,\n"
470 " or to assign any modifier bits to the \"control\" keysyms\n"
471 " other than ModControl. You can't turn a \"control\" key\n"
472 " into a \"meta\" key (or vice versa) by simply assigning the\n"
473 " key a different modifier bit. You must also make that key\n"
474 " generate an appropriate keysym (Control_L, Meta_L, etc).";
475 static char *err_msg_else =
477 " The meanings of the modifier bits Mod1 through Mod5 are\n"
478 " determined by the keysyms used to control those bits.\n"
479 " Mod1 does NOT always mean Meta, although some\n"
480 " non-ICCCM-compliant programs assume that.";
483 x_reset_modifier_mapping(struct device *d)
485 Display *display = DEVICE_X_DISPLAY(d);
486 struct x_device *xd = DEVICE_X_DATA(d);
487 int modifier_index, modifier_key, mkpm;
488 bool warned_about_overlapping_modifiers = false;
489 bool warned_about_predefined_modifiers = false;
490 bool warned_about_duplicate_modifiers = false;
496 auto void whatever();
498 xd->lock_interpretation = 0;
500 if (xd->x_modifier_keymap) {
501 XFreeModifiermap(xd->x_modifier_keymap);
503 x_reset_key_mapping(d);
505 xd->x_modifier_keymap = XGetModifierMapping(display);
507 /* Boy, I really wish C had local functions...
508 * Watch and learn, boy! This is still ugly, I don't claim
509 * otherwise, but it proves you wrong! -hrop */
513 KeyCode code = xd->x_modifier_keymap->modifiermap
514 [modifier_index * mkpm + modifier_key];
515 auto inline void modbarf() __attribute__((always_inline));
516 auto inline void modwarn() __attribute__((always_inline));
517 auto inline void store_modifier()
518 __attribute__((always_inline));
519 auto inline void check_modifier()
520 __attribute__((always_inline));
522 auto inline void modbarf(const char *name, const char *other)
525 Qkey_mapping, Qwarning,
526 "SXEmacs: %s (0x%x) generates %s, "
527 "which is nonsensical.",
529 warned_about_predefined_modifiers = true;
533 auto inline void modwarn(const char *name,
534 int old, const char *other)
536 warn_when_safe(Qkey_mapping, Qwarning,
537 "SXEmacs: %s (0x%x) generates %s, "
538 "which is generated by %s.",
539 name, code, index_to_name (old), other);
540 warned_about_overlapping_modifiers = true;
544 auto inline void store_modifier(const char *name, int *old)
546 if (*old && *old != modifier_index) {
548 Qkey_mapping, Qwarning,
549 "SXEmacs: %s (0x%x) generates both "
550 "%s and %s, which is nonsensical.",
551 name, code, index_to_name(*old),
552 index_to_name(modifier_index));
553 warned_about_duplicate_modifiers = true;
555 if (modifier_index == ShiftMapIndex) {
556 modbarf(name, "ModShift");
557 } else if (modifier_index == LockMapIndex) {
558 modbarf(name, "ModLock");
559 } else if (modifier_index == ControlMapIndex) {
560 modbarf(name, "ModControl");
562 } else if (sym == XK_Mode_switch) {
563 /* Mode_switch is special, see below... */
566 } else if (modifier_index == meta_bit &&
568 modwarn (name, meta_bit, "Meta");
569 } else if (modifier_index == super_bit &&
571 modwarn (name, super_bit, "Super");
572 } else if (modifier_index == hyper_bit &&
574 modwarn (name, hyper_bit, "Hyper");
575 } else if (modifier_index == alt_bit &&
577 modwarn (name, alt_bit, "Alt");
579 *old = modifier_index;
583 auto inline void check_modifier(const char *name, int mask)
585 if ((1 << modifier_index) != mask) {
587 Qkey_mapping, Qwarning,
588 "SXEmacs: %s (0x%x) generates %s, "
589 "which is nonsensical.",
591 index_to_name(modifier_index));
592 warned_about_predefined_modifiers = true;
597 for (int column = 0; column < 4; column += 2) {
599 ? XKeycodeToKeysym(display, code, column)
602 if (LIKELY(sym == last_sym)) {
608 /* store_modifier("Mode_switch", &mode_bit); */
609 /* handled specially here */
610 mode_bit = modifier_index;
613 store_modifier("Meta_L", &meta_bit);
616 store_modifier("Meta_R", &meta_bit);
619 store_modifier("Super_L", &super_bit);
622 store_modifier("Super_R", &super_bit);
625 store_modifier("Hyper_L", &hyper_bit);
628 store_modifier("Hyper_R", &hyper_bit);
631 store_modifier("Alt_L", &alt_bit);
634 store_modifier("Alt_R", &alt_bit);
637 check_modifier("Control_L", ControlMask);
640 check_modifier("Control_R", ControlMask);
643 check_modifier("Shift_L", ShiftMask);
646 check_modifier("Shift_R", ShiftMask);
649 check_modifier("Shift_Lock", LockMask);
650 xd->lock_interpretation = XK_Shift_Lock;
653 check_modifier("Caps_Lock", LockMask);
654 xd->lock_interpretation = XK_Caps_Lock;
657 /* It probably doesn't make any sense for a
658 modifier bit to be assigned to a key that is
659 not one of the above, but OpenWindows assigns
660 modifier bits to a couple of random function
661 keys for no reason that I can discern, so
662 printing a warning here would be annoying. */
664 /* hope we handled everything above */
671 /* The call to warn_when_safe must be on the same line as the string or
672 make-msgfile won't pick it up properly (the newline doesn't confuse
673 it, but the backslash does). */
675 mkpm = xd->x_modifier_keymap->max_keypermod;
676 for (modifier_index = 0; modifier_index < 8; modifier_index++) {
677 for (modifier_key = 0; modifier_key < mkpm; modifier_key++) {
682 /* If there was no Meta key, then try using the Alt key instead.
683 If there is both a Meta key and an Alt key, then the Alt key
684 is not disturbed and remains an Alt key. */
685 if (!meta_bit && alt_bit) {
686 meta_bit = alt_bit, alt_bit = 0;
689 /* mode_bit overrides everything, since it's processed down inside of
690 XLookupString() instead of by us. If Meta and Mode_switch both
691 generate the same modifier bit (which is an error), then we don't
692 interpret that bit as Meta, because we can't make XLookupString()
693 not interpret it as Mode_switch; and interpreting it as both would
696 const char *warn = 0;
698 if (mode_bit == meta_bit) {
701 } else if (mode_bit == hyper_bit) {
704 } else if (mode_bit == super_bit) {
707 } else if (mode_bit == alt_bit) {
713 Qkey_mapping, Qwarning,
714 "SXEmacs: %s is being used for both "
715 "Mode_switch and %s.",
716 index_to_name(mode_bit), warn);
717 warned_about_overlapping_modifiers = true;
721 xd->MetaMask = (meta_bit ? (1 << meta_bit) : 0);
722 xd->HyperMask = (hyper_bit ? (1 << hyper_bit) : 0);
723 xd->SuperMask = (super_bit ? (1 << super_bit) : 0);
724 xd->AltMask = (alt_bit ? (1 << alt_bit) : 0);
725 xd->ModeMask = (mode_bit ? (1 << mode_bit) : 0); /* unused */
727 if (warned_about_overlapping_modifiers) {
728 warn_when_safe(Qkey_mapping, Qwarning, "%s", err_overlap_mods);
731 if (warned_about_predefined_modifiers) {
732 warn_when_safe(Qkey_mapping, Qwarning, "%s", err_predef_mods);
735 /* No need to say anything more for warned_about_duplicate_modifiers. */
736 if (warned_about_overlapping_modifiers
737 || warned_about_predefined_modifiers)
738 warn_when_safe(Qkey_mapping, Qwarning, "%s", err_msg_else);
741 void x_init_modifier_mapping(struct device *d)
743 struct x_device *xd = DEVICE_X_DATA(d);
744 xd->x_keysym_map_hash_table = Qnil;
745 xd->x_keysym_map = NULL;
746 xd->x_modifier_keymap = NULL;
747 x_reset_modifier_mapping(d);
751 static int x_key_is_modifier_p(KeyCode keycode, struct device *d)
753 struct x_device *xd = DEVICE_X_DATA(d);
757 if (keycode < xd->x_keysym_map_min_code ||
758 keycode > xd->x_keysym_map_max_code) {
762 syms = &xd->x_keysym_map[(keycode - xd->x_keysym_map_min_code) *
763 xd->x_keysym_map_keysyms_per_code];
764 for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++) {
765 if (IsModifierKey(syms[i]) || syms[i] == XK_Mode_switch) {
766 /* why doesn't IsModifierKey count this? */
773 /* key-handling code is always ugly. It just ends up working out
776 Here are some pointers:
778 -- DOWN_MASK indicates which modifiers should be treated as "down"
779 when the corresponding upstroke happens. It gets reset for
780 a particular modifier when that modifier goes up, and reset
781 for all modifiers when a non-modifier key is pressed. Example:
783 I press Control-A-Shift and then release Control-A-Shift.
784 I want the Shift key to be sticky but not the Control key.
786 -- LAST_DOWNKEY and RELEASE_TIME are used to keep track of
787 auto-repeat -- see below.
789 -- If a modifier key is sticky, I can unstick it by pressing
790 the modifier key again. */
792 static void x_handle_sticky_modifiers(XEvent * ev, struct device *d)
798 if (!modifier_keys_are_sticky) {
799 /* Optimize for non-sticky modifiers */
803 xd = DEVICE_X_DATA(d);
804 keycode = ev->xkey.keycode;
807 if (keycode < xd->x_keysym_map_min_code ||
808 keycode > xd->x_keysym_map_max_code) {
812 if (!((type == KeyPress || type == KeyRelease) &&
813 x_key_is_modifier_p(keycode, d))) {
814 /* Not a modifier key */
815 bool key_event_p = (type == KeyPress || type == KeyRelease);
817 if (type == ButtonPress
819 && ((xd->last_downkey
820 && ((keycode != xd->last_downkey
821 || ev->xkey.time != xd->release_time)))
822 || (INTP(Vmodifier_keys_sticky_time)
824 > (xd->modifier_release_time
825 + XINT(Vmodifier_keys_sticky_time)))))) {
826 xd->need_to_add_mask = 0;
827 xd->last_downkey = 0;
828 } else if (type == KeyPress && !xd->last_downkey) {
829 xd->last_downkey = keycode;
831 if (type == KeyPress) {
832 xd->release_time = 0;
834 if (type == KeyPress || type == ButtonPress) {
836 xd->modifier_release_time = 0;
840 ev->xkey.state |= xd->need_to_add_mask;
842 ev->xbutton.state |= xd->need_to_add_mask;
845 if (type == KeyRelease && keycode == xd->last_downkey) {
846 /* If I hold press-and-release the Control key and then
847 press and hold down the right arrow, I want it to
848 auto-repeat Control-Right. On the other hand, if I
849 do the same but manually press the Right arrow a
850 bunch of times, I want to see one Control-Right and
851 then a bunch of Rights. This means that we need to
852 distinguish between an auto-repeated key and a key
853 pressed and released a bunch of times.
855 Naturally, the designers of the X spec didn't see fit
856 to provide an obvious way to distinguish these cases.
857 So we assume that if the release and the next press
858 occur at the same time, the key was actually auto-
859 repeated. Under Open-Windows, at least, this
861 xd->modifier_release_time = xd->release_time =
867 /* Modifier key pressed */
869 KeySym *syms = &xd->x_keysym_map[
870 (keycode - xd->x_keysym_map_min_code) *
871 xd->x_keysym_map_keysyms_per_code];
873 /* If a non-modifier key was pressed in the middle of a bunch
874 of modifiers, then it unsticks all the modifiers that were
875 previously pressed. We cannot unstick the modifiers until
876 now because we want to check for auto-repeat of the
879 if (xd->last_downkey) {
880 xd->last_downkey = 0;
881 xd->need_to_add_mask = 0;
884 if (xd->modifier_release_time
885 && INTP(Vmodifier_keys_sticky_time)
886 && (ev->xkey.time > xd->modifier_release_time +
887 XINT(Vmodifier_keys_sticky_time))) {
888 xd->need_to_add_mask = 0;
894 if (type == KeyPress) { \
895 /* If modifier key is already sticky, \
896 then unstick it. Note that we do \
897 not test down_mask to deal with the \
898 unlikely but possible case that the \
899 modifier key auto-repeats. */ \
900 if (xd->need_to_add_mask & mask) { \
901 xd->need_to_add_mask &= ~mask; \
902 xd->down_mask &= ~mask; \
904 xd->down_mask |= mask; \
907 if (xd->down_mask & mask) { \
908 xd->down_mask &= ~mask; \
909 xd->need_to_add_mask |= mask; \
912 xd->modifier_release_time = ev->xkey.time; \
915 for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++) {
942 /* hope we handled everything */
950 static void clear_sticky_modifiers(struct device *d)
952 struct x_device *xd = DEVICE_X_DATA(d);
954 xd->need_to_add_mask = 0;
955 xd->last_downkey = 0;
956 xd->release_time = 0;
961 static int keysym_obeys_caps_lock_p(KeySym sym, struct device *d)
963 struct x_device *xd = DEVICE_X_DATA(d);
964 /* Eeeeevil hack. Don't apply Caps_Lock to things that aren't
965 alphabetic characters, where "alphabetic" means something more than
966 simply A-Z. That is, if Caps_Lock is down, typing ESC doesn't
967 produce Shift-ESC. But if shift-lock is down, then it does. */
968 if (xd->lock_interpretation == XK_Shift_Lock) {
971 return ((sym >= XK_A) && (sym <= XK_Z)) ||
972 ((sym >= XK_a) && (sym <= XK_z)) ||
973 ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) ||
974 ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) ||
975 ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) ||
976 ((sym >= XK_oslash) && (sym <= XK_thorn));
979 /* called from EmacsFrame.c (actually from Xt itself) when a
980 MappingNotify event is received. In its infinite wisdom, Xt
981 decided that Xt event handlers never get MappingNotify events.
982 O'Reilly Xt Programming Manual 9.1.2 says:
984 MappingNotify is automatically handled by Xt, so it isn't passed
985 to event handlers and you don't need to worry about it.
987 Of course, we DO worry about it, so we need a special translation. */
989 emacs_Xt_mapping_action(Widget w, XEvent * event)
991 struct device *d = get_device_from_display(event->xany.display);
993 if (DEVICE_X_BEING_DELETED(d)) {
997 /* nyet. Now this is handled by Xt. */
998 XRefreshKeyboardMapping(&event->xmapping);
1000 /* xmodmap generates about a billion MappingKeyboard events, followed by
1001 a single MappingModifier event, so it might be worthwhile to take
1002 extra MappingKeyboard events out of the queue before requesting the
1003 current keymap from the server. */
1004 switch (event->xmapping.request) {
1005 case MappingKeyboard:
1006 x_reset_key_mapping(d);
1008 case MappingModifier:
1009 x_reset_modifier_mapping(d);
1011 case MappingPointer:
1012 /* Do something here? */
1019 /************************************************************************/
1020 /* X to Emacs event conversion */
1021 /************************************************************************/
1024 x_keysym_to_emacs_keysym(KeySym keysym, int simple_p)
1027 if (keysym >= XK_exclam && keysym <= XK_asciitilde) {
1028 /* We must assume that the X keysym numbers for the ASCII
1029 graphic characters are the same as their ASCII codes. */
1030 return make_char(keysym);
1034 /* These would be handled correctly by the default case, but by
1035 special-casing them here we don't garbage a string or call
1057 /* !!#### not Mule-ized */
1058 name = XKeysymToString(keysym);
1059 if (!name || !name[0]) {
1060 /* This happens if there is a mismatch between the Xlib
1061 of SXEmacs and the Xlib of the X server...
1063 Let's hard-code in some knowledge of common keysyms
1064 introduced in recent X11 releases. Snarfed from
1067 Probably we should add some stuff here for X11R6. */
1070 return KEYSYM("kp-home");
1072 return KEYSYM("kp-left");
1074 return KEYSYM("kp-up");
1076 return KEYSYM("kp-right");
1078 return KEYSYM("kp-down");
1080 return KEYSYM("kp-prior");
1082 return KEYSYM("kp-next");
1084 return KEYSYM("kp-end");
1086 return KEYSYM("kp-begin");
1088 return KEYSYM("kp-insert");
1090 return KEYSYM("kp-delete");
1094 return KEYSYM("SunF36");
1097 return KEYSYM("SunF37");
1100 int sz = snprintf(buf, sizeof(buf),
1101 "unknown-keysym-0x%X",
1103 assert(sz>=0 && sz < sizeof(buf));
1108 /* If it's got a one-character name, that's good enough. */
1110 return make_char(name[0]);
1112 /* If it's in the "Keyboard" character set, downcase it. The
1113 case of those keysyms is too totally random for us to force
1114 anyone to remember them. The case of the other character
1115 sets is significant, however.
1117 if ((((unsigned int)keysym) & (~0x1FF)) ==
1118 ((unsigned int)0xFE00)) {
1121 for (s1 = name, s2 = buf; *s1; s1++, s2++) {
1125 *s2 = tolower(*(unsigned char *)s1);
1131 return KEYSYM(name);
1136 x_to_emacs_keysym(XKeyPressedEvent * event, int simple_p)
1137 /* simple_p means don't try too hard (ASCII only) */
1143 /* Some implementations of XmbLookupString don't return
1144 XBufferOverflow correctly, so increase the size of the xim input
1145 buffer from 64 to the more reasonable size 513, as Emacs has done.
1146 From Kenichi Handa. */
1148 char *bufptr = buffer;
1149 int bufsiz = sizeof(buffer);
1154 x_any_window_to_frame(get_device_from_display(event->display),event->window);
1156 xic = FRAME_X_XIC(f);
1157 #endif /* XIM_XLIB */
1158 #endif /* HAVE_XIM */
1160 /* We use XLookupString if we're not using XIM, or are using
1161 XIM_XLIB but input context creation failed. */
1162 #if ! (defined (HAVE_XIM) && defined (XIM_MOTIF))
1163 #if defined (HAVE_XIM) && defined (XIM_XLIB)
1165 #endif /* XIM_XLIB */
1167 /* Apparently it's necessary to specify a dummy here (rather
1168 than passing in 0) to avoid crashes on German IRIX */
1170 XLookupString(event, dummy, 200, &keysym, 0);
1171 return (IsModifierKey(keysym) || keysym == XK_Mode_switch)
1172 ? Qnil : x_keysym_to_emacs_keysym(keysym, simple_p);
1174 #endif /* ! XIM_MOTIF */
1177 Lookup_String: /* Come-From XBufferOverflow */
1180 XmImMbLookupString(XtWindowToWidget(event->display, event->window),
1181 event, bufptr, bufsiz, &keysym, &status);
1182 #else /* XIM_XLIB */
1184 len = XmbLookupString(xic, event, bufptr, bufsiz, &keysym,
1187 #endif /* HAVE_XIM */
1189 #ifdef DEBUG_SXEMACS
1190 if (debug_x_events > 0) {
1191 stderr_out(" status=");
1192 #define print_status_when(S) if (status == S) stderr_out (#S)
1193 print_status_when(XLookupKeySym);
1194 print_status_when(XLookupBoth);
1195 print_status_when(XLookupChars);
1196 print_status_when(XLookupNone);
1197 print_status_when(XBufferOverflow);
1199 if (status == XLookupKeySym || status == XLookupBoth)
1200 stderr_out(" keysym=%s", XKeysymToString(keysym));
1201 if (status == XLookupChars || status == XLookupBoth) {
1204 stderr_out(" chars=\"");
1205 for (j = 0; j < len; j++)
1206 stderr_out("%c", bufptr[j]);
1208 } else if (bufptr[0] <= 32 || bufptr[0] >= 127) {
1209 stderr_out(" char=0x%x", bufptr[0]);
1211 stderr_out(" char=%c", bufptr[0]);
1216 #endif /* DEBUG_SXEMACS */
1221 return (IsModifierKey(keysym) || keysym == XK_Mode_switch)
1223 : x_keysym_to_emacs_keysym(keysym, simple_p);
1225 case XLookupChars: {
1226 /* Generate multiple emacs events */
1227 struct device *d = get_device_from_display(event->display);
1229 Lisp_Object instream, fb_instream;
1231 struct gcpro gcpro1, gcpro2;
1233 fb_instream = make_fixed_buffer_input_stream(bufptr, len);
1235 /* #### Use Fget_coding_system
1236 * (Vcomposed_input_coding_system) */
1237 instream = make_decoding_input_stream(XLSTREAM(fb_instream),
1241 istr = XLSTREAM(instream);
1243 GCPRO2(instream, fb_instream);
1244 while ((ch = Lstream_get_emchar(istr)) != EOF) {
1245 Lisp_Object emacs_event = Fmake_event(Qnil, Qnil);
1246 Lisp_Event *ev = XEVENT(emacs_event);
1247 ev->channel = DEVICE_CONSOLE(d);
1248 ev->event_type = key_press_event;
1249 ev->timestamp = event->time;
1250 ev->event.key.modifiers = 0;
1251 ev->event.key.keysym = make_char(ch);
1252 enqueue_Xt_dispatch_event(emacs_event);
1254 Lstream_close(istr);
1256 Lstream_delete(istr);
1257 Lstream_delete(XLSTREAM(fb_instream));
1262 case XBufferOverflow:
1263 bufptr = (char *)alloca(len + 1);
1269 return Qnil; /* not reached */
1270 #endif /* HAVE_XIM */
1274 set_last_server_timestamp(struct device *d, XEvent * x_event)
1277 switch (x_event->type) {
1280 t = x_event->xkey.time;
1284 t = x_event->xbutton.time;
1288 t = x_event->xcrossing.time;
1291 t = x_event->xmotion.time;
1293 case PropertyNotify:
1294 t = x_event->xproperty.time;
1296 case SelectionClear:
1297 t = x_event->xselectionclear.time;
1299 case SelectionRequest:
1300 t = x_event->xselectionrequest.time;
1302 case SelectionNotify:
1303 t = x_event->xselection.time;
1308 DEVICE_X_LAST_SERVER_TIMESTAMP(d) = t;
1312 x_event_to_emacs_event(XEvent * x_event, Lisp_Event * emacs_event)
1314 Display *display = x_event->xany.display;
1315 struct device *d = get_device_from_display(display);
1316 struct x_device *xd = DEVICE_X_DATA(d);
1318 if (DEVICE_X_BEING_DELETED(d)) {
1319 /* #### Uh, is this 0 correct? */
1323 set_last_server_timestamp(d, x_event);
1325 switch (x_event->type) {
1327 x_handle_sticky_modifiers(x_event, d);
1332 case ButtonRelease: {
1334 int shift_p, lock_p;
1335 Bool key_event_p = (x_event->type == KeyPress);
1336 unsigned int *state = key_event_p
1337 ? &x_event->xkey.state
1338 : &x_event->xbutton.state;
1340 /* If this is a synthetic KeyPress or Button event, and the user
1341 has expressed a disinterest in this security hole, then drop
1344 ? x_event->xkey.send_event
1345 : x_event->xbutton.send_event)
1346 #ifdef EXTERNAL_WIDGET
1347 /* ben: events get sent to an ExternalShell using
1349 This is not a perfect solution. */
1350 && !FRAME_X_EXTERNAL_WINDOW_P
1351 (x_any_window_to_frame(d, x_event->xany.window))
1353 && !x_allow_sendevents) {
1357 DEVICE_X_MOUSE_TIMESTAMP(d) =
1358 DEVICE_X_GLOBAL_MOUSE_TIMESTAMP(d) =
1360 ? x_event->xkey.time
1361 : x_event->xbutton.time;
1363 x_handle_sticky_modifiers(x_event, d);
1365 if (*state & ControlMask) {
1366 modifiers |= XEMACS_MOD_CONTROL;
1368 if (*state & xd->MetaMask) {
1369 modifiers |= XEMACS_MOD_META;
1371 if (*state & xd->SuperMask) {
1372 modifiers |= XEMACS_MOD_SUPER;
1374 if (*state & xd->HyperMask) {
1375 modifiers |= XEMACS_MOD_HYPER;
1377 if (*state & xd->AltMask) {
1378 modifiers |= XEMACS_MOD_ALT;
1381 int numero_de_botao = -1;
1384 numero_de_botao = x_event->xbutton.button;
1386 /* the button gets noted either in the button or the
1387 modifiers field, but not both. */
1388 if (numero_de_botao != 1 && (*state & Button1Mask)) {
1389 modifiers |= XEMACS_MOD_BUTTON1;
1391 if (numero_de_botao != 2 && (*state & Button2Mask)) {
1392 modifiers |= XEMACS_MOD_BUTTON2;
1394 if (numero_de_botao != 3 && (*state & Button3Mask)) {
1395 modifiers |= XEMACS_MOD_BUTTON3;
1397 if (numero_de_botao != 4 && (*state & Button4Mask)) {
1398 modifiers |= XEMACS_MOD_BUTTON4;
1400 if (numero_de_botao != 5 && (*state & Button5Mask)) {
1401 modifiers |= XEMACS_MOD_BUTTON5;
1405 /* Ignore the Caps_Lock key if:
1406 - any other modifiers are down, so that Caps_Lock doesn't
1407 turn C-x into C-X, which would suck.
1408 - the event was a mouse event. */
1409 if (modifiers || !key_event_p) {
1410 *state &= (~LockMask);
1413 shift_p = *state & ShiftMask;
1414 lock_p = *state & LockMask;
1416 if (shift_p || lock_p) {
1417 modifiers |= XEMACS_MOD_SHIFT;
1421 XKeyEvent *ev = &x_event->xkey;
1422 /* This used to compute the frame from the given X
1423 window and store it here, but we really don't care
1425 emacs_event->channel = DEVICE_CONSOLE(d);
1426 keysym = x_to_emacs_keysym(&x_event->xkey, 0);
1428 /* If the emacs keysym is nil, then that means that the
1429 X keysym was either a Modifier or NoSymbol, which
1430 probably means that we're in the midst of reading a
1431 Multi_key sequence, or a "dead" key prefix, or XIM
1432 input. Ignore it. */
1437 /* More Caps_Lock garbage: Caps_Lock should *only* add
1438 the shift modifier to two-case keys (that is, A-Z and
1439 related characters). So at this point (after looking
1440 up the keysym) if the keysym isn't a dual-case
1441 alphabetic, and if the caps lock key was down but the
1442 shift key wasn't, then turn off the shift modifier.
1444 /* #### type lossage: assuming equivalence of emacs and
1446 /* !!#### maybe fix for Mule */
1447 if (lock_p && !shift_p &&
1448 !(CHAR_OR_CHAR_INTP(keysym)
1449 && keysym_obeys_caps_lock_p(
1450 (KeySym) XCHAR_OR_CHAR_INT(keysym), d))) {
1451 modifiers &= (~XEMACS_MOD_SHIFT);
1454 /* If this key contains two distinct keysyms, that is,
1455 "shift" generates a different keysym than the
1456 non-shifted key, then don't apply the shift modifier
1457 bit: it's implicit. Otherwise, if there would be no
1458 other way to tell the difference between the shifted
1459 and unshifted version of this key, apply the shift
1460 bit. Non-graphics, like Backspace and F1 get the
1461 shift bit in the modifiers slot. Neither the
1462 characters "a", "A", "2", nor "@" normally have the
1463 shift bit set. However, "F1" normally does. */
1464 if (modifiers & XEMACS_MOD_SHIFT) {
1465 int Mode_switch_p = *state & xd->ModeMask;
1466 KeySym bot = XLookupKeysym(ev,
1469 KeySym top = XLookupKeysym(ev,
1472 if (top && bot && top != bot) {
1488 modifiers &= ~XEMACS_MOD_SHIFT;
1493 emacs_event->event_type = key_press_event;
1494 emacs_event->timestamp = ev->time;
1495 emacs_event->event.key.modifiers = modifiers;
1496 emacs_event->event.key.keysym = keysym;
1498 /* Mouse press/release event */
1499 XButtonEvent *ev = &x_event->xbutton;
1500 struct frame *frame = x_window_to_frame(d, ev->window);
1506 XSETFRAME(emacs_event->channel, frame);
1508 emacs_event->event_type = (x_event->type == ButtonPress)
1509 ? button_press_event
1510 : button_release_event;
1512 emacs_event->event.button.modifiers = modifiers;
1513 emacs_event->timestamp = ev->time;
1514 emacs_event->event.button.button = ev->button;
1515 emacs_event->event.button.x = ev->x;
1516 emacs_event->event.button.y = ev->y;
1517 /* because we don't seem to get a FocusIn event for
1518 button clicks when a widget-glyph is selected we will
1519 assume that we want the focus if a button gets
1521 if (x_event->type == ButtonPress) {
1522 handle_focus_event_1(frame, 1);
1528 case MotionNotify: {
1529 XMotionEvent *ev = &x_event->xmotion;
1530 struct frame *frame = x_window_to_frame(d, ev->window);
1532 XMotionEvent event2;
1539 /* We use MotionHintMask, so we will get only one motion event
1540 until the next time we call XQueryPointer or the user clicks
1541 the mouse. So call XQueryPointer now (meaning that the event
1542 will be in sync with the server just before Fnext_event()
1543 returns). If the mouse is still in motion, then the server
1544 will immediately generate exactly one more motion event,
1545 which will be on the queue waiting for us next time
1548 if (XQueryPointer(event2.display, event2.window,
1549 &event2.root, &event2.subwindow,
1550 &event2.x_root, &event2.y_root,
1551 &event2.x, &event2.y, &event2.state)) {
1552 /* only one structure copy */
1555 DEVICE_X_MOUSE_TIMESTAMP(d) = ev->time;
1557 XSETFRAME(emacs_event->channel, frame);
1558 emacs_event->event_type = pointer_motion_event;
1559 emacs_event->timestamp = ev->time;
1560 emacs_event->event.motion.x = ev->x;
1561 emacs_event->event.motion.y = ev->y;
1562 if (ev->state & ShiftMask) {
1563 modifiers |= XEMACS_MOD_SHIFT;
1565 if (ev->state & ControlMask) {
1566 modifiers |= XEMACS_MOD_CONTROL;
1568 if (ev->state & xd->MetaMask) {
1569 modifiers |= XEMACS_MOD_META;
1571 if (ev->state & xd->SuperMask) {
1572 modifiers |= XEMACS_MOD_SUPER;
1574 if (ev->state & xd->HyperMask) {
1575 modifiers |= XEMACS_MOD_HYPER;
1577 if (ev->state & xd->AltMask) {
1578 modifiers |= XEMACS_MOD_ALT;
1580 if (ev->state & Button1Mask) {
1581 modifiers |= XEMACS_MOD_BUTTON1;
1583 if (ev->state & Button2Mask) {
1584 modifiers |= XEMACS_MOD_BUTTON2;
1586 if (ev->state & Button3Mask) {
1587 modifiers |= XEMACS_MOD_BUTTON3;
1589 if (ev->state & Button4Mask) {
1590 modifiers |= XEMACS_MOD_BUTTON4;
1592 if (ev->state & Button5Mask) {
1593 modifiers |= XEMACS_MOD_BUTTON5;
1595 /* Currently ignores Shift_Lock but probably shouldn't
1596 (but it definitely should ignore Caps_Lock). */
1597 emacs_event->event.motion.modifiers = modifiers;
1601 case ClientMessage: {
1602 /* Patch bogus TAKE_FOCUS messages from MWM; CurrentTime is
1603 passed as the timestamp of the TAKE_FOCUS, which the ICCCM
1604 explicitly prohibits. */
1605 XClientMessageEvent *ev = &x_event->xclient;
1607 if (ev->message_type == DEVICE_XATOM_WM_PROTOCOLS(d)
1608 && (Atom) (ev->data.l[0]) ==
1609 DEVICE_XATOM_WM_TAKE_FOCUS(d)
1610 && (Atom) (ev->data.l[1]) == 0) {
1612 DEVICE_X_LAST_SERVER_TIMESTAMP(d);
1618 /* it's a magic event */
1619 struct frame *frame;
1621 XEvent *x_event_copy = &emacs_event->event.magic.
1624 #define FROB(event_member, window_member) \
1625 x_event_copy->event_member = x_event->event_member; \
1626 w = x_event->event_member.window_member
1628 switch (x_event->type) {
1629 case SelectionRequest:
1630 FROB(xselectionrequest, owner);
1632 case SelectionClear:
1633 FROB(xselectionclear, window);
1635 case SelectionNotify:
1636 FROB(xselection, requestor);
1638 case PropertyNotify:
1639 FROB(xproperty, window);
1642 FROB(xclient, window);
1644 case ConfigureNotify:
1645 FROB(xconfigure, window);
1648 case GraphicsExpose:
1649 FROB(xexpose, window);
1657 FROB(xcrossing, window);
1661 FROB(xfocus, window);
1663 case VisibilityNotify:
1664 FROB(xvisibility, window);
1667 FROB(xcreatewindow, window);
1670 w = x_event->xany.window;
1671 *x_event_copy = *x_event;
1675 frame = x_any_window_to_frame(d, w);
1680 emacs_event->event_type = magic_event;
1681 XSETFRAME(emacs_event->channel, frame);
1689 /************************************************************************/
1690 /* magic-event handling */
1691 /************************************************************************/
1693 static void handle_focus_event_1(struct frame *f, int in_p)
1695 handle_focus_event_2(XtWindow(FRAME_X_TEXT_WIDGET(f)), f, in_p);
1698 static void handle_focus_event_2(Window win, struct frame *f, int in_p)
1700 /* Although this treats focus differently for all widgets (including
1701 the frame) it seems to work ok. */
1702 Widget needs_it = XtWindowToWidget(FRAME_X_DISPLAY(f), win);
1704 #if XtSpecificationRelease > 5
1705 widget_with_focus = XtGetKeyboardFocusWidget(FRAME_X_TEXT_WIDGET(f));
1708 XIM_focus_event(f, in_p);
1709 #endif /* HAVE_XIM */
1711 /* On focus change, clear all memory of sticky modifiers
1712 to avoid non-intuitive behavior. */
1713 clear_sticky_modifiers(XDEVICE(FRAME_DEVICE(f)));
1715 /* We don't want to handle the focus change now, because we might
1716 be in an accept-process-output, sleep-for, or sit-for. So
1719 Actually, we half handle it: we handle it as far as changing the
1720 box cursor for redisplay, but we don't call any hooks or do any
1721 select-frame stuff until after the sit-for.
1723 Unfortunately native widgets break the model because they grab
1724 the keyboard focus and nothing sets it back again. I cannot find
1725 any reasonable way to do this elsewhere so we assert here that
1726 the keyboard focus is on the emacs text widget. Menus and dialogs
1727 do this in their selection callback, but we don't want that since
1728 a button having focus is legitimate. An edit field having focus
1729 is mandatory. Weirdly you get a FocusOut event when you click in
1730 a widget-glyph but you don't get a corresponding FocusIn when you
1731 click in the frame. Why is this? */
1733 #if XtSpecificationRelease > 5
1734 && needs_it != widget_with_focus
1737 lw_set_keyboard_focus(FRAME_X_SHELL_WIDGET(f), needs_it);
1740 /* If we are focusing on a native widget then record and exit. */
1741 if (needs_it != FRAME_X_TEXT_WIDGET(f)) {
1742 widget_with_focus = needs_it;
1746 /* We have the focus now. See comment in
1747 emacs_Xt_handle_widget_losing_focus (). */
1749 widget_with_focus = NULL;
1751 /* do the generic event-stream stuff. */
1755 struct gcpro gcpro1;
1758 conser = Fcons(frm, Fcons(FRAME_DEVICE(f), in_p ? Qt : Qnil));
1760 emacs_handle_focus_change_preliminary(conser);
1761 enqueue_magic_eval_event(
1762 emacs_handle_focus_change_final, conser);
1767 /* Create a synthetic X focus event. */
1769 enqueue_focus_event(Widget wants_it, Lisp_Object frame, int in_p)
1771 Lisp_Object emacs_event = Fmake_event(Qnil, Qnil);
1772 Lisp_Event *ev = XEVENT(emacs_event);
1773 XEvent *x_event = &ev->event.magic.underlying_x_event;
1775 x_event->type = in_p ? FocusIn : FocusOut;
1776 x_event->xfocus.window = XtWindow(wants_it);
1778 ev->channel = frame;
1779 ev->event_type = magic_event;
1781 enqueue_Xt_dispatch_event(emacs_event);
1784 /* The idea here is that when a widget glyph gets unmapped we don't
1785 want the focus to stay with it if it has focus - because it may
1786 well just get deleted next and then we have lost the focus until the
1787 user does something. So handle_focus_event_1 records the widget
1788 with keyboard focus when FocusOut is processed, and then, when a
1789 widget gets unmapped, it calls this function to restore focus if
1791 void emacs_Xt_handle_widget_losing_focus(struct frame *f, Widget losing_widget);
1792 void emacs_Xt_handle_widget_losing_focus(struct frame *f, Widget losing_widget)
1794 if (losing_widget == widget_with_focus) {
1795 handle_focus_event_1(f, 1);
1799 /* This is called from the external-widget code */
1801 void emacs_Xt_handle_focus_event(XEvent * event);
1802 void emacs_Xt_handle_focus_event(XEvent * event)
1804 struct device *d = get_device_from_display(event->xany.display);
1807 if (DEVICE_X_BEING_DELETED(d))
1811 * It's curious that we're using x_any_window_to_frame() instead
1812 * of x_window_to_frame(). I don't know what the impact of this is.
1814 f = x_any_window_to_frame(d, event->xfocus.window);
1816 /* focus events are sometimes generated just before
1817 a frame is destroyed. */
1819 handle_focus_event_1(f, event->type == FocusIn);
1822 /* both MapNotify and VisibilityNotify can cause this
1823 JV is_visible has the same semantics as f->visible*/
1824 static void change_frame_visibility(struct frame *f, int is_visible)
1828 XSETFRAME(frame, f);
1830 if (!FRAME_VISIBLE_P(f) && is_visible) {
1831 FRAME_VISIBLE_P(f) = is_visible;
1832 /* This improves the double flicker when uniconifying a frame
1833 some. A lot of it is not showing a buffer which has changed
1834 while the frame was iconified. To fix it further requires
1835 the good 'ol double redisplay structure. */
1836 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
1837 va_run_hook_with_args(Qmap_frame_hook, 1, frame);
1838 } else if (FRAME_VISIBLE_P(f) && !is_visible) {
1839 FRAME_VISIBLE_P(f) = 0;
1840 va_run_hook_with_args(Qunmap_frame_hook, 1, frame);
1841 } else if (FRAME_VISIBLE_P(f) * is_visible < 0) {
1842 FRAME_VISIBLE_P(f) = -FRAME_VISIBLE_P(f);
1843 if (FRAME_REPAINT_P(f))
1844 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED(f);
1845 va_run_hook_with_args(Qmap_frame_hook, 1, frame);
1849 static void handle_map_event(struct frame *f, XEvent * event)
1853 XSETFRAME(frame, f);
1854 if (event->type == MapNotify) {
1855 XWindowAttributes xwa;
1857 /* Bleagh!!!!!! Apparently some window managers (e.g. MWM)
1858 send synthetic MapNotify events when a window is first
1859 created, EVEN IF IT'S CREATED ICONIFIED OR INVISIBLE.
1860 Or something like that. We initially tried a different
1861 solution below, but that ran into a different window-
1864 It seems that the only reliable way is to treat a
1865 MapNotify event as a "hint" that the window might or
1866 might not be visible, and check explicitly. */
1868 XGetWindowAttributes(event->xany.display, event->xmap.window,
1870 if (xwa.map_state != IsViewable) {
1871 /* Calling Fframe_iconified_p is the only way we have to
1872 correctly update FRAME_ICONIFIED_P */
1873 Fframe_iconified_p(frame);
1877 FRAME_X_TOTALLY_VISIBLE_P(f) = 1;
1879 /* Bleagh again!!!! We initially tried the following hack
1880 around the MWM problem, but it turns out that TWM
1881 has a race condition when you un-iconify, where it maps
1882 the window and then tells the server that the window
1883 is un-iconified. Usually, SXEmacs wakes up between
1884 those two occurrences, and thus thinks that un-iconified
1885 windows are still iconified.
1887 Ah, the joys of X. */
1889 /* By Emacs definition, a frame that is iconified is not
1890 visible. Marking a frame as visible will automatically cause
1891 frame-iconified-p to return nil, regardless of whether the
1892 frame is actually iconified. Therefore, we have to ignore
1893 MapNotify events on iconified frames. (It's not obvious
1894 to me why these are being sent, but it happens at startup
1895 with frames that are initially iconified; perhaps they are
1896 synthetic MapNotify events coming from the window manager.)
1897 Note that `frame-iconified-p' queries the server
1898 to determine whether the frame is currently iconified,
1899 rather than consulting some internal (and likely
1900 inaccurate) state flag. Therefore, ignoring the MapNotify
1902 if (!FRAME_VISIBLE_P(f) && NILP(Fframe_iconified_p(frame)))
1904 change_frame_visibility(f, 1);
1906 FRAME_X_TOTALLY_VISIBLE_P(f) = 0;
1907 change_frame_visibility(f, 0);
1908 /* Calling Fframe_iconified_p is the only way we have to
1909 correctly update FRAME_ICONIFIED_P */
1910 Fframe_iconified_p(frame);
1914 static void handle_client_message(struct frame *f, XEvent * event)
1916 struct device *d = XDEVICE(FRAME_DEVICE(f));
1919 XSETFRAME(frame, f);
1921 if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS(d) &&
1922 (Atom) (event->xclient.data.l[0]) ==
1923 DEVICE_XATOM_WM_DELETE_WINDOW(d)) {
1924 /* WM_DELETE_WINDOW is a misc-user event, but other
1925 ClientMessages, such as WM_TAKE_FOCUS, are eval events.
1926 That's because delete-window was probably executed with a
1927 mouse click, while the others could have been sent as a
1928 result of mouse motion or some other implicit action. (Call
1929 this a "heuristic"...) The reason for caring about this is
1930 so that clicking on the close-box will make emacs prompt
1931 using a dialog box instead of the minibuffer if there are
1934 enqueue_misc_user_event(frame, Qeval,
1935 list3(Qdelete_frame, frame, Qt));
1936 } else if (event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS(d)
1937 && (Atom) event->xclient.data.l[0] ==
1938 DEVICE_XATOM_WM_TAKE_FOCUS(d)) {
1939 handle_focus_event_1(f, 1);
1941 /* If there is a dialog box up, focus on it.
1943 #### Actually, we're raising it too, which is wrong. We should
1944 #### just focus on it, but lwlib doesn't currently give us an
1945 #### easy way to do that. This should be fixed.
1947 unsigned long take_focus_timestamp = event->xclient.data.l[1];
1948 Widget widget = lw_raise_all_pop_up_widgets();
1950 /* kludge: raise_all returns bottommost widget, but we really
1951 want the topmost. So just raise it for now. */
1952 XMapRaised(XtDisplay(widget), XtWindow(widget));
1953 /* Grab the focus with the timestamp of the TAKE_FOCUS. */
1954 XSetInputFocus(XtDisplay(widget), XtWindow(widget),
1955 RevertToParent, take_focus_timestamp);
1961 /* #### I'm struggling to understand how the X event loop really works.
1962 Here is the problem:
1964 When widgets get mapped / changed etc the actual display updates
1965 are done asynchronously via X events being processed - this
1966 normally happens when XtAppProcessEvent() gets called. However, if
1967 we are executing lisp code or even doing redisplay we won't
1968 necessarily process X events for a very long time. This has the
1969 effect of widgets only getting updated when SXEmacs only goes into
1970 idle, or some other event causes processing of the X event queue.
1972 XtAppProcessEvent can get called from the following places:
1974 emacs_Xt_next_event () - this is normal event processing, almost
1975 any non-X event will take precedence and this means that we
1976 cannot rely on it to do the right thing at the right time for
1979 drain_X_queue () - this happens when SIGIO gets tripped,
1980 processing the event queue allows C-g to be checked for. It gets
1981 called from emacs_Xt_event_pending_p ().
1983 In order to solve this I have tried introducing a list primitive -
1984 dispatch-non-command-events - which forces processing of X events
1985 related to display. Unfortunately this has a number of problems,
1986 one is that it is possible for event_stream_event_pending_p to
1987 block for ever if there isn't actually an event. I guess this can
1988 happen if we drop the synthetic event for reason. It also relies on
1989 SIGIO processing which makes things rather fragile.
1991 People have seen behaviour whereby SXEmacs blocks until you move the
1992 mouse. This seems to indicate that dispatch-non-command-events is
1993 blocking. It may be that in a SIGIO world forcing SIGIO processing
1994 does the wrong thing.
1996 static void emacs_Xt_force_event_pending(struct frame *f)
2000 Display *dpy = DEVICE_X_DISPLAY(XDEVICE(FRAME_DEVICE(f)));
2001 event.xclient.type = ClientMessage;
2002 event.xclient.display = dpy;
2003 event.xclient.message_type = XInternAtom(dpy, "BumpQueue", False);
2004 event.xclient.format = 32;
2005 event.xclient.window = 0;
2007 /* Send the drop message */
2008 XSendEvent(dpy, XtWindow(FRAME_X_SHELL_WIDGET(f)),
2009 True, NoEventMask, &event);
2010 /* We rely on SIGIO and friends to realise we have generated an
2014 static void emacs_Xt_handle_magic_event(Lisp_Event * emacs_event)
2016 /* This function can GC */
2017 XEvent *event = &emacs_event->event.magic.underlying_x_event;
2018 struct frame *f = XFRAME(EVENT_CHANNEL(emacs_event));
2020 if (!FRAME_LIVE_P(f)
2021 || DEVICE_X_BEING_DELETED(XDEVICE(FRAME_DEVICE(f))))
2024 switch (event->type) {
2025 case SelectionRequest:
2026 x_handle_selection_request(&event->xselectionrequest);
2029 case SelectionClear:
2030 x_handle_selection_clear(&event->xselectionclear);
2033 case SelectionNotify:
2034 x_handle_selection_notify(&event->xselection);
2037 case PropertyNotify:
2038 x_handle_property_notify(&event->xproperty);
2042 if (!check_for_ignored_expose
2043 (f, event->xexpose.x, event->xexpose.y,
2044 event->xexpose.width, event->xexpose.height)
2045 && !find_matching_subwindow(f, event->xexpose.x,
2047 event->xexpose.width,
2048 event->xexpose.height))
2049 x_redraw_exposed_area(f, event->xexpose.x,
2051 event->xexpose.width,
2052 event->xexpose.height);
2055 case GraphicsExpose:
2056 /* This occurs when an XCopyArea's source area was
2057 * obscured or not available. */
2058 x_redraw_exposed_area(f, event->xexpose.x, event->xexpose.y,
2059 event->xexpose.width,
2060 event->xexpose.height);
2065 handle_map_event(f, event);
2069 if (event->xcrossing.detail != NotifyInferior) {
2072 XSETFRAME(frame, f);
2073 /* FRAME_X_MOUSE_P (f) = 1; */
2074 va_run_hook_with_args(Qmouse_enter_frame_hook, 1,
2080 if (event->xcrossing.detail != NotifyInferior) {
2083 XSETFRAME(frame, f);
2084 /* FRAME_X_MOUSE_P (f) = 0; */
2085 va_run_hook_with_args(Qmouse_leave_frame_hook, 1,
2093 #ifdef EXTERNAL_WIDGET
2094 /* External widget lossage:
2095 Ben said: YUCK. The only way to make focus changes work
2096 properly is to completely ignore all FocusIn/FocusOut events
2097 and depend only on notifications from the ExternalClient
2099 if (FRAME_X_EXTERNAL_WINDOW_P(f)) {
2103 handle_focus_event_2(event->xfocus.window, f,
2104 event->type == FocusIn);
2108 handle_client_message(f, event);
2111 case VisibilityNotify:
2112 /* window visibility has changed */
2113 if (event->xvisibility.window ==
2114 XtWindow(FRAME_X_SHELL_WIDGET(f))) {
2115 FRAME_X_TOTALLY_VISIBLE_P(f) =
2116 (event->xvisibility.state == VisibilityUnobscured);
2117 /* Note that the fvwm pager only sends VisibilityNotify
2118 when changing pages. Is this all we need to do ?
2120 /* Nope. We must at least trigger a redisplay here.
2121 Since this case seems similar to MapNotify, I've
2122 factored out some code to change_frame_visibility().
2123 This triggers the necessary redisplay and runs
2124 (un)map-frame-hook. - dkindred@cs.cmu.edu */
2125 /* Changed it again to support the tristate visibility
2127 change_frame_visibility(f, (event->xvisibility.state
2129 VisibilityFullyObscured) ? 1
2134 case ConfigureNotify:
2148 /************************************************************************/
2149 /* timeout events */
2150 /************************************************************************/
2152 static int timeout_id_tick;
2154 /* Xt interval id's might not fit into an int (they're pointers, as it
2155 happens), so we need to provide a conversion list. */
2157 /* pending_timeouts is a set (unordered), implemented as a stack.
2158 completed_timeouts* is a queue. */
2159 static struct Xt_timeout {
2161 XtIntervalId interval_id;
2162 struct Xt_timeout *next;
2163 } *pending_timeouts, *completed_timeouts_head, *completed_timeouts_tail;
2165 static struct Xt_timeout_blocktype {
2166 Blocktype_declare(struct Xt_timeout);
2167 } *the_Xt_timeout_blocktype;
2169 /* called by XtAppNextEvent() */
2170 static void Xt_timeout_callback(XtPointer closure, XtIntervalId * id)
2172 struct Xt_timeout *timeout = (struct Xt_timeout *)closure;
2173 struct Xt_timeout *t2 = pending_timeouts;
2175 /* Remove this one from the set of pending timeouts */
2176 if (t2 == timeout) {
2177 pending_timeouts = pending_timeouts->next;
2179 while (t2->next && t2->next != timeout) {
2183 t2->next = t2->next->next;
2185 /* Add this one to the queue of completed timeouts */
2186 timeout->next = NULL;
2187 if (completed_timeouts_head) {
2188 completed_timeouts_tail->next = timeout;
2190 completed_timeouts_head = timeout;
2192 completed_timeouts_tail = timeout;
2195 static int emacs_Xt_add_timeout(EMACS_TIME thyme)
2197 struct Xt_timeout *timeout = Blocktype_alloc(the_Xt_timeout_blocktype);
2198 EMACS_TIME current_time;
2201 timeout->id = timeout_id_tick++;
2202 timeout->next = pending_timeouts;
2203 pending_timeouts = timeout;
2204 EMACS_GET_TIME(current_time);
2205 EMACS_SUB_TIME(thyme, thyme, current_time);
2206 milliseconds = EMACS_SECS(thyme) * 1000 + EMACS_USECS(thyme) / 1000;
2208 if (milliseconds < 1) {
2211 timeout->interval_id = XtAppAddTimeOut(Xt_app_con, milliseconds,
2212 Xt_timeout_callback,
2213 (XtPointer) timeout);
2217 #ifdef EF_USE_ASYNEQ
2218 #if 1 /* timeout based */
2219 static void Xt_watch_eq_cb(XtPointer closure, XtIntervalId *id);
2220 static int emacs_Xt_watch_event_queue(event_queue_t eq);
2221 extern void asyneq_handle_event(event_queue_t eq);
2222 extern void asyneq_handle_non_command_event(event_queue_t eq);
2225 Xt_watch_eq_cb(XtPointer closure, XtIntervalId *id)
2227 event_queue_t eq = (event_queue_t)closure;
2228 /* reestablish timeout, in case asyneq_handle_event gets to exit
2230 emacs_Xt_watch_event_queue(eq);
2231 asyneq_handle_non_command_event(eq);
2235 emacs_Xt_watch_event_queue(event_queue_t eq)
2237 int milliseconds = 10;
2238 size_t eqsz = eq_queue_size(eq)+1; /* never be 0 */
2241 while ((milliseconds*eqsz) > 100)
2247 return XtAppAddTimeOut(
2248 Xt_app_con, milliseconds, Xt_watch_eq_cb, (XtPointer)eq);
2250 #else /* work-procedure based (sets cpu on fire) */
2252 Xt_watch_eq_cb(XtPointer closure)
2254 event_queue_t eq = (event_queue_t)closure;
2255 asyneq_handle_event(eq);
2256 return FALSE; /* we never finish with this job */
2260 emacs_Xt_watch_event_queue(event_queue_t eq)
2262 return XtAppAddWorkProc(Xt_app_con, Xt_watch_eq_cb, (XtPointer)eq);
2265 #endif /* EF_USE_ASYNEQ */
2267 static void emacs_Xt_remove_timeout(int id)
2269 struct Xt_timeout *timeout, *t2;
2273 /* Find the timeout on the list of pending ones, if it's still there. */
2274 if (pending_timeouts) {
2275 if (id == pending_timeouts->id) {
2276 timeout = pending_timeouts;
2277 pending_timeouts = pending_timeouts->next;
2279 t2 = pending_timeouts;
2280 while (t2->next && t2->next->id != id)
2282 if (t2->next) { /*found it */
2284 t2->next = t2->next->next;
2287 /* if it was pending, we have removed it from the list */
2289 XtRemoveTimeOut(timeout->interval_id);
2292 /* It could be that Xt_timeout_callback was already called but we didn't
2293 convert into an Emacs event yet */
2294 if (!timeout && completed_timeouts_head) {
2295 /* Thank God for code duplication! */
2296 if (id == completed_timeouts_head->id) {
2297 timeout = completed_timeouts_head;
2298 completed_timeouts_head = completed_timeouts_head->next;
2299 /* this may not be necessary? */
2300 if (!completed_timeouts_head)
2301 completed_timeouts_tail = NULL;
2303 t2 = completed_timeouts_head;
2304 while (t2->next && t2->next->id != id)
2306 if (t2->next) { /* found it */
2308 t2->next = t2->next->next;
2310 completed_timeouts_tail = t2;
2315 /* If we found the thing on the lists of timeouts,
2316 and removed it, deallocate
2319 Blocktype_free(the_Xt_timeout_blocktype, timeout);
2324 Xt_timeout_to_emacs_event(Lisp_Event * emacs_event)
2326 struct Xt_timeout *timeout = completed_timeouts_head;
2328 completed_timeouts_head = completed_timeouts_head->next;
2329 /* probably unnecessary */
2330 if (!completed_timeouts_head) {
2331 completed_timeouts_tail = NULL;
2333 emacs_event->event_type = timeout_event;
2334 /* timeout events have nil as channel */
2335 emacs_event->timestamp = 0; /* #### wrong!! */
2336 emacs_event->event.timeout.interval_id = timeout->id;
2337 emacs_event->event.timeout.function = Qnil;
2338 emacs_event->event.timeout.object = Qnil;
2339 Blocktype_free(the_Xt_timeout_blocktype, timeout);
2342 /************************************************************************/
2343 /* process and tty events */
2344 /************************************************************************/
2346 struct what_is_ready_closure {
2352 static Lisp_Object filedesc_with_input[MAXDESC];
2353 static struct what_is_ready_closure *filedesc_to_what_closure[MAXDESC];
2355 static void init_what_input_once(void)
2360 filedesc_with_input = xnew_array(Lisp_Object, MAXDESC);
2361 filedesc_to_what_closure =
2362 xnew_array(struct what_is_ready_closure *, MAXDESC);
2365 for (i = 0; i < MAXDESC; i++) {
2366 filedesc_to_what_closure[i] = NULL;
2367 filedesc_with_input[i] = Qnil;
2370 process_events_occurred = 0;
2371 tty_events_occurred = 0;
2376 mark_what_as_being_ready(struct what_is_ready_closure *closure)
2378 if (NILP(filedesc_with_input[closure->fd])) {
2379 SELECT_TYPE temp_mask;
2380 FD_ZERO(&temp_mask);
2381 FD_SET(closure->fd, &temp_mask);
2382 /* Check to make sure there's *really* input available.
2383 Sometimes things seem to get confused and this gets called
2384 for the tty fd when there's really only input available
2385 on some process's fd. (It will subsequently get called
2386 for that process's fd, so returning without setting any
2387 flags will take care of it.) To see the problem, uncomment
2388 the stderr_out below, turn NORMAL_QUIT_CHECK_TIMEOUT_MSECS
2389 down to 25, do sh -c 'sxemacs -nw -q -f shell 2>/tmp/log'
2390 and press return repeatedly. (Seen under AIX & Linux.)
2391 -dkindred@cs.cmu.edu */
2392 if (!poll_fds_for_input(temp_mask)) {
2395 "mark_what_as_being_ready: "
2396 "no input available (fd=%d)\n",
2401 filedesc_with_input[closure->fd] = closure->what;
2402 if (PROCESSP(closure->what)) {
2403 /* Don't increment this if the current process is
2404 already marked as having input. */
2405 process_events_occurred++;
2407 tty_events_occurred++;
2414 Xt_what_callback(void *closure, int *source, XtInputId *id)
2416 /* If closure is 0, then we got a fake event from a signal handler.
2417 The only purpose of this is to make XtAppProcessEvent() stop
2420 mark_what_as_being_ready(closure);
2422 fake_event_occurred++;
2423 drain_signal_event_pipe();
2429 select_filedesc(int fd, Lisp_Object what)
2431 struct what_is_ready_closure *closure;
2433 /* If somebody is trying to select something that's already selected
2434 for, then something went wrong. The generic routines ought to
2435 detect this and error before here. */
2436 assert(!filedesc_to_what_closure[fd]);
2438 closure = xnew(struct what_is_ready_closure);
2440 closure->what = what;
2441 closure->id = XtAppAddInput(
2443 (XtPointer)(XtInputReadMask /* | XtInputExceptMask */),
2444 Xt_what_callback, closure);
2445 filedesc_to_what_closure[fd] = closure;
2450 unselect_filedesc(int fd)
2452 struct what_is_ready_closure *closure = filedesc_to_what_closure[fd];
2455 if (!NILP(filedesc_with_input[fd])) {
2456 /* We are unselecting this process before we have drained the
2457 rest of the input from it, probably from status_notify() in
2458 the command loop. This can happen like so:
2460 - We are waiting in XtAppNextEvent()
2461 - Process generates output
2462 - Process is marked as being ready
2463 - Process dies, SIGCHLD gets generated before we return (!?)
2464 It could happen I guess.
2465 - sigchld_handler() marks process as dead
2466 - Somehow we end up getting a new KeyPress event on the queue
2467 at the same time (I'm really so sure how that happens but I'm
2468 not sure it can't either so let's assume it can...).
2469 - Key events have priority so we return that
2470 instead of the proc.
2471 - Before dispatching the lisp key event we call
2473 - which deselects the process that SIGCHLD marked as dead.
2475 Thus we never remove it from _with_input and turn it into a
2476 lisp event, so we need to do it here. But this does not mean
2477 that we're throwing away the last block of output -
2478 status_notify() has already taken care of running the proc
2481 filedesc_with_input[fd] = Qnil;
2482 if (PROCESSP(closure->what)) {
2483 assert(process_events_occurred > 0);
2484 process_events_occurred--;
2486 assert(tty_events_occurred > 0);
2487 tty_events_occurred--;
2490 XtRemoveInput(closure->id);
2492 filedesc_to_what_closure[fd] = 0;
2497 emacs_Xt_select_process(Lisp_Process * p)
2499 Lisp_Object process;
2500 int infd = event_stream_unixoid_select_process(p);
2502 XSETPROCESS(process, p);
2504 select_filedesc(infd, process);
2509 emacs_Xt_unselect_process(Lisp_Process * p)
2511 int infd = event_stream_unixoid_unselect_process(p);
2514 unselect_filedesc(infd);
2519 emacs_Xt_create_stream_pair(void *inhandle, void *outhandle,
2520 Lisp_Object *instream, Lisp_Object *outstream,
2523 USID u = event_stream_unixoid_create_stream_pair(
2524 inhandle, outhandle, instream, outstream, flags);
2525 if (u != USID_ERROR) {
2532 emacs_Xt_delete_stream_pair(Lisp_Object instream, Lisp_Object outstream)
2534 event_stream_unixoid_delete_stream_pair(instream, outstream);
2535 return USID_DONTHASH;
2538 /* This is called from GC when a process object is about to be freed.
2539 If we've still got pointers to it in this file, we're gonna lose hard.
2541 void debug_process_finalization(Lisp_Process * p)
2545 Lisp_Object instr, outstr;
2547 get_process_streams(p, &instr, &outstr);
2548 /* if it still has fds, then it hasn't been killed yet. */
2549 assert(NILP(instr));
2550 assert(NILP(outstr));
2551 /* Better not still be in the "with input" table; we know it's got no fds. */
2552 for (i = 0; i < MAXDESC; i++) {
2553 Lisp_Object process = filedesc_fds_with_input[i];
2554 assert(!PROCESSP(process) || XPROCESS(process) != p);
2561 Xt_process_to_emacs_event(Lisp_Event * emacs_event)
2565 assert(process_events_occurred > 0);
2567 for (i = 0; i < MAXDESC; i++) {
2568 Lisp_Object process = filedesc_with_input[i];
2569 if (PROCESSP(process)) {
2570 filedesc_with_input[i] = Qnil;
2571 process_events_occurred--;
2572 /* process events have nil as channel */
2573 emacs_event->event_type = process_event;
2574 emacs_event->timestamp = 0; /* #### */
2575 emacs_event->event.process.process = process;
2583 emacs_Xt_select_console(struct console *con)
2585 Lisp_Object console;
2588 if (CONSOLE_X_P(con)) {
2589 /* X consoles are automatically selected for when we
2590 initialize them in Xt */
2593 infd = event_stream_unixoid_select_console(con);
2594 XSETCONSOLE(console, con);
2596 select_filedesc(infd, console);
2601 emacs_Xt_unselect_console(struct console *con)
2603 Lisp_Object console;
2606 if (CONSOLE_X_P(con)) {
2607 /* X consoles are automatically selected for when we
2608 initialize them in Xt */
2611 infd = event_stream_unixoid_unselect_console(con);
2612 XSETCONSOLE(console, con);
2614 unselect_filedesc(infd);
2618 /* read an event from a tty, if one is available. Returns non-zero
2619 if an event was available. Note that when this function is
2620 called, there should always be a tty marked as ready for input.
2621 However, the input condition might actually be EOF, so there
2622 may not really be any input available. (In this case,
2623 read_event_from_tty_or_stream_desc() will arrange for the TTY device
2627 Xt_tty_to_emacs_event(Lisp_Event * emacs_event)
2631 assert(tty_events_occurred > 0);
2632 for (i = 0; i < MAXDESC; i++) {
2633 Lisp_Object console = filedesc_with_input[i];
2634 if (CONSOLEP(console)) {
2635 assert(tty_events_occurred > 0);
2636 tty_events_occurred--;
2637 filedesc_with_input[i] = Qnil;
2638 if (read_event_from_tty_or_stream_desc(
2639 emacs_event, XCONSOLE(console), i)) {
2648 /************************************************************************/
2649 /* debugging functions to decipher an event */
2650 /************************************************************************/
2652 #ifdef DEBUG_SXEMACS
2653 #include "xintrinsicp.h" /* only describe_event() needs this */
2654 #include <X11/Xproto.h> /* only describe_event() needs this */
2656 static void describe_event_window(Window window, Display * display)
2660 stderr_out(" window: 0x%lx", (unsigned long)window);
2661 w = XtWindowToWidget(display, window);
2663 stderr_out(" %s", w->core.widget_class->core_class.class_name);
2664 f = x_any_window_to_frame(get_device_from_display(display), window);
2666 int len = XSTRING_LENGTH(f->name) + 4;
2669 int sz = snprintf(buf, len, " \"%s\"", XSTRING_DATA(f->name));
2670 assert(sz >= 0 && sz < len);
2671 write_string_to_stdio_stream(stderr, 0, (Bufbyte*)buf, 0,
2677 static const char *XEvent_mode_to_string(int mode)
2686 case NotifyWhileGrabbed:
2687 return "WhileGrabbed";
2693 static const char *XEvent_detail_to_string(int detail)
2696 case NotifyAncestor:
2698 case NotifyInferior:
2700 case NotifyNonlinear:
2702 case NotifyNonlinearVirtual:
2703 return "NonlinearVirtual";
2706 case NotifyPointerRoot:
2707 return "PointerRoot";
2708 case NotifyDetailNone:
2709 return "DetailNone";
2715 static const char *XEvent_visibility_to_string(int state)
2718 case VisibilityFullyObscured:
2719 return "FullyObscured";
2720 case VisibilityPartiallyObscured:
2721 return "PartiallyObscured";
2722 case VisibilityUnobscured:
2723 return "Unobscured";
2729 static void describe_event(XEvent * event)
2732 struct device *d = get_device_from_display(event->xany.display);
2734 int sz = snprintf(buf, sizeof(buf),
2735 "%s%s", x_event_name(event->type),
2736 event->xany.send_event ? " (send)" : "");
2737 assert(sz >= 0 && sz < sizeof(buf));
2738 stderr_out("%-30s", buf);
2739 switch (event->type) {
2742 XFocusChangeEvent *ev = &event->xfocus;
2743 describe_event_window(ev->window, ev->display);
2744 stderr_out(" mode: %s\n",
2745 XEvent_mode_to_string(ev->mode));
2746 stderr_out(" detail: %s\n",
2747 XEvent_detail_to_string(ev->detail));
2752 XKeyEvent *ev = &event->xkey;
2753 unsigned int state = ev->state;
2755 describe_event_window(ev->window, ev->display);
2756 stderr_out(" subwindow: %ld\n", ev->subwindow);
2757 stderr_out(" state: ");
2758 /* Complete list of modifier key masks */
2759 if (state & ShiftMask)
2760 stderr_out("Shift ");
2761 if (state & LockMask)
2762 stderr_out("Lock ");
2763 if (state & ControlMask)
2764 stderr_out("Control ");
2765 if (state & Mod1Mask)
2766 stderr_out("Mod1 ");
2767 if (state & Mod2Mask)
2768 stderr_out("Mod2 ");
2769 if (state & Mod3Mask)
2770 stderr_out("Mod3 ");
2771 if (state & Mod4Mask)
2772 stderr_out("Mod4 ");
2773 if (state & Mod5Mask)
2774 stderr_out("Mod5 ");
2777 stderr_out("vanilla\n");
2780 if (x_key_is_modifier_p(ev->keycode, d))
2781 stderr_out(" Modifier key");
2782 stderr_out(" keycode: 0x%x\n", ev->keycode);
2787 if (debug_x_events > 1) {
2788 XExposeEvent *ev = &event->xexpose;
2789 describe_event_window(ev->window, ev->display);
2790 stderr_out(" region: x=%d y=%d width=%d height=%d\n",
2791 ev->x, ev->y, ev->width, ev->height);
2792 stderr_out(" count: %d\n", ev->count);
2798 case GraphicsExpose:
2799 if (debug_x_events > 1) {
2800 XGraphicsExposeEvent *ev = &event->xgraphicsexpose;
2801 describe_event_window(ev->drawable, ev->display);
2802 stderr_out(" major: %s\n",
2803 (ev->major_code == X_CopyArea ? "CopyArea" :
2805 X_CopyPlane ? "CopyPlane" : "?")));
2806 stderr_out(" region: x=%d y=%d width=%d height=%d\n",
2807 ev->x, ev->y, ev->width, ev->height);
2808 stderr_out(" count: %d\n", ev->count);
2816 if (debug_x_events > 1) {
2817 XCrossingEvent *ev = &event->xcrossing;
2818 describe_event_window(ev->window, ev->display);
2820 stderr_out(" subwindow: 0x%x\n", ev->subwindow);
2821 stderr_out(" pos: %d %d\n", ev->x, ev->y);
2822 stderr_out(" root pos: %d %d\n", ev->x_root,
2825 stderr_out(" mode: %s\n",
2826 XEvent_mode_to_string(ev->mode));
2827 stderr_out(" detail: %s\n",
2828 XEvent_detail_to_string(ev->detail));
2829 stderr_out(" focus: %d\n", ev->focus);
2831 stderr_out(" state: 0x%x\n", ev->state);
2838 case ConfigureNotify:
2839 if (debug_x_events > 1) {
2840 XConfigureEvent *ev = &event->xconfigure;
2841 describe_event_window(ev->window, ev->display);
2842 stderr_out(" above: 0x%lx\n", ev->above);
2843 stderr_out(" size: %d %d %d %d\n", ev->x, ev->y,
2844 ev->width, ev->height);
2845 stderr_out(" redirect: %d\n", ev->override_redirect);
2851 case VisibilityNotify:
2852 if (debug_x_events > 1) {
2853 XVisibilityEvent *ev = &event->xvisibility;
2854 describe_event_window(ev->window, ev->display);
2855 stderr_out(" state: %s\n",
2856 XEvent_visibility_to_string(ev->state));
2862 case ClientMessage: {
2863 XClientMessageEvent *ev = &event->xclient;
2864 char *name = XGetAtomName(ev->display, ev->message_type);
2865 stderr_out("%s", name);
2866 if (!strcmp(name, "WM_PROTOCOLS")) {
2868 XGetAtomName(ev->display, ev->data.l[0]);
2869 stderr_out("(%s)", protname);
2885 #endif /* include describe_event definition */
2887 /************************************************************************/
2888 /* get the next event from Xt */
2889 /************************************************************************/
2891 static Lisp_Object dispatch_event_queue, dispatch_event_queue_tail;
2893 void enqueue_Xt_dispatch_event(Lisp_Object event)
2895 enqueue_event(event, &dispatch_event_queue, &dispatch_event_queue_tail);
2898 static Lisp_Object dequeue_Xt_dispatch_event(void)
2900 return dequeue_event(&dispatch_event_queue, &dispatch_event_queue_tail);
2903 /* This business exists because menu events "happen" when
2904 menubar_selection_callback() is called from somewhere deep
2905 within XtAppProcessEvent in emacs_Xt_next_event(). The
2906 callback needs to terminate the modal loop in that function
2907 or else it will continue waiting until another event is
2910 Same business applies to scrollbar events. */
2913 signal_special_Xt_user_event(Lisp_Object channel, Lisp_Object function,
2916 Lisp_Object event = Fmake_event(Qnil, Qnil);
2918 XEVENT(event)->event_type = misc_user_event;
2919 XEVENT(event)->channel = channel;
2920 XEVENT(event)->event.eval.function = function;
2921 XEVENT(event)->event.eval.object = object;
2923 enqueue_Xt_dispatch_event(event);
2926 static void emacs_Xt_next_event(Lisp_Event * emacs_event)
2928 we_didnt_get_an_event:
2930 while (NILP(dispatch_event_queue) &&
2931 !completed_timeouts_head &&
2932 !fake_event_occurred &&
2933 !process_events_occurred && !tty_events_occurred) {
2935 /* Stupid logic in XtAppProcessEvent() dictates that, if process
2936 events and X events are both available, the process event
2937 gets taken first. This will cause an infinite loop if we're
2938 being called from Fdiscard_input().
2940 if (XtAppPending(Xt_app_con) & XtIMXEvent) {
2941 XtAppProcessEvent(Xt_app_con, XtIMXEvent);
2943 Lisp_Object devcons, concons;
2945 /* We're about to block. Xt has a bug in it (big
2946 surprise, there) in that it blocks using select() and
2947 doesn't flush the Xlib output buffers (XNextEvent()
2948 does this automatically before blocking). So it's
2949 necessary for us to do this ourselves. If we don't
2950 do it, then display output may not be seen until the
2951 next time an X event is received. (This happens
2952 esp. with subprocess output that gets sent to a
2955 #### The above comment may not have any validity. */
2957 DEVICE_LOOP_NO_BREAK(devcons, concons) {
2959 d = XDEVICE(XCAR(devcons));
2961 if (DEVICE_X_P(d) && DEVICE_X_DISPLAY(d)) {
2962 /* emacs may be exiting */
2963 XFlush(DEVICE_X_DISPLAY(d));
2966 XtAppProcessEvent(Xt_app_con, XtIMAll);
2970 if (!NILP(dispatch_event_queue)) {
2971 Lisp_Object event, event2;
2972 XSETEVENT(event2, emacs_event);
2973 event = dequeue_Xt_dispatch_event();
2974 Fcopy_event(event, event2);
2975 Fdeallocate_event(event);
2976 } else if (tty_events_occurred) {
2977 if (!Xt_tty_to_emacs_event(emacs_event))
2978 goto we_didnt_get_an_event;
2979 } else if (completed_timeouts_head) {
2980 Xt_timeout_to_emacs_event(emacs_event);
2981 } else if (fake_event_occurred) {
2982 /* A dummy event, so that a cycle of the command loop will occur. */
2983 fake_event_occurred = 0;
2984 /* eval events have nil as channel */
2985 emacs_event->event_type = eval_event;
2986 emacs_event->event.eval.function = Qidentity;
2987 emacs_event->event.eval.object = Qnil;
2989 /* if (process_events_occurred) */
2990 Xt_process_to_emacs_event(emacs_event);
2993 /* No need to call XFilterEvent; Xt does it for us */
2997 emacs_Xt_event_handler(Widget SXE_UNUSED(wid),
2998 XtPointer SXE_UNUSED(closure),
3000 Boolean * SXE_UNUSED(continue_to_dispatch))
3002 Lisp_Object emacs_event = Fmake_event(Qnil, Qnil);
3004 #ifdef DEBUG_SXEMACS
3005 if (debug_x_events > 0) {
3006 describe_event(event);
3008 #endif /* DEBUG_SXEMACS */
3009 if (x_event_to_emacs_event(event, XEVENT(emacs_event))) {
3010 enqueue_Xt_dispatch_event(emacs_event);
3012 Fdeallocate_event(emacs_event);
3016 /************************************************************************/
3017 /* input pending / C-g checking */
3018 /************************************************************************/
3021 quit_char_predicate(Display * display, XEvent * event, XPointer data)
3023 struct device *d = get_device_from_display(display);
3024 struct x_device *xd = DEVICE_X_DATA(d);
3026 Bool *critical = (Bool *) data;
3032 if ((event->type != KeyPress) ||
3033 (!x_any_window_to_frame(d, event->xany.window)) ||
3035 & (xd->MetaMask | xd->HyperMask | xd->SuperMask | xd->AltMask))) {
3039 /* This duplicates some code that exists elsewhere, but it's relatively
3040 fast and doesn't cons. */
3041 keysym = x_to_emacs_keysym(&event->xkey, 1);
3045 if (CHAR_OR_CHAR_INTP(keysym)) {
3046 c = XCHAR_OR_CHAR_INT(keysym);
3047 } else if (EQ(keysym, QKbackspace)) {
3048 /* Highly doubtful that these are the quit character, but... */
3050 } else if (EQ(keysym, QKtab)) {
3052 } else if (EQ(keysym, QKlinefeed)) {
3054 } else if (EQ(keysym, QKreturn)) {
3056 } else if (EQ(keysym, QKescape)) {
3058 } else if (EQ(keysym, QKspace)) {
3060 } else if (EQ(keysym, QKdelete)) {
3066 if (event->xkey.state & xd->MetaMask) {
3069 if ((event->xkey.state & ControlMask) && !(c >= 'A' && c <= 'Z')) {
3070 /* unshifted control characters */
3073 quit_char = CONSOLE_QUIT_CHAR(XCONSOLE(DEVICE_CONSOLE(d)));
3074 if (c == quit_char) {
3077 /* If we've got Control-Shift-G instead of Control-G, that means
3078 we have a critical_quit. Caps_Lock is its own modifier, so it
3079 won't cause ^G to act differently than before. */
3080 if (event->xkey.state & ControlMask) {
3083 if (c == quit_char) {
3092 /* This scans the X input queue for a KeyPress event that matches the
3093 quit character, and sets Vquit_flag. This is called from the
3094 QUIT macro to determine whether we should quit.
3096 In a SIGIO world, this won't be called unless a SIGIO has happened
3097 since the last time we checked.
3099 In a non-SIGIO world, this is called from emacs_Xt_event_pending_p
3100 (which is called from input_pending_p).
3103 x_check_for_quit_char(Display * display)
3107 Bool critical_quit = False;
3109 XEventsQueued(display, QueuedAfterReading);
3110 queued = XCheckIfEvent(display, &event,
3111 quit_char_predicate, (char *)&critical_quit);
3113 Vquit_flag = (critical_quit ? Qcritical : Qt);
3114 /* don't put the event back onto the queue. Those functions that
3115 wanted to read a ^G directly have arranged to do this. */
3120 check_for_tty_quit_char(struct device *d)
3122 SELECT_TYPE temp_mask;
3123 int infd = DEVICE_INFD(d);
3124 struct console *con = XCONSOLE(DEVICE_CONSOLE(d));
3125 Emchar quit_char = CONSOLE_QUIT_CHAR(con);
3127 FD_ZERO(&temp_mask);
3128 FD_SET(infd, &temp_mask);
3134 if (!poll_fds_for_input(temp_mask)) {
3138 event = Fmake_event(Qnil, Qnil);
3139 if (!read_event_from_tty_or_stream_desc
3140 (XEVENT(event), con, infd)) {
3141 /* EOF, or something ... */
3144 /* #### bogus. quit-char should be allowed to be any sort
3146 the_char = event_to_character(XEVENT(event), 1, 0, 0);
3147 if (the_char >= 0 && the_char == quit_char) {
3149 /* do not queue the C-g. See above. */
3153 /* queue the read event to be read for real later. */
3154 enqueue_Xt_dispatch_event(event);
3158 static void emacs_Xt_quit_p(void)
3160 Lisp_Object devcons, concons;
3161 CONSOLE_LOOP(concons) {
3162 struct console *con = XCONSOLE(XCAR(concons));
3163 if (!con->input_enabled) {
3167 CONSOLE_DEVICE_LOOP(devcons, con) {
3169 d = XDEVICE(XCAR(devcons));
3171 if (DEVICE_X_P(d) && DEVICE_X_DISPLAY(d)) {
3172 /* emacs may be exiting */
3173 x_check_for_quit_char(DEVICE_X_DISPLAY(d));
3174 } else if (DEVICE_TTY_P(d)) {
3175 check_for_tty_quit_char(d);
3181 static void drain_X_queue(void)
3183 Lisp_Object devcons, concons;
3184 CONSOLE_LOOP(concons) {
3185 struct console *con = XCONSOLE(XCAR(concons));
3186 if (!con->input_enabled) {
3190 /* sjt sez: Have you tried the loop over devices with
3191 XtAppPending(), not XEventsQueued()?
3192 Ben Sigelman sez: No.
3193 sjt sez: I'm guessing that the reason that your patch
3198 + d = XDEVICE (XCAR (devcons));
3199 + if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d)) {
3201 Ie, if the device goes down, SXEmacs detects that and deletes
3202 it. Then the if() fails (DEVICE_X_DISPLAY(d) is NULL), and
3203 we don't go into the Xlib-of-no-return. If you know
3204 different, I'd like to hear about it. ;-)
3206 These ideas haven't been tested; the code below works for
3209 CONSOLE_DEVICE_LOOP(devcons, con) {
3212 d = XDEVICE(XCAR(devcons));
3213 if (DEVICE_X_P(d) && DEVICE_X_DISPLAY(d)) {
3214 display = DEVICE_X_DISPLAY(d);
3215 while (XEventsQueued
3216 (display, QueuedAfterReading)) {
3217 XtAppProcessEvent(Xt_app_con,
3223 /* This is the old code, before Ben Sigelman's patch. */
3225 while (XtAppPending (Xt_app_con) & XtIMXEvent)
3226 XtAppProcessEvent (Xt_app_con, XtIMXEvent);
3231 emacs_Xt_event_pending_p(int user_p)
3236 /* If `user_p' is false, then this function returns whether there are any
3237 X, timeout, or fd events pending (that is, whether emacs_Xt_next_event()
3238 would return immediately without blocking).
3240 if `user_p' is true, then this function returns whether there are any
3241 *user generated* events available (that is, whether there are keyboard
3242 or mouse-click events ready to be read). This also implies that
3243 emacs_Xt_next_event() would not block.
3245 In a non-SIGIO world, this also checks whether the user has typed ^G,
3246 since this is a convenient place to do so. We don't need to do this
3247 in a SIGIO world, since input causes an interrupt.
3251 /* I don't think there's any point to this and it will nullify
3252 the speed gains achieved by the sigio_happened checking below.
3253 Its only advantage is that it may possibly make C-g response
3254 a bit faster. The C-g will be noticed within 0.25 second, anyway,
3255 even without this. */
3257 /* First check for C-g if necessary */
3262 /* This function used to simply check whether there were any X
3263 events (or if user_p was 1, it iterated over all the pending
3264 X events using XCheckIfEvent(), looking for keystrokes and
3265 button events). That worked in the old cheesoid event loop,
3266 which didn't go through XtAppDispatchEvent(), but it doesn't
3267 work any more -- X events may not result in anything. For
3268 example, a button press in a blank part of the menubar appears
3269 as an X event but will not result in any Emacs events (a
3270 button press that activates the menubar results in an Emacs
3271 event through the stop_next_event mechanism).
3273 The only accurate way of determining whether these X events
3274 translate into Emacs events is to go ahead and dispatch them
3275 until there's something on the dispatch queue. */
3277 /* See if there are any user events already on the queue. */
3278 EVENT_CHAIN_LOOP(event, dispatch_event_queue) {
3279 if (!user_p || command_event_p(event)) {
3284 /* See if there's any TTY input available.
3286 if (poll_fds_for_input(tty_only_mask)) {
3291 /* If not user_p and there are any timer or file-desc events
3292 pending, we know there will be an event so we're through. */
3293 XtInputMask pending_value;
3295 /* Note that formerly we just checked the value of
3296 XtAppPending() to determine if there was file-desc input.
3297 This doesn't work any more with the signal_event_pipe;
3298 XtAppPending() will says "yes" in this case but there isn't
3299 really any input. Another way of fixing this problem is for
3300 the signal_event_pipe to generate actual input in the form of
3301 an identity eval event or something. (#### maybe this
3302 actually happens?) */
3304 if (poll_fds_for_input(process_only_mask)) {
3307 pending_value = XtAppPending(Xt_app_con);
3309 if (pending_value & XtIMTimer) {
3314 /* XtAppPending() can be super-slow, esp. over a network connection.
3315 Quantify results have indicated that in some cases the
3316 call to detect_input_pending() completely dominates the
3317 running time of redisplay(). Fortunately, in a SIGIO world
3318 we can more quickly determine whether there are any X events:
3319 if an event has happened since the last time we checked, then
3320 a SIGIO will have happened. On a machine with broken SIGIO,
3321 we'll still be in an OK state -- the sigio_happened flag
3322 will get set at least once a second, so we'll be no more than
3323 one second behind reality. (In general it's OK if we
3324 erroneously report no input pending when input is actually
3325 pending() -- preemption is just a bit less efficient, that's
3326 all. It's bad bad bad if you err the other way -- you've
3327 promised that `next-event' won't block but it actually will,
3328 and some action might get delayed until the next time you
3332 /* quit_check_signal_tick_count is volatile so try to avoid race
3333 conditions by using a temporary variable */
3334 tick_count_val = quit_check_signal_tick_count;
3335 if (last_quit_check_signal_tick_count != tick_count_val
3336 #if !defined (SIGIO)
3337 || (XtIMXEvent & XtAppPending(Xt_app_con))
3340 last_quit_check_signal_tick_count = tick_count_val;
3342 /* We need to drain the entire queue now -- if we only
3343 drain part of it, we may later on end up with events
3344 actually pending but detect_input_pending() returning
3345 false because there wasn't another SIGIO. */
3348 EVENT_CHAIN_LOOP(event, dispatch_event_queue) {
3349 if (!user_p || command_event_p(event)) {
3359 emacs_Xt_current_event_timestamp(struct console *c)
3362 Lisp_Object devs = CONSOLE_DEVICE_LIST(c);
3367 struct device *d = XDEVICE(XCAR(devs));
3368 return DEVICE_X_LAST_SERVER_TIMESTAMP(d);
3372 /************************************************************************/
3373 /* replacement for standard string-to-pixel converter */
3374 /************************************************************************/
3376 /* This was constructed by ripping off the standard string-to-pixel
3377 converter from Converters.c in the Xt source code and modifying
3382 /* This is exported by the Xt library (at least by mine). If this
3383 isn't the case somewhere, rename this appropriately and remove
3384 the '#if 0'. Note, however, that I got "unknown structure"
3385 errors when I tried this. */
3386 XtConvertArgRec Const colorConvertArgs[] = {
3387 {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.screen),
3390 {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.colormap),
3396 #define done(type, value) \
3397 if (toVal->addr != NULL) { \
3398 if (toVal->size < sizeof(type)) { \
3399 toVal->size = sizeof(type); \
3402 *(type*)(toVal->addr) = (value); \
3404 static type static_val; \
3405 static_val = (value); \
3406 toVal->addr = (XPointer)&static_val; \
3408 toVal->size = sizeof(type); \
3409 return True /* Caller supplies `;' */
3411 /* JH: We use this because I think there's a possibility this
3412 is called before the device is properly set up, in which case
3413 I don't want to abort. */
3414 extern struct device *get_device_from_display_1(Display * dpy);
3417 Boolean EmacsXtCvtStringToPixel(Display * dpy,
3419 Cardinal * num_args,
3420 XrmValuePtr fromVal,
3421 XrmValuePtr toVal, XtPointer * closure_ret)
3423 String str = (String) fromVal->addr;
3432 Cardinal num_params = 1;
3433 XtAppContext the_app_con = XtDisplayToApplicationContext(dpy);
3435 if (*num_args != 2) {
3436 XtAppWarningMsg(the_app_con, "wrongParameters",
3437 "cvtStringToPixel", "XtToolkitError",
3438 "String to pixel conversion needs "
3439 "screen and colormap arguments",
3440 (String *) NULL, (Cardinal *) NULL);
3444 screen = *((Screen **) args[0].addr);
3445 colormap = *((Colormap *) args[1].addr);
3447 /* The original uses the private function CompareISOLatin1().
3448 Use XmuCompareISOLatin1() if you want, but I don't think it
3449 makes any difference here. */
3450 if (strcmp(str, XtDefaultBackground) == 0) {
3451 *closure_ret = False;
3452 /* This refers to the display's "*reverseVideo" resource.
3453 These display resources aren't documented anywhere that
3454 I can find, so I'm going to ignore this. */
3455 /* if (pd->rv) done(Pixel, BlackPixelOfScreen(screen)) else */
3456 done(Pixel, WhitePixelOfScreen(screen));
3458 if (strcmp(str, XtDefaultForeground) == 0) {
3459 *closure_ret = False;
3460 /* if (pd->rv) done(Pixel, WhitePixelOfScreen(screen)) else */
3461 done(Pixel, BlackPixelOfScreen(screen));
3464 /* Originally called XAllocNamedColor() here. */
3465 if ((d = get_device_from_display_1(dpy))) {
3466 visual = DEVICE_X_VISUAL(d);
3467 if (colormap != DEVICE_X_COLORMAP(d)) {
3468 XtAppWarningMsg(the_app_con, "weirdColormap",
3469 "cvtStringToPixel", "XtToolkitWarning",
3470 "The colormap passed to "
3471 "cvtStringToPixel doesn't match the "
3472 "one registered to the device.\n",
3474 status = XAllocNamedColor(dpy, colormap, (char *)str,
3475 &screenColor, &exactColor);
3477 status = XParseColor(dpy, colormap, (char *)str,
3480 status = allocate_nearest_color(
3481 dpy, colormap, visual, &screenColor);
3485 /* We haven't set up this device totally yet, so just punt */
3486 status = XAllocNamedColor(dpy, colormap, (char *)str,
3487 &screenColor, &exactColor);
3491 /* Server returns a specific error code but Xlib discards it.
3493 if (XLookupColor(DisplayOfScreen(screen), colormap, (char*)str,
3494 &exactColor, &screenColor)) {
3495 XtAppWarningMsg(the_app_con, "noColormap",
3496 "cvtStringToPixel", "XtToolkitError",
3497 "Cannot allocate colormap entry for "
3499 params, &num_params);
3502 XtAppWarningMsg(the_app_con, "badValue",
3503 "cvtStringToPixel", "XtToolkitError",
3504 "Color name \"%s\" is not defined",
3505 params, &num_params);
3508 *closure_ret = False;
3511 *closure_ret = (char *)True;
3512 done(Pixel, screenColor.pixel);
3517 static void EmacsFreePixel(XtAppContext app,
3520 XrmValuePtr args, Cardinal * num_args)
3522 if (*num_args != 2) {
3523 XtAppWarningMsg(app, "wrongParameters", "freePixel",
3525 "Freeing a pixel requires screen and "
3526 "colormap arguments",
3527 (String *) NULL, (Cardinal *) NULL);
3532 Screen *screen = *((Screen **) args[0].addr);
3533 Colormap colormap = *((Colormap *) args[1].addr);
3534 XFreeColors(DisplayOfScreen(screen), colormap,
3535 (unsigned long *)toVal->addr, 1, (unsigned long)0);
3539 /************************************************************************/
3540 /* handle focus changes for native widgets */
3541 /************************************************************************/
3543 emacs_Xt_event_widget_focus_in(Widget w,
3545 String * params, Cardinal * num_params)
3548 x_any_widget_or_parent_to_frame(get_device_from_display
3549 (event->xany.display), w);
3551 XtSetKeyboardFocus(FRAME_X_SHELL_WIDGET(f), w);
3555 emacs_Xt_event_widget_focus_out(Widget w,
3557 String * params, Cardinal * num_params)
3561 static XtActionsRec widgetActionsList[] = {
3562 {"widget-focus-in", emacs_Xt_event_widget_focus_in},
3563 {"widget-focus-out", emacs_Xt_event_widget_focus_out},
3567 emacs_Xt_event_add_widget_actions(XtAppContext ctx)
3569 XtAppAddActions(ctx, widgetActionsList, 2);
3572 /************************************************************************/
3573 /* initialization */
3574 /************************************************************************/
3575 static struct event_stream _Xt_event_stream = {
3576 .event_pending_p = emacs_Xt_event_pending_p,
3577 .force_event_pending = emacs_Xt_force_event_pending,
3578 .next_event_cb = emacs_Xt_next_event,
3579 .handle_magic_event_cb = emacs_Xt_handle_magic_event,
3580 .add_timeout_cb = emacs_Xt_add_timeout,
3581 .remove_timeout_cb = emacs_Xt_remove_timeout,
3582 .select_console_cb = emacs_Xt_select_console,
3583 .unselect_console_cb = emacs_Xt_unselect_console,
3584 .select_process_cb = emacs_Xt_select_process,
3585 .unselect_process_cb = emacs_Xt_unselect_process,
3586 .quit_p_cb = emacs_Xt_quit_p,
3587 .create_stream_pair_cb = emacs_Xt_create_stream_pair,
3588 .delete_stream_pair_cb = emacs_Xt_delete_stream_pair,
3589 .current_event_timestamp_cb = emacs_Xt_current_event_timestamp,
3592 void syms_of_event_Xt(void)
3594 defsymbol(&Qkey_mapping, "key-mapping");
3595 defsymbol(&Qsans_modifiers, "sans-modifiers");
3596 defsymbol(&Qself_insert_command, "self-insert-command");
3599 void reinit_vars_of_event_Xt(void)
3601 Xt_event_stream = &_Xt_event_stream;
3602 the_Xt_timeout_blocktype = Blocktype_new(struct Xt_timeout_blocktype);
3604 last_quit_check_signal_tick_count = 0;
3606 /* this function only makes safe calls */
3607 init_what_input_once();
3611 void vars_of_event_Xt(void)
3613 reinit_vars_of_event_Xt();
3615 dispatch_event_queue = Qnil;
3616 staticpro(&dispatch_event_queue);
3617 dispatch_event_queue_tail = Qnil;
3618 dump_add_root_object(&dispatch_event_queue_tail);
3620 DEFVAR_BOOL("x-allow-sendevents", &x_allow_sendevents /*
3621 *Non-nil means to allow synthetic events. Nil means they are ignored.
3622 Beware: allowing emacs to process SendEvents opens a big security hole.
3624 x_allow_sendevents = 0;
3626 #ifdef DEBUG_SXEMACS
3627 DEFVAR_INT("debug-x-events", &debug_x_events /*
3628 If non-zero, display debug information about X events that SXEmacs sees.
3629 Information is displayed on stderr. Currently defined values are:
3631 1 == non-verbose output
3638 /* This mess is a hack that patches the shell widget to treat visual
3639 inheritance the same as colormap and depth inheritance */
3641 static XtInitProc orig_shell_init_proc;
3644 ShellVisualPatch(Widget wanted, Widget new,
3645 ArgList args, Cardinal * num_args)
3648 ShellWidget w = (ShellWidget) new;
3650 /* first, call the original setup */
3651 (*orig_shell_init_proc) (wanted, new, args, num_args);
3653 /* if the visual isn't explicitly set, grab it from the nearest shell
3655 if (w->shell.visual == CopyFromParent) {
3657 while (p && !XtIsShell(p)) {
3661 w->shell.visual = ((ShellWidget) p)->shell.visual;
3666 void init_event_Xt_late(void)
3668 /* called when already initialized */
3669 timeout_id_tick = 1;
3670 pending_timeouts = NULL;
3671 completed_timeouts_head = NULL; /* queue is empty */
3672 completed_timeouts_tail = NULL; /* just to be picky */
3674 event_stream = Xt_event_stream;
3676 #if defined(HAVE_XIM) || defined(USE_XFONTSET)
3677 Initialize_Locale();
3678 #endif /* HAVE_XIM || USE_XFONTSET */
3680 XtToolkitInitialize();
3681 Xt_app_con = XtCreateApplicationContext();
3682 XtAppSetFallbackResources(Xt_app_con, (String*)x_fallback_resources);
3685 x_selection_timeout = (XtAppGetSelectionTimeout(Xt_app_con) / 1000);
3686 XSetErrorHandler(x_error_handler);
3687 XSetIOErrorHandler(x_IO_error_handler);
3689 XtAppAddInput(Xt_app_con, signal_event_pipe[0],
3690 (XtPointer) (XtInputReadMask /* | XtInputExceptMask */ ),
3691 Xt_what_callback, 0);
3693 XtAppSetTypeConverter(Xt_app_con, XtRString, XtRPixel,
3694 EmacsXtCvtStringToPixel,
3695 (XtConvertArgList)colorConvertArgs,
3696 2, XtCacheByDisplay, EmacsFreePixel);
3699 XtAppSetTypeConverter(Xt_app_con, XtRString, XtRXimStyles,
3700 EmacsXtCvtStringToXIMStyles,
3701 NULL, 0, XtCacheByDisplay, EmacsFreeXIMStyles);
3702 #endif /* XIM_XLIB */
3703 /* Add extra actions to native widgets to handle focus and friends. */
3704 emacs_Xt_event_add_widget_actions(Xt_app_con);
3706 /* insert the visual inheritance patch/hack described above */
3707 orig_shell_init_proc = shellClassRec.core_class.initialize;
3708 shellClassRec.core_class.initialize = ShellVisualPatch;
3710 #if defined(EF_USE_ASYNEQ)
3711 emacs_Xt_watch_event_queue(asyneq);
3715 /* event-Xt.c ends here */