]> code.delx.au - gnu-emacs/blobdiff - src/xterm.c
Condense Tramp entries.
[gnu-emacs] / src / xterm.c
index c5b0a8b00d31c5e91e9fe2309159bce318d5aeb5..a27ddb22612eb8ff4bac2b240652bb2fec4e8e8d 100644 (file)
@@ -97,17 +97,23 @@ Boston, MA 02111-1307, USA.  */
 #include <unistd.h>
 #endif
 
+#ifdef USE_GTK
+#include "gtkutil.h"
+#endif
+
 #ifdef USE_LUCID
 extern int xlwmenu_window_p P_ ((Widget w, Window window));
 extern void xlwmenu_redisplay P_ ((Widget));
 #endif
 
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
 
 extern void free_frame_menubar P_ ((struct frame *));
 extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
                                                    int));
+#endif
 
+#ifdef USE_X_TOOLKIT
 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
 #define HACK_EDITRES
 extern void _XEditResCheckMessages ();
@@ -138,7 +144,7 @@ extern void _XEditResCheckMessages ();
 
 #endif /* USE_X_TOOLKIT */
 
-#ifndef USE_X_TOOLKIT
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
 #define x_any_window_to_frame x_window_to_frame
 #define x_top_window_to_frame x_window_to_frame
 #endif
@@ -520,6 +526,12 @@ static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
                                            unsigned long *));
 static void x_check_fullscreen P_ ((struct frame *));
 static void x_check_fullscreen_move P_ ((struct frame *));
+static int handle_one_xevent P_ ((struct x_display_info *,
+                                  XEvent *,
+                                  struct input_event **,
+                                  int *,
+                                  int *));
+
 
 /* Flush display of frame F, or of all frames if F is null.  */
 
@@ -4330,6 +4342,7 @@ x_draw_image_glyph_string (s)
 
   height = s->height - 2 * box_line_vwidth;
 
+
   /* Fill background with face under the image.  Do it only if row is
      taller than image or if image has a clip mask to reduce
      flickering.  */
@@ -7074,7 +7087,7 @@ note_mouse_highlight (f, x, y)
   struct buffer *b;
 
   /* When a menu is active, don't highlight because this looks odd.  */
-#ifdef USE_X_TOOLKIT
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
   if (popup_activated ())
     return;
 #endif
@@ -8399,7 +8412,7 @@ static void
 x_process_timeouts (timer)
      struct atimer *timer;
 {
-  if (toolkit_scroll_bar_interaction || popup_activated_flag)
+  if (toolkit_scroll_bar_interaction || popup_activated ())
     {
       BLOCK_INPUT;
       while (XtAppPending (Xt_app_con) & XtIMTimer)
@@ -8494,10 +8507,6 @@ static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
                                                int, int, int));
 
 
-/* Id of action hook installed for scroll bars.  */
-
-static XtActionHookId action_hook_id;
-
 /* Lisp window being scrolled.  Set when starting to interact with
    a toolkit scroll bar, reset to nil when ending the interaction.  */
 
@@ -8510,6 +8519,11 @@ static int last_scroll_bar_part;
 /* Whether this is an Xaw with arrow-scrollbars.  This should imply
    that movements of 1/20 of the screen size are mapped to up/down.  */
 
+#ifndef USE_GTK
+/* Id of action hook installed for scroll bars.  */
+
+static XtActionHookId action_hook_id;
+
 static Boolean xaw3d_arrow_scroll;
 
 /* Whether the drag scrolling maintains the mouse at the top of the
@@ -8562,6 +8576,7 @@ xt_action_hook (widget, client_data, action_name, event, params,
       toolkit_scroll_bar_interaction = 0;
     }
 }
+#endif /* not USE_GTK */
 
 /* A vector of windows used for communication between
    x_send_scroll_bar_event and x_scroll_bar_to_input_event.  */
@@ -8655,7 +8670,11 @@ x_scroll_bar_to_input_event (event, ievent)
   ievent->kind = SCROLL_BAR_CLICK_EVENT;
   ievent->frame_or_window = window;
   ievent->arg = Qnil;
+#ifdef USE_GTK
+  ievent->timestamp = CurrentTime;
+#else
   ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
+#endif
   ievent->part = ev->data.l[1];
   ievent->code = ev->data.l[2];
   ievent->x = make_number ((int) ev->data.l[3]);
@@ -8749,8 +8768,80 @@ xm_scroll_callback (widget, client_data, call_data)
 }
 
 
-#else /* !USE_MOTIF, i.e. Xaw.  */
+#else /* !USE_MOTIF, i.e. Xaw or GTK */
+#ifdef USE_GTK
+/* Scroll bar callback for Gtk scroll bars.  WIDGET is the scroll
+   bar adjustment widget.  DATA is a pointer to the scroll_bar structure. */
+
+static void
+xg_scroll_callback (widget, data)
+     GtkWidget *widget;
+     gpointer data;
+{
+  struct scroll_bar *bar = (struct scroll_bar *) data;
+  gdouble previous;
+  gdouble position;
+  gdouble *p;
+  int diff;
+
+  int part = -1, whole = 0, portion = 0;
+  GtkAdjustment *adj = GTK_ADJUSTMENT (widget);
+
+  if (xg_ignore_gtk_scrollbar) return;
+
+  position = gtk_adjustment_get_value (adj);
+
+  p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA);
+  if (! p)
+    {
+      p = (gdouble*) xmalloc (sizeof (gdouble));
+      *p = XG_SB_MIN;
+      g_object_set_data (G_OBJECT (widget), XG_LAST_SB_DATA, p);
+    }
+
+  previous = *p;
+  *p = position;
+
+  diff = (int) (position - previous);
+
+  if (diff == (int) adj->step_increment)
+    {
+      part = scroll_bar_down_arrow;
+      bar->dragging = Qnil;
+    }
+  else if (-diff == (int) adj->step_increment)
+    {
+      part = scroll_bar_up_arrow;
+      bar->dragging = Qnil;
+    }
+  else if (diff == (int) adj->page_increment)
+    {
+      part = scroll_bar_below_handle;
+      bar->dragging = Qnil;
+    }
+  else if (-diff == (int) adj->page_increment)
+    {
+      part = scroll_bar_above_handle;
+      bar->dragging = Qnil;
+    }
+  else
+    {
+      part = scroll_bar_handle;
+      whole = adj->upper - adj->page_size;
+      portion = min (position, whole);
+      bar->dragging = make_number (portion);
+    }
+
+  if (part >= 0)
+    {
+      xg_ignore_next_thumb = 1;
+      window_being_scrolled = bar->window;
+      last_scroll_bar_part = part;
+      x_send_scroll_bar_event (bar->window, part, portion, whole);
+    }
+}
 
+#else /* not USE_GTK */
 
 /* Xaw scroll bar callback.  Invoked when the thumb is dragged.
    WIDGET is the scroll bar widget.  CLIENT_DATA is a pointer to the
@@ -8833,13 +8924,30 @@ xaw_scroll_callback (widget, client_data, call_data)
   x_send_scroll_bar_event (bar->window, part, position, height);
 }
 
-
+#endif /* not USE_GTK */
 #endif /* not USE_MOTIF */
 
+#define SCROLL_BAR_NAME "verticalScrollBar"
 
 /* Create the widget for scroll bar BAR on frame F.  Record the widget
    and X window of the scroll bar in BAR.  */
 
+#ifdef USE_GTK
+static void
+x_create_toolkit_scroll_bar (f, bar)
+     struct frame *f;
+     struct scroll_bar *bar;
+{
+  char *scroll_bar_name = SCROLL_BAR_NAME;
+
+  BLOCK_INPUT;
+  xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
+                        scroll_bar_name);
+  UNBLOCK_INPUT;
+}
+
+#else /* not USE_GTK */
+
 static void
 x_create_toolkit_scroll_bar (f, bar)
      struct frame *f;
@@ -8849,7 +8957,7 @@ x_create_toolkit_scroll_bar (f, bar)
   Widget widget;
   Arg av[20];
   int ac = 0;
-  char *scroll_bar_name = "verticalScrollBar";
+  char *scroll_bar_name = SCROLL_BAR_NAME;
   unsigned long pixel;
 
   BLOCK_INPUT;
@@ -9022,11 +9130,22 @@ x_create_toolkit_scroll_bar (f, bar)
 
   UNBLOCK_INPUT;
 }
+#endif /* not USE_GTK */
 
 
 /* Set the thumb size and position of scroll bar BAR.  We are currently
    displaying PORTION out of a whole WHOLE, and our position POSITION.  */
 
+#ifdef USE_GTK
+static void
+x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
+     struct scroll_bar *bar;
+     int portion, position, whole;
+{
+  xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
+}
+
+#else /* not USE_GTK */
 static void
 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
      struct scroll_bar *bar;
@@ -9149,6 +9268,7 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
 
   UNBLOCK_INPUT;
 }
+#endif /* not USE_GTK */
 
 #endif /* USE_TOOLKIT_SCROLL_BARS */
 
@@ -9237,6 +9357,15 @@ x_scroll_bar_create (w, top, left, width, height)
   /* Map the window/widget.  */
 #ifdef USE_TOOLKIT_SCROLL_BARS
   {
+#ifdef USE_GTK
+    xg_update_scrollbar_pos (f,
+                             SCROLL_BAR_X_WINDOW (bar),
+                             top,
+                             left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                             width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
+                             max (height, 1));
+    xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar));
+#else /* not USE_GTK */
     Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
     XtConfigureWidget (scroll_bar,
                       left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
@@ -9244,6 +9373,7 @@ x_scroll_bar_create (w, top, left, width, height)
                       width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
                       max (height, 1), 0);
     XtMapWidget (scroll_bar);
+#endif /* not USE_GTK */
     }
 #else /* not USE_TOOLKIT_SCROLL_BARS */
   XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
@@ -9378,7 +9508,11 @@ x_scroll_bar_remove (bar)
   BLOCK_INPUT;
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_GTK
+  xg_remove_scroll_bar (f, SCROLL_BAR_X_WINDOW (bar));
+#else /* not USE_GTK */
   XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
+#endif /* not USE_GTK */
 #else
   XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
 #endif
@@ -9472,20 +9606,30 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
 
+#ifdef USE_GTK
+      if (mask)
+        xg_update_scrollbar_pos (f,
+                                 SCROLL_BAR_X_WINDOW (bar),
+                                 top,
+                                 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                                 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
+                                 max (height, 1));
+#else /* not USE_GTK */
+
       /* Since toolkit scroll bars are smaller than the space reserved
-        for them on the frame, we have to clear "under" them.  */
+         for them on the frame, we have to clear "under" them.  */
       if (width > 0 && height > 0)
-       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                     left, top, width, height, False);
-
+        x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                          left, top, width, height, False);
       /* Move/size the scroll bar widget.  */
       if (mask)
-       XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
-                          sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                          top,
-                          sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-                          max (height, 1), 0);
+          XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
+                             sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                             top,
+                             sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
+                             max (height, 1), 0);
 
+#endif /* not USE_GTK */
 #else /* not USE_TOOLKIT_SCROLL_BARS */
 
       /* Clear areas not covered by the scroll bar because of
@@ -9934,51 +10078,6 @@ x_scroll_bar_clear (f)
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
 }
 
-/* This processes Expose events from the menu-bar specific X event
-   loop in xmenu.c.  This allows to redisplay the frame if necessary
-   when handling menu-bar or pop-up items.  */
-
-int
-process_expose_from_menu (event)
-     XEvent event;
-{
-  FRAME_PTR f;
-  struct x_display_info *dpyinfo;
-  int frame_exposed_p = 0;
-
-  BLOCK_INPUT;
-
-  dpyinfo = x_display_info_for_display (event.xexpose.display);
-  f = x_window_to_frame (dpyinfo, event.xexpose.window);
-  if (f)
-    {
-      if (f->async_visible == 0)
-       {
-         f->async_visible = 1;
-         f->async_iconified = 0;
-         f->output_data.x->has_been_visible = 1;
-         SET_FRAME_GARBAGED (f);
-       }
-      else
-       {
-         expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
-                       event.xexpose.x, event.xexpose.y,
-                       event.xexpose.width, event.xexpose.height);
-         frame_exposed_p = 1;
-       }
-    }
-  else
-    {
-      struct scroll_bar *bar
-       = x_window_to_scroll_bar (event.xexpose.window);
-
-      if (bar)
-       x_scroll_bar_expose (bar, &event);
-    }
-
-  UNBLOCK_INPUT;
-  return frame_exposed_p;
-}
 \f
 /* Define a queue to save up SelectionRequest events for later handling.  */
 
@@ -10107,131 +10206,132 @@ static struct x_display_info *next_noop_dpyinfo;
 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
 #define SET_SAVED_KEY_EVENT    SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
 
-/* Read events coming from the X server.
-   This routine is called by the SIGIO handler.
-   We return as soon as there are no more events to be read.
 
-   Events representing keys are stored in buffer BUFP,
-   which can hold up to NUMCHARS characters.
-   We return the number of characters stored into the buffer,
-   thus pretending to be `read'.
+enum
+{
+  X_EVENT_NORMAL,
+  X_EVENT_GOTO_OUT,
+  X_EVENT_DROP
+};
 
-   EXPECTED is nonzero if the caller knows input is available.  */
+/* Filter events for the current X input method.
+   DPYINFO is the display this event is for.
+   EVENT is the X event to filter.
 
+   Returns non-zero if the event was filtered, caller shall not process
+   this event further.
+   Returns zero if event is wasn't filtered.  */
+
+#ifdef HAVE_X_I18N
 static int
