comparison src/event-Xt.c @ 2:ac2d302a0011 r19-15b2

Import from CVS: tag r19-15b2
author cvs
date Mon, 13 Aug 2007 08:46:35 +0200
parents 376386a54a3c
children 4b173ad71786
comparison
equal deleted inserted replaced
1:c0c6a60d29db 2:ac2d302a0011
163 } 163 }
164 164
165 static CONST char * 165 static CONST char *
166 index_to_name (int indice) 166 index_to_name (int indice)
167 { 167 {
168 return ((indice == ShiftMapIndex ? "ModShift" 168 switch (indice)
169 : (indice == LockMapIndex ? "ModLock" 169 {
170 : (indice == ControlMapIndex ? "ModControl" 170 case ShiftMapIndex: return "ModShift";
171 : (indice == Mod1MapIndex ? "Mod1" 171 case LockMapIndex: return "ModLock";
172 : (indice == Mod2MapIndex ? "Mod2" 172 case ControlMapIndex: return "ModControl";
173 : (indice == Mod3MapIndex ? "Mod3" 173 case Mod1MapIndex: return "Mod1";
174 : (indice == Mod4MapIndex ? "Mod4" 174 case Mod2MapIndex: return "Mod2";
175 : (indice == Mod5MapIndex ? "Mod5" 175 case Mod3MapIndex: return "Mod3";
176 : "???"))))))))); 176 case Mod4MapIndex: return "Mod4";
177 case Mod5MapIndex: return "Mod5";
178 default: return "???";
179 }
177 } 180 }
178 181
179 /* Boy, I really wish C had local functions... */ 182 /* Boy, I really wish C had local functions... */
180 struct c_doesnt_have_closures /* #### not yet used */ 183 struct c_doesnt_have_closures /* #### not yet used */
181 { 184 {
194 { 197 {
195 Display *display = DEVICE_X_DISPLAY (d); 198 Display *display = DEVICE_X_DISPLAY (d);
196 struct x_device *xd = DEVICE_X_DATA (d); 199 struct x_device *xd = DEVICE_X_DATA (d);
197 int modifier_index, modifier_key, column, mkpm; 200 int modifier_index, modifier_key, column, mkpm;
198 int warned_about_overlapping_modifiers = 0; 201 int warned_about_overlapping_modifiers = 0;
199 int warned_about_predefined_modifiers = 0; 202 int warned_about_predefined_modifiers = 0;
200 int warned_about_duplicate_modifiers = 0; 203 int warned_about_duplicate_modifiers = 0;
201 int meta_bit = 0; 204 int meta_bit = 0;
202 int hyper_bit = 0; 205 int hyper_bit = 0;
203 int super_bit = 0; 206 int super_bit = 0;
204 int alt_bit = 0; 207 int alt_bit = 0;
205 int mode_bit = 0; 208 int mode_bit = 0;
206 209
207 xd->lock_interpretation = 0; 210 xd->lock_interpretation = 0;
208 211
209 if (xd->x_modifier_keymap) 212 if (xd->x_modifier_keymap)
210 XFreeModifiermap (xd->x_modifier_keymap); 213 XFreeModifiermap (xd->x_modifier_keymap);
411 the modifier key again. */ 414 the modifier key again. */
412 415
413 static void 416 static void
414 x_handle_sticky_modifiers (XEvent *ev, struct device *d) 417 x_handle_sticky_modifiers (XEvent *ev, struct device *d)
415 { 418 {
416 struct x_device *xd = DEVICE_X_DATA (d); 419 struct x_device *xd;
417 KeyCode keycode = ev->xkey.keycode; 420 KeyCode keycode;
418 int type = ev->xany.type; 421 int type;
419 int is_modifier = 422
420 (type == KeyPress || type == KeyRelease) && 423 if (!modifier_keys_are_sticky) /* Optimize for non-sticky modifiers */
421 x_key_is_modifier_p (keycode, d);
422
423 if (!modifier_keys_are_sticky)
424 return; 424 return;
425 425
426 if (!is_modifier) 426 xd = DEVICE_X_DATA (d);
427 { 427 keycode = ev->xkey.keycode;
428 type = ev->type;
429
430 if (! ((type == KeyPress || type == KeyRelease) &&
431 x_key_is_modifier_p (keycode, d)))
432 { /* Not a modifier key */
433 Bool key_event_p = (type == KeyPress || type == KeyRelease);
434
428 if (type == KeyPress && !xd->last_downkey) 435 if (type == KeyPress && !xd->last_downkey)
429 xd->last_downkey = keycode; 436 xd->last_downkey = keycode;
430 else if (type == ButtonPress || 437 else if (type == ButtonPress ||
431 (type == KeyPress && xd->last_downkey && 438 (type == KeyPress && xd->last_downkey &&
432 (keycode != xd->last_downkey || 439 (keycode != xd->last_downkey ||
438 if (type == KeyPress) 445 if (type == KeyPress)
439 xd->release_time = 0; 446 xd->release_time = 0;
440 if (type == KeyPress || type == ButtonPress) 447 if (type == KeyPress || type == ButtonPress)
441 xd->down_mask = 0; 448 xd->down_mask = 0;
442 449
443 ev->xkey.state |= xd->need_to_add_mask; 450 if (key_event_p)
451 ev->xkey.state |= xd->need_to_add_mask;
452 else
453 ev->xbutton.state |= xd->need_to_add_mask;
444 454
445 if (type == KeyRelease && keycode == xd->last_downkey) 455 if (type == KeyRelease && keycode == xd->last_downkey)
446 /* If I hold press-and-release the Control key and then press 456 /* If I hold press-and-release the Control key and then press
447 and hold down the right arrow, I want it to auto-repeat 457 and hold down the right arrow, I want it to auto-repeat
448 Control-Right. On the other hand, if I do the same but 458 Control-Right. On the other hand, if I do the same but
456 to provide an obvious way to distinguish these cases. 466 to provide an obvious way to distinguish these cases.
457 So we assume that if the release and the next press 467 So we assume that if the release and the next press
458 occur at the same time, the key was actually auto- 468 occur at the same time, the key was actually auto-
459 repeated. Under Open-Windows, at least, this works. 469 repeated. Under Open-Windows, at least, this works.
460 */ 470 */
461 xd->release_time = ev->xkey.time; 471 xd->release_time = key_event_p ? ev->xkey.time : ev->xbutton.time;
462 } 472 }
463 else 473 else /* Modifier key pressed */
464 { 474 {
475 int i;
465 KeySym *syms = &xd->x_keysym_map [(keycode - xd->x_keysym_map_min_code) * 476 KeySym *syms = &xd->x_keysym_map [(keycode - xd->x_keysym_map_min_code) *
466 xd->x_keysym_map_keysyms_per_code]; 477 xd->x_keysym_map_keysyms_per_code];
467 int i; 478
479 /* If a non-modifier key was pressed in the middle of a bunch
480 of modifiers, then it unsticks all the modifiers that were
481 previously pressed. We cannot unstick the modifiers until
482 now because we want to check for auto-repeat of the
483 non-modifier key. */
484
485 if (xd->last_downkey)
486 {
487 xd->last_downkey = 0;
488 xd->need_to_add_mask = 0;
489 }
468 490
469 #define FROB(mask) \ 491 #define FROB(mask) \
470 do { \ 492 do { \
471 if (type == KeyPress) \ 493 if (type == KeyPress) \
472 { \ 494 { \
491 xd->need_to_add_mask |= mask; \ 513 xd->need_to_add_mask |= mask; \
492 } \ 514 } \
493 } \ 515 } \
494 } while (0) 516 } while (0)
495 517
496 /* If a non-modifier key was pressed in the middle of a bunch
497 of modifiers, then it unsticks all the modifiers that were
498 previously pressed. We cannot unstick the modifiers until
499 now because we want to check for auto-repeat of the
500 non-modifier key. */
501
502 if (xd->last_downkey)
503 {
504 xd->last_downkey = 0;
505 xd->need_to_add_mask = 0;
506 }
507
508 for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++) 518 for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++)
509 { 519 switch (syms[i])
510 if (syms[i] == XK_Control_L || syms[i] == XK_Control_R) 520 {
511 FROB (ControlMask); 521 case XK_Control_L: case XK_Control_R: FROB (ControlMask); break;
512 if (syms[i] == XK_Shift_L || syms[i] == XK_Shift_R) 522 case XK_Shift_L: case XK_Shift_R: FROB (ShiftMask); break;
513 FROB (ShiftMask); 523 case XK_Meta_L: case XK_Meta_R: FROB (xd->MetaMask); break;
514 if (syms[i] == XK_Meta_L || syms[i] == XK_Meta_R) 524 case XK_Super_L: case XK_Super_R: FROB (xd->SuperMask); break;
515 FROB (xd->MetaMask); 525 case XK_Hyper_L: case XK_Hyper_R: FROB (xd->HyperMask); break;
516 if (syms[i] == XK_Super_L || syms[i] == XK_Super_R) 526 case XK_Alt_L: case XK_Alt_R: FROB (xd->AltMask); break;
517 FROB (xd->SuperMask); 527 }
518 if (syms[i] == XK_Hyper_L || syms[i] == XK_Hyper_R)
519 FROB (xd->HyperMask);
520 if (syms[i] == XK_Alt_L || syms[i] == XK_Alt_R)
521 FROB (xd->AltMask);
522 }
523 } 528 }
524 #undef FROB 529 #undef FROB
525 } 530 }
526 531
527 static void 532 static void
537 542
538 static int 543 static int
539 keysym_obeys_caps_lock_p (KeySym sym, struct device *d) 544 keysym_obeys_caps_lock_p (KeySym sym, struct device *d)
540 { 545 {
541 struct x_device *xd = DEVICE_X_DATA (d); 546 struct x_device *xd = DEVICE_X_DATA (d);
542 /* Eeeeevil hack. Don't apply caps-lock to things that aren't alphabetic 547 /* Eeeeevil hack. Don't apply Caps_Lock to things that aren't alphabetic
543 characters, where "alphabetic" means something more than simply A-Z. 548 characters, where "alphabetic" means something more than simply A-Z.
544 That is, if caps-lock is down, typing ESC doesn't produce Shift-ESC. 549 That is, if Caps_Lock is down, typing ESC doesn't produce Shift-ESC.
545 But if shift-lock is down, then it does. 550 But if shift-lock is down, then it does.
546 */ 551 */
547 if (xd->lock_interpretation == XK_Shift_Lock) 552 if (xd->lock_interpretation == XK_Shift_Lock)
548 return 1; 553 return 1;
549 if (((sym >= XK_A) && (sym <= XK_Z)) || 554
550 ((sym >= XK_a) && (sym <= XK_z)) || 555 return
551 ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) || 556 ((sym >= XK_A) && (sym <= XK_Z)) ||
552 ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) || 557 ((sym >= XK_a) && (sym <= XK_z)) ||
553 ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) || 558 ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) ||
554 ((sym >= XK_oslash) && (sym <= XK_thorn))) 559 ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) ||
555 return 1; 560 ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) ||
556 else 561 ((sym >= XK_oslash) && (sym <= XK_thorn));
557 return 0;
558 } 562 }
559 563
560 /* called from EmacsFrame.c (actually from Xt itself) when a 564 /* called from EmacsFrame.c (actually from Xt itself) when a
561 MappingNotify event is received. For non-obvious reasons, 565 MappingNotify event is received. In its infinite wisdom, Xt
562 our event handler does not see these events, so we need a 566 decided that Xt event handlers never get MappingNotify events.
563 special translation. */ 567 O'Reilly Xt Programming Manual 9.1.2 says:
568
569 MappingNotify is automatically handled by Xt, so it isn't passed
570 to event handlers and you don't need to worry about it.
571
572 Of course, we DO worry about it, so we need a special translation. */
564 void 573 void
565 emacs_Xt_mapping_action (Widget w, XEvent* event) 574 emacs_Xt_mapping_action (Widget w, XEvent* event)
566 { 575 {
567 struct device *d = get_device_from_display (event->xany.display); 576 struct device *d = get_device_from_display (event->xany.display);
568 #if 0 577 #if 0
572 /* xmodmap generates about a billion MappingKeyboard events, followed 581 /* xmodmap generates about a billion MappingKeyboard events, followed
573 by a single MappingModifier event, so it might be worthwhile to 582 by a single MappingModifier event, so it might be worthwhile to
574 take extra MappingKeyboard events out of the queue before requesting 583 take extra MappingKeyboard events out of the queue before requesting
575 the current keymap from the server. 584 the current keymap from the server.
576 */ 585 */
577 if (event->xmapping.request == MappingKeyboard) 586 switch (event->xmapping.request)
578 x_reset_key_mapping (d); 587 {
579 else if (event->xmapping.request == MappingModifier) 588 case MappingKeyboard: x_reset_key_mapping (d); break;
580 x_reset_modifier_mapping (d); 589 case MappingModifier: x_reset_modifier_mapping (d); break;
590 case MappingPointer: /* Do something here? */ break;
591 default: abort();
592 }
581 } 593 }
582 594
583 595
584 /************************************************************************/ 596 /************************************************************************/
585 /* X to Emacs event conversion */ 597 /* X to Emacs event conversion */
599 #endif /* !SUNOS_GCC_L0_BUG */ 611 #endif /* !SUNOS_GCC_L0_BUG */
600 /* simple_p means don't try too hard (ASCII only) */ 612 /* simple_p means don't try too hard (ASCII only) */
601 { 613 {
602 char *name; 614 char *name;
603 KeySym keysym = 0; 615 KeySym keysym = 0;
604 struct device *d = get_device_from_display (event->xany.display); 616 /* struct device *d = get_device_from_display (event->xany.display); */
605 /* Apparently it's necessary to specify a dummy here (rather than 617 /* Apparently it's necessary to specify a dummy here (rather than
606 passing in 0) to avoid crashes on German IRIX */ 618 passing in 0) to avoid crashes on German IRIX */
607 char dummy[256]; 619 char dummy[256];
608 620
609 #ifdef SUNOS_GCC_L0_BUG 621 #ifdef SUNOS_GCC_L0_BUG
691 #endif 703 #endif
692 704
693 static void 705 static void
694 set_last_server_timestamp (struct device *d, XEvent *x_event) 706 set_last_server_timestamp (struct device *d, XEvent *x_event)
695 { 707 {
696 switch (x_event->xany.type) 708 Time t;
709 switch (x_event->type)
697 { 710 {
698 case KeyPress: 711 case KeyPress:
699 case KeyRelease: 712 case KeyRelease: t = x_event->xkey.time; break;
700 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = x_event->xkey.time;
701 break;
702
703 case ButtonPress: 713 case ButtonPress:
704 case ButtonRelease: 714 case ButtonRelease: t = x_event->xbutton.time; break;
705 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = x_event->xbutton.time;
706 break;
707
708 case MotionNotify:
709 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = x_event->xmotion.time;
710 break;
711
712 case EnterNotify: 715 case EnterNotify:
713 case LeaveNotify: 716 case LeaveNotify: t = x_event->xcrossing.time; break;
714 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = x_event->xcrossing.time; 717 case MotionNotify: t = x_event->xmotion.time; break;
715 break; 718 case PropertyNotify: t = x_event->xproperty.time; break;
716 719 case SelectionClear: t = x_event->xselectionclear.time; break;
717 case PropertyNotify: 720 case SelectionRequest: t = x_event->xselectionrequest.time; break;
718 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = x_event->xproperty.time; 721 case SelectionNotify: t = x_event->xselection.time; break;
719 break; 722 default: return;
720 723 }
721 case SelectionClear: 724 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = t;
722 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = x_event->xselectionclear.time;
723 break;
724
725 case SelectionRequest:
726 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = x_event->xselectionrequest.time;
727 break;
728
729 case SelectionNotify:
730 DEVICE_X_LAST_SERVER_TIMESTAMP (d) = x_event->xselection.time;
731 break;
732 }
733 } 725 }
734 726
735 static int 727 static int
736 x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event) 728 x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
737 { 729 {
738 Display *display = x_event->xany.display; 730 Display *display = x_event->xany.display;
739 struct device *d = get_device_from_display (display); 731 struct device *d = get_device_from_display (display);
740 struct x_device *xd = DEVICE_X_DATA (d); 732 struct x_device *xd = DEVICE_X_DATA (d);
741 733
742 set_last_server_timestamp (d, x_event); 734 set_last_server_timestamp (d, x_event);
743 735
744 switch (x_event->xany.type) 736 switch (x_event->type)
745 { 737 {
746 case KeyRelease: 738 case KeyRelease:
747 x_handle_sticky_modifiers (x_event, d); 739 x_handle_sticky_modifiers (x_event, d);
748 return 0; 740 return 0;
749 741
750 case KeyPress: 742 case KeyPress:
751 case ButtonPress: 743 case ButtonPress:
752 case ButtonRelease: 744 case ButtonRelease:
753 { 745 {
754 unsigned int modifiers = 0; 746 unsigned int modifiers = 0;
755 int shift_p; 747 int shift_p;
756 int lock_p; 748 int lock_p;
749 Bool key_event_p = (x_event->type == KeyPress);
750 unsigned int *state =
751 key_event_p ? &x_event->xkey.state : &x_event->xbutton.state;
752
753 /* If this is a synthetic KeyPress or Button event, and the user
754 has expressed a disinterest in this security hole, then drop
755 it on the floor. */
756 if ((key_event_p
757 ? x_event->xkey.send_event
758 : x_event->xbutton.send_event)
757 #ifdef EXTERNAL_WIDGET 759 #ifdef EXTERNAL_WIDGET
758 struct frame *f = x_any_window_to_frame (d, x_event->xany.window); 760 /* ben: events get sent to an ExternalShell using XSendEvent.
761 This is not a perfect solution. */
762 && !FRAME_X_EXTERNAL_WINDOW_P (
763 x_any_window_to_frame (d, x_event->xany.window))
759 #endif 764 #endif
760 765 && !x_allow_sendevents)
761 /* If this is a synthetic KeyPress or Button event, and the user 766 return 0;
762 has expressed a disinterest in this security hole, then drop 767
763 it on the floor. 768 DEVICE_X_MOUSE_TIMESTAMP (d) =
764 */ 769 DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d) =
765 if (((x_event->xany.type == KeyPress) 770 key_event_p ? x_event->xkey.time : x_event->xbutton.time;
766 ? x_event->xkey.send_event 771
767 : x_event->xbutton.send_event) 772 x_handle_sticky_modifiers (x_event, d);
768 #ifdef EXTERNAL_WIDGET 773
769 /* ben: events get sent to an ExternalShell using XSendEvent. 774 if (*state & ControlMask) modifiers |= MOD_CONTROL;
770 This is not a perfect solution. */ 775 if (*state & xd->MetaMask) modifiers |= MOD_META;
771 && !FRAME_X_EXTERNAL_WINDOW_P (f) 776 if (*state & xd->SuperMask) modifiers |= MOD_SUPER;
772 #endif 777 if (*state & xd->HyperMask) modifiers |= MOD_HYPER;
773 && !x_allow_sendevents) 778 if (*state & xd->AltMask) modifiers |= MOD_ALT;
774 return 0; 779
775 780 /* Ignore the Caps_Lock key if:
776 x_handle_sticky_modifiers (x_event, d); 781 - any other modifiers are down, so that Caps_Lock doesn't
777 782 turn C-x into C-X, which would suck.
778 shift_p = x_event->xkey.state & ShiftMask; 783 - the event was a mouse event. */
779 lock_p = x_event->xkey.state & LockMask; 784 if (modifiers || ! key_event_p)
780 785 *state &= (~LockMask);
781 if (x_event->xany.type == KeyPress) 786
782 DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d) = x_event->xkey.time; 787 shift_p = *state & ShiftMask;
783 else 788 lock_p = *state & LockMask;
784 DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d) = x_event->xbutton.time; 789
785 790 if (shift_p || lock_p)
786 /* Ignore the caps-lock key w.r.t. mouse presses and releases. */ 791 modifiers |= MOD_SHIFT;
787 if (x_event->xany.type != KeyPress) 792
788 lock_p = 0; 793 if (key_event_p)
789 794 {
790 if (x_event->xkey.state & ControlMask) modifiers |= MOD_CONTROL; 795 Lisp_Object keysym;
791 if (x_event->xkey.state & xd->MetaMask) modifiers |= MOD_META; 796 XKeyEvent *ev = &x_event->xkey;
792 if (x_event->xkey.state & xd->SuperMask) modifiers |= MOD_SUPER; 797 KeyCode keycode = ev->keycode;
793 if (x_event->xkey.state & xd->HyperMask) modifiers |= MOD_HYPER; 798
794 if (x_event->xkey.state & xd->AltMask) modifiers |= MOD_ALT; 799
795 800 if (x_key_is_modifier_p (keycode, d)) /* it's a modifier key */
796 /* Ignore the caps-lock key if any other modifiers are down; this is 801 return 0;
797 so that Caps doesn't turn C-x into C-X, which would suck. */ 802
798 if (modifiers) 803 /* This used to compute the frame from the given X window and
799 { 804 store it here, but we really don't care about the frame. */
800 x_event->xkey.state &= (~LockMask); 805 emacs_event->channel = DEVICE_CONSOLE (d);
801 lock_p = 0; 806 keysym = x_to_emacs_keysym (x_event, 0);
802 }
803
804 if (shift_p || lock_p)
805 modifiers |= MOD_SHIFT;
806
807 DEVICE_X_MOUSE_TIMESTAMP (d) = DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d);
808
809 switch (x_event->xany.type)
810 {
811 case KeyPress:
812 {
813 Lisp_Object keysym;
814 KeyCode keycode = x_event->xkey.keycode;
815 807
816 if (x_key_is_modifier_p (keycode, d)) /* it's a modifier key */ 808 /* If the emacs keysym is nil, then that means that the
817 return 0; 809 X keysym was NoSymbol, which probably means that
818 810 we're in the midst of reading a Multi_key sequence,
819 /* This used to compute the frame from the given X window 811 or a "dead" key prefix. Ignore it. */
820 and store it here, but we really don't care about the 812 if (NILP (keysym))
821 frame. */ 813 return 0;
822 emacs_event->channel = DEVICE_CONSOLE (d);
823 keysym = x_to_emacs_keysym (x_event, 0);
824 814
825 /* If the emacs keysym is nil, then that means that the 815 /* More Caps_Lock garbage: Caps_Lock should *only* add the
826 X keysym was NoSymbol, which probably means that 816 shift modifier to two-case keys (that is, A-Z and
827 we're in the midst of reading a Multi_key sequence, 817 related characters). So at this point (after looking up
828 or a "dead" key prefix. Ignore it. */ 818 the keysym) if the keysym isn't a dual-case alphabetic,
829 if (NILP (keysym)) 819 and if the caps lock key was down but the shift key
830 return 0; 820 wasn't, then turn off the shift modifier. Gag barf */
821 /* #### type lossage: assuming equivalence of emacs and
822 X keysyms */
823 /* !!#### maybe fix for Mule */
824 if (lock_p && !shift_p &&
825 ! (CHAR_OR_CHAR_INTP (keysym)
826 && keysym_obeys_caps_lock_p
827 ((KeySym) XCHAR_OR_CHAR_INT (keysym), d)))
828 modifiers &= (~MOD_SHIFT);
831 829
832 /* More caps-lock garbage: caps-lock should *only* add 830 /* If this key contains two distinct keysyms, that is,
833 the shift modifier to two-case keys (that is, A-Z and 831 "shift" generates a different keysym than the
834 related characters). So at this point (after looking 832 non-shifted key, then don't apply the shift modifier
835 up the keysym) if the keysym isn't a dual-case 833 bit: it's implicit. Otherwise, if there would be no
836 alphabetic, and if the caps lock key was down but the 834 other way to tell the difference between the shifted
837 shift key wasn't, then turn off the shift modifier. 835 and unshifted version of this key, apply the shift bit.
838 Gag barf retch. */ 836 Non-graphics, like Backspace and F1 get the shift bit
839 /* #### type lossage: assuming equivalence of emacs and 837 in the modifiers slot. Neither the characters "a",
840 X keysyms */ 838 "A", "2", nor "@" normally have the shift bit set.
841 /* !!#### maybe fix for Mule */ 839 However, "F1" normally does. */
842 if (! (CHAR_OR_CHAR_INTP (keysym) 840 if (modifiers & MOD_SHIFT)
843 && keysym_obeys_caps_lock_p 841 {
844 ((KeySym) XCHAR_OR_CHAR_INT (keysym), d)) 842 int Mode_switch_p = *state & xd->ModeMask;
845 && lock_p 843 KeySym bot = XLookupKeysym (ev, Mode_switch_p ? 2 : 0);
846 && !shift_p) 844 KeySym top = XLookupKeysym (ev, Mode_switch_p ? 3 : 1);
847 modifiers &= (~MOD_SHIFT); 845 if (top && bot && top != bot)
848 846 modifiers &= ~MOD_SHIFT;
849 /* If this key contains two distinct keysyms, that is, 847 }
850 "shift" generates a different keysym than the 848 emacs_event->event_type = key_press_event;
851 non-shifted key, then don't apply the shift modifier 849 emacs_event->timestamp = ev->time;
852 bit: it's implicit. Otherwise, if there would be no 850 emacs_event->event.key.modifiers = modifiers;
853 other way to tell the difference between the shifted 851 emacs_event->event.key.keysym = keysym;
854 and unshifted version of this key, apply the shift 852 }
855 bit. Non-graphics, like Backspace and F1 get the 853 else /* Mouse press/release event */
856 shift bit in the modifiers slot. Neither the 854 {
857 characters "a", "A", "2", nor "@" normally have the 855 XButtonEvent *ev = &x_event->xbutton;
858 shift bit set. However, "F1" normally does. */ 856 struct frame *frame = x_window_to_frame (d, ev->window);
859 if (modifiers & MOD_SHIFT) 857 if (! frame)
860 { 858 return 0; /* not for us */
861 KeySym top, bot; 859 XSETFRAME (emacs_event->channel, frame);
862 if (x_event->xkey.state & xd->ModeMask) 860
863 bot = XLookupKeysym (&x_event->xkey, 2), 861 emacs_event->event_type = (x_event->type == ButtonPress) ?
864 top = XLookupKeysym (&x_event->xkey, 3); 862 button_press_event : button_release_event;
865 else 863
866 bot = XLookupKeysym (&x_event->xkey, 0), 864 emacs_event->event.button.modifiers = modifiers;
867 top = XLookupKeysym (&x_event->xkey, 1); 865 emacs_event->timestamp = ev->time;
868 if (top && bot && top != bot) 866 emacs_event->event.button.button = ev->button;
869 modifiers &= ~MOD_SHIFT; 867 emacs_event->event.button.x = ev->x;
870 } 868 emacs_event->event.button.y = ev->y;
871 emacs_event->event_type = key_press_event; 869 }
872 emacs_event->timestamp = x_event->xkey.time;
873 emacs_event->event.key.modifiers = modifiers;
874 emacs_event->event.key.keysym = keysym;
875 break;
876 }
877 case ButtonPress:
878 case ButtonRelease:
879 {
880 struct frame *frame =
881 x_window_to_frame (d, x_event->xbutton.window);
882 if (! frame)
883 return 0; /* not for us */
884 XSETFRAME (emacs_event->channel, frame);
885 }
886
887 if (x_event->type == ButtonPress)
888 emacs_event->event_type = button_press_event;
889 else emacs_event->event_type = button_release_event;
890 emacs_event->timestamp = x_event->xbutton.time;
891 emacs_event->event.button.modifiers = modifiers;
892 emacs_event->event.button.button = x_event->xbutton.button;
893 emacs_event->event.button.x = x_event->xbutton.x;
894 emacs_event->event.button.y = x_event->xbutton.y;
895 break;
896 }
897 } 870 }
898 break; 871 break;
899 872
900 case MotionNotify: 873 case MotionNotify:
901 { 874 {
902 Window w = x_event->xmotion.window; 875 XMotionEvent *ev = &x_event->xmotion;
903 struct frame *frame = x_window_to_frame (d, w); 876 struct frame *frame = x_window_to_frame (d, ev->window);
904 XEvent event2; 877 unsigned int modifiers = 0;
878 XMotionEvent event2;
905 879
906 if (! frame) 880 if (! frame)
907 return 0; /* not for us */ 881 return 0; /* not for us */
908 882
909 /* We use MotionHintMask, so we will get only one motion event 883 /* We use MotionHintMask, so we will get only one motion event
910 until the next time we call XQueryPointer or the user clicks 884 until the next time we call XQueryPointer or the user
911 the mouse. So call XQueryPointer now (meaning that the event 885 clicks the mouse. So call XQueryPointer now (meaning that
912 will be in sync with the server just before Fnext_event() 886 the event will be in sync with the server just before
913 returns). If the mouse is still in motion, then the server 887 Fnext_event() returns). If the mouse is still in motion,
914 will immediately generate exactly one more motion event, which 888 then the server will immediately generate exactly one more
915 will be on the queue waiting for us next time around. 889 motion event, which will be on the queue waiting for us
916 */ 890 next time around. */
917 event2 = *x_event; 891 event2 = *ev;
918 if (XQueryPointer (x_event->xmotion.display, event2.xmotion.window, 892 if (XQueryPointer (event2.display, event2.window,
919 &event2.xmotion.root, &event2.xmotion.subwindow, 893 &event2.root, &event2.subwindow,
920 &event2.xmotion.x_root, &event2.xmotion.y_root, 894 &event2.x_root, &event2.y_root,
921 &event2.xmotion.x, &event2.xmotion.y, 895 &event2.x, &event2.y,
922 &event2.xmotion.state)) 896 &event2.state))
923 *x_event = event2; 897 ev = &event2; /* only one structure copy */
924 898
925 DEVICE_X_MOUSE_TIMESTAMP (d) = x_event->xmotion.time; 899 DEVICE_X_MOUSE_TIMESTAMP (d) = ev->time;
926 900
927 XSETFRAME (emacs_event->channel, frame); 901 XSETFRAME (emacs_event->channel, frame);
928 emacs_event->event_type = pointer_motion_event; 902 emacs_event->event_type = pointer_motion_event;
929 emacs_event->timestamp = x_event->xmotion.time; 903 emacs_event->timestamp = ev->time;
930 emacs_event->event.motion.x = x_event->xmotion.x; 904 emacs_event->event.motion.x = ev->x;
931 emacs_event->event.motion.y = x_event->xmotion.y; 905 emacs_event->event.motion.y = ev->y;
932 { 906 if (ev->state & ShiftMask) modifiers |= MOD_SHIFT;
933 unsigned int modifiers = 0; 907 if (ev->state & ControlMask) modifiers |= MOD_CONTROL;
934 if (x_event->xmotion.state & ShiftMask) modifiers |= MOD_SHIFT; 908 if (ev->state & xd->MetaMask) modifiers |= MOD_META;
935 if (x_event->xmotion.state & ControlMask) modifiers |= MOD_CONTROL; 909 if (ev->state & xd->SuperMask) modifiers |= MOD_SUPER;
936 if (x_event->xmotion.state & xd->MetaMask) modifiers |= MOD_META; 910 if (ev->state & xd->HyperMask) modifiers |= MOD_HYPER;
937 if (x_event->xmotion.state & xd->SuperMask) modifiers |= MOD_SUPER; 911 if (ev->state & xd->AltMask) modifiers |= MOD_ALT;
938 if (x_event->xmotion.state & xd->HyperMask) modifiers |= MOD_HYPER; 912 /* Currently ignores Shift_Lock but probably shouldn't
939 if (x_event->xmotion.state & xd->AltMask) modifiers |= MOD_ALT; 913 (but it definitely should ignore Caps_Lock). */
940 /* Currently ignores Shift_Lock but probably shouldn't 914 emacs_event->event.motion.modifiers = modifiers;
941 (but it definitely should ignore Caps_Lock). */
942 emacs_event->event.motion.modifiers = modifiers;
943 }
944 } 915 }
945 break; 916 break;
946 917
947 case ClientMessage: 918 case ClientMessage:
948 /* Patch bogus TAKE_FOCUS messages from MWM; CurrentTime is passed as the 919 {
949 timestamp of the TAKE_FOCUS, which the ICCCM explicitly prohibits. */ 920 /* Patch bogus TAKE_FOCUS messages from MWM; CurrentTime is
950 if (x_event->xclient.message_type == DEVICE_XATOM_WM_PROTOCOLS (d) 921 passed as the timestamp of the TAKE_FOCUS, which the ICCCM
951 && x_event->xclient.data.l[0] == DEVICE_XATOM_WM_TAKE_FOCUS (d) 922 explicitly prohibits. */
952 && x_event->xclient.data.l[1] == 0) 923 XClientMessageEvent *ev = &x_event->xclient;
953 { 924 if (ev->message_type == DEVICE_XATOM_WM_PROTOCOLS (d)
954 x_event->xclient.data.l[1] = DEVICE_X_LAST_SERVER_TIMESTAMP (d); 925 && ev->data.l[0] == DEVICE_XATOM_WM_TAKE_FOCUS (d)
955 } 926 && ev->data.l[1] == 0)
956 /* fall through */ 927 {
928 ev->data.l[1] = DEVICE_X_LAST_SERVER_TIMESTAMP (d);
929 }
930 }
931 /* fall through */
957 932
958 default: /* it's a magic event */ 933 default: /* it's a magic event */
959 { 934 {
960 struct frame *f; 935 struct frame *frame;
961 936 Window w;
962 switch (x_event->type) 937
963 { 938 switch (x_event->type)
964 /* Note: the number of cases could be reduced to two or 939 {
965 three by using xany.window, but it's perhaps clearer 940 /* Note: the number of cases could be reduced to two or
966 and potentially more robust this way */ 941 three by using xany.window, but it's perhaps clearer
967 case SelectionRequest: 942 and potentially more robust this way */
968 f = x_window_to_frame (d, x_event->xselectionrequest.owner); 943 case SelectionRequest: w = x_event->xselectionrequest.owner; break;
969 break; 944 case SelectionClear: w = x_event->xselectionclear.window; break;
970 945 case SelectionNotify: w = x_event->xselection.requestor; break;
971 case SelectionClear: 946 case PropertyNotify: w = x_event->xproperty.window; break;
972 f = x_window_to_frame (d, x_event->xselectionclear.window); 947 case ClientMessage: w = x_event->xclient.window; break;
973 break; 948 case ConfigureNotify: w = x_event->xconfigure.window; break;
974 949 case Expose:
975 case SelectionNotify: 950 case GraphicsExpose: w = x_event->xexpose.window; break;
976 f = x_window_to_frame (d, x_event->xselection.requestor); 951 case MapNotify:
977 break; 952 case UnmapNotify: w = x_event->xmap.window; break;
978 953 case EnterNotify:
979 case PropertyNotify: 954 case LeaveNotify: w = x_event->xcrossing.window; break;
980 f = x_window_to_frame (d, x_event->xproperty.window); 955 case FocusIn:
981 break; 956 case FocusOut: w = x_event->xfocus.window; break;
982 957 case VisibilityNotify: w = x_event->xvisibility.window; break;
983 case Expose: 958 default: w = x_event->xany.window; break;
984 case GraphicsExpose: 959 }
985 f = x_window_to_frame (d, x_event->xexpose.window); 960 frame = x_any_window_to_frame (d, w);
986 break; 961
987 962 if (!frame)
988 case MapNotify: 963 return 0;
989 case UnmapNotify: 964
990 f = x_any_window_to_frame (d, x_event->xmap.window); 965 emacs_event->event_type = magic_event;
991 break; 966 XSETFRAME (emacs_event->channel, frame);
992 967 emacs_event->event.magic.underlying_x_event = *x_event;
993 case EnterNotify: 968 break;
994 case LeaveNotify:
995 f = x_any_window_to_frame (d, x_event->xcrossing.window);
996 break;
997
998 case FocusIn:
999 case FocusOut:
1000 /* It's curious that we're using x_any_window_to_frame()
1001 here. I don't know if this causes problems. */
1002 f = x_any_window_to_frame (d, x_event->xfocus.window);
1003
1004 case ClientMessage:
1005 f = x_any_window_to_frame (d, x_event->xclient.window);
1006 break;
1007
1008 case MappingNotify:
1009 case VisibilityNotify:
1010 f = x_any_window_to_frame (d, x_event->xvisibility.window);
1011 break;
1012
1013 case ConfigureNotify:
1014 f = x_any_window_to_frame (d, x_event->xconfigure.window);
1015 break;
1016
1017 default:
1018 f = x_any_window_to_frame (d, x_event->xany.window);
1019 break;
1020 }
1021
1022 if (!f)
1023 return 0;
1024
1025 emacs_event->event_type = magic_event;
1026 XSETFRAME (emacs_event->channel, f);
1027 memcpy ((char *) &emacs_event->event.magic.underlying_x_event,
1028 (char *) x_event,
1029 sizeof (XEvent));
1030 break;
1031 } 969 }
1032 } 970 }
1033 return 1; 971 return 1;
1034 } 972 }
1035 973
1084 event->xfocus.window); 1022 event->xfocus.window);
1085 if (!f) 1023 if (!f)
1086 /* focus events are sometimes generated just before 1024 /* focus events are sometimes generated just before
1087 a frame is destroyed. */ 1025 a frame is destroyed. */
1088 return; 1026 return;
1089 handle_focus_event_1 (f, event->xany.type == FocusIn); 1027 handle_focus_event_1 (f, event->type == FocusIn);
1090 } 1028 }
1091 1029
1092 static void 1030 static void
1093 handle_map_event (struct frame *f, XEvent *event) 1031 handle_map_event (struct frame *f, XEvent *event)
1094 { 1032 {
1095 Lisp_Object frame = Qnil; 1033 Lisp_Object frame = Qnil;
1096 1034
1097 XSETFRAME (frame, f); 1035 XSETFRAME (frame, f);
1098 if (event->xany.type == MapNotify) 1036 if (event->type == MapNotify)
1099 { 1037 {
1100 XWindowAttributes xwa; 1038 XWindowAttributes xwa;
1101 1039
1102 /* Bleagh!!!!!! Apparently some window managers (e.g. MWM) 1040 /* Bleagh!!!!!! Apparently some window managers (e.g. MWM)
1103 send synthetic MapNotify events when a window is first 1041 send synthetic MapNotify events when a window is first
1308 completely ignore all FocusIn/FocusOut events and depend only 1246 completely ignore all FocusIn/FocusOut events and depend only
1309 on notifications from the ExternalClient widget. */ 1247 on notifications from the ExternalClient widget. */
1310 if (FRAME_X_EXTERNAL_WINDOW_P (f)) 1248 if (FRAME_X_EXTERNAL_WINDOW_P (f))
1311 break; 1249 break;
1312 #endif 1250 #endif
1313 handle_focus_event_1 (f, event->xany.type == FocusIn); 1251 handle_focus_event_1 (f, event->type == FocusIn);
1314 break; 1252 break;
1315 1253
1316 case ClientMessage: 1254 case ClientMessage:
1317 handle_client_message (f, event); 1255 handle_client_message (f, event);
1318 break; 1256 break;
1319
1320 #if 0
1321 /* this is where we ought to be handling this event, but
1322 we don't see it here. --ben */
1323 case MappingNotify: /* The user has run xmodmap */
1324 #endif
1325 1257
1326 case VisibilityNotify: /* window visiblity has changed */ 1258 case VisibilityNotify: /* window visiblity has changed */
1327 if (event->xvisibility.state == VisibilityUnobscured) 1259 if (event->xvisibility.state == VisibilityUnobscured)
1328 FRAME_X_TOTALLY_VISIBLE_P (f) = 1; 1260 FRAME_X_TOTALLY_VISIBLE_P (f) = 1;
1329 else 1261 else
1330 FRAME_X_TOTALLY_VISIBLE_P (f) = 0; 1262 FRAME_X_TOTALLY_VISIBLE_P (f) = 0;
1331 break; 1263 break;
1332 1264
1333 case ConfigureNotify: 1265 case ConfigureNotify:
1334 if (event->xconfigure.window != XtWindow (FRAME_X_SHELL_WIDGET (f))) 1266 #ifdef HAVE_XIM
1335 break; 1267 XIC_SetGeometry (f);
1336 FRAME_X_SHELL_WIDGET (f)->core.x = event->xconfigure.x; 1268 #endif
1337 FRAME_X_SHELL_WIDGET (f)->core.y = event->xconfigure.y; 1269 /* ### If the following code fails to work, simply always call
1270 x_smash_bastardly_shell_position always. In this case we no
1271 longer rely on the data in the events, merely on their
1272 occurrence. */
1273 /* ### Well, actually we shouldn't have to ever call
1274 x_smash_bastardly_shell_position. We should just call
1275 XtTranslateCoordinates and only access the core.{x,y} fields
1276 using XtGetValue -- mrb */
1277 {
1278 XConfigureEvent *ev = &event->xconfigure;
1279 if (ev->window == XtWindow (FRAME_X_SHELL_WIDGET (f)) &&
1280 ! (ev->x == 0 && ev->y == 0 && !ev->send_event))
1281 {
1282 FRAME_X_SHELL_WIDGET (f)->core.x = ev->x;
1283 FRAME_X_SHELL_WIDGET (f)->core.y = ev->y;
1284 }
1285 }
1338 break; 1286 break;
1339 1287
1340 default: 1288 default:
1341 break; 1289 break;
1342 } 1290 }
1757 static CONST char * 1705 static CONST char *
1758 XEvent_mode_to_string (int mode) 1706 XEvent_mode_to_string (int mode)
1759 { 1707 {
1760 switch (mode) 1708 switch (mode)
1761 { 1709 {
1762 case NotifyNormal: return "Normal"; 1710 case NotifyNormal: return "Normal";
1763 case NotifyGrab: return "Grab"; 1711 case NotifyGrab: return "Grab";
1764 case NotifyUngrab: return "Ungrab"; 1712 case NotifyUngrab: return "Ungrab";
1765 case NotifyWhileGrabbed: return "WhileGrabbed"; 1713 case NotifyWhileGrabbed: return "WhileGrabbed";
1766 default: 1714 default: return "???";
1767 return "???";
1768 } 1715 }
1769 } 1716 }
1770 1717
1771 static CONST char * 1718 static CONST char *
1772 XEvent_detail_to_string (int detail) 1719 XEvent_detail_to_string (int detail)
1773 { 1720 {
1774 switch (detail) 1721 switch (detail)
1775 { 1722 {
1776 case NotifyAncestor: return "Ancestor"; 1723 case NotifyAncestor: return "Ancestor";
1777 case NotifyInferior: return "Inferior"; 1724 case NotifyInferior: return "Inferior";
1778 case NotifyNonlinear: return "Nonlinear"; 1725 case NotifyNonlinear: return "Nonlinear";
1779 case NotifyNonlinearVirtual: return "NonlinearVirtual"; 1726 case NotifyNonlinearVirtual: return "NonlinearVirtual";
1780 case NotifyPointer: return "Pointer"; 1727 case NotifyPointer: return "Pointer";
1781 case NotifyPointerRoot: return "PointerRoot"; 1728 case NotifyPointerRoot: return "PointerRoot";
1782 case NotifyDetailNone: return "DetailNone"; 1729 case NotifyDetailNone: return "DetailNone";
1783 default: 1730 default: return "???";
1784 return "???";
1785 } 1731 }
1786 } 1732 }
1787 1733
1788 static CONST char * 1734 static CONST char *
1789 XEvent_visibility_to_string (int state) 1735 XEvent_visibility_to_string (int state)
1790 { 1736 {
1791 switch (state) 1737 switch (state)
1792 { 1738 {
1793 case VisibilityFullyObscured: return "FullyObscured"; 1739 case VisibilityFullyObscured: return "FullyObscured";
1794 case VisibilityPartiallyObscured: return "PartiallyObscured"; 1740 case VisibilityPartiallyObscured: return "PartiallyObscured";
1795 case VisibilityUnobscured: return "Unobscured"; 1741 case VisibilityUnobscured: return "Unobscured";
1796 default: 1742 default: return "???";
1797 return "???";
1798 } 1743 }
1799 } 1744 }
1800 1745
1801 static void 1746 static void
1802 describe_event (XEvent *event) 1747 describe_event (XEvent *event)
1852 stderr_out (" Modifier key"); 1797 stderr_out (" Modifier key");
1853 stderr_out (" keycode: 0x%x\n", ev->keycode); 1798 stderr_out (" keycode: 0x%x\n", ev->keycode);
1854 keysym = x_to_emacs_keysym (event, 0); 1799 keysym = x_to_emacs_keysym (event, 0);
1855 if (CHAR_OR_CHAR_INTP (keysym)) 1800 if (CHAR_OR_CHAR_INTP (keysym))
1856 { 1801 {
1857 if (XCHAR_OR_CHAR_INT (keysym) > 32 1802 Emchar c = XCHAR_OR_CHAR_INT (keysym);
1858 && XCHAR_OR_CHAR_INT (keysym) < 127) 1803 if (c > 32 && c < 127)
1859 stderr_out (" keysym: %c\n", XCHAR_OR_CHAR_INT (keysym)); 1804 stderr_out (" keysym: %c\n", c);
1860 else 1805 else
1861 stderr_out (" keysym: %d\n", XCHAR_OR_CHAR_INT (keysym)); 1806 stderr_out (" keysym: %d\n", c);
1862 } 1807 }
1863 else 1808 else
1864 stderr_out (" keysym: %s\n", string_data (XSYMBOL (keysym)->name)); 1809 stderr_out (" keysym: %s\n", string_data (XSYMBOL (keysym)->name));
1865 } 1810 }
1866 break; 1811 break;
1868 case Expose: 1813 case Expose:
1869 if (x_debug_events > 1) 1814 if (x_debug_events > 1)
1870 { 1815 {
1871 XExposeEvent *ev = &event->xexpose; 1816 XExposeEvent *ev = &event->xexpose;
1872 describe_event_window (ev->window, ev->display); 1817 describe_event_window (ev->window, ev->display);
1873 stderr_out (" region: %d %d %d %d\n", ev->x, ev->y, 1818 stderr_out (" region: x=%d y=%d width=%d height=%d\n",
1874 ev->width, ev->height); 1819 ev->x, ev->y, ev->width, ev->height);
1875 stderr_out (" count: %d\n", ev->count); 1820 stderr_out (" count: %d\n", ev->count);
1876 } 1821 }
1877 else 1822 else
1878 stderr_out ("\n"); 1823 stderr_out ("\n");
1879 break; 1824 break;
1884 XGraphicsExposeEvent *ev = &event->xgraphicsexpose; 1829 XGraphicsExposeEvent *ev = &event->xgraphicsexpose;
1885 describe_event_window (ev->drawable, ev->display); 1830 describe_event_window (ev->drawable, ev->display);
1886 stderr_out (" major: %s\n", 1831 stderr_out (" major: %s\n",
1887 (ev ->major_code == X_CopyArea ? "CopyArea" : 1832 (ev ->major_code == X_CopyArea ? "CopyArea" :
1888 (ev->major_code == X_CopyPlane ? "CopyPlane" : "?"))); 1833 (ev->major_code == X_CopyPlane ? "CopyPlane" : "?")));
1889 stderr_out (" region: %d %d %d %d\n", ev->x, ev->y, 1834 stderr_out (" region: x=%d y=%d width=%d height=%d\n",
1890 ev->width, ev->height); 1835 ev->x, ev->y, ev->width, ev->height);
1891 stderr_out (" count: %d\n", ev->count); 1836 stderr_out (" count: %d\n", ev->count);
1892 } 1837 }
1893 else 1838 else
1894 stderr_out ("\n"); 1839 stderr_out ("\n");
1895 break; 1840 break;
2014 emacs_Xt_next_event (struct Lisp_Event *emacs_event) 1959 emacs_Xt_next_event (struct Lisp_Event *emacs_event)
2015 { 1960 {
2016 we_didnt_get_an_event: 1961 we_didnt_get_an_event:
2017 1962
2018 while (NILP (dispatch_event_queue) && 1963 while (NILP (dispatch_event_queue) &&
2019 !completed_timeouts && 1964 !completed_timeouts &&
2020 !fake_event_occurred && 1965 !fake_event_occurred &&
2021 !process_events_occurred && 1966 !process_events_occurred &&
2022 !tty_events_occurred) 1967 !tty_events_occurred)
2023 { 1968 {
2024 1969
2025 /* Stupid logic in XtAppProcessEvent() dictates that, if process 1970 /* Stupid logic in XtAppProcessEvent() dictates that, if process
2026 events and X events are both available, the process event gets 1971 events and X events are both available, the process event gets