Reformatted.
[chise/xemacs-chise.git] / src / event-Xt.c
index 40c0752..ccfde91 100644 (file)
@@ -65,20 +65,11 @@ Boston, MA 02111-1307, USA.  */
 #include "offix.h"
 #endif
 
 #include "offix.h"
 #endif
 
-#ifdef WINDOWSNT
-/* Hmm, under unix we want X modifiers, under NT we want X modifiers if
-   we are running X and Windows modifiers otherwise.
-   gak. This is a kludge until we support multiple native GUIs!
-*/
-#undef MOD_ALT
-#undef MOD_CONTROL
-#undef MOD_SHIFT
-#endif
-
 #include "events-mod.h"
 
 #include "events-mod.h"
 
-static void enqueue_Xt_dispatch_event (Lisp_Object event);
+void enqueue_focus_event (Widget wants_it, Lisp_Object frame, int in_p);
 static void handle_focus_event_1 (struct frame *f, int in_p);
 static void handle_focus_event_1 (struct frame *f, int in_p);
+static void handle_focus_event_2 (Window w, struct frame *f, int in_p);
 
 static struct event_stream *Xt_event_stream;
 
 
 static struct event_stream *Xt_event_stream;
 
@@ -97,19 +88,18 @@ XtAppContext Xt_app_con;
 /* Do we accept events sent by other clients? */
 int x_allow_sendevents;
 
 /* Do we accept events sent by other clients? */
 int x_allow_sendevents;
 
-int modifier_keys_are_sticky;
-
 #ifdef DEBUG_XEMACS
 #ifdef DEBUG_XEMACS
-int x_debug_events;
+Fixnum debug_x_events;
 #endif
 
 static int process_events_occurred;
 static int tty_events_occurred;
 #endif
 
 static int process_events_occurred;
 static int tty_events_occurred;
+static Widget widget_with_focus;
 
 /* Mask of bits indicating the descriptors that we wait for input on */
 extern SELECT_TYPE input_wait_mask, process_only_mask, tty_only_mask;
 
 
 /* Mask of bits indicating the descriptors that we wait for input on */
 extern SELECT_TYPE input_wait_mask, process_only_mask, tty_only_mask;
 
-static CONST String x_fallback_resources[] =
+static const String x_fallback_resources[] =
 {
   /* This file is automatically generated from the app-defaults file
      in ../etc/Emacs.ad.  These resources are consulted only if no
 {
   /* This file is automatically generated from the app-defaults file
      in ../etc/Emacs.ad.  These resources are consulted only if no
@@ -121,7 +111,7 @@ static CONST String x_fallback_resources[] =
 
 static Lisp_Object x_keysym_to_emacs_keysym (KeySym keysym, int simple_p);
 void emacs_Xt_mapping_action (Widget w, XEvent *event);
 
 static Lisp_Object x_keysym_to_emacs_keysym (KeySym keysym, int simple_p);
 void emacs_Xt_mapping_action (Widget w, XEvent *event);
-void debug_process_finalization (struct Lisp_Process *p);
+void debug_process_finalization (Lisp_Process *p);
 void emacs_Xt_event_handler (Widget wid, XtPointer closure, XEvent *event,
                             Boolean *continue_to_dispatch);
 
 void emacs_Xt_event_handler (Widget wid, XtPointer closure, XEvent *event,
                             Boolean *continue_to_dispatch);
 
@@ -175,6 +165,206 @@ Lisp_Object Qsans_modifiers;
    use a pop-up-window instead.)
  */
 
    use a pop-up-window instead.)
  */
 