-XTread_socket (sd, bufp, numchars, expected)
-     register int sd;
-     /* register */ struct input_event *bufp;
-     /* register */ int numchars;
-     int expected;
+x_filter_event (dpyinfo, event)
+     struct x_display_info *dpyinfo;
+     XEvent *event;
 {
-  int count = 0;
-  int nbytes = 0;
-  XEvent event;
-  struct frame *f;
-  int event_found = 0;
-  struct x_display_info *dpyinfo;
-  struct coding_system coding;
+  /* XFilterEvent returns non-zero if the input method has
+   consumed the event.  We pass the frame's X window to
+   XFilterEvent because that's the one for which the IC
+   was created.  */
 
-  if (interrupt_input_blocked)
-    {
-      interrupt_input_pending = 1;
-      return -1;
-    }
-
-  interrupt_input_pending = 0;
-  BLOCK_INPUT;
+  struct frame *f1 = x_any_window_to_frame (dpyinfo,
+                                            event->xclient.window);
 
-  /* So people can tell when we have read the available input.  */
-  input_signal_count++;
+  return XFilterEvent (event, f1 ? FRAME_X_WINDOW (f1) : None);
+}
+#endif
 
-  if (numchars <= 0)
-    abort ();                  /* Don't think this happens.  */
+#ifdef USE_GTK
+static struct x_display_info *current_dpyinfo;
+static struct input_event **current_bufp;
+static int *current_numcharsp;
+static int current_count;
+static int current_finish;
 
-  ++handling_signal;
+/* This is the filter function invoked by the GTK event loop.
+   It is invoked before the XEvent is translated to a GdkEvent,
+   so we have a chanse to act on the event before GTK. */
+static GdkFilterReturn
+event_handler_gdk (gxev, ev, data)
+     GdkXEvent *gxev;
+     GdkEvent *ev;
+     gpointer data;
+{
+  XEvent *xev = (XEvent*)gxev;
 
-  /* Find the display we are supposed to read input for.
-     It's the one communicating on descriptor SD.  */
-  for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
+  if (current_numcharsp)
     {
-#if 0 /* This ought to be unnecessary; let's verify it.  */
-#ifdef FIOSNBIO
-      /* If available, Xlib uses FIOSNBIO to make the socket
-        non-blocking, and then looks for EWOULDBLOCK.  If O_NDELAY is set,
-        FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
-        a read returns 0, which Xlib interprets as equivalent to EPIPE.  */
-      fcntl (dpyinfo->connection, F_SETFL, 0);
-#endif /* ! defined (FIOSNBIO) */
+#ifdef HAVE_X_I18N
+      /* Filter events for the current X input method.
+         GTK calls XFilterEvent but not for key press and release,
+         so we do it here.  */
+      if (xev->type == KeyPress || xev->type == KeyRelease)
+        if (x_filter_event (current_dpyinfo, xev))
+          return GDK_FILTER_REMOVE;
 #endif
+      current_count += handle_one_xevent (current_dpyinfo,
+                                          xev,
+                                          current_bufp,
+                                          current_numcharsp,
+                                          &current_finish);
+    }
+  else
+    current_finish = x_dispatch_event (xev, GDK_DISPLAY ());
 
-#if 0 /* This code can't be made to work, with multiple displays,
-        and appears not to be used on any system any more.
-        Also keyboard.c doesn't turn O_NDELAY on and off
-        for X connections.  */
-#ifndef SIGIO
-#ifndef HAVE_SELECT
-      if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
-       {
-         extern int read_alarm_should_throw;
-         read_alarm_should_throw = 1;
-         XPeekEvent (dpyinfo->display, &event);
-         read_alarm_should_throw = 0;
-       }
-#endif /* HAVE_SELECT */
-#endif /* SIGIO */
-#endif
+  if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
+    return GDK_FILTER_REMOVE;
 
-      /* For debugging, this gives a way to fake an I/O error.  */
-      if (dpyinfo == XTread_socket_fake_io_error)
-       {
-         XTread_socket_fake_io_error = 0;
-         x_io_error_quitter (dpyinfo->display);
-       }
+  return GDK_FILTER_CONTINUE;
+}
+#endif /* USE_GTK */
 
-#ifdef HAVE_X_SM
-      BLOCK_INPUT;
-      count += x_session_check_input (bufp, &numchars);
-      UNBLOCK_INPUT;
-#endif
 
-      while (XPending (dpyinfo->display))
-       {
-         XNextEvent (dpyinfo->display, &event);
+/* Handles the XEvent EVENT on display DPYINFO.
 
-#ifdef HAVE_X_I18N
-         {
-           /* Filter events for the current X input method.
-              XFilterEvent returns non-zero if the input method has
-              consumed the event.  We pass the frame's X window to
-              XFilterEvent because that's the one for which the IC
-              was created.  */
-           struct frame *f1 = x_any_window_to_frame (dpyinfo,
-                                                     event.xclient.window);
-           if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
-             break;
-         }
-#endif
-         event_found = 1;
+   *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
+   *FINISH is zero if caller should continue reading events.
+   *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
 
-         switch (event.type)
-           {
-           case ClientMessage:
-             {
-               if (event.xclient.message_type
-                   == dpyinfo->Xatom_wm_protocols
-                   && event.xclient.format == 32)
-                 {
-                   if (event.xclient.data.l[0]
-                       == dpyinfo->Xatom_wm_take_focus)
-                     {
-                       /* Use x_any_window_to_frame because this
-                          could be the shell widget window
-                          if the frame has no title bar.  */
-                       f = x_any_window_to_frame (dpyinfo, event.xclient.window);
+   Events representing keys are stored in buffer *BUFP_R,
+   which can hold up to *NUMCHARSP characters.
+   We return the number of characters stored into the buffer. */
+
+static int
+handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
+     struct x_display_info *dpyinfo;
+     XEvent *eventp;
+     /* register */ struct input_event **bufp_r;
+     /* register */ int *numcharsp;
+     int *finish;
+{
+  int count = 0;
+  int nbytes = 0;
+  struct frame *f;
+  struct coding_system coding;
+  struct input_event *bufp = *bufp_r;
+  int numchars = *numcharsp;
+  XEvent event = *eventp;
+
+  *finish = X_EVENT_NORMAL;
+
+  switch (event.type)
+    {
+    case ClientMessage:
+      {
+        if (event.xclient.message_type
+            == dpyinfo->Xatom_wm_protocols
+            && event.xclient.format == 32)
+          {
+            if (event.xclient.data.l[0]
+                == dpyinfo->Xatom_wm_take_focus)
+              {
+                /* Use x_any_window_to_frame because this
+                   could be the shell widget window
+                   if the frame has no title bar.  */
+                f = x_any_window_to_frame (dpyinfo, event.xclient.window);
 #ifdef HAVE_X_I18N
-                       /* Not quite sure this is needed -pd */
-                       if (f && FRAME_XIC (f))
-                         XSetICFocus (FRAME_XIC (f));
+                /* Not quite sure this is needed -pd */
+                if (f && FRAME_XIC (f))
+                  XSetICFocus (FRAME_XIC (f));
 #endif
 #if 0 /* Emacs sets WM hints whose `input' field is `true'.  This
         instructs the WM to set the input focus automatically for
@@ -10246,1165 +10346,1383 @@ XTread_socket (sd, bufp, numchars, expected)
         below can generate additional FocusIn events which confuse
         Emacs.  */
 
-                       /* Since we set WM_TAKE_FOCUS, we must call
-                          XSetInputFocus explicitly.  But not if f is null,
-                          since that might be an event for a deleted frame.  */
-                       if (f)
-                         {
-                           Display *d = event.xclient.display;
-                           /* Catch and ignore errors, in case window has been
-                              iconified by a window manager such as GWM.  */
-                           int count = x_catch_errors (d);
-                           XSetInputFocus (d, event.xclient.window,
-                                           /* The ICCCM says this is
-                                              the only valid choice.  */
-                                           RevertToParent,
-                                           event.xclient.data.l[1]);
-                           /* This is needed to detect the error
-                              if there is an error.  */
-                           XSync (d, False);
-                           x_uncatch_errors (d, count);
-                         }
-                       /* Not certain about handling scroll bars here */
+                /* Since we set WM_TAKE_FOCUS, we must call
+                   XSetInputFocus explicitly.  But not if f is null,
+                   since that might be an event for a deleted frame.  */
+                if (f)
+                  {
+                    Display *d = event.xclient.display;
+                    /* Catch and ignore errors, in case window has been
+                       iconified by a window manager such as GWM.  */
+                    int count = x_catch_errors (d);
+                    XSetInputFocus (d, event.xclient.window,
+                                    /* The ICCCM says this is
+                                       the only valid choice.  */
+                                    RevertToParent,
+                                    event.xclient.data.l[1]);
+                    /* This is needed to detect the error
+                       if there is an error.  */
+                    XSync (d, False);
+                    x_uncatch_errors (d, count);
+                  }
+                /* Not certain about handling scroll bars here */
 #endif /* 0 */
-                     }
-                   else if (event.xclient.data.l[0]
-                            == dpyinfo->Xatom_wm_save_yourself)
-                     {
-                       /* Save state modify the WM_COMMAND property to
-                          something which can reinstate us.  This notifies
-                          the session manager, who's looking for such a
-                          PropertyNotify.  Can restart processing when
-                          a keyboard or mouse event arrives.  */
-                        /* If we have a session manager, don't set this.
-                           KDE will then start two Emacsen, one for the
-                           session manager and one for this. */
-                       if (numchars > 0
+              }
+            else if (event.xclient.data.l[0]
+                     == dpyinfo->Xatom_wm_save_yourself)
+              {
+                /* Save state modify the WM_COMMAND property to
+                   something which can reinstate us.  This notifies
+                   the session manager, who's looking for such a
+                   PropertyNotify.  Can restart processing when
+                   a keyboard or mouse event arrives.  */
+                /* If we have a session manager, don't set this.
+                   KDE will then start two Emacsen, one for the
+                   session manager and one for this. */
+                if (numchars > 0
 #ifdef HAVE_X_SM
-                            && ! x_session_have_connection ()
+                    && ! x_session_have_connection ()
 #endif
-                            )
-                         {
-                           f = x_top_window_to_frame (dpyinfo,
-                                                      event.xclient.window);
-                           /* This is just so we only give real data once
-                              for a single Emacs process.  */
-                           if (f == SELECTED_FRAME ())
-                             XSetCommand (FRAME_X_DISPLAY (f),
-                                          event.xclient.window,
-                                          initial_argv, initial_argc);
-                           else if (f)
-                             XSetCommand (FRAME_X_DISPLAY (f),
-                                          event.xclient.window,
-                                          0, 0);
-                         }
-                     }
-                   else if (event.xclient.data.l[0]
-                            == dpyinfo->Xatom_wm_delete_window)
-                     {
-                       struct frame *f
-                         = x_any_window_to_frame (dpyinfo,
-                                                  event.xclient.window);
-
-                       if (f)
-                         {
-                           if (numchars == 0)
-                             abort ();
-
-                           bufp->kind = DELETE_WINDOW_EVENT;
-                           XSETFRAME (bufp->frame_or_window, f);
-                           bufp->arg = Qnil;
-                           bufp++;
+                    )
+                  {
+                    f = x_top_window_to_frame (dpyinfo,
+                                               event.xclient.window);
+                    /* This is just so we only give real data once
+                       for a single Emacs process.  */
+                    if (f == SELECTED_FRAME ())
+                      XSetCommand (FRAME_X_DISPLAY (f),
+                                   event.xclient.window,
+                                   initial_argv, initial_argc);
+                    else if (f)
+                      XSetCommand (FRAME_X_DISPLAY (f),
+                                   event.xclient.window,
+                                   0, 0);
+                  }
+              }
+            else if (event.xclient.data.l[0]
+                     == dpyinfo->Xatom_wm_delete_window)
+              {
+                struct frame *f
+                  = x_any_window_to_frame (dpyinfo,
+                                           event.xclient.window);
 
-                           count += 1;
-                           numchars -= 1;
-                         }
-                     }
-                 }
-               else if (event.xclient.message_type
-                        == dpyinfo->Xatom_wm_configure_denied)
-                 {
-                 }
-               else if (event.xclient.message_type
-                        == dpyinfo->Xatom_wm_window_moved)
-                 {
-                   int new_x, new_y;
-                   struct frame *f
-                     = x_window_to_frame (dpyinfo, event.xclient.window);
+                if (f)
+                  {
+                    if (numchars == 0)
+                      abort ();
 
-                   new_x = event.xclient.data.s[0];
-                   new_y = event.xclient.data.s[1];
+                    bufp->kind = DELETE_WINDOW_EVENT;
+                    XSETFRAME (bufp->frame_or_window, f);
+                    bufp->arg = Qnil;
+                    bufp++;
 
-                   if (f)
-                     {
-                       f->output_data.x->left_pos = new_x;
-                       f->output_data.x->top_pos = new_y;
-                     }
-                 }
+                    count += 1;
+                    numchars -= 1;
+                  }
+                else
+                  goto OTHER; /* May be a dialog that is to be removed  */
+              }
+          }
+        else if (event.xclient.message_type
+                 == dpyinfo->Xatom_wm_configure_denied)
+          {
+          }
+        else if (event.xclient.message_type
+                 == dpyinfo->Xatom_wm_window_moved)
+          {
+            int new_x, new_y;
+            struct frame *f
+              = x_window_to_frame (dpyinfo, event.xclient.window);
+
+            new_x = event.xclient.data.s[0];
+            new_y = event.xclient.data.s[1];
+
+            if (f)
+              {
+                f->output_data.x->left_pos = new_x;
+                f->output_data.x->top_pos = new_y;
+              }
+          }
 #ifdef HACK_EDITRES
-               else if (event.xclient.message_type
-                        == dpyinfo->Xatom_editres)
-                 {
-                   struct frame *f
-                     = x_any_window_to_frame (dpyinfo, event.xclient.window);
-                   _XEditResCheckMessages (f->output_data.x->widget, NULL,
-                                           &event, NULL);
-                 }
+        else if (event.xclient.message_type
+                 == dpyinfo->Xatom_editres)
+          {
+            struct frame *f
+              = x_any_window_to_frame (dpyinfo, event.xclient.window);
+            _XEditResCheckMessages (f->output_data.x->widget, NULL,
+                                    &event, NULL);
+          }
 #endif /* HACK_EDITRES */
-               else if ((event.xclient.message_type
-                         == dpyinfo->Xatom_DONE)
-                        || (event.xclient.message_type
-                            == dpyinfo->Xatom_PAGE))
-                 {
-                   /* Ghostview job completed.  Kill it.  We could
-                      reply with "Next" if we received "Page", but we
-                      currently never do because we are interested in
-                      images, only, which should have 1 page.  */
-                   Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
-                   struct frame *f
-                     = x_window_to_frame (dpyinfo, event.xclient.window);
-                   x_kill_gs_process (pixmap, f);
-                   expose_frame (f, 0, 0, 0, 0);
-                 }
+        else if ((event.xclient.message_type
+                  == dpyinfo->Xatom_DONE)
+                 || (event.xclient.message_type
+                     == dpyinfo->Xatom_PAGE))
+          {
+            /* Ghostview job completed.  Kill it.  We could
+               reply with "Next" if we received "Page", but we
+               currently never do because we are interested in
+               images, only, which should have 1 page.  */
+            Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
+            struct frame *f
+              = x_window_to_frame (dpyinfo, event.xclient.window);
+            x_kill_gs_process (pixmap, f);
+            expose_frame (f, 0, 0, 0, 0);
+          }
 #ifdef USE_TOOLKIT_SCROLL_BARS
-               /* Scroll bar callbacks send a ClientMessage from which
-                  we construct an input_event.  */
-               else if (event.xclient.message_type
-                        == dpyinfo->Xatom_Scrollbar)
-                 {
-                   x_scroll_bar_to_input_event (&event, bufp);
-                   ++bufp, ++count, --numchars;
-                   goto out;
-                 }
+        /* Scroll bar callbacks send a ClientMessage from which
+           we construct an input_event.  */
+        else if (event.xclient.message_type
+                 == dpyinfo->Xatom_Scrollbar)
+          {
+            x_scroll_bar_to_input_event (&event, bufp);
+            ++bufp, ++count, --numchars;
+            goto out;
+          }
 #endif /* USE_TOOLKIT_SCROLL_BARS */
-               else
-                 goto OTHER;
-             }
-             break;
+        else
+          goto OTHER;
+      }
+      break;
 
-           case SelectionNotify:
+    case SelectionNotify:
 #ifdef USE_X_TOOLKIT
-             if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
-               goto OTHER;
+      if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
+        goto OTHER;
 #endif /* not USE_X_TOOLKIT */
-             x_handle_selection_notify (&event.xselection);
-             break;
+      x_handle_selection_notify (&event.xselection);
+      break;
 
-           case SelectionClear:        /* Someone has grabbed ownership.  */
+    case SelectionClear:       /* Someone has grabbed ownership.  */
 #ifdef USE_X_TOOLKIT
-             if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
-               goto OTHER;
+      if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
+        goto OTHER;
 #endif /* USE_X_TOOLKIT */
-             {
-               XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
+      {
+        XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
 
-               if (numchars == 0)
-                 abort ();
+        if (numchars == 0)
+          abort ();
 
-               bufp->kind = SELECTION_CLEAR_EVENT;
-               SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
-               SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
-               SELECTION_EVENT_TIME (bufp) = eventp->time;
-               bufp->frame_or_window = Qnil;
-               bufp->arg = Qnil;
-               bufp++;
+        bufp->kind = SELECTION_CLEAR_EVENT;
+        SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
+        SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
+        SELECTION_EVENT_TIME (bufp) = eventp->time;
+        bufp->frame_or_window = Qnil;
+        bufp->arg = Qnil;
+        bufp++;
 
-               count += 1;
-               numchars -= 1;
-             }
-             break;
+        count += 1;
+        numchars -= 1;
+      }
+      break;
 
-           case SelectionRequest:      /* Someone wants our selection.  */
+    case SelectionRequest:     /* Someone wants our selection.  */
 #ifdef USE_X_TOOLKIT
-             if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
-               goto OTHER;
+      if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
+        goto OTHER;
 #endif /* USE_X_TOOLKIT */
-             if (x_queue_selection_requests)
-               x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
-                              &event);
-             else
-               {
-                 XSelectionRequestEvent *eventp
-                   = (XSelectionRequestEvent *) &event;
-
-                 if (numchars == 0)
-                   abort ();
-
-                 bufp->kind = SELECTION_REQUEST_EVENT;
-                 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
-                 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
-                 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
-                 SELECTION_EVENT_TARGET (bufp) = eventp->target;
-                 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
-                 SELECTION_EVENT_TIME (bufp) = eventp->time;
-                 bufp->frame_or_window = Qnil;
-                 bufp->arg = Qnil;
-                 bufp++;
-
-                 count += 1;
-                 numchars -= 1;
-               }
-             break;
+      if (x_queue_selection_requests)
+        x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
+                       &event);
+      else
+        {
+          XSelectionRequestEvent *eventp
+            = (XSelectionRequestEvent *) &event;
+
+          if (numchars == 0)
+            abort ();
+
+          bufp->kind = SELECTION_REQUEST_EVENT;
+          SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
+          SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
+          SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
+          SELECTION_EVENT_TARGET (bufp) = eventp->target;
+          SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
+          SELECTION_EVENT_TIME (bufp) = eventp->time;
+          bufp->frame_or_window = Qnil;
+          bufp->arg = Qnil;
+          bufp++;
+
+          count += 1;
+          numchars -= 1;
+        }
+      break;
 
-           case PropertyNotify:
+    case PropertyNotify:
 #if 0 /* This is plain wrong.  In the case that we are waiting for a
         PropertyNotify used as an ACK in incremental selection
         transfer, the property will be on the receiver's window.  */
 #if defined USE_X_TOOLKIT
-             if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
-               goto OTHER;
+      if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
+        goto OTHER;
 #endif
 #endif
-             x_handle_property_notify (&event.xproperty);
-             goto OTHER;
+      x_handle_property_notify (&event.xproperty);
+      goto OTHER;
 
-           case ReparentNotify:
-             f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
-             if (f)
-               {
-                 int x, y;
-                 f->output_data.x->parent_desc = event.xreparent.parent;
-                 x_real_positions (f, &x, &y);
-                 f->output_data.x->left_pos = x;
-                 f->output_data.x->top_pos = y;
-                  goto OTHER;
-               }
-             break;
+    case ReparentNotify:
+      f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
+      if (f)
+        {
+          int x, y;
+          f->output_data.x->parent_desc = event.xreparent.parent;
+          x_real_positions (f, &x, &y);
+          f->output_data.x->left_pos = x;
+          f->output_data.x->top_pos = y;
+          goto OTHER;
+        }
+      break;
 
-           case Expose:
-             f = x_window_to_frame (dpyinfo, event.xexpose.window);
-             if (f)
-               {
-                  x_check_fullscreen (f);
+    case Expose:
+      f = x_window_to_frame (dpyinfo, event.xexpose.window);
+      if (f)
+        {
+          x_check_fullscreen (f);
 
-                 if (f->async_visible == 0)
-                   {
-                     f->async_visible = 1;
-                     f->async_iconified = 0;
-                     f->output_data.x->has_been_visible = 1;
-                     SET_FRAME_GARBAGED (f);
-                   }
-                 else
-                   expose_frame (x_window_to_frame (dpyinfo,
-                                                    event.xexpose.window),
-                                 event.xexpose.x, event.xexpose.y,
-                                 event.xexpose.width, event.xexpose.height);
-               }
-             else
-               {
+          if (f->async_visible == 0)
+            {
+              f->async_visible = 1;
+              f->async_iconified = 0;
+              f->output_data.x->has_been_visible = 1;
+              SET_FRAME_GARBAGED (f);
+            }
+          else
+            expose_frame (x_window_to_frame (dpyinfo,
+                                             event.xexpose.window),
+                          event.xexpose.x, event.xexpose.y,
+                          event.xexpose.width, event.xexpose.height);
+        }
+      else
+        {
 #ifndef USE_TOOLKIT_SCROLL_BARS
-                 struct scroll_bar *bar;
+          struct scroll_bar *bar;
 #endif
 #if defined USE_LUCID
-                 /* Submenus of the Lucid menu bar aren't widgets
-                    themselves, so there's no way to dispatch events
-                    to them.  Recognize this case separately.  */
-                 {
-                   Widget widget
-                     = x_window_to_menu_bar (event.xexpose.window);
-                   if (widget)
-                     xlwmenu_redisplay (widget);
-                 }
+          /* Submenus of the Lucid menu bar aren't widgets
+             themselves, so there's no way to dispatch events
+             to them.  Recognize this case separately.  */
+          {
+            Widget widget
+              = x_window_to_menu_bar (event.xexpose.window);
+            if (widget)
+              xlwmenu_redisplay (widget);
+          }
 #endif /* USE_LUCID */
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
-                 /* Dispatch event to the widget.  */
-                 goto OTHER;
+          /* Dispatch event to the widget.  */
+          goto OTHER;
 #else /* not USE_TOOLKIT_SCROLL_BARS */
-                 bar = x_window_to_scroll_bar (event.xexpose.window);
+          bar = x_window_to_scroll_bar (event.xexpose.window);
 
-                 if (bar)
-                   x_scroll_bar_expose (bar, &event);
+          if (bar)
+            x_scroll_bar_expose (bar, &event);
 #ifdef USE_X_TOOLKIT
-                 else
-                   goto OTHER;
+          else
+            goto OTHER;
 #endif /* USE_X_TOOLKIT */
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
-               }
-             break;
+        }
+      break;
 
-           case GraphicsExpose:        /* This occurs when an XCopyArea's
-                                          source area was obscured or not
-                                          available.  */
-             f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
-             if (f)
-               {
-                 expose_frame (f,
-                               event.xgraphicsexpose.x, event.xgraphicsexpose.y,
-                               event.xgraphicsexpose.width,
-                               event.xgraphicsexpose.height);
-               }
+    case GraphicsExpose:       /* This occurs when an XCopyArea's
+                                   source area was obscured or not
+                                   available.  */
+      f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
+      if (f)
+        {
+          expose_frame (f,
+                        event.xgraphicsexpose.x, event.xgraphicsexpose.y,
+                        event.xgraphicsexpose.width,
+                        event.xgraphicsexpose.height);
+        }
 #ifdef USE_X_TOOLKIT
-             else
-               goto OTHER;
+      else
+        goto OTHER;
 #endif /* USE_X_TOOLKIT */
-             break;
-
-           case NoExpose:              /* This occurs when an XCopyArea's
-                                          source area was completely
-                                          available.  */
-             break;
+      break;
 
-           case UnmapNotify:
-             /* Redo the mouse-highlight after the tooltip has gone.  */
-             if (event.xmap.window == tip_window)
-               {
-                 tip_window = 0;
-                 redo_mouse_highlight ();
-               }
+    case NoExpose:             /* This occurs when an XCopyArea's
+                                   source area was completely
+                                   available.  */
+      break;
 
-             f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
-             if (f)            /* F may no longer exist if
-                                  the frame was deleted.  */
-               {
-                 /* While a frame is unmapped, display generation is
-                    disabled; you don't want to spend time updating a
-                    display that won't ever be seen.  */
-                 f->async_visible = 0;
-                 /* We can't distinguish, from the event, whether the window
-                    has become iconified or invisible.  So assume, if it
-                    was previously visible, than now it is iconified.
-                    But x_make_frame_invisible clears both
-                    the visible flag and the iconified flag;
-                    and that way, we know the window is not iconified now.  */
-                 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
-                   {
-                     f->async_iconified = 1;
-
-                     bufp->kind = ICONIFY_EVENT;
-                     XSETFRAME (bufp->frame_or_window, f);
-                     bufp->arg = Qnil;
-                     bufp++;
-                     count++;
-                     numchars--;
-                   }
-               }
-             goto OTHER;
-
-           case MapNotify:
-             if (event.xmap.window == tip_window)
-               /* The tooltip has been drawn already.  Avoid
-                  the SET_FRAME_GARBAGED below.  */
-               goto OTHER;
-
-             /* We use x_top_window_to_frame because map events can
-                come for sub-windows and they don't mean that the
-                frame is visible.  */
-             f = x_top_window_to_frame (dpyinfo, event.xmap.window);
-             if (f)
-               {
-                 f->async_visible = 1;
-                 f->async_iconified = 0;
-                 f->output_data.x->has_been_visible = 1;
+    case UnmapNotify:
+      /* Redo the mouse-highlight after the tooltip has gone.  */
+      if (event.xmap.window == tip_window)
+        {
+          tip_window = 0;
+          redo_mouse_highlight ();
+        }
 
-                 /* wait_reading_process_input will notice this and update
-                    the frame's display structures.  */
-                 SET_FRAME_GARBAGED (f);
+      f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
+      if (f)           /* F may no longer exist if
+                           the frame was deleted.  */
+        {
+          /* While a frame is unmapped, display generation is
+             disabled; you don't want to spend time updating a
+             display that won't ever be seen.  */
+          f->async_visible = 0;
+          /* We can't distinguish, from the event, whether the window
+             has become iconified or invisible.  So assume, if it
+             was previously visible, than now it is iconified.
+             But x_make_frame_invisible clears both
+             the visible flag and the iconified flag;
+             and that way, we know the window is not iconified now.  */
+          if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
+            {
+              f->async_iconified = 1;
 
-                 if (f->iconified)
-                   {
-                     bufp->kind = DEICONIFY_EVENT;
-                     XSETFRAME (bufp->frame_or_window, f);
-                     bufp->arg = Qnil;
-                     bufp++;
-                     count++;
-                     numchars--;
-                   }
-                 else if (! NILP (Vframe_list)
-                          && ! NILP (XCDR (Vframe_list)))
-                   /* Force a redisplay sooner or later
-                      to update the frame titles
-                      in case this is the second frame.  */
-                   record_asynch_buffer_change ();
-               }
-             goto OTHER;
+              bufp->kind = ICONIFY_EVENT;
+              XSETFRAME (bufp->frame_or_window, f);
+              bufp->arg = Qnil;
+              bufp++;
+              count++;
+              numchars--;
+            }
+        }
+      goto OTHER;
+
+    case MapNotify:
+      if (event.xmap.window == tip_window)
+        /* The tooltip has been drawn already.  Avoid
+           the SET_FRAME_GARBAGED below.  */
+        goto OTHER;
+
+      /* We use x_top_window_to_frame because map events can
+         come for sub-windows and they don't mean that the
+         frame is visible.  */
+      f = x_top_window_to_frame (dpyinfo, event.xmap.window);
+      if (f)
+        {
+          /* wait_reading_process_input will notice this and update
+             the frame's display structures.
+             If we where iconified, we should not set garbaged,
+             because that stops redrawing on Expose events.  This looks
+             bad if we are called from a recursive event loop
+             (x_dispatch_event), for example when a dialog is up.  */
+          if (! f->async_iconified)
+            SET_FRAME_GARBAGED (f);
+
+          f->async_visible = 1;
+          f->async_iconified = 0;
+          f->output_data.x->has_been_visible = 1;
+
+          if (f->iconified)
+            {
+              bufp->kind = DEICONIFY_EVENT;
+              XSETFRAME (bufp->frame_or_window, f);
+              bufp->arg = Qnil;
+              bufp++;
+              count++;
+              numchars--;
+            }
+          else if (! NILP (Vframe_list)
+                   && ! NILP (XCDR (Vframe_list)))
+            /* Force a redisplay sooner or later
+               to update the frame titles
+               in case this is the second frame.  */
+            record_asynch_buffer_change ();
+        }
+      goto OTHER;
 
-           case KeyPress:
+    case KeyPress:
 
-             /* Dispatch KeyPress events when in menu.  */
-             if (popup_activated_flag)
-               goto OTHER;
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+      /* Dispatch KeyPress events when in menu.  */
+      if (popup_activated ())
+        goto OTHER;
+#endif
 
-             f = x_any_window_to_frame (dpyinfo, event.xkey.window);
+      f = x_any_window_to_frame (dpyinfo, event.xkey.window);
 
-             if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
-               {
-                 dpyinfo->mouse_face_hidden = 1;
-                 clear_mouse_face (dpyinfo);
-               }
+      if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+        {
+          dpyinfo->mouse_face_hidden = 1;
+          clear_mouse_face (dpyinfo);
+        }
 
 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
-             if (f == 0)
-               {
-                 /* Scroll bars consume key events, but we want
-                    the keys to go to the scroll bar's frame.  */
-                 Widget widget = XtWindowToWidget (dpyinfo->display,
-                                                   event.xkey.window);
-                 if (widget && XmIsScrollBar (widget))
-                   {
-                     widget = XtParent (widget);
-                     f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
-                   }
-               }
+      if (f == 0)
+        {
+          /* Scroll bars consume key events, but we want
+             the keys to go to the scroll bar's frame.  */
+          Widget widget = XtWindowToWidget (dpyinfo->display,
+                                            event.xkey.window);
+          if (widget && XmIsScrollBar (widget))
+            {
+              widget = XtParent (widget);
+              f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
+            }
+        }
 #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
 
-             if (f != 0)
-               {
-                 KeySym keysym, orig_keysym;
-                 /* al%imercury@uunet.uu.net says that making this 81
-                    instead of 80 fixed a bug whereby meta chars made
-                    his Emacs hang.
-
-                    It seems that some version of XmbLookupString has
-                    a bug of not returning XBufferOverflow in
-                    status_return even if the input is too long to
-                    fit in 81 bytes.  So, we must prepare sufficient
-                    bytes for copy_buffer.  513 bytes (256 chars for
-                    two-byte character set) seems to be a fairly good
-                    approximation.  -- 2000.8.10 handa@etl.go.jp  */
-                 unsigned char copy_buffer[513];
-                 unsigned char *copy_bufptr = copy_buffer;
-                 int copy_bufsiz = sizeof (copy_buffer);
-                 int modifiers;
-                 Lisp_Object coding_system = Qlatin_1;
-
-                 event.xkey.state
-                   |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                              extra_keyboard_modifiers);
-                 modifiers = event.xkey.state;
-
-                 /* This will have to go some day...  */
-
-                 /* make_lispy_event turns chars into control chars.
-                    Don't do it here because XLookupString is too eager.  */
-                 event.xkey.state &= ~ControlMask;
-                 event.xkey.state &= ~(dpyinfo->meta_mod_mask
-                                       | dpyinfo->super_mod_mask
-                                       | dpyinfo->hyper_mod_mask
-                                       | dpyinfo->alt_mod_mask);
-
-                 /* In case Meta is ComposeCharacter,
-                    clear its status.  According to Markus Ehrnsperger
-                    Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
-                    this enables ComposeCharacter to work whether or
-                    not it is combined with Meta.  */
-                 if (modifiers & dpyinfo->meta_mod_mask)
-                   bzero (&compose_status, sizeof (compose_status));
+      if (f != 0)
+        {
+          KeySym keysym, orig_keysym;
+          /* al%imercury@uunet.uu.net says that making this 81
+             instead of 80 fixed a bug whereby meta chars made
+             his Emacs hang.
+
+             It seems that some version of XmbLookupString has
+             a bug of not returning XBufferOverflow in
+             status_return even if the input is too long to
+             fit in 81 bytes.  So, we must prepare sufficient
+             bytes for copy_buffer.  513 bytes (256 chars for
+             two-byte character set) seems to be a fairly good
+             approximation.  -- 2000.8.10 handa@etl.go.jp  */
+          unsigned char copy_buffer[513];
+          unsigned char *copy_bufptr = copy_buffer;
+          int copy_bufsiz = sizeof (copy_buffer);
+          int modifiers;
+          Lisp_Object coding_system = Qlatin_1;
+
+          event.xkey.state
+            |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
+                                       extra_keyboard_modifiers);
+          modifiers = event.xkey.state;
+
+          /* This will have to go some day...  */
+
+          /* make_lispy_event turns chars into control chars.
+             Don't do it here because XLookupString is too eager.  */
+          event.xkey.state &= ~ControlMask;
+          event.xkey.state &= ~(dpyinfo->meta_mod_mask
+                                | dpyinfo->super_mod_mask
+                                | dpyinfo->hyper_mod_mask
+                                | dpyinfo->alt_mod_mask);
+
+          /* In case Meta is ComposeCharacter,
+             clear its status.  According to Markus Ehrnsperger
+             Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
+             this enables ComposeCharacter to work whether or
+             not it is combined with Meta.  */
+          if (modifiers & dpyinfo->meta_mod_mask)
+            bzero (&compose_status, sizeof (compose_status));
 
 #ifdef HAVE_X_I18N
-                 if (FRAME_XIC (f))
-                   {
-                     Status status_return;
-
-                     coding_system = Vlocale_coding_system;
-                     nbytes = XmbLookupString (FRAME_XIC (f),
-                                               &event.xkey, copy_bufptr,
-                                               copy_bufsiz, &keysym,
-                                               &status_return);
-                     if (status_return == XBufferOverflow)
-                       {
-                         copy_bufsiz = nbytes + 1;
-                         copy_bufptr = (char *) alloca (copy_bufsiz);
-                         nbytes = XmbLookupString (FRAME_XIC (f),
-                                                   &event.xkey, copy_bufptr,
-                                                   copy_bufsiz, &keysym,
-                                                   &status_return);
-                       }
-/* Xutf8LookupString is a new but already deprecated interface.  -stef  */
+          if (FRAME_XIC (f))
+            {
+              Status status_return;
+
+              coding_system = Vlocale_coding_system;
+              nbytes = XmbLookupString (FRAME_XIC (f),
+                                        &event.xkey, copy_bufptr,
+                                        copy_bufsiz, &keysym,
+                                        &status_return);
+              if (status_return == XBufferOverflow)
+                {
+                  copy_bufsiz = nbytes + 1;
+                  copy_bufptr = (char *) alloca (copy_bufsiz);
+                  nbytes = XmbLookupString (FRAME_XIC (f),
+                                            &event.xkey, copy_bufptr,
+                                            copy_bufsiz, &keysym,
+                                            &status_return);
+                }
+              /* Xutf8LookupString is a new but already deprecated interface.  -stef  */
 #if 0 && defined X_HAVE_UTF8_STRING
-                     else if (status_return == XLookupKeySym)
-                       {  /* Try again but with utf-8.  */
-                         coding_system = Qutf_8;
-                         nbytes = Xutf8LookupString (FRAME_XIC (f),
-                                                     &event.xkey, copy_bufptr,
-                                                     copy_bufsiz, &keysym,
-                                                     &status_return);
-                         if (status_return == XBufferOverflow)
-                           {
-                             copy_bufsiz = nbytes + 1;
-                             copy_bufptr = (char *) alloca (copy_bufsiz);
-                             nbytes = Xutf8LookupString (FRAME_XIC (f),
-                                                         &event.xkey,
-                                                         copy_bufptr,
-                                                         copy_bufsiz, &keysym,
-                                                         &status_return);
-                           }
-                       }
+              else if (status_return == XLookupKeySym)
+                {  /* Try again but with utf-8.  */
+                  coding_system = Qutf_8;
+                  nbytes = Xutf8LookupString (FRAME_XIC (f),
+                                              &event.xkey, copy_bufptr,
+                                              copy_bufsiz, &keysym,
+                                              &status_return);
+                  if (status_return == XBufferOverflow)
+                    {
+                      copy_bufsiz = nbytes + 1;
+                      copy_bufptr = (char *) alloca (copy_bufsiz);
+                      nbytes = Xutf8LookupString (FRAME_XIC (f),
+                                                  &event.xkey,
+                                                  copy_bufptr,
+                                                  copy_bufsiz, &keysym,
+                                                  &status_return);
+                    }
+                }
 #endif
 
-                     if (status_return == XLookupNone)
-                       break;
-                     else if (status_return == XLookupChars)
-                       {
-                         keysym = NoSymbol;
-                         modifiers = 0;
-                       }
-                     else if (status_return != XLookupKeySym
-                              && status_return != XLookupBoth)
-                       abort ();
-                   }
-                 else
-                   nbytes = XLookupString (&event.xkey, copy_bufptr,
-                                           copy_bufsiz, &keysym,
-                                           &compose_status);
+              if (status_return == XLookupNone)
+                break;
+              else if (status_return == XLookupChars)
+                {
+                  keysym = NoSymbol;
+                  modifiers = 0;
+                }
+              else if (status_return != XLookupKeySym
+                       && status_return != XLookupBoth)
+                abort ();
+            }
+          else
+            nbytes = XLookupString (&event.xkey, copy_bufptr,
+                                    copy_bufsiz, &keysym,
+                                    &compose_status);
 #else
-                 nbytes = XLookupString (&event.xkey, copy_bufptr,
-                                         copy_bufsiz, &keysym,
-                                         &compose_status);
+          nbytes = XLookupString (&event.xkey, copy_bufptr,
+                                  copy_bufsiz, &keysym,
+                                  &compose_status);
 #endif
 
-                 orig_keysym = keysym;
+          orig_keysym = keysym;
 
-                 if (numchars > 1)
-                   {
-                     Lisp_Object c;
-
-                     /* First deal with keysyms which have defined
-                        translations to characters.  */
-                     if (keysym >= 32 && keysym < 128)
-                       /* Avoid explicitly decoding each ASCII character.  */
-                       {
-                         bufp->kind = ASCII_KEYSTROKE_EVENT;
-                         bufp->code = keysym;
-                         XSETFRAME (bufp->frame_or_window, f);
-                         bufp->arg = Qnil;
-                         bufp->modifiers
-                           = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                                     modifiers);
-                         bufp->timestamp = event.xkey.time;
-                         bufp++;
-                         count++;
-                         numchars--;
-                       }
-                     /* Now non-ASCII.  */
-                     else if (HASH_TABLE_P (Vx_keysym_table)
-                              && (NATNUMP (c = Fgethash (make_number (keysym),
-                                                         Vx_keysym_table,
-                                                         Qnil))))
-                       {
-                         bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
-                                       ? ASCII_KEYSTROKE_EVENT
-                                       : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-                         bufp->code = XFASTINT (c);
-                         XSETFRAME (bufp->frame_or_window, f);
-                         bufp->arg = Qnil;
-                         bufp->modifiers
-                           = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                                     modifiers);
-                         bufp->timestamp = event.xkey.time;
-                         bufp++;
-                         count++;
-                         numchars--;
-                       }
-                     /* Random non-modifier sorts of keysyms.  */
-                     else if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
-                               || keysym == XK_Delete
+          if (numchars > 1)
+            {
+              Lisp_Object c;
+
+              /* First deal with keysyms which have defined
+                 translations to characters.  */
+              if (keysym >= 32 && keysym < 128)
+                /* Avoid explicitly decoding each ASCII character.  */
+                {
+                  bufp->kind = ASCII_KEYSTROKE_EVENT;
+                  bufp->code = keysym;
+                  XSETFRAME (bufp->frame_or_window, f);
+                  bufp->arg = Qnil;
+                  bufp->modifiers
+                    = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
+                                              modifiers);
+                  bufp->timestamp = event.xkey.time;
+                  bufp++;
+                  count++;
+                  numchars--;
+                }
+              /* Now non-ASCII.  */
+              else if (HASH_TABLE_P (Vx_keysym_table)
+                       && (NATNUMP (c = Fgethash (make_number (keysym),
+                                                  Vx_keysym_table,
+                                                  Qnil))))
+                {
+                  bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
+                                ? ASCII_KEYSTROKE_EVENT
+                                : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+                  bufp->code = XFASTINT (c);
+                  XSETFRAME (bufp->frame_or_window, f);
+                  bufp->arg = Qnil;
+                  bufp->modifiers
+                    = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
+                                              modifiers);
+                  bufp->timestamp = event.xkey.time;
+                  bufp++;
+                  count++;
+                  numchars--;
+                }
+              /* Random non-modifier sorts of keysyms.  */
+              else if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
+                        || keysym == XK_Delete
 #ifdef XK_ISO_Left_Tab