+/* For every key on the keyboard that has a known character correspondence,
+   we define the ascii-character property of the keysym, and make the
+   default binding for the key be self-insert-command.
+
+   The following magic is basically intimate knowledge of X11/keysymdef.h.
+   The keysym mappings defined by X11 are based on the iso8859 standards,
+   except for Cyrillic and Greek.
+
+   In a non-Mule world, a user can still have a multi-lingual editor, by doing
+   (set-face-font "...-iso8859-2" (current-buffer))
+   for all their Latin-2 buffers, etc.  */
+
+static Lisp_Object
+x_keysym_to_character (KeySym keysym)
+{
+#ifdef MULE
+  Lisp_Object charset = Qzero;
+#define USE_CHARSET(var,cs) \
+  ((var) = CHARSET_BY_LEADING_BYTE (LEADING_BYTE_##cs))
+#else
+#define USE_CHARSET(var,lb)
+#endif /* MULE */
+  int code = 0;
+
+  if ((keysym & 0xff) < 0xa0)
+    return Qnil;
+
+  switch (keysym >> 8)
+    {
+    case 0: /* ASCII + Latin1 */
+      USE_CHARSET (charset, LATIN_ISO8859_1);
+      code = keysym & 0x7f;
+      break;
+    case 1: /* Latin2 */
+      USE_CHARSET (charset, LATIN_ISO8859_2);
+      code = keysym & 0x7f;
+      break;
+    case 2: /* Latin3 */
+      USE_CHARSET (charset, LATIN_ISO8859_3);
+      code = keysym & 0x7f;
+      break;
+    case 3: /* Latin4 */
+      USE_CHARSET (charset, LATIN_ISO8859_4);
+      code = keysym & 0x7f;
+      break;
+    case 4: /* Katakana */
+      USE_CHARSET (charset, KATAKANA_JISX0201);
+      if ((keysym & 0xff) > 0xa0)
+       code = keysym & 0x7f;
+      break;
+    case 5: /* Arabic */
+      USE_CHARSET (charset, ARABIC_ISO8859_6);
+      code = keysym & 0x7f;
+      break;
+    case 6: /* Cyrillic */
+      {
+       static unsigned char const cyrillic[] = /* 0x20 - 0x7f */
+       {0x00, 0x72, 0x73, 0x71, 0x74, 0x75, 0x76, 0x77,
+        0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x00, 0x7e, 0x7f,
+        0x70, 0x22, 0x23, 0x21, 0x24, 0x25, 0x26, 0x27,
+        0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x00, 0x2e, 0x2f,
+        0x6e, 0x50, 0x51, 0x66, 0x54, 0x55, 0x64, 0x53,
+        0x65, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
+        0x5f, 0x6f, 0x60, 0x61, 0x62, 0x63, 0x56, 0x52,
+        0x6c, 0x6b, 0x57, 0x68, 0x6d, 0x69, 0x67, 0x6a,
+        0x4e, 0x30, 0x31, 0x46, 0x34, 0x35, 0x44, 0x33,
+        0x45, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
+        0x3f, 0x4f, 0x40, 0x41, 0x42, 0x43, 0x36, 0x32,
+        0x4c, 0x4b, 0x37, 0x48, 0x4d, 0x49, 0x47, 0x4a};
+       USE_CHARSET (charset, CYRILLIC_ISO8859_5);
+       code = cyrillic[(keysym & 0x7f) - 0x20];
+       break;
+      }
+    case 7: /* Greek */
+      {
+       static unsigned char const greek[] = /* 0x20 - 0x7f */
+       {0x00, 0x36, 0x38, 0x39, 0x3a, 0x5a, 0x00, 0x3c,
+        0x3e, 0x5b, 0x00, 0x3f, 0x00, 0x00, 0x35, 0x2f,
+        0x00, 0x5c, 0x5d, 0x5e, 0x5f, 0x7a, 0x40, 0x7c,
+        0x7d, 0x7b, 0x60, 0x7e, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+        0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+        0x50, 0x51, 0x53, 0x00, 0x54, 0x55, 0x56, 0x57,
+        0x58, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+        0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+        0x70, 0x71, 0x73, 0x72, 0x74, 0x75, 0x76, 0x77,
+        0x78, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+       USE_CHARSET (charset, GREEK_ISO8859_7);
+       code = greek[(keysym & 0x7f) - 0x20];
+       break;
+      }
+    case 8: /* Technical */
+      break;
+    case 9: /* Special */
+      break;
+    case 10: /* Publishing */
+      break;
+    case 11: /* APL */
+      break;
+    case 12: /* Hebrew */
+      USE_CHARSET (charset, HEBREW_ISO8859_8);
+      code = keysym & 0x7f;
+      break;
+    case 13: /* Thai */
+      /* #### This needs to deal with character composition. */
+      USE_CHARSET (charset, THAI_TIS620);
+      code = keysym & 0x7f;
+      break;
+    case 14: /* Korean Hangul */
+      break;
+    case 19: /* Latin 9 - ISO8859-15 - unsupported charset. */
+      break;
+    case 32: /* Currency */
+      break;
+    default:
+      break;
+    }
+
+  if (code == 0)
+    return Qnil;
+
+#ifdef MULE
+  return make_char (MAKE_CHAR (charset, code, 0));
+#else
+  return make_char (code + 0x80);
+#endif
+}
+
+/* #### The way that keysym correspondence to characters should work:
+   - a Lisp_Event should contain a keysym AND a character slot.
+   - keybindings are tried with the keysym.  If no binding can be found,
+   and there is a corresponding character, call self-insert-command.
+
+   #### Nuke x-iso8859-1.el.
+   #### Nuke the Qascii_character property.
+   #### Nuke Vcharacter_set_property.
+*/
+static void
+maybe_define_x_key_as_self_inserting_character (KeySym keysym, Lisp_Object symbol)
+{
+  Lisp_Object character = x_keysym_to_character (keysym);
+
+  if (CHARP (character))
+    {
+      extern Lisp_Object Vcurrent_global_map;
+      extern Lisp_Object Qascii_character;
+      if (NILP (Flookup_key (Vcurrent_global_map, symbol, Qnil))) 
+        {
+         Fput (symbol, Qascii_character, character);
+         Fdefine_key (Vcurrent_global_map, symbol, Qself_insert_command); 
+        }
+    }
+}
+
+static void
+x_has_keysym (KeySym keysym, Lisp_Object hash_table, int with_modifiers)
+{
+  KeySym upper_lower[2];
+  int j;
+
+  if (keysym < 0x80) /* Optimize for ASCII keysyms */
+    return;
+
+  /* If you execute:
+     xmodmap -e 'keysym NN = scaron'
+     and then press (Shift scaron), X11 will return the different
+     keysym `Scaron', but  `xmodmap -pke'  might not even mention `Scaron'.
+     So we "register" both `scaron' and `Scaron'. */
+#ifdef HAVE_XCONVERTCASE
+  XConvertCase (keysym, &upper_lower[0], &upper_lower[1]);
+#else
+  upper_lower[0] = upper_lower[1] = keysym;
+#endif
+
+  for (j = 0; j < (upper_lower[0] == upper_lower[1] ? 1 : 2); j++)
+    {
+      char *name;
+      keysym = upper_lower[j];
+
+      name = XKeysymToString (keysym);
+      if (name)
+       {
+         /* X guarantees NAME to be in the Host Portable Character Encoding */
+         Lisp_Object sym = x_keysym_to_emacs_keysym (keysym, 0);
+         Lisp_Object new_value = with_modifiers ? Qt : Qsans_modifiers;
+         Lisp_Object old_value = Fgethash (sym, hash_table, Qnil);
+
+         if (! EQ (old_value, new_value)
+             && ! (EQ (old_value, Qsans_modifiers) &&
+                   EQ (new_value, Qt)))
+           {
+             maybe_define_x_key_as_self_inserting_character (keysym, sym);
+             Fputhash (build_ext_string (name, Qbinary), new_value, hash_table);
+             Fputhash (sym, new_value, hash_table);
+           }
+       }
+    }
+}
+
 static void
 x_reset_key_mapping (struct device *d)
 {
 static void
 x_reset_key_mapping (struct device *d)
 {
@@ -212,34 +402,18 @@ x_reset_key_mapping (struct device *d)
       if (keysym[0] == NoSymbol)
        continue;
 
       if (keysym[0] == NoSymbol)
        continue;
 
-      {
-       char *name = XKeysymToString (keysym[0]);
-       Lisp_Object sym = x_keysym_to_emacs_keysym (keysym[0], 0);
-       if (name)
-         {
-           Fputhash (build_string (name), Qsans_modifiers, hash_table);
-           Fputhash (sym, Qsans_modifiers, hash_table);
-         }
-      }
+      x_has_keysym (keysym[0], hash_table, 0);
 
       for (j = 1; j < keysyms_per_code; j++)
        {
          if (keysym[j] != keysym[0] &&
              keysym[j] != NoSymbol)
 
       for (j = 1; j < keysyms_per_code; j++)
        {
          if (keysym[j] != keysym[0] &&
              keysym[j] != NoSymbol)
-           {
-             char *name = XKeysymToString (keysym[j]);
-             Lisp_Object sym = x_keysym_to_emacs_keysym (keysym[j], 0);
-             if (name && NILP (Fgethash (sym, hash_table, Qnil)))
-               {
-                 Fputhash (build_string (name), Qt, hash_table);
-                 Fputhash (sym, Qt, hash_table);
-               }
-           }
+           x_has_keysym (keysym[j], hash_table, 1);
        }
     }
 }
 
        }
     }
 }
 
-static CONST char *
+static const char *
 index_to_name (int indice)
 {
   switch (indice)
 index_to_name (int indice)
 {
   switch (indice)
@@ -287,7 +461,14 @@ x_reset_modifier_mapping (struct device *d)
   xd->lock_interpretation = 0;
 
   if (xd->x_modifier_keymap)
   xd->lock_interpretation = 0;
 
   if (xd->x_modifier_keymap)
-    XFreeModifiermap (xd->x_modifier_keymap);
+    {
+      XFreeModifiermap (xd->x_modifier_keymap);
+      /* Set it to NULL in case we receive two MappingModifier events in a
+         row, and the second is processed during some CHECK_QUITs within
+         x_reset_key_mapping. If that happens, XFreeModifierMap will be
+         called twice on the same map, and we crash.  */
+      xd->x_modifier_keymap = NULL;
+    }
 
   x_reset_key_mapping (d);
 
 
   x_reset_key_mapping (d);
 
@@ -394,7 +575,7 @@ x_reset_modifier_mapping (struct device *d)
      be totally wrong. */
   if (mode_bit)
     {
      be totally wrong. */
   if (mode_bit)
     {
-      CONST char *warn = 0;
+      const char *warn = 0;
       if      (mode_bit == meta_bit)  warn = "Meta",  meta_bit  = 0;
       else if (mode_bit == hyper_bit) warn = "Hyper", hyper_bit = 0;
       else if (mode_bit == super_bit) warn = "Super", super_bit = 0;
       if      (mode_bit == meta_bit)  warn = "Meta",  meta_bit  = 0;
       else if (mode_bit == hyper_bit) warn = "Hyper", hyper_bit = 0;
       else if (mode_bit == super_bit) warn = "Super", super_bit = 0;
@@ -518,20 +699,29 @@ x_handle_sticky_modifiers (XEvent *ev, struct device *d)
     { /* Not a modifier key */
       Bool key_event_p = (type == KeyPress || type == KeyRelease);
 
     { /* Not a modifier key */
       Bool key_event_p = (type == KeyPress || type == KeyRelease);
 
-      if (type == KeyPress && !xd->last_downkey)
-       xd->last_downkey = keycode;
-      else if (type == ButtonPress ||
-              (type == KeyPress && xd->last_downkey &&
-               (keycode != xd->last_downkey ||
-                ev->xkey.time != xd->release_time)))
+      if (type == ButtonPress
+         || (type == KeyPress
+             && ((xd->last_downkey
+                  && ((keycode != xd->last_downkey
+                       || ev->xkey.time != xd->release_time)))
+                 || (INTP (Vmodifier_keys_sticky_time)
+                     && ev->xkey.time
+                     > (xd->modifier_release_time
+                        + XINT (Vmodifier_keys_sticky_time))))))
        {
          xd->need_to_add_mask = 0;
          xd->last_downkey = 0;
        }
        {
          xd->need_to_add_mask = 0;
          xd->last_downkey = 0;
        }
+      else if (type == KeyPress && !xd->last_downkey)
+       xd->last_downkey = keycode;
+
       if (type == KeyPress)
        xd->release_time = 0;
       if (type == KeyPress || type == ButtonPress)
       if (type == KeyPress)
        xd->release_time = 0;
       if (type == KeyPress || type == ButtonPress)
-       xd->down_mask = 0;
+       {
+         xd->down_mask = 0;
+         xd->modifier_release_time = 0;
+       }
 
       if (key_event_p)
         ev->xkey.state    |= xd->need_to_add_mask;
 
       if (key_event_p)
         ev->xkey.state    |= xd->need_to_add_mask;
@@ -553,7 +743,8 @@ x_handle_sticky_modifiers (XEvent *ev, struct device *d)
           So we assume that if the release and the next press
           occur at the same time, the key was actually auto-
           repeated.  Under Open-Windows, at least, this works. */
           So we assume that if the release and the next press
           occur at the same time, the key was actually auto-
           repeated.  Under Open-Windows, at least, this works. */
-       xd->release_time = key_event_p ? ev->xkey.time : ev->xbutton.time;
+       xd->modifier_release_time = xd->release_time
+         = key_event_p ? ev->xkey.time : ev->xbutton.time;
     }
   else                          /* Modifier key pressed */
     {
     }
   else                          /* Modifier key pressed */
     {
@@ -573,6 +764,15 @@ x_handle_sticky_modifiers (XEvent *ev, struct device *d)
          xd->need_to_add_mask = 0;
        }
 
          xd->need_to_add_mask = 0;
        }
 
+      if (xd->modifier_release_time
+         && INTP (Vmodifier_keys_sticky_time)
+         && (ev->xkey.time
+             > xd->modifier_release_time + XINT (Vmodifier_keys_sticky_time)))
+       {
+         xd->need_to_add_mask = 0;
+         xd->down_mask = 0;
+       }
+
 #define FROB(mask)                             \
 do {                                           \
   if (type == KeyPress)                                \
 #define FROB(mask)                             \
 do {                                           \
   if (type == KeyPress)                                \
@@ -598,6 +798,7 @@ do {                                                \
          xd->need_to_add_mask |= mask;         \
        }                                       \
     }                                          \
          xd->need_to_add_mask |= mask;         \
        }                                       \
     }                                          \
+  xd->modifier_release_time = ev->xkey.time;   \
 } while (0)
 
       for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++)
 } while (0)
 
       for (i = 0; i < xd->x_keysym_map_keysyms_per_code; i++)
@@ -674,7 +875,7 @@ emacs_Xt_mapping_action (Widget w, XEvent* event)
     case MappingKeyboard:  x_reset_key_mapping      (d); break;
     case MappingModifier:  x_reset_modifier_mapping (d); break;
     case MappingPointer:   /* Do something here? */      break;
     case MappingKeyboard:  x_reset_key_mapping      (d); break;
     case MappingModifier:  x_reset_modifier_mapping (d); break;
     case MappingPointer:   /* Do something here? */      break;
-    default: abort();
+    default: ABORT();
     }
 }
 
     }
 }
 
@@ -775,7 +976,11 @@ x_to_emacs_keysym (XKeyPressedEvent *event, int simple_p)
 
 #ifdef HAVE_XIM
   int len;
 
 #ifdef HAVE_XIM
   int len;
-  char buffer[64];
+  /* Some implementations of XmbLookupString don't return
+     XBufferOverflow correctly, so increase the size of the xim input
+     buffer from 64 to the more reasonable size 513, as Emacs has done.
+     From Kenichi Handa. */
+  char buffer[513];
   char *bufptr = buffer;
   int   bufsiz = sizeof (buffer);
   Status status;
   char *bufptr = buffer;
   int   bufsiz = sizeof (buffer);
   Status status;