-                               || (keysym >= XK_ISO_Left_Tab
-                                   && keysym <= XK_ISO_Enter)
+                        || (keysym >= XK_ISO_Left_Tab
+                            && keysym <= XK_ISO_Enter)
 #endif
-                               || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
-                               || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
+                        || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
+                        || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
 #ifdef HPUX
-                               /* This recognizes the "extended function
-                                  keys".  It seems there's no cleaner way.
-                                  Test IsModifierKey to avoid handling
-                                  mode_switch incorrectly.  */
-                               || ((unsigned) (keysym) >= XK_Select
-                                   && (unsigned)(keysym) < XK_KP_Space)
+                        /* This recognizes the "extended function
+                           keys".  It seems there's no cleaner way.
+                           Test IsModifierKey to avoid handling
+                           mode_switch incorrectly.  */
+                        || ((unsigned) (keysym) >= XK_Select
+                            && (unsigned)(keysym) < XK_KP_Space)
 #endif
 #ifdef XK_dead_circumflex
-                               || orig_keysym == XK_dead_circumflex
+                        || orig_keysym == XK_dead_circumflex
 #endif
 #ifdef XK_dead_grave
-                               || orig_keysym == XK_dead_grave
+                        || orig_keysym == XK_dead_grave
 #endif
 #ifdef XK_dead_tilde