@@ -808,11 +1013,12 @@ x_to_emacs_keysym (XKeyPressedEvent *event, int simple_p)
   len = XmImMbLookupString (XtWindowToWidget (event->display, event->window),
                            event, bufptr, bufsiz, &keysym, &status);
 #else /* XIM_XLIB */
   len = XmImMbLookupString (XtWindowToWidget (event->display, event->window),
                            event, bufptr, bufsiz, &keysym, &status);
 #else /* XIM_XLIB */
-  len = XmbLookupString (xic, event, bufptr, bufsiz, &keysym, &status);
+  if (xic)
+    len = XmbLookupString (xic, event, bufptr, bufsiz, &keysym, &status);
 #endif /* HAVE_XIM */
 
 #ifdef DEBUG_XEMACS
 #endif /* HAVE_XIM */
 
 #ifdef DEBUG_XEMACS
-  if (x_debug_events > 0)
+  if (debug_x_events > 0)
     {
       stderr_out ("   status=");
 #define print_status_when(S) if (status == S) stderr_out (#S)
     {
       stderr_out ("   status=");
 #define print_status_when(S) if (status == S) stderr_out (#S)
@@ -859,10 +1065,9 @@ x_to_emacs_keysym (XKeyPressedEvent *event, int simple_p)
        Lstream *istr;
        struct gcpro gcpro1, gcpro2;
 
        Lstream *istr;
        struct gcpro gcpro1, gcpro2;
 
-       fb_instream =
-          make_fixed_buffer_input_stream ((unsigned char *) bufptr, len);
+       fb_instream = make_fixed_buffer_input_stream (bufptr, len);
 
 
-        /* ### Use Fget_coding_system (Vcomposed_input_coding_system) */
+        /* #### Use Fget_coding_system (Vcomposed_input_coding_system) */
        instream =
          make_decoding_input_stream (XLSTREAM (fb_instream),
                                      Fget_coding_system (Qundecided));
        instream =
          make_decoding_input_stream (XLSTREAM (fb_instream),
                                      Fget_coding_system (Qundecided));
@@ -873,7 +1078,7 @@ x_to_emacs_keysym (XKeyPressedEvent *event, int simple_p)
         while ((ch = Lstream_get_emchar (istr)) != EOF)
           {
             Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
         while ((ch = Lstream_get_emchar (istr)) != EOF)
           {
             Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
-           struct Lisp_Event *ev = XEVENT (emacs_event);
+           Lisp_Event *ev          = XEVENT (emacs_event);
             ev->channel                    = DEVICE_CONSOLE (d);
             ev->event_type         = key_press_event;
             ev->timestamp          = event->time;
             ev->channel                    = DEVICE_CONSOLE (d);
             ev->event_type         = key_press_event;
             ev->timestamp          = event->time;
@@ -920,7 +1125,7 @@ set_last_server_timestamp (struct device *d, XEvent *x_event)
 }
 
 static int
 }
 
 static int
-x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
+x_event_to_emacs_event (XEvent *x_event, Lisp_Event *emacs_event)
 {
   Display *display    = x_event->xany.display;
   struct device *d    = get_device_from_display (display);
 {
   Display *display    = x_event->xany.display;
   struct device *d    = get_device_from_display (display);
@@ -942,7 +1147,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
     case ButtonPress:
     case ButtonRelease:
       {
     case ButtonPress:
     case ButtonRelease:
       {
-       unsigned int modifiers = 0;
+       int modifiers = 0;
        int shift_p, lock_p;
        Bool key_event_p = (x_event->type == KeyPress);
        unsigned int *state =
        int shift_p, lock_p;
        Bool key_event_p = (x_event->type == KeyPress);
        unsigned int *state =
@@ -969,11 +1174,30 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
 
        x_handle_sticky_modifiers (x_event, d);
 
 
        x_handle_sticky_modifiers (x_event, d);
 
-       if (*state & ControlMask)    modifiers |= MOD_CONTROL;
-       if (*state & xd->MetaMask)   modifiers |= MOD_META;
-       if (*state & xd->SuperMask)  modifiers |= MOD_SUPER;
-       if (*state & xd->HyperMask)  modifiers |= MOD_HYPER;
-       if (*state & xd->AltMask)    modifiers |= MOD_ALT;
+       if (*state & ControlMask)    modifiers |= XEMACS_MOD_CONTROL;
+       if (*state & xd->MetaMask)   modifiers |= XEMACS_MOD_META;
+       if (*state & xd->SuperMask)  modifiers |= XEMACS_MOD_SUPER;
+       if (*state & xd->HyperMask)  modifiers |= XEMACS_MOD_HYPER;
+       if (*state & xd->AltMask)    modifiers |= XEMACS_MOD_ALT;
+       {
+         int numero_de_botao = -1;
+
+         if (!key_event_p)
+           numero_de_botao = x_event->xbutton.button;
+
+         /* the button gets noted either in the button or the modifiers
+            field, but not both. */
+         if (numero_de_botao != 1 && (*state & Button1Mask))
+           modifiers |= XEMACS_MOD_BUTTON1;
+         if (numero_de_botao != 2 && (*state & Button2Mask))
+           modifiers |= XEMACS_MOD_BUTTON2;
+         if (numero_de_botao != 3 && (*state & Button3Mask))
+           modifiers |= XEMACS_MOD_BUTTON3;
+         if (numero_de_botao != 4 && (*state & Button4Mask))
+           modifiers |= XEMACS_MOD_BUTTON4;
+         if (numero_de_botao != 5 && (*state & Button5Mask))
+           modifiers |= XEMACS_MOD_BUTTON5;
+       }
 
        /* Ignore the Caps_Lock key if:
           - any other modifiers are down, so that Caps_Lock doesn't
 
        /* Ignore the Caps_Lock key if:
           - any other modifiers are down, so that Caps_Lock doesn't
@@ -986,7 +1210,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
        lock_p  = *state & LockMask;
 
        if (shift_p || lock_p)
        lock_p  = *state & LockMask;
 
        if (shift_p || lock_p)
-         modifiers |= MOD_SHIFT;
+         modifiers |= XEMACS_MOD_SHIFT;
 
        if (key_event_p)
          {
 
        if (key_event_p)
          {
@@ -1018,7 +1242,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
                ! (CHAR_OR_CHAR_INTP (keysym)
                   && keysym_obeys_caps_lock_p
                   ((KeySym) XCHAR_OR_CHAR_INT (keysym), d)))
                ! (CHAR_OR_CHAR_INTP (keysym)
                   && keysym_obeys_caps_lock_p
                   ((KeySym) XCHAR_OR_CHAR_INT (keysym), d)))
-             modifiers &= (~MOD_SHIFT);
+             modifiers &= (~XEMACS_MOD_SHIFT);
 
            /* If this key contains two distinct keysyms, that is,
               "shift" generates a different keysym than the
 
            /* If this key contains two distinct keysyms, that is,
               "shift" generates a different keysym than the
@@ -1030,13 +1254,13 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
               in the modifiers slot.  Neither the characters "a",
               "A", "2", nor "@" normally have the shift bit set.
               However, "F1" normally does. */
               in the modifiers slot.  Neither the characters "a",
               "A", "2", nor "@" normally have the shift bit set.
               However, "F1" normally does. */
-           if (modifiers & MOD_SHIFT)
+           if (modifiers & XEMACS_MOD_SHIFT)
              {
                int Mode_switch_p = *state & xd->ModeMask;
                KeySym bot = XLookupKeysym (ev, Mode_switch_p ? 2 : 0);
                KeySym top = XLookupKeysym (ev, Mode_switch_p ? 3 : 1);
                if (top && bot && top != bot)
              {
                int Mode_switch_p = *state & xd->ModeMask;
                KeySym bot = XLookupKeysym (ev, Mode_switch_p ? 2 : 0);
                KeySym top = XLookupKeysym (ev, Mode_switch_p ? 3 : 1);
                if (top && bot && top != bot)
-                 modifiers &= ~MOD_SHIFT;
+                 modifiers &= ~XEMACS_MOD_SHIFT;
              }
            emacs_event->event_type          = key_press_event;
            emacs_event->timestamp           = ev->time;
              }
            emacs_event->event_type          = key_press_event;
            emacs_event->timestamp           = ev->time;
@@ -1073,7 +1297,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
       {
         XMotionEvent *ev = &x_event->xmotion;
         struct frame *frame = x_window_to_frame (d, ev->window);
       {
         XMotionEvent *ev = &x_event->xmotion;
         struct frame *frame = x_window_to_frame (d, ev->window);
-        unsigned int modifiers = 0;
+        int modifiers = 0;
         XMotionEvent event2;
 
         if (! frame)
         XMotionEvent event2;
 
         if (! frame)
@@ -1102,12 +1326,17 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
         emacs_event->timestamp      = ev->time;
         emacs_event->event.motion.x = ev->x;
         emacs_event->event.motion.y = ev->y;
         emacs_event->timestamp      = ev->time;
         emacs_event->event.motion.x = ev->x;
         emacs_event->event.motion.y = ev->y;
-        if (ev->state & ShiftMask)     modifiers |= MOD_SHIFT;
-        if (ev->state & ControlMask)   modifiers |= MOD_CONTROL;
-        if (ev->state & xd->MetaMask)  modifiers |= MOD_META;
-        if (ev->state & xd->SuperMask) modifiers |= MOD_SUPER;
-        if (ev->state & xd->HyperMask) modifiers |= MOD_HYPER;
-        if (ev->state & xd->AltMask)   modifiers |= MOD_ALT;
+        if (ev->state & ShiftMask)     modifiers |= XEMACS_MOD_SHIFT;
+        if (ev->state & ControlMask)   modifiers |= XEMACS_MOD_CONTROL;
+        if (ev->state & xd->MetaMask)  modifiers |= XEMACS_MOD_META;
+        if (ev->state & xd->SuperMask) modifiers |= XEMACS_MOD_SUPER;
+        if (ev->state & xd->HyperMask) modifiers |= XEMACS_MOD_HYPER;
+        if (ev->state & xd->AltMask)   modifiers |= XEMACS_MOD_ALT;
+        if (ev->state & Button1Mask)   modifiers |= XEMACS_MOD_BUTTON1;
+        if (ev->state & Button2Mask)   modifiers |= XEMACS_MOD_BUTTON2;
+        if (ev->state & Button3Mask)   modifiers |= XEMACS_MOD_BUTTON3;
+        if (ev->state & Button4Mask)   modifiers |= XEMACS_MOD_BUTTON4;
+        if (ev->state & Button5Mask)   modifiers |= XEMACS_MOD_BUTTON5;
         /* Currently ignores Shift_Lock but probably shouldn't
            (but it definitely should ignore Caps_Lock). */
         emacs_event->event.motion.modifiers = modifiers;
         /* Currently ignores Shift_Lock but probably shouldn't
            (but it definitely should ignore Caps_Lock). */
         emacs_event->event.motion.modifiers = modifiers;
@@ -1123,7 +1352,9 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
 #ifdef HAVE_OFFIX_DND
        if (DndIsDropMessage(x_event))
          {
 #ifdef HAVE_OFFIX_DND
        if (DndIsDropMessage(x_event))
          {
-           unsigned int state, modifiers = 0, button=0;
+           unsigned int state;
+           int modifiers = 0;
+           unsigned int button=0;
            struct frame *frame = x_any_window_to_frame (d, ev->window);
            Extbyte *data;
            unsigned long size, dtype;
            struct frame *frame = x_any_window_to_frame (d, ev->window);
            Extbyte *data;
            unsigned long size, dtype;
@@ -1131,10 +1362,10 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
            Lisp_Object l_dndlist = Qnil, l_item = Qnil;
            struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
            Lisp_Object l_dndlist = Qnil, l_item = Qnil;
            struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
-           GCPRO4 (l_type, l_data, l_dndlist, l_item);
-
            if (! frame)
              return 0; /* not for us */
            if (! frame)
              return 0; /* not for us */
+
+           GCPRO4 (l_type, l_data, l_dndlist, l_item);
            XSETFRAME (emacs_event->channel, frame);
 
            emacs_event->event_type = misc_user_event;
            XSETFRAME (emacs_event->channel, frame);
 
            emacs_event->event_type = misc_user_event;
@@ -1142,12 +1373,17 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
 
            state=DndDragButtons(x_event);
 
 
            state=DndDragButtons(x_event);
 
-           if (state & ShiftMask)      modifiers |= MOD_SHIFT;
-           if (state & ControlMask)    modifiers |= MOD_CONTROL;
-           if (state & xd->MetaMask)   modifiers |= MOD_META;
-           if (state & xd->SuperMask)  modifiers |= MOD_SUPER;
-           if (state & xd->HyperMask)  modifiers |= MOD_HYPER;
-           if (state & xd->AltMask)    modifiers |= MOD_ALT;
+           if (state & ShiftMask)      modifiers |= XEMACS_MOD_SHIFT;
+           if (state & ControlMask)    modifiers |= XEMACS_MOD_CONTROL;
+           if (state & xd->MetaMask)   modifiers |= XEMACS_MOD_META;
+           if (state & xd->SuperMask)  modifiers |= XEMACS_MOD_SUPER;
+           if (state & xd->HyperMask)  modifiers |= XEMACS_MOD_HYPER;
+           if (state & xd->AltMask)    modifiers |= XEMACS_MOD_ALT;
+           if (state & Button1Mask)    modifiers |= XEMACS_MOD_BUTTON1;
+           if (state & Button2Mask)    modifiers |= XEMACS_MOD_BUTTON2;
+           if (state & Button3Mask)    modifiers |= XEMACS_MOD_BUTTON3;
+           if (state & Button4Mask)    modifiers |= XEMACS_MOD_BUTTON4;
+           if (state & Button5Mask)    modifiers |= XEMACS_MOD_BUTTON5;
 
            if (state & Button5Mask)    button = Button5;
            if (state & Button4Mask)    button = Button4;
 
            if (state & Button5Mask)    button = Button5;
            if (state & Button4Mask)    button = Button4;
@@ -1190,7 +1426,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
                                            make_string ((Bufbyte *)"8bit", 4),
                                            make_ext_string ((Extbyte *)data,
                                                             strlen((char *)data),
                                            make_string ((Bufbyte *)"8bit", 4),
                                            make_ext_string ((Extbyte *)data,
                                                             strlen((char *)data),
-                                                            FORMAT_CTEXT) ) );
+                                                            Qctext) ) );
                break;
              case DndMIME:
                /* we have to parse this in some way to extract
                break;
              case DndMIME:
                /* we have to parse this in some way to extract
@@ -1203,7 +1439,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
                l_type = Qdragdrop_MIME;
                l_dndlist = list1 ( make_ext_string ((Extbyte *)data,
                                                     strlen((char *)data),
                l_type = Qdragdrop_MIME;
                l_dndlist = list1 ( make_ext_string ((Extbyte *)data,
                                                     strlen((char *)data),
-                                                    FORMAT_BINARY) );
+                                                    Qbinary) );
                break;
              case DndFile:
              case DndDir:
                break;
              case DndFile:
              case DndDir:
@@ -1224,7 +1460,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
                   and escaping again will break them (cause % is unsave) */
                l_dndlist = list1 ( make_ext_string ((Extbyte *)data,
                                                     strlen ((char *)data),
                   and escaping again will break them (cause % is unsave) */
                l_dndlist = list1 ( make_ext_string ((Extbyte *)data,
                                                     strlen ((char *)data),
-                                                    FORMAT_FILENAME) );
+                                                    Qfile_name) );
                l_type = Qdragdrop_URL;
                break;
              default: /* Unknown, RawData and any other type */
                l_type = Qdragdrop_URL;
                break;
              default: /* Unknown, RawData and any other type */
@@ -1232,7 +1468,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
                                            make_string ((Bufbyte *)"8bit", 4),
                                            make_ext_string ((Extbyte *)data,
                                                             size,
                                            make_string ((Bufbyte *)"8bit", 4),
                                            make_ext_string ((Extbyte *)data,
                                                             size,
-                                                            FORMAT_BINARY) ) );
+                                                            Qbinary) ) );
                l_type = Qdragdrop_MIME;
                break;
              }
                l_type = Qdragdrop_MIME;
                break;
              }
@@ -1281,6 +1517,7 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
          case FocusIn:
          case FocusOut:         FROB(xfocus, window);            break;
          case VisibilityNotify: FROB(xvisibility, window);       break;
          case FocusIn:
          case FocusOut:         FROB(xfocus, window);            break;
          case VisibilityNotify: FROB(xvisibility, window);       break;
+         case CreateNotify: FROB(xcreatewindow, window);         break;
           default:
            w = x_event->xany.window;
            *x_event_copy = *x_event;
           default:
            w = x_event->xany.window;
            *x_event_copy = *x_event;
@@ -1310,8 +1547,18 @@ x_event_to_emacs_event (XEvent *x_event, struct Lisp_Event *emacs_event)
 static void
 handle_focus_event_1 (struct frame *f, int in_p)
 {
 static void
 handle_focus_event_1 (struct frame *f, int in_p)
 {
+  handle_focus_event_2 (XtWindow (FRAME_X_TEXT_WIDGET (f)), f, in_p);
+}
+
+static void
+handle_focus_event_2 (Window win, struct frame *f, int in_p)
+{
+  /* Although this treats focus differently for all widgets (including
+     the frame) it seems to work ok. */
+  Widget needs_it = XtWindowToWidget (FRAME_X_DISPLAY (f), win);
+
 #if XtSpecificationRelease > 5
 #if XtSpecificationRelease > 5
-  Widget focus_widget = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f));
+  widget_with_focus = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f));
 #endif
 #ifdef HAVE_XIM
   XIM_focus_event (f, in_p);
 #endif
 #ifdef HAVE_XIM
   XIM_focus_event (f, in_p);
@@ -1332,21 +1579,32 @@ handle_focus_event_1 (struct frame *f, int in_p)
      Unfortunately native widgets break the model because they grab
      the keyboard focus and nothing sets it back again. I cannot find
      any reasonable way to do this elsewhere so we assert here that
      Unfortunately native widgets break the model because they grab
      the keyboard focus and nothing sets it back again. I cannot find
      any reasonable way to do this elsewhere so we assert here that
-     the keybpard focus is on the emacs text widget. Menus and dialogs
+     the keyboard focus is on the emacs text widget. Menus and dialogs
      do this in their selection callback, but we don't want that since
      a button having focus is legitimate. An edit field having focus
      do this in their selection callback, but we don't want that since
      a button having focus is legitimate. An edit field having focus
-     is mandatory. Weirdly you get a FocusOut event when you glick in
-     a widget-glyph but you don't get a correspondng FocusIn when you
+     is mandatory. Weirdly you get a FocusOut event when you click in
+     a widget-glyph but you don't get a corresponding FocusIn when you
      click in the frame. Why is this?  */
      click in the frame. Why is this?  */
-  if (in_p 
-#if XtSpecificationRelease > 5      
-      && FRAME_X_TEXT_WIDGET (f) != focus_widget
+  if (in_p
+#if XtSpecificationRelease > 5
+      && needs_it != widget_with_focus
 #endif
       )
     {
 #endif
       )
     {
-      lw_set_keyboard_focus (FRAME_X_SHELL_WIDGET (f),
-                            FRAME_X_TEXT_WIDGET (f));
+      lw_set_keyboard_focus (FRAME_X_SHELL_WIDGET (f), needs_it);
     }
     }