-                               || orig_keysym == XK_dead_tilde
+                        || orig_keysym == XK_dead_tilde
 #endif
 #ifdef XK_dead_diaeresis
-                               || orig_keysym == XK_dead_diaeresis
+                        || orig_keysym == XK_dead_diaeresis
 #endif
 #ifdef XK_dead_macron
-                               || orig_keysym == XK_dead_macron
+                        || orig_keysym == XK_dead_macron
 #endif
 #ifdef XK_dead_degree
-                               || orig_keysym == XK_dead_degree
+                        || orig_keysym == XK_dead_degree
 #endif
 #ifdef XK_dead_acute
-                               || orig_keysym == XK_dead_acute
+                        || orig_keysym == XK_dead_acute
 #endif
 #ifdef XK_dead_cedilla
-                               || orig_keysym == XK_dead_cedilla
+                        || orig_keysym == XK_dead_cedilla
 #endif
 #ifdef XK_dead_breve
-                               || orig_keysym == XK_dead_breve
+                        || orig_keysym == XK_dead_breve
 #endif
 #ifdef XK_dead_ogonek
-                               || orig_keysym == XK_dead_ogonek
+                        || orig_keysym == XK_dead_ogonek
 #endif
 #ifdef XK_dead_caron
-                               || orig_keysym == XK_dead_caron
+                        || orig_keysym == XK_dead_caron
 #endif
 #ifdef XK_dead_doubleacute
-                               || orig_keysym == XK_dead_doubleacute
+                        || orig_keysym == XK_dead_doubleacute
 #endif
 #ifdef XK_dead_abovedot
-                               || orig_keysym == XK_dead_abovedot
+                        || orig_keysym == XK_dead_abovedot
 #endif
-                               || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
-                               || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
-                               /* Any "vendor-specific" key is ok.  */
-                               || (orig_keysym & (1 << 28))
-                               || (keysym != NoSymbol && nbytes == 0))
-                              && ! (IsModifierKey (orig_keysym)
+                        || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
+                        || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
+                        /* Any "vendor-specific" key is ok.  */
+                        || (orig_keysym & (1 << 28))
+                        || (keysym != NoSymbol && nbytes == 0))
+                       && ! (IsModifierKey (orig_keysym)
 #ifndef HAVE_X11R5
 #ifdef XK_Mode_switch
-                                    || ((unsigned)(orig_keysym) == XK_Mode_switch)
+                             || ((unsigned)(orig_keysym) == XK_Mode_switch)
 #endif
 #ifdef XK_Num_Lock
-                                    || ((unsigned)(orig_keysym) == XK_Num_Lock)
+                             || ((unsigned)(orig_keysym) == XK_Num_Lock)
 #endif
 #endif /* not HAVE_X11R5 */
-                                    /* The symbols from XK_ISO_Lock
-                                       to XK_ISO_Last_Group_Lock
-                                       don't have real modifiers but
-                                       should be treated similarly to
-                                       Mode_switch by Emacs. */
+                             /* The symbols from XK_ISO_Lock
+                                to XK_ISO_Last_Group_Lock
+                                don't have real modifiers but
+                                should be treated similarly to
+                                Mode_switch by Emacs. */
 #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
-                                    || ((unsigned)(orig_keysym)
-                                        >=  XK_ISO_Lock
-                                        && (unsigned)(orig_keysym)
-                                        <= XK_ISO_Last_Group_Lock)
+                             || ((unsigned)(orig_keysym)
+                                 >=  XK_ISO_Lock
+                                 && (unsigned)(orig_keysym)
+                                 <= XK_ISO_Last_Group_Lock)
 #endif
-                                    ))
-                       {
-                         if (temp_index == sizeof temp_buffer / sizeof (short))
-                           temp_index = 0;
-                         temp_buffer[temp_index++] = keysym;
-                         /* make_lispy_event will convert this to a symbolic
-                            key.  */
-                         bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
-                         bufp->code = keysym;
-                         XSETFRAME (bufp->frame_or_window, f);
-                         bufp->arg = Qnil;
-                         bufp->modifiers
-                           = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                                     modifiers);
-                         bufp->timestamp = event.xkey.time;
-                         bufp++;
-                         count++;
-                         numchars--;
-                       }
-                     else if (numchars > nbytes)
-                       {       /* Raw bytes, not keysym.  */
-                         register int i;
-                         register int c;
-                         int nchars, len;
-
-                         /* The input should be decoded with `coding_system'
-                            which depends on which X*LookupString function
-                            we used just above and the locale.  */
-                         setup_coding_system (coding_system, &coding);
-                         coding.src_multibyte = 0;
-                         coding.dst_multibyte = 1;
-                         /* The input is converted to events, thus we can't
-                            handle composition.  Anyway, there's no XIM that
-                            gives us composition information.  */
-                         coding.composing = COMPOSITION_DISABLED;
-
-                         for (i = 0; i < nbytes; i++)
-                           {
-                             if (temp_index == (sizeof temp_buffer
-                                                / sizeof (short)))
-                               temp_index = 0;
-                             temp_buffer[temp_index++] = copy_bufptr[i];
-                           }
+                             ))
+                {
+                  if (temp_index == sizeof temp_buffer / sizeof (short))
+                    temp_index = 0;
+                  temp_buffer[temp_index++] = keysym;
+                  /* make_lispy_event will convert this to a symbolic
+                     key.  */
+                  bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
+                  bufp->code = keysym;
+                  XSETFRAME (bufp->frame_or_window, f);
+                  bufp->arg = Qnil;
+                  bufp->modifiers
+                    = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
+                                              modifiers);
+                  bufp->timestamp = event.xkey.time;
+                  bufp++;
+                  count++;
+                  numchars--;
+                }
+              else if (numchars > nbytes)
+                {      /* Raw bytes, not keysym.  */
+                  register int i;
+                  register int c;
+                  int nchars, len;
+
+                  /* The input should be decoded with `coding_system'
+                     which depends on which X*LookupString function
+                     we used just above and the locale.  */
+                  setup_coding_system (coding_system, &coding);
+                  coding.src_multibyte = 0;
+                  coding.dst_multibyte = 1;
+                  /* The input is converted to events, thus we can't
+                     handle composition.  Anyway, there's no XIM that
+                     gives us composition information.  */
+                  coding.composing = COMPOSITION_DISABLED;
+
+                  for (i = 0; i < nbytes; i++)
+                    {
+                      if (temp_index == (sizeof temp_buffer
+                                         / sizeof (short)))
+                        temp_index = 0;
+                      temp_buffer[temp_index++] = copy_bufptr[i];
+                    }
 
-                         {
-                           /* Decode the input data.  */
-                           int require;
-                           unsigned char *p;
-
-                           require = decoding_buffer_size (&coding, nbytes);
-                           p = (unsigned char *) alloca (require);
-                           coding.mode |= CODING_MODE_LAST_BLOCK;
-                           /* We explicitely disable composition
-                              handling because key data should
-                              not contain any composition
-                              sequence.  */
-                           coding.composing = COMPOSITION_DISABLED;
-                           decode_coding (&coding, copy_bufptr, p,
-                                          nbytes, require);
-                           nbytes = coding.produced;
-                           nchars = coding.produced_char;
-                           copy_bufptr = p;
-                         }
+                  {
+                    /* Decode the input data.  */
+                    int require;
+                    unsigned char *p;
+
+                    require = decoding_buffer_size (&coding, nbytes);
+                    p = (unsigned char *) alloca (require);
+                    coding.mode |= CODING_MODE_LAST_BLOCK;
+                    /* We explicitely disable composition
+                       handling because key data should
+                       not contain any composition
+                       sequence.  */
+                    coding.composing = COMPOSITION_DISABLED;
+                    decode_coding (&coding, copy_bufptr, p,
+                                   nbytes, require);
+                    nbytes = coding.produced;
+                    nchars = coding.produced_char;
+                    copy_bufptr = p;
+                  }
 
-                         /* Convert the input data to a sequence of
-                            character events.  */
-                         for (i = 0; i < nbytes; i += len)
-                           {
-                             if (nchars == nbytes)
-                               c = copy_bufptr[i], len = 1;
-                             else
-                               c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
-                                                           nbytes - i, len);
-
-                             bufp->kind = (SINGLE_BYTE_CHAR_P (c)
-                                           ? ASCII_KEYSTROKE_EVENT
-                                           : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-                             bufp->code = c;
-                             XSETFRAME (bufp->frame_or_window, f);
-                             bufp->arg = Qnil;
-                             bufp->modifiers
-                               = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                                         modifiers);
-                             bufp->timestamp = event.xkey.time;
-                             bufp++;
-                           }
-
-                         count += nchars;
-                         numchars -= nchars;
-
-                         if (keysym == NoSymbol)
-                           break;
-                       }
-                     else
-                       abort ();
-                   }
-                 else
-                   abort ();
-               }
+                  /* Convert the input data to a sequence of
+                     character events.  */
+                  for (i = 0; i < nbytes; i += len)
+                    {
+                      if (nchars == nbytes)
+                        c = copy_bufptr[i], len = 1;
+                      else
+                        c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
+                                                    nbytes - i, len);
+
+                      bufp->kind = (SINGLE_BYTE_CHAR_P (c)
+                                    ? ASCII_KEYSTROKE_EVENT
+                                    : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+                      bufp->code = c;
+                      XSETFRAME (bufp->frame_or_window, f);
+                      bufp->arg = Qnil;
+                      bufp->modifiers
+                        = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
+                                                  modifiers);
+                      bufp->timestamp = event.xkey.time;
+                      bufp++;
+                    }
+
+                  count += nchars;
+                  numchars -= nchars;
+
+                  if (keysym == NoSymbol)
+                    break;
+                }
+              else
+                abort ();
+            }
+          else
+            abort ();
+        }
 #ifdef HAVE_X_I18N
-             /* Don't dispatch this event since XtDispatchEvent calls
-                XFilterEvent, and two calls in a row may freeze the
-                client.  */
-             break;
+      /* Don't dispatch this event since XtDispatchEvent calls
+         XFilterEvent, and two calls in a row may freeze the
+         client.  */
+      break;
 #else
-             goto OTHER;
+      goto OTHER;
 #endif
 
-           case KeyRelease:
+    case KeyRelease:
 #ifdef HAVE_X_I18N
-             /* Don't dispatch this event since XtDispatchEvent calls
-                XFilterEvent, and two calls in a row may freeze the
-                client.  */
-             break;
+      /* Don't dispatch this event since XtDispatchEvent calls
+         XFilterEvent, and two calls in a row may freeze the
+         client.  */
+      break;
 #else
-             goto OTHER;
+      goto OTHER;
 #endif
 
-           case EnterNotify:
-             {
-                int n;
+    case EnterNotify:
+      {
+        int n;
 
-                n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
-                if (n > 0)
-                {
-                  bufp += n, count += n, numchars -= n;
-                }
+        n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+        if (n > 0)
+          {
+            bufp += n, count += n, numchars -= n;
+          }
 
-               f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
+        f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
 
 #if 0
-               if (event.xcrossing.focus)
-                 {
-                   /* Avoid nasty pop/raise loops.  */
-                   if (f && (!(f->auto_raise)
-                             || !(f->auto_lower)
-                             || (event.xcrossing.time - enter_timestamp) > 500))
-                     {
-                       x_new_focus_frame (dpyinfo, f);
-                       enter_timestamp = event.xcrossing.time;
-                     }
-                 }
-               else if (f == dpyinfo->x_focus_frame)
-                 x_new_focus_frame (dpyinfo, 0);
+        if (event.xcrossing.focus)
+          {
+            /* Avoid nasty pop/raise loops.  */
+            if (f && (!(f->auto_raise)
+                      || !(f->auto_lower)
+                      || (event.xcrossing.time - enter_timestamp) > 500))
+              {
+                x_new_focus_frame (dpyinfo, f);
+                enter_timestamp = event.xcrossing.time;
+              }
+          }
+        else if (f == dpyinfo->x_focus_frame)
+          x_new_focus_frame (dpyinfo, 0);
 #endif
 
-               /* EnterNotify counts as mouse movement,
-                  so update things that depend on mouse position.  */
-               if (f && !f->output_data.x->hourglass_p)
-                 note_mouse_movement (f, &event.xmotion);
-               goto OTHER;
-             }
+        /* EnterNotify counts as mouse movement,
+           so update things that depend on mouse position.  */
+        if (f && !f->output_data.x->hourglass_p)
+          note_mouse_movement (f, &event.xmotion);
+        goto OTHER;
+      }
 