+
+  /* If we are focusing on a native widget then record and exit. */
+  if (needs_it != FRAME_X_TEXT_WIDGET (f)) {
+    widget_with_focus = needs_it;
+    return;
+  }
+
+  /* We have the focus now. See comment in
+     emacs_Xt_handle_widget_losing_focus (). */
+  if (in_p)
+    widget_with_focus = NULL;
+
   /* do the generic event-stream stuff. */
   {
     Lisp_Object frm;
   /* do the generic event-stream stuff. */
   {
     Lisp_Object frm;
@@ -1363,6 +1621,40 @@ handle_focus_event_1 (struct frame *f, int in_p)
   }
 }
 
   }
 }
 
+/* Create a synthetic X focus event. */
+void
+enqueue_focus_event (Widget wants_it, Lisp_Object frame, int in_p)
+{
+  Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
+  Lisp_Event *ev          = XEVENT (emacs_event);
+  XEvent *x_event = &ev->event.magic.underlying_x_event;
+
+  x_event->type = in_p ? FocusIn : FocusOut;
+  x_event->xfocus.window = XtWindow (wants_it);
+
+  ev->channel              = frame;
+  ev->event_type           = magic_event;
+
+  enqueue_Xt_dispatch_event (emacs_event);
+}
+
+/* The idea here is that when a widget glyph gets unmapped we don't
+   want the focus to stay with it if it has focus - because it may
+   well just get deleted next and then we have lost the focus until the
+   user does something. So handle_focus_event_1 records the widget
+   with keyboard focus when FocusOut is processed, and then, when a
+   widget gets unmapped, it calls this function to restore focus if
+   appropriate. */
+void emacs_Xt_handle_widget_losing_focus (struct frame* f, Widget losing_widget);
+void
+emacs_Xt_handle_widget_losing_focus (struct frame* f, Widget losing_widget)
+{
+  if (losing_widget == widget_with_focus)
+    {
+      handle_focus_event_1 (f, 1);
+    }
+}
+
 /* This is called from the external-widget code */
 
 void emacs_Xt_handle_focus_event (XEvent *event);
 /* This is called from the external-widget code */
 
 void emacs_Xt_handle_focus_event (XEvent *event);
@@ -1539,8 +1831,62 @@ handle_client_message (struct frame *f, XEvent *event)
     }
 }
 
     }
 }
 
+/* #### I'm struggling to understand how the X event loop really works. 
+   Here is the problem:
+   
+   When widgets get mapped / changed etc the actual display updates
+   are done asynchronously via X events being processed - this
+   normally happens when XtAppProcessEvent() gets called. However, if
+   we are executing lisp code or even doing redisplay we won't
+   necessarily process X events for a very long time. This has the
+   effect of widgets only getting updated when XEmacs only goes into
+   idle, or some other event causes processing of the X event queue.
+
+   XtAppProcessEvent can get called from the following places:
+
+     emacs_Xt_next_event () - this is normal event processing, almost
+     any non-X event will take precedence and this means that we
+     cannot rely on it to do the right thing at the right time for
+     widget display.
+
+     drain_X_queue () - this happens when SIGIO gets tripped,
+     processing the event queue allows C-g to be checked for. It gets
+     called from emacs_Xt_event_pending_p ().
+
+   In order to solve this I have tried introducing a list primitive -
+   dispatch-non-command-events - which forces processing of X events
+   related to display. Unfortunately this has a number of problems,
+   one is that it is possible for event_stream_event_pending_p to
+   block for ever if there isn't actually an event. I guess this can
+   happen if we drop the synthetic event for reason. It also relies on
+   SIGIO processing which makes things rather fragile.
+
+   People have seen behaviour whereby XEmacs blocks until you move the
+   mouse. This seems to indicate that dispatch-non-command-events is
+   blocking. It may be that in a SIGIO world forcing SIGIO processing
+   does the wrong thing.
+*/
 static void
 static void
-emacs_Xt_handle_magic_event (struct Lisp_Event *emacs_event)
+emacs_Xt_force_event_pending (struct frame* f)
+{
+  XEvent event;
+
+  Display* dpy = DEVICE_X_DISPLAY (XDEVICE (FRAME_DEVICE  (f)));
+  event.xclient.type           = ClientMessage;
+  event.xclient.display                = dpy;
+  event.xclient.message_type   = XInternAtom (dpy, "BumpQueue", False);
+  event.xclient.format         = 32;
+  event.xclient.window         = 0;
+
+  /* Send the drop message */
+  XSendEvent(dpy, XtWindow (FRAME_X_SHELL_WIDGET (f)),
+            True, NoEventMask, &event);
+  /* We rely on SIGIO and friends to realise we have generated an
+     event. */
+}
+
+static void
+emacs_Xt_handle_magic_event (Lisp_Event *emacs_event)
 {
   /* This function can GC */
   XEvent *event = &emacs_event->event.magic.underlying_x_event;
 {
   /* This function can GC */
   XEvent *event = &emacs_event->event.magic.underlying_x_event;
@@ -1568,8 +1914,13 @@ emacs_Xt_handle_magic_event (struct Lisp_Event *emacs_event)
       break;
 
     case Expose:
       break;
 
     case Expose:
-      x_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y,
-                            event->xexpose.width, event->xexpose.height);
+      if (!check_for_ignored_expose (f, event->xexpose.x, event->xexpose.y,
+                                    event->xexpose.width, event->xexpose.height)
+         &&
+         !find_matching_subwindow (f, event->xexpose.x, event->xexpose.y,
+         event->xexpose.width, event->xexpose.height))
+       x_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y,
+                              event->xexpose.width, event->xexpose.height);
       break;
 
     case GraphicsExpose: /* This occurs when an XCopyArea's source area was
       break;
 
     case GraphicsExpose: /* This occurs when an XCopyArea's source area was
@@ -1616,7 +1967,7 @@ emacs_Xt_handle_magic_event (struct Lisp_Event *emacs_event)
       if (FRAME_X_EXTERNAL_WINDOW_P (f))
        break;
 #endif
       if (FRAME_X_EXTERNAL_WINDOW_P (f))
        break;
 #endif
-      handle_focus_event_1 (f, event->type == FocusIn);
+      handle_focus_event_2 (event->xfocus.window, f, event->type == FocusIn);
       break;
 
     case ClientMessage:
       break;
 
     case ClientMessage:
@@ -1647,6 +1998,9 @@ emacs_Xt_handle_magic_event (struct Lisp_Event *emacs_event)
 #endif
       break;
 
 #endif
       break;
 
+    case CreateNotify:
+      break;
+
     default:
       break;
     }
     default:
       break;
     }
@@ -1662,14 +2016,16 @@ static int timeout_id_tick;
 /* Xt interval id's might not fit into an int (they're pointers, as it
    happens), so we need to provide a conversion list. */
 
 /* Xt interval id's might not fit into an int (they're pointers, as it
    happens), so we need to provide a conversion list. */
 
-struct Xt_timeout
+/* pending_timeouts is a set (unordered), implemented as a stack.
+   completed_timeouts* is a queue. */
+static struct Xt_timeout
 {
   int id;
   XtIntervalId interval_id;
   struct Xt_timeout *next;
 {
   int id;
   XtIntervalId interval_id;
   struct Xt_timeout *next;
-} *pending_timeouts, *completed_timeouts;
+} *pending_timeouts, *completed_timeouts_head, *completed_timeouts_tail;
 
 
-struct Xt_timeout_blocktype
+static struct Xt_timeout_blocktype
 {
   Blocktype_declare (struct Xt_timeout);
 } *the_Xt_timeout_blocktype;
 {
   Blocktype_declare (struct Xt_timeout);
 } *the_Xt_timeout_blocktype;
@@ -1680,7 +2036,7 @@ Xt_timeout_callback (XtPointer closure, XtIntervalId *id)
 {
   struct Xt_timeout *timeout = (struct Xt_timeout *) closure;
   struct Xt_timeout *t2 = pending_timeouts;
 {
   struct Xt_timeout *timeout = (struct Xt_timeout *) closure;
   struct Xt_timeout *t2 = pending_timeouts;
-  /* Remove this one from the list of pending timeouts */
+  /* Remove this one from the set of pending timeouts */
   if (t2 == timeout)
     pending_timeouts = pending_timeouts->next;
   else
   if (t2 == timeout)
     pending_timeouts = pending_timeouts->next;
   else
@@ -1689,9 +2045,13 @@ Xt_timeout_callback (XtPointer closure, XtIntervalId *id)
       assert (t2->next);
       t2->next = t2->next->next;
     }
       assert (t2->next);
       t2->next = t2->next->next;
     }
-  /* Add this one to the list of completed timeouts */
-  timeout->next = completed_timeouts;
-  completed_timeouts = timeout;
+  /* Add this one to the queue of completed timeouts */
+  timeout->next = NULL;
+  if (completed_timeouts_head)
+    completed_timeouts_tail->next = timeout;
+  else
+    completed_timeouts_head = timeout;
+  completed_timeouts_tail = timeout;
 }
 
 static int
 }
 
 static int
@@ -1746,24 +2106,27 @@ emacs_Xt_remove_timeout (int id)
        XtRemoveTimeOut (timeout->interval_id);
     }
 
        XtRemoveTimeOut (timeout->interval_id);
     }
 
-  /* It could be that the Xt call back was already called but we didn't convert
-     into an Emacs event yet */
-  if (!timeout && completed_timeouts)
+  /* It could be that Xt_timeout_callback was already called but we didn't
+     convert into an Emacs event yet */
+  if (!timeout && completed_timeouts_head)
     {
     {
-      /* Code duplication! */
-      if (id == completed_timeouts->id)
+      /* Thank God for code duplication! */
+      if (id == completed_timeouts_head->id)
        {
        {
-         timeout = completed_timeouts;
-         completed_timeouts = completed_timeouts->next;
+         timeout = completed_timeouts_head;
+         completed_timeouts_head = completed_timeouts_head->next;
+         /* this may not be necessary? */
+         if (!completed_timeouts_head) completed_timeouts_tail = NULL;
        }
       else
        {
        }
       else
        {
-         t2 = completed_timeouts;
+         t2 = completed_timeouts_head;
          while (t2->next && t2->next->id != id) t2 = t2->next;
          while (t2->next && t2->next->id != id) t2 = t2->next;
-         if ( t2->next)   /*found it */
+         if (t2->next)   /* found it */
            {
              timeout = t2->next;
              t2->next = t2->next->next;
            {
              timeout = t2->next;
              t2->next = t2->next->next;
+             if (!t2->next) completed_timeouts_tail = t2;
            }
        }
     }
            }
        }
     }
@@ -1776,11 +2139,13 @@ emacs_Xt_remove_timeout (int id)
 }
 
 static void
 }
 
 static void
-Xt_timeout_to_emacs_event (struct Lisp_Event *emacs_event)
+Xt_timeout_to_emacs_event (Lisp_Event *emacs_event)
 {
 {
-  struct Xt_timeout *timeout = completed_timeouts;
+  struct Xt_timeout *timeout = completed_timeouts_head;
   assert (timeout);
   assert (timeout);
-  completed_timeouts = completed_timeouts->next;
+  completed_timeouts_head = completed_timeouts_head->next;
+  /* probably unnecessary */
+  if (!completed_timeouts_head) completed_timeouts_tail = NULL;
   emacs_event->event_type = timeout_event;
   /* timeout events have nil as channel */
   emacs_event->timestamp  = 0; /* #### wrong!! */
   emacs_event->event_type = timeout_event;
   /* timeout events have nil as channel */
   emacs_event->timestamp  = 0; /* #### wrong!! */
@@ -1943,7 +2308,7 @@ unselect_filedesc (int fd)
 }
 
 static void
 }
 
 static void
-emacs_Xt_select_process (struct Lisp_Process *p)
+emacs_Xt_select_process (Lisp_Process *p)
 {
   Lisp_Object process;
   int infd = event_stream_unixoid_select_process (p);
 {
   Lisp_Object process;
   int infd = event_stream_unixoid_select_process (p);
@@ -1953,7 +2318,7 @@ emacs_Xt_select_process (struct Lisp_Process *p)
 }
 
 static void
 }
 
 static void
-emacs_Xt_unselect_process (struct Lisp_Process *p)
+emacs_Xt_unselect_process (Lisp_Process *p)
 {
   int infd = event_stream_unixoid_unselect_process (p);
 
 {
   int infd = event_stream_unixoid_unselect_process (p);
 
@@ -1982,7 +2347,7 @@ emacs_Xt_delete_stream_pair (Lisp_Object instream, Lisp_Object outstream)
    If we've still got pointers to it in this file, we're gonna lose hard.
  */
 void
    If we've still got pointers to it in this file, we're gonna lose hard.
  */
 void
-debug_process_finalization (struct Lisp_Process *p)
+debug_process_finalization (Lisp_Process *p)
 {
 #if 0 /* #### */
   int i;
 {
 #if 0 /* #### */
   int i;
@@ -2002,25 +2367,27 @@ debug_process_finalization (struct Lisp_Process *p)
 }
 
 static void
 }
 
 static void
-Xt_process_to_emacs_event (struct Lisp_Event *emacs_event)
+Xt_process_to_emacs_event (Lisp_Event *emacs_event)
 {
   int i;
 {
   int i;
-  Lisp_Object process;
 
   assert (process_events_occurred > 0);
 
   assert (process_events_occurred > 0);
+
   for (i = 0; i < MAXDESC; i++)
     {
   for (i = 0; i < MAXDESC; i++)
     {
-      process = filedesc_with_input[i];
+      Lisp_Object process = filedesc_with_input[i];
       if (PROCESSP (process))
       if (PROCESSP (process))
-       break;
+       {
+         filedesc_with_input[i] = Qnil;
+         process_events_occurred--;
+         /* process events have nil as channel */
+         emacs_event->event_type = process_event;
+         emacs_event->timestamp  = 0; /* #### */
+         emacs_event->event.process.process = process;
+         return;
+       }
     }
     }
-  assert (i < MAXDESC);
-  filedesc_with_input[i] = Qnil;
-  process_events_occurred--;
-  /* process events have nil as channel */
-  emacs_event->event_type = process_event;
-  emacs_event->timestamp  = 0; /* #### */
-  emacs_event->event.process.process = process;
+  ABORT ();
 }
 
 static void
 }
 
 static void
@@ -2028,9 +2395,6 @@ emacs_Xt_select_console (struct console *con)
 {
   Lisp_Object console;
   int infd;
 {
   Lisp_Object console;
   int infd;
-#ifdef HAVE_GPM
-  int mousefd;
-#endif
 
   if (CONSOLE_X_P (con))
     return; /* X consoles are automatically selected for when we
 
   if (CONSOLE_X_P (con))
     return; /* X consoles are automatically selected for when we
@@ -2038,22 +2402,6 @@ emacs_Xt_select_console (struct console *con)
   infd = event_stream_unixoid_select_console (con);
   XSETCONSOLE (console, con);
   select_filedesc (infd, console);
   infd = event_stream_unixoid_select_console (con);
   XSETCONSOLE (console, con);
   select_filedesc (infd, console);
-#ifdef HAVE_GPM
-  /* On a stream device (ie: noninteractive), bad things can happen. */
-  if (EQ (CONSOLE_TYPE (con), Qtty)) {
-    mousefd = CONSOLE_TTY_MOUSE_FD (con);
-       /* We check filedesc_to_what_closure[fd] here because if you run
-       ** XEmacs from a TTY, it will fire up GPM, select the mouse fd, then
-       ** if you run gnuattach to connect to another TTY, it will fire up
-       ** GPM again, and try to reselect the mouse fd.  GPM uses the same
-       ** fd for every connection apparently, and select_filedesc will
-       ** fail its assertion if we try to select it twice.
-       */
-    if ((mousefd >= 0) && !filedesc_to_what_closure[mousefd]) {
-      select_filedesc (mousefd, console);
-    }
-  }
-#endif
 }
 
 static void
 }
 
 static void
@@ -2061,9 +2409,6 @@ emacs_Xt_unselect_console (struct console *con)
 {
   Lisp_Object console;
   int infd;
 {
   Lisp_Object console;
   int infd;
-#ifdef HAVE_GPM
-  int mousefd;
-#endif
 
   if (CONSOLE_X_P (con))
     return; /* X consoles are automatically selected for when we
 
   if (CONSOLE_X_P (con))
     return; /* X consoles are automatically selected for when we
@@ -2071,15 +2416,6 @@ emacs_Xt_unselect_console (struct console *con)
   infd = event_stream_unixoid_unselect_console (con);
   XSETCONSOLE (console, con);
   unselect_filedesc (infd);
   infd = event_stream_unixoid_unselect_console (con);
   XSETCONSOLE (console, con);
   unselect_filedesc (infd);
-#ifdef HAVE_GPM
-  /* On a stream device (ie: noninteractive), bad things can happen. */
-  if (EQ (CONSOLE_TYPE (con), Qtty)) {
-    mousefd = CONSOLE_TTY_MOUSE_FD (con);
-    if (mousefd >= 0) {
-      unselect_filedesc (mousefd);
-    }
-  }
-#endif
 }
 
 /* read an event from a tty, if one is available.  Returns non-zero
 }
 
 /* read an event from a tty, if one is available.  Returns non-zero
@@ -2091,7 +2427,7 @@ emacs_Xt_unselect_console (struct console *con)
    to be deleted.) */
 
 static int
    to be deleted.) */
 
 static int
-Xt_tty_to_emacs_event (struct Lisp_Event *emacs_event)
+Xt_tty_to_emacs_event (Lisp_Event *emacs_event)
 {
   int i;
 
 {
   int i;
 
@@ -2137,12 +2473,12 @@ describe_event_window (Window window, Display *display)
       char *buf = alloca_array (char, XSTRING_LENGTH (f->name) + 4);
       sprintf (buf, " \"%s\"", XSTRING_DATA (f->name));
       write_string_to_stdio_stream (stderr, 0, (Bufbyte *) buf, 0,
       char *buf = alloca_array (char, XSTRING_LENGTH (f->name) + 4);
       sprintf (buf, " \"%s\"", XSTRING_DATA (f->name));
       write_string_to_stdio_stream (stderr, 0, (Bufbyte *) buf, 0,
-                                   strlen (buf), FORMAT_TERMINAL);
+                                   strlen (buf), Qterminal, 1);
     }
   stderr_out ("\n");
 }
 
     }
   stderr_out ("\n");
 }
 
-static CONST char *
+static const char *
 XEvent_mode_to_string (int mode)
 {
   switch (mode)
 XEvent_mode_to_string (int mode)
 {
   switch (mode)
@@ -2155,7 +2491,7 @@ XEvent_mode_to_string (int mode)
   }
 }
 
   }
 }
 
-static CONST char *
+static const char *
 XEvent_detail_to_string (int detail)
 {
   switch (detail)
 XEvent_detail_to_string (int detail)
 {
   switch (detail)
@@ -2171,7 +2507,7 @@ XEvent_detail_to_string (int detail)
   }
 }
 
   }
 }
 