-           case FocusIn:
-              {
-                int n;
+    case FocusIn:
+      {
+        int n;
+
+        n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+        if (n > 0)
+          {
+            bufp += n, count += n, numchars -= n;
+          }
+      }
 
-                n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
-                if (n > 0)
+      goto OTHER;
+
+    case LeaveNotify:
+      {
+        int n;
+
+        n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+        if (n > 0)
+          {
+            bufp += n, count += n, numchars -= n;
+          }
+      }
+
+      f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
+      if (f)
+        {
+          if (f == dpyinfo->mouse_face_mouse_frame)
+            {
+              /* If we move outside the frame, then we're
+                 certainly no longer on any text in the frame.  */
+              clear_mouse_face (dpyinfo);
+              dpyinfo->mouse_face_mouse_frame = 0;
+            }
+
+          /* Generate a nil HELP_EVENT to cancel a help-echo.
+             Do it only if there's something to cancel.
+             Otherwise, the startup message is cleared when
+             the mouse leaves the frame.  */
+          if (any_help_event_p)
+            {
+              Lisp_Object frame;
+              int n;
+
+              XSETFRAME (frame, f);
+              help_echo = Qnil;
+              n = gen_help_event (bufp, numchars,
+                                  Qnil, frame, Qnil, Qnil, 0);
+              bufp += n, count += n, numchars -= n;
+            }
+
+        }
+      goto OTHER;
+
+    case FocusOut:
+      {
+        int n;
+
+        n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
+        if (n > 0)
+          {
+            bufp += n, count += n, numchars -= n;
+          }
+      }
+
+      goto OTHER;
+
+    case MotionNotify:
+      {
+        previous_help_echo = help_echo;
+        help_echo = help_echo_object = help_echo_window = Qnil;
+        help_echo_pos = -1;
+
+        if (dpyinfo->grabbed && last_mouse_frame
+            && FRAME_LIVE_P (last_mouse_frame))
+          f = last_mouse_frame;
+        else
+          f = x_window_to_frame (dpyinfo, event.xmotion.window);
+
+        if (dpyinfo->mouse_face_hidden)
+          {
+            dpyinfo->mouse_face_hidden = 0;
+            clear_mouse_face (dpyinfo);
+          }
+
+        if (f)
+          {
+
+            /* Generate SELECT_WINDOW_EVENTs when needed.  */
+            if (mouse_autoselect_window)
+              {
+                Lisp_Object window;
+                int area;
+
+                window = window_from_coordinates (f,
+                                                  event.xmotion.x, event.xmotion.y,
+                                                  &area, 0);
+
+                /* Window will be selected only when it is not selected now and
+                   last mouse movement event was not in it.  Minibuffer window
+                   will be selected iff it is active.  */
+                if (WINDOWP(window)
+                    && !EQ (window, last_window)
+                    && !EQ (window, selected_window)
+                    && numchars > 0)
                   {
-                    bufp += n, count += n, numchars -= n;
+                    bufp->kind = SELECT_WINDOW_EVENT;
+                    bufp->frame_or_window = window;
+                    bufp->arg = Qnil;
+                    ++bufp, ++count, --numchars;
                   }
+
+                last_window=window;
               }
+            note_mouse_movement (f, &event.xmotion);
+          }
+        else
+          {
+#ifndef USE_TOOLKIT_SCROLL_BARS
+            struct scroll_bar *bar
+              = x_window_to_scroll_bar (event.xmotion.window);
 
-             goto OTHER;
+            if (bar)
+              x_scroll_bar_note_movement (bar, &event);
+#endif /* USE_TOOLKIT_SCROLL_BARS */
 
-           case LeaveNotify:
-              {
-                int n;
+            /* If we move outside the frame, then we're
+               certainly no longer on any text in the frame.  */
+            clear_mouse_face (dpyinfo);
+          }
+
+        /* If the contents of the global variable help_echo
+           has changed, generate a HELP_EVENT.  */
+        if (!NILP (help_echo)
+            || !NILP (previous_help_echo))
+          {
+            Lisp_Object frame;
+            int n;
+
+            if (f)
+              XSETFRAME (frame, f);
+            else
+              frame = Qnil;
+
+            any_help_event_p = 1;
+            n = gen_help_event (bufp, numchars, help_echo, frame,
+                                help_echo_window, help_echo_object,
+                                help_echo_pos);
+            bufp += n, count += n, numchars -= n;
+          }
+
+        goto OTHER;
+      }
 
-                n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
-                if (n > 0)
-                {
-                  bufp += n, count += n, numchars -= n;
-                }
-              }
+    case ConfigureNotify:
+      f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
+      if (f)
+        {
+#ifndef USE_X_TOOLKIT
+#ifdef USE_GTK
+          xg_resize_widgets (f, event.xconfigure.width,
+                             event.xconfigure.height);
+#else /* not USE_GTK */
+          /* If there is a pending resize for fullscreen, don't
+             do this one, the right one will come later.
+             The toolkit version doesn't seem to need this, but we
+             need to reset it below.  */
+          int dont_resize =
+            ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
+             && FRAME_NEW_WIDTH (f) != 0);
+          int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
+          int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
+          if (dont_resize)
+            goto OTHER;
+
+          /* In the toolkit version, change_frame_size
+             is called by the code that handles resizing
+             of the EmacsFrame widget.  */
+
+          /* Even if the number of character rows and columns has
+             not changed, the font size may have changed, so we need
+             to check the pixel dimensions as well.  */
+          if (columns != f->width
+              || rows != f->height
+              || event.xconfigure.width != f->output_data.x->pixel_width
+              || event.xconfigure.height != f->output_data.x->pixel_height)
+            {
+              change_frame_size (f, rows, columns, 0, 1, 0);
+              SET_FRAME_GARBAGED (f);
+              cancel_mouse_face (f);
+            }
+#endif /* not USE_GTK */
+#endif
 
-             f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
-             if (f)
-               {
-                 if (f == dpyinfo->mouse_face_mouse_frame)
-                   {
-                     /* If we move outside the frame, then we're
-                        certainly no longer on any text in the frame.  */
-                     clear_mouse_face (dpyinfo);
-                     dpyinfo->mouse_face_mouse_frame = 0;
-                   }
+          f->output_data.x->pixel_width = event.xconfigure.width;
+          f->output_data.x->pixel_height = event.xconfigure.height;
 
-                 /* Generate a nil HELP_EVENT to cancel a help-echo.
-                    Do it only if there's something to cancel.
-                    Otherwise, the startup message is cleared when
-                    the mouse leaves the frame.  */
-                 if (any_help_event_p)
-                   {
-                     Lisp_Object frame;
-                     int n;
-
-                     XSETFRAME (frame, f);
-                     help_echo = Qnil;
-                     n = gen_help_event (bufp, numchars,
-                                         Qnil, frame, Qnil, Qnil, 0);
-                     bufp += n, count += n, numchars -= n;
-                   }
+#ifdef USE_GTK
+          /* GTK creates windows but doesn't map them.
+             Only get real positions and check fullscreen when mapped. */
+          if (FRAME_GTK_OUTER_WIDGET (f)
+              && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f)))
+            {
+#endif
+          /* What we have now is the position of Emacs's own window.
+             Convert that to the position of the window manager window.  */
+          x_real_positions (f, &f->output_data.x->left_pos,
+                            &f->output_data.x->top_pos);
+
+          x_check_fullscreen_move (f);
+          if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
+            f->output_data.x->want_fullscreen &=
+              ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
+#ifdef USE_GTK
+            }
+#endif
+#ifdef HAVE_X_I18N
+          if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
+            xic_set_statusarea (f);
+#endif
 
-               }
-             goto OTHER;
+          if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
+            {
+              /* Since the WM decorations come below top_pos now,
+                 we must put them below top_pos in the future.  */
+              f->output_data.x->win_gravity = NorthWestGravity;
+              x_wm_set_size_hint (f, (long) 0, 0);
+            }
+        }
+      goto OTHER;
 
-           case FocusOut:
+    case ButtonRelease:
+    case ButtonPress:
+      {
+        /* If we decide we want to generate an event to be seen
+           by the rest of Emacs, we put it here.  */
+        struct input_event emacs_event;
+        int tool_bar_p = 0;
+
+        emacs_event.kind = NO_EVENT;
+        bzero (&compose_status, sizeof (compose_status));
+
+        if (dpyinfo->grabbed
+            && last_mouse_frame
+            && FRAME_LIVE_P (last_mouse_frame))
+          f = last_mouse_frame;
+        else
+          f = x_window_to_frame (dpyinfo, event.xbutton.window);
+
+        if (f)
+          {
+            /* Is this in the tool-bar?  */
+            if (WINDOWP (f->tool_bar_window)
+                && XFASTINT (XWINDOW (f->tool_bar_window)->height))
               {
-                int n;
+                Lisp_Object window;
+                int p, x, y;
+
+                x = event.xbutton.x;
+                y = event.xbutton.y;
 
-                n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
-                if (n > 0)
+                /* Set x and y.  */
+                window = window_from_coordinates (f, x, y, &p, 1);
+                if (EQ (window, f->tool_bar_window))
+                  {
+                    x_handle_tool_bar_click (f, &event.xbutton);
+                    tool_bar_p = 1;
+                  }
+              }
+
+            if (!tool_bar_p)
+              if (!dpyinfo->x_focus_frame
+                  || f == dpyinfo->x_focus_frame)
                 {
-                  bufp += n, count += n, numchars -= n;
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+                  if (! popup_activated ())
+#endif
+                    construct_mouse_click (&emacs_event, &event, f);
                 }
-              }
+          }
+        else
+          {
+#ifndef USE_TOOLKIT_SCROLL_BARS
+            struct scroll_bar *bar
+              = x_window_to_scroll_bar (event.xbutton.window);
 
-             goto OTHER;
+            if (bar)
+              x_scroll_bar_handle_click (bar, &event, &emacs_event);
+#endif /* not USE_TOOLKIT_SCROLL_BARS */
+          }
+
+        if (event.type == ButtonPress)
+          {
+            dpyinfo->grabbed |= (1 << event.xbutton.button);
+            last_mouse_frame = f;
+            /* Ignore any mouse motion that happened
+               before this event; any subsequent mouse-movement
+               Emacs events should reflect only motion after
+               the ButtonPress.  */
+            if (f != 0)
+              f->mouse_moved = 0;
+
+            if (!tool_bar_p)
+              last_tool_bar_item = -1;
+          }
+        else
+          dpyinfo->grabbed &= ~(1 << event.xbutton.button);
+
+        if (numchars >= 1 && emacs_event.kind != NO_EVENT)
+          {
+            bcopy (&emacs_event, bufp, sizeof (struct input_event));
+            bufp++;
+            count++;
+            numchars--;
+          }
+
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+        f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
+        /* For a down-event in the menu bar,
+           don't pass it to Xt right now.
+           Instead, save it away
+           and we will pass it to Xt from kbd_buffer_get_event.
+           That way, we can run some Lisp code first.  */
+        if (
+#ifdef USE_GTK
+            ! popup_activated ()
+            &&
+#endif
+            f && event.type == ButtonPress
+            /* Verify the event is really within the menu bar
+               and not just sent to it due to grabbing.  */
+            && event.xbutton.x >= 0
+            && event.xbutton.x < f->output_data.x->pixel_width
+            && event.xbutton.y >= 0
+            && event.xbutton.y < f->output_data.x->menubar_height
+            && event.xbutton.same_screen)
+          {
+            SET_SAVED_BUTTON_EVENT;
+            XSETFRAME (last_mouse_press_frame, f);
+#ifdef USE_GTK
+            *finish = X_EVENT_DROP;
+#endif
+          }
+        else if (event.type == ButtonPress)
+          {
+            last_mouse_press_frame = Qnil;
+            goto OTHER;
+          }
 
-           case MotionNotify:
-             {
-               previous_help_echo = help_echo;
-               help_echo = help_echo_object = help_echo_window = Qnil;
-               help_echo_pos = -1;
+#ifdef USE_MOTIF /* This should do not harm for Lucid,
+                   but I am trying to be cautious.  */
+        else if (event.type == ButtonRelease)
+          {
+            if (!NILP (last_mouse_press_frame))
+              {
+                f = XFRAME (last_mouse_press_frame);
+                if (f->output_data.x)
+                  SET_SAVED_BUTTON_EVENT;
+              }
+            else
+              goto OTHER;
+          }
+#endif /* USE_MOTIF */
+        else
+          goto OTHER;
+#endif /* USE_X_TOOLKIT || USE_GTK */
+      }
+      break;
 
-               if (dpyinfo->grabbed && last_mouse_frame
-                   && FRAME_LIVE_P (last_mouse_frame))
-                 f = last_mouse_frame;
-               else
-                 f = x_window_to_frame (dpyinfo, event.xmotion.window);
+    case CirculateNotify:
+      goto OTHER;
 
-               if (dpyinfo->mouse_face_hidden)
-                 {
-                   dpyinfo->mouse_face_hidden = 0;
-                   clear_mouse_face (dpyinfo);
-                 }
+    case CirculateRequest:
+      goto OTHER;
 