-static CONST char *
+static const char *
 XEvent_visibility_to_string (int state)
 {
   switch (state)
 XEvent_visibility_to_string (int state)
 {
   switch (state)
@@ -2233,7 +2569,7 @@ describe_event (XEvent *event)
     break;
 
     case Expose:
     break;
 
     case Expose:
-      if (x_debug_events > 1)
+      if (debug_x_events > 1)
        {
          XExposeEvent *ev = &event->xexpose;
          describe_event_window (ev->window, ev->display);
        {
          XExposeEvent *ev = &event->xexpose;
          describe_event_window (ev->window, ev->display);
@@ -2246,7 +2582,7 @@ describe_event (XEvent *event)
       break;
 
     case GraphicsExpose:
       break;
 
     case GraphicsExpose:
-      if (x_debug_events > 1)
+      if (debug_x_events > 1)
        {
          XGraphicsExposeEvent *ev = &event->xgraphicsexpose;
          describe_event_window (ev->drawable, ev->display);
        {
          XGraphicsExposeEvent *ev = &event->xgraphicsexpose;
          describe_event_window (ev->drawable, ev->display);
@@ -2263,7 +2599,7 @@ describe_event (XEvent *event)
 
     case EnterNotify:
     case LeaveNotify:
 
     case EnterNotify:
     case LeaveNotify:
-      if (x_debug_events > 1)
+      if (debug_x_events > 1)
        {
          XCrossingEvent *ev = &event->xcrossing;
          describe_event_window (ev->window, ev->display);
        {
          XCrossingEvent *ev = &event->xcrossing;
          describe_event_window (ev->window, ev->display);
@@ -2284,7 +2620,7 @@ describe_event (XEvent *event)
       break;
 
     case ConfigureNotify:
       break;
 
     case ConfigureNotify:
-      if (x_debug_events > 1)
+      if (debug_x_events > 1)
        {
          XConfigureEvent *ev = &event->xconfigure;
          describe_event_window (ev->window, ev->display);
        {
          XConfigureEvent *ev = &event->xconfigure;
          describe_event_window (ev->window, ev->display);
@@ -2298,7 +2634,7 @@ describe_event (XEvent *event)
       break;
 
     case VisibilityNotify:
       break;
 
     case VisibilityNotify:
-      if (x_debug_events > 1)
+      if (debug_x_events > 1)
        {
          XVisibilityEvent *ev = &event->xvisibility;
          describe_event_window (ev->window, ev->display);
        {
          XVisibilityEvent *ev = &event->xvisibility;
          describe_event_window (ev->window, ev->display);
@@ -2340,7 +2676,7 @@ describe_event (XEvent *event)
 
 static Lisp_Object dispatch_event_queue, dispatch_event_queue_tail;
 
 
 static Lisp_Object dispatch_event_queue, dispatch_event_queue_tail;
 
-static void
+void
 enqueue_Xt_dispatch_event (Lisp_Object event)
 {
   enqueue_event (event, &dispatch_event_queue, &dispatch_event_queue_tail);
 enqueue_Xt_dispatch_event (Lisp_Object event)
 {
   enqueue_event (event, &dispatch_event_queue, &dispatch_event_queue_tail);
@@ -2376,12 +2712,12 @@ signal_special_Xt_user_event (Lisp_Object channel, Lisp_Object function,
 }
 
 static void
 }
 
 static void
-emacs_Xt_next_event (struct Lisp_Event *emacs_event)
+emacs_Xt_next_event (Lisp_Event *emacs_event)
 {
  we_didnt_get_an_event:
 
   while (NILP (dispatch_event_queue) &&
 {
  we_didnt_get_an_event:
 
   while (NILP (dispatch_event_queue) &&
-        !completed_timeouts         &&
+        !completed_timeouts_head    &&
         !fake_event_occurred        &&
         !process_events_occurred    &&
         !tty_events_occurred)
         !fake_event_occurred        &&
         !process_events_occurred    &&
         !tty_events_occurred)
@@ -2435,7 +2771,7 @@ emacs_Xt_next_event (struct Lisp_Event *emacs_event)
       if (!Xt_tty_to_emacs_event (emacs_event))
        goto we_didnt_get_an_event;
     }
       if (!Xt_tty_to_emacs_event (emacs_event))
        goto we_didnt_get_an_event;
     }
-  else if (completed_timeouts)
+  else if (completed_timeouts_head)
     Xt_timeout_to_emacs_event (emacs_event);
   else if (fake_event_occurred)
     {
     Xt_timeout_to_emacs_event (emacs_event);
   else if (fake_event_occurred)
     {
@@ -2461,7 +2797,7 @@ emacs_Xt_event_handler (Widget wid /* unused */,
   Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
 
 #ifdef DEBUG_XEMACS
   Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
 
 #ifdef DEBUG_XEMACS
-  if (x_debug_events > 0)
+  if (debug_x_events > 0)
     {
       describe_event (event);
     }
     {
       describe_event (event);
     }
@@ -2621,8 +2957,47 @@ emacs_Xt_quit_p (void)
 static void
 drain_X_queue (void)
 {
 static void
 drain_X_queue (void)
 {
+  Lisp_Object devcons, concons;
+  CONSOLE_LOOP (concons)
+  {
+    struct console *con = XCONSOLE (XCAR (concons));
+    if (!con->input_enabled)
+      continue;
+
+    /* sjt sez: Have you tried the loop over devices with XtAppPending(),
+       not XEventsQueued()?
+       Ben Sigelman sez: No.
+       sjt sez: I'm guessing that the reason that your patch "works" is this:
+
+       +      struct device* d;
+       +      Display* display;
+       +      d = XDEVICE (XCAR (devcons));
+       +      if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d)) {
+
+       Ie, if the device goes down, XEmacs detects that and deletes it.
+       Then the if() fails (DEVICE_X_DISPLAY(d) is NULL), and we don't go
+       into the Xlib-of-no-return.  If you know different, I'd like to hear
+       about it. ;-)
+
+       These ideas haven't been tested; the code below works for Ben.
+    */
+    CONSOLE_DEVICE_LOOP (devcons, con)
+    {
+      struct device* d;
+      Display* display;
+      d = XDEVICE (XCAR (devcons));
+      if (DEVICE_X_P (d) && DEVICE_X_DISPLAY (d)) {
+        display = DEVICE_X_DISPLAY (d);
+        while (XEventsQueued (display, QueuedAfterReading))
+          XtAppProcessEvent (Xt_app_con, XtIMXEvent);
+      }
+    }
+  }
+  /* This is the old code, before Ben Sigelman's patch. */
+  /*
   while (XtAppPending (Xt_app_con) & XtIMXEvent)
     XtAppProcessEvent (Xt_app_con, XtIMXEvent);
   while (XtAppPending (Xt_app_con) & XtIMXEvent)
     XtAppProcessEvent (Xt_app_con, XtIMXEvent);
+  */
 }
 
 static int
 }
 
 static int
@@ -2727,7 +3102,11 @@ emacs_Xt_event_pending_p (int user_p)
   /* quit_check_signal_tick_count is volatile so try to avoid race conditions
      by using a temporary variable */
   tick_count_val = quit_check_signal_tick_count;
   /* quit_check_signal_tick_count is volatile so try to avoid race conditions
      by using a temporary variable */
   tick_count_val = quit_check_signal_tick_count;
-  if (last_quit_check_signal_tick_count != tick_count_val)
+  if (last_quit_check_signal_tick_count != tick_count_val
+#if !defined (SIGIO) || defined (CYGWIN)
+      || (XtIMXEvent & XtAppPending (Xt_app_con))
+#endif 
+      )
     {
       last_quit_check_signal_tick_count = tick_count_val;
 
     {
       last_quit_check_signal_tick_count = tick_count_val;
 
@@ -2745,6 +3124,21 @@ emacs_Xt_event_pending_p (int user_p)
   return 0;
 }
 
   return 0;
 }
 
+static int
+emacs_Xt_current_event_timestamp (struct console *c)
+{
+  /* semi-yuck. */
+  Lisp_Object devs = CONSOLE_DEVICE_LIST (c);
+
+  if (NILP (devs))
+    return 0;
+  else
+    {
+      struct device *d = XDEVICE (XCAR (devs));
+      return DEVICE_X_LAST_SERVER_TIMESTAMP (d);
+    }
+}
+
 \f
 /************************************************************************/
 /*            replacement for standard string-to-pixel converter        */
 \f
 /************************************************************************/
 /*            replacement for standard string-to-pixel converter        */
@@ -2761,10 +3155,10 @@ emacs_Xt_event_pending_p (int user_p)
    the '#if 0'.  Note, however, that I got "unknown structure"
    errors when I tried this. */
 XtConvertArgRec Const colorConvertArgs[] = {
    the '#if 0'.  Note, however, that I got "unknown structure"
    errors when I tried this. */
 XtConvertArgRec Const colorConvertArgs[] = {
-  {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
-   sizeof(Screen *)},
-  {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
-   sizeof(Colormap)}
+  { XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
+    sizeof (Screen *) },
+  { XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
+    sizeof (Colormap) }
 };
 
 #endif
 };
 
 #endif
@@ -2786,7 +3180,7 @@ XtConvertArgRec Const colorConvertArgs[] = {
 
 /* JH: We use this because I think there's a possibility this
    is called before the device is properly set up, in which case
 
 /* JH: We use this because I think there's a possibility this
    is called before the device is properly set up, in which case
-   I don't want to abort. */
+   I don't want to ABORT. */
 extern struct device *get_device_from_display_1 (Display *dpy);
 
 static
 extern struct device *get_device_from_display_1 (Display *dpy);
 
 static
@@ -2842,9 +3236,9 @@ Boolean EmacsXtCvtStringToPixel (
   if ((d = get_device_from_display_1(dpy))) {
     visual = DEVICE_X_VISUAL(d);
     if (colormap != DEVICE_X_COLORMAP(d)) {
   if ((d = get_device_from_display_1(dpy))) {
     visual = DEVICE_X_VISUAL(d);
     if (colormap != DEVICE_X_COLORMAP(d)) {
-      XtAppWarningMsg(the_app_con, "wierdColormap", "cvtStringToPixel",
+      XtAppWarningMsg(the_app_con, "weirdColormap", "cvtStringToPixel",
                      "XtToolkitWarning",
                      "XtToolkitWarning",
-                     "The colormap passed to cvtStringToPixel doesn't match the one registerd to the device.\n",
+                     "The colormap passed to cvtStringToPixel doesn't match the one registered to the device.\n",
                      NULL, 0);
       status = XAllocNamedColor(dpy, colormap, (char*)str, &screenColor, &exactColor);
     } else {
                      NULL, 0);
       status = XAllocNamedColor(dpy, colormap, (char*)str, &screenColor, &exactColor);
     } else {
@@ -2906,6 +3300,42 @@ static void EmacsFreePixel (
 
 \f
 /************************************************************************/
 
 \f
 /************************************************************************/
+/*            handle focus changes for native widgets                  */
+/************************************************************************/
+static void
+emacs_Xt_event_widget_focus_in (Widget   w,
+                               XEvent   *event,
+                               String   *params,
+                               Cardinal *num_params)
+{
+  struct frame* f =
+    x_any_widget_or_parent_to_frame (get_device_from_display (event->xany.display), w);
+
+  XtSetKeyboardFocus (FRAME_X_SHELL_WIDGET (f), w);
+}
+
+static void
+emacs_Xt_event_widget_focus_out (Widget   w,
+                                XEvent   *event,
+                                String   *params,
+                                Cardinal *num_params)
+{
+}
+
+static XtActionsRec widgetActionsList[] =
+{
+  {"widget-focus-in",  emacs_Xt_event_widget_focus_in  },
+  {"widget-focus-out", emacs_Xt_event_widget_focus_out },
+};
+
+static void
+emacs_Xt_event_add_widget_actions (XtAppContext ctx)
+{
+  XtAppAddActions (ctx, widgetActionsList, 2);
+}
+
+\f
+/************************************************************************/
 /*                            initialization                            */
 /************************************************************************/
 
 /*                            initialization                            */
 /************************************************************************/
 
@@ -2914,20 +3344,15 @@ syms_of_event_Xt (void)
 {
   defsymbol (&Qkey_mapping, "key-mapping");
   defsymbol (&Qsans_modifiers, "sans-modifiers");
 {
   defsymbol (&Qkey_mapping, "key-mapping");
   defsymbol (&Qsans_modifiers, "sans-modifiers");
+  defsymbol (&Qself_insert_command, "self-insert-command");
 }
 
 void
 }
 
 void
-vars_of_event_Xt (void)
+reinit_vars_of_event_Xt (void)
 {
 {
-  dispatch_event_queue = Qnil;
-  staticpro (&dispatch_event_queue);
-  dispatch_event_queue_tail = Qnil;
-
-  /* this function only makes safe calls */
-  init_what_input_once ();
-
   Xt_event_stream = xnew (struct event_stream);
   Xt_event_stream->event_pending_p      = emacs_Xt_event_pending_p;
   Xt_event_stream = xnew (struct event_stream);
   Xt_event_stream->event_pending_p      = emacs_Xt_event_pending_p;
+  Xt_event_stream->force_event_pending          = emacs_Xt_force_event_pending;
   Xt_event_stream->next_event_cb        = emacs_Xt_next_event;
   Xt_event_stream->handle_magic_event_cb = emacs_Xt_handle_magic_event;
   Xt_event_stream->add_timeout_cb       = emacs_Xt_add_timeout;
   Xt_event_stream->next_event_cb        = emacs_Xt_next_event;
   Xt_event_stream->handle_magic_event_cb = emacs_Xt_handle_magic_event;
   Xt_event_stream->add_timeout_cb       = emacs_Xt_add_timeout;
@@ -2939,15 +3364,26 @@ vars_of_event_Xt (void)
   Xt_event_stream->quit_p_cb            = emacs_Xt_quit_p;
   Xt_event_stream->create_stream_pair_cb = emacs_Xt_create_stream_pair;
   Xt_event_stream->delete_stream_pair_cb = emacs_Xt_delete_stream_pair;
   Xt_event_stream->quit_p_cb            = emacs_Xt_quit_p;
   Xt_event_stream->create_stream_pair_cb = emacs_Xt_create_stream_pair;
   Xt_event_stream->delete_stream_pair_cb = emacs_Xt_delete_stream_pair;
+  Xt_event_stream->current_event_timestamp_cb =
+    emacs_Xt_current_event_timestamp;
 
 
-  DEFVAR_BOOL ("modifier-keys-are-sticky", &modifier_keys_are_sticky /*
-*Non-nil makes modifier keys sticky.
-This means that you can release the modifier key before pressing down
-the key that you wish to be modified.  Although this is non-standard
-behavior, it is recommended because it reduces the strain on your hand,
-thus reducing the incidence of the dreaded Emacs-pinky syndrome.
-*/ );
-  modifier_keys_are_sticky = 0;
+  the_Xt_timeout_blocktype = Blocktype_new (struct Xt_timeout_blocktype);
+
+  last_quit_check_signal_tick_count = 0;
+
+  /* this function only makes safe calls */
+  init_what_input_once ();
+}
+
+void
+vars_of_event_Xt (void)
+{
+  reinit_vars_of_event_Xt ();
+
+  dispatch_event_queue = Qnil;
+  staticpro (&dispatch_event_queue);
+  dispatch_event_queue_tail = Qnil;
+  dump_add_root_object (&dispatch_event_queue_tail);
 
   DEFVAR_BOOL ("x-allow-sendevents", &x_allow_sendevents /*
 *Non-nil means to allow synthetic events.  Nil means they are ignored.
 
   DEFVAR_BOOL ("x-allow-sendevents", &x_allow_sendevents /*
 *Non-nil means to allow synthetic events.  Nil means they are ignored.
@@ -2956,19 +3392,15 @@ Beware: allowing emacs to process SendEvents opens a big security hole.
   x_allow_sendevents = 0;
 
 #ifdef DEBUG_XEMACS
   x_allow_sendevents = 0;
 
 #ifdef DEBUG_XEMACS
-  DEFVAR_INT ("x-debug-events", &x_debug_events /*
+  DEFVAR_INT ("debug-x-events", &debug_x_events /*
 If non-zero, display debug information about X events that XEmacs sees.
 Information is displayed on stderr.  Currently defined values are:
 
 1 == non-verbose output
 2 == verbose output
 */ );
 If non-zero, display debug information about X events that XEmacs sees.
 Information is displayed on stderr.  Currently defined values are:
 
 1 == non-verbose output
 2 == verbose output
 */ );
-  x_debug_events = 0;
+  debug_x_events = 0;
 #endif
 #endif
-
-  the_Xt_timeout_blocktype = Blocktype_new (struct Xt_timeout_blocktype);
-
-  last_quit_check_signal_tick_count = 0;
 }
 
 /* This mess is a hack that patches the shell widget to treat visual inheritance
 }
 
 /* This mess is a hack that patches the shell widget to treat visual inheritance
@@ -2997,8 +3429,9 @@ void
 init_event_Xt_late (void) /* called when already initialized */
 {
   timeout_id_tick = 1;
 init_event_Xt_late (void) /* called when already initialized */
 {
   timeout_id_tick = 1;
-  pending_timeouts = 0;
-  completed_timeouts = 0;
+  pending_timeouts = NULL;
+  completed_timeouts_head = NULL; /* queue is empty */
+  completed_timeouts_tail = NULL; /* just to be picky */
 
   event_stream = Xt_event_stream;
 
 
   event_stream = Xt_event_stream;
 
@@ -3010,12 +3443,12 @@ init_event_Xt_late (void) /* called when already initialized */
   Xt_app_con = XtCreateApplicationContext ();
   XtAppSetFallbackResources (Xt_app_con, (String *) x_fallback_resources);
 
   Xt_app_con = XtCreateApplicationContext ();
   XtAppSetFallbackResources (Xt_app_con, (String *) x_fallback_resources);
 
-  /* In xselect.c */
+  /* In select-x.c */
   x_selection_timeout = (XtAppGetSelectionTimeout (Xt_app_con) / 1000);
   XSetErrorHandler (x_error_handler);
   XSetIOErrorHandler (x_IO_error_handler);
 
   x_selection_timeout = (XtAppGetSelectionTimeout (Xt_app_con) / 1000);
   XSetErrorHandler (x_error_handler);
   XSetIOErrorHandler (x_IO_error_handler);
 
-#ifndef WINDOWSNT
+#ifndef WIN32_NATIVE
   XtAppAddInput (Xt_app_con, signal_event_pipe[0],
                 (XtPointer) (XtInputReadMask /* | XtInputExceptMask */),
                 Xt_what_callback, 0);
   XtAppAddInput (Xt_app_con, signal_event_pipe[0],
                 (XtPointer) (XtInputReadMask /* | XtInputExceptMask */),
                 Xt_what_callback, 0);
@@ -3032,6 +3465,8 @@ init_event_Xt_late (void) /* called when already initialized */
                         NULL, 0,
                         XtCacheByDisplay, EmacsFreeXIMStyles);
 #endif /* XIM_XLIB */
                         NULL, 0,
                         XtCacheByDisplay, EmacsFreeXIMStyles);
 #endif /* XIM_XLIB */
+  /* Add extra actions to native widgets to handle focus and friends. */
+  emacs_Xt_event_add_widget_actions (Xt_app_con);
 
   /* insert the visual inheritance patch/hack described above */
   orig_shell_init_proc = shellClassRec.core_class.initialize;
 
   /* insert the visual inheritance patch/hack described above */
   orig_shell_init_proc = shellClassRec.core_class.initialize;