-               if (f)
-                 {
+    case VisibilityNotify:
+      goto OTHER;
 
-                   /* Generate SELECT_WINDOW_EVENTs when needed.  */
-                   if (mouse_autoselect_window)
-                     {
-                       Lisp_Object window;
-                       int area;
-
-                       window = window_from_coordinates (f,
-                                                         event.xmotion.x, event.xmotion.y,
-                                                         &area, 0);
-
-                       /* Window will be selected only when it is not selected now and
-                          last mouse movement event was not in it.  Minibuffer window
-                          will be selected iff it is active.  */
-                       if (WINDOWP(window)
-                           && !EQ (window, last_window)
-                           && !EQ (window, selected_window)
-                           && numchars > 0)
-                         {
-                           bufp->kind = SELECT_WINDOW_EVENT;
-                           bufp->frame_or_window = window;
-                           bufp->arg = Qnil;
-                           ++bufp, ++count, --numchars;
-                         }
+    case MappingNotify:
+      /* Someone has changed the keyboard mapping - update the
+         local cache.  */
+      switch (event.xmapping.request)
+        {
+        case MappingModifier:
+          x_find_modifier_meanings (dpyinfo);
+          /* This is meant to fall through.  */
+        case MappingKeyboard:
+          XRefreshKeyboardMapping (&event.xmapping);
+        }
+      goto OTHER;
 
-                       last_window=window;
-                     }
-                   note_mouse_movement (f, &event.xmotion);
-                 }
-               else
-                 {
-#ifndef USE_TOOLKIT_SCROLL_BARS
-                   struct scroll_bar *bar
-                     = x_window_to_scroll_bar (event.xmotion.window);
+    default:
+    OTHER:
+#ifdef USE_X_TOOLKIT
+    BLOCK_INPUT;
+    XtDispatchEvent (&event);
+    UNBLOCK_INPUT;
+#endif /* USE_X_TOOLKIT */
+    break;
+    }
 
-                   if (bar)
-                     x_scroll_bar_note_movement (bar, &event);
-#endif /* USE_TOOLKIT_SCROLL_BARS */
+  goto ret;
 
-                   /* If we move outside the frame, then we're
-                      certainly no longer on any text in the frame.  */
-                   clear_mouse_face (dpyinfo);
-                 }
+ out:
+  *finish = X_EVENT_GOTO_OUT;
 
-               /* If the contents of the global variable help_echo
-                  has changed, generate a HELP_EVENT.  */
-               if (!NILP (help_echo)
-                   || !NILP (previous_help_echo))
-                 {
-                   Lisp_Object frame;
-                   int n;
-
-                   if (f)
-                     XSETFRAME (frame, f);
-                   else
-                     frame = Qnil;
-
-                   any_help_event_p = 1;
-                   n = gen_help_event (bufp, numchars, help_echo, frame,
-                                       help_echo_window, help_echo_object,
-                                       help_echo_pos);
-                   bufp += n, count += n, numchars -= n;
-                 }
+ ret:
+  *bufp_r = bufp;
+  *numcharsp = numchars;
+  *eventp = event;
 
-               goto OTHER;
-             }
+  return count;
+}
 
-           case ConfigureNotify:
-             f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
-             if (f)
-               {
-#ifndef USE_X_TOOLKIT
-                  /* If there is a pending resize for fullscreen, don't
-                     do this one, the right one will come later.
-                    The toolkit version doesn't seem to need this, but we
-                    need to reset it below.  */
-                  int dont_resize =
-                    ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
-                     && FRAME_NEW_WIDTH (f) != 0);
-                 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
-                 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
-                  if (dont_resize)
-                    goto OTHER;
-
-                 /* In the toolkit version, change_frame_size
-                    is called by the code that handles resizing
-                    of the EmacsFrame widget.  */
-
-                 /* Even if the number of character rows and columns has
-                    not changed, the font size may have changed, so we need
-                    to check the pixel dimensions as well.  */
-                 if (columns != f->width
-                     || rows != f->height
-                     || event.xconfigure.width != f->output_data.x->pixel_width
-                     || event.xconfigure.height != f->output_data.x->pixel_height)
-                   {
-                     change_frame_size (f, rows, columns, 0, 1, 0);
-                     SET_FRAME_GARBAGED (f);
-                     cancel_mouse_face (f);
-                   }
-#endif
 
-                 f->output_data.x->pixel_width = event.xconfigure.width;
-                 f->output_data.x->pixel_height = event.xconfigure.height;
+/* Handles the XEvent EVENT on display DISPLAY.
+   This is used for event loops outside the normal event handling,
+   i.e. looping while a popup menu or a dialog is posted.
 
-                 /* What we have now is the position of Emacs's own window.
-                    Convert that to the position of the window manager window.  */
-                 x_real_positions (f, &f->output_data.x->left_pos,
-                                   &f->output_data.x->top_pos);
+   Returns the value handle_one_xevent sets in the finish argument.  */
+int
+x_dispatch_event (event, display)
+     XEvent *event;
+     Display *display;
+{
+  struct x_display_info *dpyinfo;
+  struct input_event bufp[10];
+  struct input_event *bufpp = bufp;
+  int numchars = 10;
+  int finish = X_EVENT_NORMAL;
 
-                  x_check_fullscreen_move(f);
-                  if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
-                    f->output_data.x->want_fullscreen &=
-                      ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
-#ifdef HAVE_X_I18N
-                 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
-                   xic_set_statusarea (f);
-#endif
+  for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
+    if (dpyinfo->display == display)
+      break;
 
-                 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
-                   {
-                     /* Since the WM decorations come below top_pos now,
-                        we must put them below top_pos in the future.  */
-                     f->output_data.x->win_gravity = NorthWestGravity;
-                     x_wm_set_size_hint (f, (long) 0, 0);
-                   }
-               }
-             goto OTHER;
+  if (dpyinfo)
+    {
+      int i, events;
+      events = handle_one_xevent (dpyinfo,
+                                  event,
+                                  &bufpp,
+                                  &numchars,
+                                  &finish);
+      for (i = 0; i < events; ++i)
+        kbd_buffer_store_event (&bufp[i]);
+    }
 
-           case ButtonPress:
-           case ButtonRelease:
-             {
-               /* If we decide we want to generate an event to be seen
-                  by the rest of Emacs, we put it here.  */
-               struct input_event emacs_event;
-               int tool_bar_p = 0;
-
-               emacs_event.kind = NO_EVENT;
-               bzero (&compose_status, sizeof (compose_status));
-
-               if (dpyinfo->grabbed
-                   && last_mouse_frame
-                   && FRAME_LIVE_P (last_mouse_frame))
-                 f = last_mouse_frame;
-               else
-                 f = x_window_to_frame (dpyinfo, event.xbutton.window);
-
-               if (f)
-                 {
-                   /* Is this in the tool-bar?  */
-                   if (WINDOWP (f->tool_bar_window)
-                       && XFASTINT (XWINDOW (f->tool_bar_window)->height))
-                     {
-                       Lisp_Object window;
-                       int p, x, y;
+  return finish;
+}
 
-                       x = event.xbutton.x;
-                       y = event.xbutton.y;
 
-                       /* Set x and y.  */
-                       window = window_from_coordinates (f, x, y, &p, 1);
-                       if (EQ (window, f->tool_bar_window))
-                         {
-                           x_handle_tool_bar_click (f, &event.xbutton);
-                           tool_bar_p = 1;
-                         }
-                     }
+/* Read events coming from the X server.
+   This routine is called by the SIGIO handler.
+   We return as soon as there are no more events to be read.
 
-                   if (!tool_bar_p)
-                     if (!dpyinfo->x_focus_frame
-                         || f == dpyinfo->x_focus_frame)
-                       construct_mouse_click (&emacs_event, &event, f);
-                 }
-               else
-                 {
-#ifndef USE_TOOLKIT_SCROLL_BARS
-                   struct scroll_bar *bar
-                     = x_window_to_scroll_bar (event.xbutton.window);
+   Events representing keys are stored in buffer BUFP,
+   which can hold up to NUMCHARS characters.
+   We return the number of characters stored into the buffer,
+   thus pretending to be `read'.
 
-                   if (bar)
-                     x_scroll_bar_handle_click (bar, &event, &emacs_event);
-#endif /* not USE_TOOLKIT_SCROLL_BARS */
-                 }
+   EXPECTED is nonzero if the caller knows input is available.  */
 
-               if (event.type == ButtonPress)
-                 {
-                   dpyinfo->grabbed |= (1 << event.xbutton.button);
-                   last_mouse_frame = f;
-                   /* Ignore any mouse motion that happened
-                      before this event; any subsequent mouse-movement
-                      Emacs events should reflect only motion after
-                      the ButtonPress.  */
-                   if (f != 0)
-                     f->mouse_moved = 0;
-
-                   if (!tool_bar_p)
-                     last_tool_bar_item = -1;
-                 }
-               else
-                 {
-                   dpyinfo->grabbed &= ~(1 << event.xbutton.button);
-                 }
+static int
+XTread_socket (sd, bufp, numchars, expected)
+     register int sd;
+     /* register */ struct input_event *bufp;
+     /* register */ int numchars;
+     int expected;
+{
+  int count = 0;
+  int nbytes = 0;
+  XEvent event;
+  int event_found = 0;
+  struct x_display_info *dpyinfo;
 
-               if (numchars >= 1 && emacs_event.kind != NO_EVENT)
-                 {
-                   bcopy (&emacs_event, bufp, sizeof (struct input_event));
-                   bufp++;
-                   count++;
-                   numchars--;
-                 }
+  if (interrupt_input_blocked)
+    {
+      interrupt_input_pending = 1;
+      return -1;
+    }
 
-#ifdef USE_X_TOOLKIT
-               f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
-               /* For a down-event in the menu bar,
-                  don't pass it to Xt right now.
-                  Instead, save it away
-                  and we will pass it to Xt from kbd_buffer_get_event.
-                  That way, we can run some Lisp code first.  */
-               if (f && event.type == ButtonPress
-                   /* Verify the event is really within the menu bar
-                      and not just sent to it due to grabbing.  */
-                   && event.xbutton.x >= 0
-                   && event.xbutton.x < f->output_data.x->pixel_width
-                   && event.xbutton.y >= 0
-                   && event.xbutton.y < f->output_data.x->menubar_height
-                   && event.xbutton.same_screen)
-                 {
-                   SET_SAVED_BUTTON_EVENT;
-                   XSETFRAME (last_mouse_press_frame, f);
-                 }
-               else if (event.type == ButtonPress)
-                 {
-                   last_mouse_press_frame = Qnil;
-                   goto OTHER;
-                 }
+  interrupt_input_pending = 0;
+  BLOCK_INPUT;
 
-#ifdef USE_MOTIF /* This should do not harm for Lucid,
-                   but I am trying to be cautious.  */
-               else if (event.type == ButtonRelease)
-                 {
-                   if (!NILP (last_mouse_press_frame))
-                     {
-                       f = XFRAME (last_mouse_press_frame);
-                       if (f->output_data.x)
-                         SET_SAVED_BUTTON_EVENT;
-                     }
-                   else
-                     goto OTHER;
-                 }
-#endif /* USE_MOTIF */
-               else
-                 goto OTHER;
-#endif /* USE_X_TOOLKIT */
-             }
-             break;
+  /* So people can tell when we have read the available input.  */
+  input_signal_count++;
 
-           case CirculateNotify:
-             goto OTHER;
+  if (numchars <= 0)
+    abort ();                  /* Don't think this happens.  */
 
-           case CirculateRequest:
-             goto OTHER;
+  ++handling_signal;
 
-           case VisibilityNotify:
-             goto OTHER;
+  /* Find the display we are supposed to read input for.
+     It's the one communicating on descriptor SD.  */
+  for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
+    {
+#if 0 /* This ought to be unnecessary; let's verify it.  */
+#ifdef FIOSNBIO
+      /* If available, Xlib uses FIOSNBIO to make the socket
+        non-blocking, and then looks for EWOULDBLOCK.  If O_NDELAY is set,
+        FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
+        a read returns 0, which Xlib interprets as equivalent to EPIPE.  */
+      fcntl (dpyinfo->connection, F_SETFL, 0);
+#endif /* ! defined (FIOSNBIO) */
+#endif
 
-           case MappingNotify:
-             /* Someone has changed the keyboard mapping - update the
-                local cache.  */
-             switch (event.xmapping.request)
-               {
-               case MappingModifier:
-                 x_find_modifier_meanings (dpyinfo);
-                 /* This is meant to fall through.  */
-               case MappingKeyboard:
-                 XRefreshKeyboardMapping (&event.xmapping);
-               }
-             goto OTHER;
+#if 0 /* This code can't be made to work, with multiple displays,
+        and appears not to be used on any system any more.
+        Also keyboard.c doesn't turn O_NDELAY on and off
+        for X connections.  */
+#ifndef SIGIO
+#ifndef HAVE_SELECT
+      if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
+       {
+         extern int read_alarm_should_throw;
+         read_alarm_should_throw = 1;
+         XPeekEvent (dpyinfo->display, &event);
+         read_alarm_should_throw = 0;
+       }
+#endif /* HAVE_SELECT */
+#endif /* SIGIO */
+#endif
 
-           default:
-           OTHER:
-#ifdef USE_X_TOOLKIT
-             BLOCK_INPUT;
-             XtDispatchEvent (&event);
-             UNBLOCK_INPUT;
-#endif /* USE_X_TOOLKIT */
-             break;
-           }
+      /* For debugging, this gives a way to fake an I/O error.  */
+      if (dpyinfo == XTread_socket_fake_io_error)
+       {
+         XTread_socket_fake_io_error = 0;
+         x_io_error_quitter (dpyinfo->display);
        }
+
+#ifdef HAVE_X_SM
+      BLOCK_INPUT;
+      count += x_session_check_input (bufp, &numchars);
+      UNBLOCK_INPUT;
+#endif
+
+#ifdef USE_GTK
+      /* For GTK we must use the GTK event loop.  But XEvents gets passed
+         to our filter function above, and then to the big event switch.
+         We use a bunch of globals to communicate with our filter function,
+         that is kind of ugly, but it works. */
+      current_dpyinfo = dpyinfo;
+
+      while (gtk_events_pending ())
+        {
+          static int nr = 0;
+          current_count = count;
+          current_numcharsp = &numchars;
+          current_bufp = &bufp;
+
+          gtk_main_iteration ();
+
+          count = current_count;
+          current_bufp = 0;
+          current_numcharsp = 0;
+
+          if (current_finish == X_EVENT_GOTO_OUT)
+            goto out;
+        }
+
+#else /* not USE_GTK */
+      while (XPending (dpyinfo->display))
+       {
+          int finish;
+
+         XNextEvent (dpyinfo->display, &event);
+
+#ifdef HAVE_X_I18N
+          /* Filter events for the current X input method.  */
+          if (x_filter_event (dpyinfo, &event))
+            break;
+#endif
+         event_found = 1;
+
+          count += handle_one_xevent (dpyinfo,
+                                      &event,
+                                      &bufp,
+                                      &numchars,
+                                      &finish);
+
+          if (finish == X_EVENT_GOTO_OUT)
+            goto out;
+        }
+#endif /* USE_GTK */
     }
 
  out:;
@@ -12114,15 +12432,10 @@ x_text_icon (f, icon_name)
     text.encoding = XA_STRING;
     text.format = 8;
     text.nitems = strlen (icon_name);
-#ifdef USE_X_TOOLKIT
-    XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
-                   &text);
-#else /* not USE_X_TOOLKIT */
-    XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
-#endif /* not USE_X_TOOLKIT */
+    XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
   }
 #else /* not HAVE_X11R4 */
-  XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
+  XSetIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), icon_name);
 #endif /* not HAVE_X11R4 */
 
   if (f->output_data.x->icon_bitmap > 0)
@@ -12179,7 +12492,9 @@ x_catch_errors (dpy)
   /* Make sure any errors from previous requests have been dealt with.  */
   XSync (dpy, False);
 
-  record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
+  record_unwind_protect (x_catch_errors_unwind,
+                        Fcons (make_save_value (dpy, 0),
+                               x_error_message_string));
 
   x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
   SSET (x_error_message_string, 0, 0);
@@ -12193,7 +12508,13 @@ static Lisp_Object
 x_catch_errors_unwind (old_val)
      Lisp_Object old_val;
 {
-  x_error_message_string = old_val;
+  Lisp_Object first;
+
+  first = XCAR (old_val);
+
+  XSync (XSAVE_VALUE (first)->pointer, False);
+
+  x_error_message_string = XCDR (old_val);
   return Qnil;
 }
 
@@ -12731,7 +13052,7 @@ struct xim_inst_t
 };
 
 /* XIM instantiate callback function, which is called whenever an XIM
-   server is available.  DISPLAY is teh display of the XIM.
+   server is available.  DISPLAY is the display of the XIM.
    CLIENT_DATA contains a pointer to an xim_inst_t structure created
    when the callback was registered.  */
 
@@ -12862,11 +13183,7 @@ x_calc_absolute_position (f)
   if (! ((flags & XNegative) || (flags & YNegative)))
     return;
 
-#ifdef USE_X_TOOLKIT
-  this_window = XtWindow (f->output_data.x->widget);
-#else
-  this_window = FRAME_X_WINDOW (f);
-#endif
+  this_window = FRAME_OUTER_WINDOW (f);
 
   /* Find the position of the outside upper-left corner of
      the inner window, with respect to the outer window.
@@ -12997,13 +13314,8 @@ x_set_offset (f, xoff, yoff, change_gravity)
     }
 #endif
 
-#ifdef USE_X_TOOLKIT
-  XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
-              modified_left, modified_top);
-#else /* not USE_X_TOOLKIT */
-  XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-              modified_left, modified_top);
-#endif /* not USE_X_TOOLKIT */
+  XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+               modified_left, modified_top);
   UNBLOCK_INPUT;
 }
 
@@ -13189,7 +13501,12 @@ x_set_window_size (f, change_gravity, cols, rows)
 {
   BLOCK_INPUT;
 
-#ifdef USE_X_TOOLKIT
+#ifdef USE_GTK
+  if (FRAME_GTK_WIDGET (f))
+    xg_frame_set_char_size (f, cols, rows);
+  else
+    x_set_window_size_1 (f, change_gravity, cols, rows);
+#elif USE_X_TOOLKIT
 
   if (f->output_data.x->widget != NULL)
     {
@@ -13302,11 +13619,7 @@ x_raise_frame (f)
   if (f->async_visible)
     {
       BLOCK_INPUT;
-#ifdef USE_X_TOOLKIT
-      XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
-#else /* not USE_X_TOOLKIT */
-      XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-#endif /* not USE_X_TOOLKIT */
+      XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
       XFlush (FRAME_X_DISPLAY (f));
       UNBLOCK_INPUT;
     }
@@ -13321,11 +13634,7 @@ x_lower_frame (f)
   if (f->async_visible)
     {
       BLOCK_INPUT;
-#ifdef USE_X_TOOLKIT
-      XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
-#else /* not USE_X_TOOLKIT */
-      XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-#endif /* not USE_X_TOOLKIT */
+      XLowerWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
       XFlush (FRAME_X_DISPLAY (f));
       UNBLOCK_INPUT;
     }
@@ -13385,7 +13694,12 @@ x_make_frame_visible (f)
       /* This was XtPopup, but that did nothing for an iconified frame.  */
       XtMapWidget (f->output_data.x->widget);
 #else /* not USE_X_TOOLKIT */
+#ifdef USE_GTK
+      gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
+      gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
+#else
       XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+#endif /* not USE_GTK */
 #endif /* not USE_X_TOOLKIT */
 #if 0 /* This seems to bring back scroll bars in the wrong places
         if the window configuration has changed.  They seem
@@ -13511,12 +13825,8 @@ x_make_frame_invisible (f)
 {
   Window window;
 
-#ifdef USE_X_TOOLKIT
   /* Use the frame's outermost window, not the one we normally draw on.  */
-  window = XtWindow (f->output_data.x->widget);
-#else /* not USE_X_TOOLKIT */
-  window = FRAME_X_WINDOW (f);
-#endif /* not USE_X_TOOLKIT */
+  window = FRAME_OUTER_WINDOW (f);
 
   /* Don't keep the highlight on an invisible frame.  */
   if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
@@ -13536,6 +13846,14 @@ x_make_frame_invisible (f)
      by hand again (they have already done that once for this window.)  */
   x_wm_set_size_hint (f, (long) 0, 1);
 
+#ifdef USE_GTK
+  if (FRAME_GTK_OUTER_WIDGET (f))
+    {
+      gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
+      goto out;
+    }
+#endif
+
 #ifdef HAVE_X11R4
 
   if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
@@ -13570,6 +13888,7 @@ x_make_frame_invisible (f)
   XUnmapWindow (FRAME_X_DISPLAY (f), window);
 #endif /* ! defined (HAVE_X11R4) */
 
+ out:
   /* We can't distinguish this from iconification
      just by the event that we get from the server.
      So we can't win using the usual strategy of letting
@@ -13609,6 +13928,22 @@ x_iconify_frame (f)
   if (!NILP (type))
     x_bitmap_icon (f, type);
 
+#ifdef USE_GTK
+  if (FRAME_GTK_OUTER_WIDGET (f))
+    {
+      if (! FRAME_VISIBLE_P (f))
+        gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
+
+      gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
+      f->iconified = 1;
+      f->visible = 1;
+      f->async_iconified = 1;
+      f->async_visible = 0;
+      UNBLOCK_INPUT;
+      return;
+    }
+#endif
+
 #ifdef USE_X_TOOLKIT
 
   if (! FRAME_VISIBLE_P (f))
@@ -13743,6 +14078,18 @@ x_free_frame_resources (f)
 
       free_frame_menubar (f);
 #else  /* !USE_X_TOOLKIT */
+
+#ifdef USE_GTK
+      /* In the GTK version, tooltips are normal X
+         frames.  We must check and free both types. */
+      if (FRAME_GTK_OUTER_WIDGET (f))
+        {
+          gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
+          FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow below */
+          FRAME_GTK_OUTER_WIDGET (f) = 0;
+        }
+#endif /* USE_GTK */
+
       if (FRAME_X_WINDOW (f))
        XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
 #endif /* !USE_X_TOOLKIT */
@@ -13828,8 +14175,10 @@ x_destroy_window (f)
    FLAGS is the flags word to use--or 0 meaning preserve the flags
    that the window now has.
    If USER_POSITION is nonzero, we set the USPosition
-   flag (this is useful when FLAGS is 0).  */
+   flag (this is useful when FLAGS is 0).
+   The GTK version is in gtkutils.c  */
 
+#ifndef USE_GTK
 void
 x_wm_set_size_hint (f, flags, user_position)
      struct frame *f;
@@ -13842,10 +14191,9 @@ x_wm_set_size_hint (f, flags, user_position)
   Arg al[2];
   int ac = 0;
   Dimension widget_width, widget_height;
-  Window window = XtWindow (f->output_data.x->widget);
-#else /* not USE_X_TOOLKIT */
-  Window window = FRAME_X_WINDOW (f);
-#endif /* not USE_X_TOOLKIT */
+#endif
+
+  Window window = FRAME_OUTER_WINDOW (f);
 
   /* Setting PMaxSize caused various problems.  */
   size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
@@ -13972,6 +14320,7 @@ x_wm_set_size_hint (f, flags, user_position)
   XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
 #endif
 }
+#endif /* not USE_GTK */
 
 /* Used for IconicState or NormalState */
 
@@ -14003,7 +14352,7 @@ x_wm_set_icon_pixmap (f, pixmap_id)
   Pixmap icon_pixmap;
 
 #ifndef USE_X_TOOLKIT
-  Window window = FRAME_X_WINDOW (f);
+  Window window = FRAME_OUTER_WINDOW (f);
 #endif
 
   if (pixmap_id > 0)
@@ -14048,11 +14397,7 @@ x_wm_set_icon_position (f, icon_x, icon_y)
      struct frame *f;
      int icon_x, icon_y;
 {
-#ifdef USE_X_TOOLKIT
-  Window window = XtWindow (f->output_data.x->widget);
-#else
-  Window window = FRAME_X_WINDOW (f);
-#endif
+  Window window = FRAME_OUTER_WINDOW (f);
 
   f->output_data.x->wm_hints.flags |= IconPositionHint;
   f->output_data.x->wm_hints.icon_x = icon_x;
@@ -14804,6 +15149,71 @@ x_term_init (display_name, xrm_option, resource_name)
       x_initialized = 1;
     }
 
+#ifdef USE_GTK
+  {
+#define NUM_ARGV 10
+    int argc;
+    char *argv[NUM_ARGV];
+    char **argv2 = argv;
+    GdkAtom atom;
+
+    /* GTK 2.0 can only handle one display, GTK 2.2 can handle more
+       than one, but this remains to be implemented.  */
+    if (x_initialized > 1)
+      return 0;
+
+    x_initialized++;
+
+    for (argc = 0; argc < NUM_ARGV; ++argc)
+      argv[argc] = 0;
+
+    argc = 0;
+    argv[argc++] = initial_argv[0];
+
+    if (! NILP (display_name))
+      {
+        argv[argc++] = "--display";
+        argv[argc++] = SDATA (display_name);
+      }
+
+    argv[argc++] = "--name";
+    argv[argc++] = resource_name;
+
+#ifdef HAVE_X11R5
+    XSetLocaleModifiers ("");
+#endif
+
+    gtk_init (&argc, &argv2);
+
+    /* gtk_init does set_locale.  We must fix locale after calling it.  */
+    fixup_locale ();
+    xg_initialize ();
+
+    dpy = GDK_DISPLAY ();
+
+    /* NULL window -> events for all windows go to our function */
+    gdk_window_add_filter (NULL, event_handler_gdk, NULL);
+
+    /* Load our own gtkrc if it exists.  */
+    {
+      struct gcpro gcpro1, gcpro2;
+      char *file = "~/.emacs.d/gtkrc";
+      Lisp_Object s, abs_file;
+
+      GCPRO2 (str, abs_file);
+      s = make_string (file, strlen (file));
+      abs_file = Fexpand_file_name(s, Qnil);
+
+      if (! NILP (abs_file) && Ffile_readable_p (abs_file))
+        gtk_rc_parse (SDATA (abs_file));
+
+      UNGCPRO;
+    }
+
+    XSetErrorHandler (x_error_handler);
+    XSetIOErrorHandler (x_io_error_quitter);
+  }
+#else /* not USE_GTK */
 #ifdef USE_X_TOOLKIT
   /* weiner@footloose.sps.mot.com reports that this causes
      errors with X11R5:
@@ -14844,6 +15254,7 @@ x_term_init (display_name, xrm_option, resource_name)
 #endif
   dpy = XOpenDisplay (SDATA (display_name));
 #endif /* not USE_X_TOOLKIT */
+#endif /* not USE_GTK*/
 
   /* Detect failure.  */
   if (dpy == 0)
@@ -15303,8 +15714,10 @@ x_initialize ()
 #endif
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
+#ifndef USE_GTK
   xaw3d_arrow_scroll = False;
   xaw3d_pick_top = True;
+#endif
 #endif
 
   /* Note that there is no real way portable across R3/R4 to get the
@@ -15385,6 +15798,8 @@ Otherwise, value is a symbol describing the X toolkit.  */);
   Vx_toolkit_scroll_bars = intern ("motif");
 #elif defined HAVE_XAW3D
   Vx_toolkit_scroll_bars = intern ("xaw3d");
+#elif USE_GTK
+  Vx_toolkit_scroll_bars = intern ("gtk");
 #else
   Vx_toolkit_scroll_bars = intern ("xaw");
 #endif