Improve window dividers code.
[bpt/emacs.git] / src / xterm.c
index f470afe..e187312 100644 (file)
@@ -1,6 +1,6 @@
 /* X Communication module for terminals which understand the X protocol.
 
-Copyright (C) 1989, 1993-2013 Free Software Foundation, Inc.
+Copyright (C) 1989, 1993-2014 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -23,8 +23,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <config.h>
 #include <stdio.h>
 
-#ifdef HAVE_X_WINDOWS
-
 #include "lisp.h"
 #include "blockinput.h"
 #include "syssignal.h"
@@ -86,7 +84,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #endif
 #endif
 
-#ifdef USE_LUCID
+#if defined (USE_LUCID) || defined (USE_MOTIF)
 #include "../lwlib/xlwmenu.h"
 #endif
 
@@ -100,7 +98,7 @@ extern void _XEditResCheckMessages (Widget, XtPointer, XEvent *, Boolean *);
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
 #if defined USE_MOTIF
-#include <Xm/Xm.h>             /* for LESSTIF_VERSION */
+#include <Xm/Xm.h>             /* For LESSTIF_VERSION */
 #include <Xm/ScrollBar.h>
 #else /* !USE_MOTIF i.e. use Xaw */
 
@@ -135,9 +133,9 @@ extern void _XEditResCheckMessages (Widget, XtPointer, XEvent *, Boolean *);
 
 /* Default to using XIM if available.  */
 #ifdef USE_XIM
-int use_xim = 1;
+bool use_xim = true;
 #else
-int use_xim = 0;  /* configure --without-xim */
+bool use_xim = false;  /* configure --without-xim */
 #endif
 
 /* Non-zero means that a HELP_EVENT has been generated since Emacs
@@ -150,94 +148,22 @@ static bool any_help_event_p;
 
 struct x_display_info *x_display_list;
 
-/* This is a list of cons cells, each of the form (NAME
-   . FONT-LIST-CACHE), one for each element of x_display_list and in
-   the same order.  NAME is the name of the frame.  FONT-LIST-CACHE
-   records previous values returned by x-list-fonts.  */
-
-Lisp_Object x_display_name_list;
-
-/* This is a frame waiting to be auto-raised, within XTread_socket.  */
-
-static struct frame *pending_autoraise_frame;
-
-/* This is a frame waiting for an event matching mask, within XTread_socket.  */
-
-static struct {
-  struct frame *f;
-  int eventtype;
-} pending_event_wait;
-
 #ifdef USE_X_TOOLKIT
+
 /* The application context for Xt use.  */
 XtAppContext Xt_app_con;
 static String Xt_default_resources[] = {0};
 
 /* Non-zero means user is interacting with a toolkit scroll bar.  */
+static bool toolkit_scroll_bar_interaction;
 
-static int toolkit_scroll_bar_interaction;
 #endif /* USE_X_TOOLKIT */
 
 /* Non-zero timeout value means ignore next mouse click if it arrives
    before that timeout elapses (i.e. as part of the same sequence of
    events resulting from clicking on a frame to select it).  */
 
-static unsigned long ignore_next_mouse_click_timeout;
-
-/* Mouse movement.
-
-   Formerly, we used PointerMotionHintMask (in standard_event_mask)
-   so that we would have to call XQueryPointer after each MotionNotify
-   event to ask for another such event.  However, this made mouse tracking
-   slow, and there was a bug that made it eventually stop.
-
-   Simply asking for MotionNotify all the time seems to work better.
-
-   In order to avoid asking for motion events and then throwing most
-   of them away or busy-polling the server for mouse positions, we ask
-   the server for pointer motion hints.  This means that we get only
-   one event per group of mouse movements.  "Groups" are delimited by
-   other kinds of events (focus changes and button clicks, for
-   example), or by XQueryPointer calls; when one of these happens, we
-   get another MotionNotify event the next time the mouse moves.  This
-   is at least as efficient as getting motion events when mouse
-   tracking is on, and I suspect only negligibly worse when tracking
-   is off.  */
-
-/* Where the mouse was last time we reported a mouse event.  */
-
-static XRectangle last_mouse_glyph;
-static struct frame *last_mouse_glyph_frame;
-
-/* The scroll bar in which the last X motion event occurred.
-
-   If the last X motion event occurred in a scroll bar, we set this so
-   XTmouse_position can know whether to report a scroll bar motion or
-   an ordinary motion.
-
-   If the last X motion event didn't occur in a scroll bar, we set
-   this to Qnil, to tell XTmouse_position to return an ordinary motion
-   event.  */
-
-static Lisp_Object last_mouse_scroll_bar;
-
-/* This is a hack.  We would really prefer that XTmouse_position would
-   return the time associated with the position it returns, but there
-   doesn't seem to be any way to wrest the time-stamp from the server
-   along with the position query.  So, we just keep track of the time
-   of the last movement we received, and return that in hopes that
-   it's somewhat accurate.  */
-
-static Time last_mouse_movement_time;
-
-/* Time for last user interaction as returned in X events.  */
-
-static Time last_user_time;
-
-/* Incremented by XTread_socket whenever it really tries to read
-   events.  */
-
-static int volatile input_signal_count;
+static Time ignore_next_mouse_click_timeout;
 
 /* Used locally within XTread_socket.  */
 
@@ -283,7 +209,7 @@ enum xembed_message
   };
 
 static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
-static void x_set_window_size_1 (struct frame *, int, int, int);
+static void x_set_window_size_1 (struct frame *, int, int, int, bool);
 static void x_raise_frame (struct frame *);
 static void x_lower_frame (struct frame *);
 static const XColor *x_color_cells (Display *, int *);
@@ -299,8 +225,6 @@ static void frame_unhighlight (struct frame *);
 static void x_new_focus_frame (struct x_display_info *, struct frame *);
 static void  x_focus_changed (int, int, struct x_display_info *,
                               struct frame *, struct input_event *);
-static void x_detect_focus_change (struct x_display_info *,
-                                   XEvent *, struct input_event *);
 static void XTframe_rehighlight (struct frame *);
 static void x_frame_rehighlight (struct x_display_info *);
 static void x_draw_hollow_cursor (struct window *, struct glyph_row *);
@@ -317,13 +241,14 @@ static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
                                         enum scroll_bar_part *,
                                         Lisp_Object *, Lisp_Object *,
                                         Time *);
-static int x_handle_net_wm_state (struct frame *, XPropertyEvent *);
+static int x_handle_net_wm_state (struct frame *, const XPropertyEvent *);
 static void x_check_fullscreen (struct frame *);
 static void x_check_expected_move (struct frame *, int, int);
 static void x_sync_with_move (struct frame *, int, int, int);
-static int handle_one_xevent (struct x_display_info *, XEvent *,
-                              int *, struct input_event *);
-#ifdef USE_GTK
+static int handle_one_xevent (struct x_display_info *,
+                             const XEvent *, int *,
+                             struct input_event *);
+#if ! (defined USE_X_TOOLKIT || defined USE_MOTIF)
 static int x_dispatch_event (XEvent *, Display *);
 #endif
 /* Don't declare this _Noreturn because we want no
@@ -334,29 +259,19 @@ static void x_wm_set_icon_pixmap (struct frame *, ptrdiff_t);
 static void x_initialize (void);
 
 
-/* Flush display of frame F, or of all frames if F is null.  */
+/* Flush display of frame F.  */
 
 static void
 x_flush (struct frame *f)
 {
+  eassert (f && FRAME_X_P (f));
   /* Don't call XFlush when it is not safe to redisplay; the X
      connection may be broken.  */
   if (!NILP (Vinhibit_redisplay))
     return;
 
   block_input ();
-  if (f)
-    {
-      eassert (FRAME_X_P (f));
-      XFlush (FRAME_X_DISPLAY (f));
-    }
-  else
-    {
-      /* Flush all displays and so all frames on them.  */
-      struct x_display_info *xdi;
-      for (xdi = x_display_list; xdi; xdi = xdi->next)
-       XFlush (xdi->display);
-    }
+  XFlush (FRAME_X_DISPLAY (f));
   unblock_input ();
 }
 
@@ -426,7 +341,7 @@ x_find_topmost_parent (struct frame *f)
   Window win = None, wi = x->parent_desc;
   Display *dpy = FRAME_X_DISPLAY (f);
 
-  while (wi != FRAME_X_DISPLAY_INFO (f)->root_window)
+  while (wi != FRAME_DISPLAY_INFO (f)->root_window)
     {
       Window root;
       Window *children;
@@ -445,7 +360,7 @@ x_find_topmost_parent (struct frame *f)
 void
 x_set_frame_alpha (struct frame *f)
 {
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   Display *dpy = FRAME_X_DISPLAY (f);
   Window win = FRAME_OUTER_WINDOW (f);
   double alpha = 1.0;
@@ -589,6 +504,59 @@ x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
             f->output_data.x->normal_gc, x, y0, x, y1);
 }
 
+/* Draw a window divider from (x0,y0) to (x1,y1)  */
+
+static void
+x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
+{
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  struct face *face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
+  struct face *face_first = FACE_FROM_ID (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
+  struct face *face_last = FACE_FROM_ID (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
+  unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
+  unsigned long color_first = (face_first
+                              ? face_first->foreground
+                              : FRAME_FOREGROUND_PIXEL (f));
+  unsigned long color_last = (face_last
+                             ? face_last->foreground
+                             : FRAME_FOREGROUND_PIXEL (f));
+  Display *display = FRAME_X_DISPLAY (f);
+  Window window = FRAME_X_WINDOW (f);
+
+  if (y1 - y0 > x1 - x0 && x1 - x0 > 2)
+    /* Vertical.  */
+    {
+      XSetForeground (display, f->output_data.x->normal_gc, color_first);
+      XFillRectangle (display, window, f->output_data.x->normal_gc,
+                     x0, y0, 1, y1 - y0);
+      XSetForeground (display, f->output_data.x->normal_gc, color);
+      XFillRectangle (display, window, f->output_data.x->normal_gc,
+                     x0 + 1, y0, x1 - x0 - 2, y1 - y0);
+      XSetForeground (display, f->output_data.x->normal_gc, color_last);
+      XFillRectangle (display, window, f->output_data.x->normal_gc,
+                     x1 - 1, y0, 1, y1 - y0);
+    }
+  else if (x1 - x0 > y1 - y0 && y1 - y0 > 3)
+    /* Horizontal.  */
+    {
+      XSetForeground (display, f->output_data.x->normal_gc, color_first);
+      XFillRectangle (display, window, f->output_data.x->normal_gc,
+                     x0, y0, x1 - x0, 1);
+      XSetForeground (display, f->output_data.x->normal_gc, color);
+      XFillRectangle (display, window, f->output_data.x->normal_gc,
+                     x0, y0 + 1, x1 - x0, y1 - y0 - 2);
+      XSetForeground (display, f->output_data.x->normal_gc, color_last);
+      XFillRectangle (display, window, f->output_data.x->normal_gc,
+                     x0, y1 - 1, x1 - x0, 1);
+    }
+  else
+    {
+      XSetForeground (display, f->output_data.x->normal_gc, color);
+      XFillRectangle (display, window, f->output_data.x->normal_gc,
+                     x0, y0, x1 - x0, y1 - y0);
+    }
+}
+
 /* End update of window W.
 
    Draw vertical borders between horizontally adjacent windows, and
@@ -616,7 +584,12 @@ x_update_window_end (struct window *w, bool cursor_on_p,
                                w->output_cursor.x, w->output_cursor.y);
 
       if (draw_window_fringes (w, 1))
-       x_draw_vertical_border (w);
+       {
+         if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+           x_draw_right_divider (w);
+         else
+           x_draw_vertical_border (w);
+       }
 
       unblock_input ();
     }
@@ -656,6 +629,32 @@ XTframe_up_to_date (struct frame *f)
 }
 
 
+/* Clear under internal border if any for non-toolkit builds. */
+
+
+#if !defined USE_X_TOOLKIT && !defined USE_GTK
+void
+x_clear_under_internal_border (struct frame *f)
+{
+  if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
+    {
+      Display *display = FRAME_X_DISPLAY (f);
+      Window window = FRAME_X_WINDOW (f);
+      int border = FRAME_INTERNAL_BORDER_WIDTH (f);
+      int width = FRAME_PIXEL_WIDTH (f);
+      int height = FRAME_PIXEL_HEIGHT (f);
+      int margin = FRAME_TOP_MARGIN_HEIGHT (f);
+
+      block_input ();
+      x_clear_area (display, window, 0, 0, border, height);
+      x_clear_area (display, window, 0, margin, width, border);
+      x_clear_area (display, window, width - border, 0, border, height);
+      x_clear_area (display, window, 0, height - border, width, border);
+      unblock_input ();
+    }
+}
+#endif
+
 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
    arrow bitmaps, or clear the fringes if no bitmaps are required
    before DESIRED_ROW is made current.  This function is called from
@@ -665,38 +664,42 @@ XTframe_up_to_date (struct frame *f)
 static void
 x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
 {
-  struct frame *f;
-  int width, height;
-
   eassert (w);
 
   if (!desired_row->mode_line_p && !w->pseudo_window_p)
     desired_row->redraw_fringe_bitmaps_p = 1;
 
+#ifdef USE_X_TOOLKIT
   /* When a window has disappeared, make sure that no rest of
      full-width rows stays visible in the internal border.  Could
      check here if updated window is the leftmost/rightmost window,
      but I guess it's not worth doing since vertically split windows
      are almost never used, internal border is rarely set, and the
      overhead is very small.  */
-  if (windows_or_buffers_changed
-      && desired_row->full_width_p
-      && (f = XFRAME (w->frame),
-         width = FRAME_INTERNAL_BORDER_WIDTH (f),
-         width != 0)
-      && (height = desired_row->visible_height,
-         height > 0))
-    {
-      int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
+  {
+    struct frame *f;
+    int width, height;
+
+    if (windows_or_buffers_changed
+       && desired_row->full_width_p
+       && (f = XFRAME (w->frame),
+           width = FRAME_INTERNAL_BORDER_WIDTH (f),
+           width != 0)
+       && (height = desired_row->visible_height,
+           height > 0))
+      {
+       int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
 
-      block_input ();
-      x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                   0, y, width, height);
-      x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                   FRAME_PIXEL_WIDTH (f) - width,
-                   y, width, height);
-      unblock_input ();
-    }
+       block_input ();
+       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                     0, y, width, height);
+       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                     FRAME_PIXEL_WIDTH (f) - width,
+                     y, width, height);
+       unblock_input ();
+      }
+  }
+#endif
 }
 
 static void
@@ -711,10 +714,8 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
   /* Must clip because of partially visible lines.  */
   x_clip_to_row (w, row, ANY_AREA, gc);
 
-  if (!p->overlay_p)
+  if (p->bx >= 0 && !p->overlay_p)
     {
-      int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
-
       /* In case the same realized face is used for fringes and
         for something displayed in the text (e.g. face `region' on
         mono-displays, the fill style may have been changed to
@@ -724,55 +725,8 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
       else
        XSetForeground (display, face->gc, face->background);
 
-#ifdef USE_TOOLKIT_SCROLL_BARS
-      /* If the fringe is adjacent to the left (right) scroll bar of a
-        leftmost (rightmost, respectively) window, then extend its
-        background to the gap between the fringe and the bar.  */
-      if ((WINDOW_LEFTMOST_P (w)
-          && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
-         || (WINDOW_RIGHTMOST_P (w)
-             && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
-       {
-         int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
-         if (sb_width > 0)
-           {
-             int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
-             int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
-                                   * FRAME_COLUMN_WIDTH (f));
-
-             if (bx < 0)
-               {
-                 /* Bitmap fills the fringe.  */
-                 if (bar_area_x + bar_area_width == p->x)
-                   bx = bar_area_x + sb_width;
-                 else if (p->x + p->wd == bar_area_x)
-                   bx = bar_area_x;
-                 if (bx >= 0)
-                   {
-                     int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
-
-                     nx = bar_area_width - sb_width;
-                     by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
-                                                           row->y));
-                     ny = row->visible_height;
-                   }
-               }
-             else
-               {
-                 if (bar_area_x + bar_area_width == bx)
-                   {
-                     bx = bar_area_x + sb_width;
-                     nx += bar_area_width - sb_width;
-                   }
-                 else if (bx + nx == bar_area_x)
-                   nx += bar_area_width - sb_width;
-               }
-           }
-       }
-#endif
-      if (bx >= 0 && nx > 0)
-       XFillRectangle (display, window, face->gc, bx, by, nx, ny);
+      XFillRectangle (display, window, face->gc,
+                     p->bx, p->by, p->nx, p->ny);
 
       if (!face->stipple)
        XSetForeground (display, face->gc, face->foreground);
@@ -802,7 +756,7 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
       if (p->overlay_p)
        {
          clipmask = XCreatePixmapFromBitmapData (display,
-                                                 FRAME_X_DISPLAY_INFO (f)->root_window,
+                                                 FRAME_DISPLAY_INFO (f)->root_window,
                                                  bits, p->wd, p->h,
                                                  1, 0, 1);
          gcv.clip_mask = clipmask;
@@ -906,14 +860,14 @@ x_set_cursor_gc (struct glyph_string *s)
       xgcv.graphics_exposures = False;
       mask = GCForeground | GCBackground | GCGraphicsExposures;
 
-      if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
-       XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
+      if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
+       XChangeGC (s->display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
                   mask, &xgcv);
       else
-       FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
+       FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
          = XCreateGC (s->display, s->window, mask, &xgcv);
 
-      s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
+      s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
     }
 }
 
@@ -953,14 +907,14 @@ x_set_mouse_face_gc (struct glyph_string *s)
       xgcv.graphics_exposures = False;
       mask = GCForeground | GCBackground | GCGraphicsExposures;
 
-      if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
-       XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
+      if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
+       XChangeGC (s->display, FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
                   mask, &xgcv);
       else
-       FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
+       FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
          = XCreateGC (s->display, s->window, mask, &xgcv);
 
-      s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
+      s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
 
     }
   eassert (s->gc != 0);
@@ -1396,7 +1350,7 @@ x_frame_of_widget (Widget widget)
       f = XFRAME (frame);
       if (FRAME_X_P (f)
          && f->output_data.nothing != 1
-         && FRAME_X_DISPLAY_INFO (f) == dpyinfo
+         && FRAME_DISPLAY_INFO (f) == dpyinfo
          && f->output_data.x->widget == widget)
        return f;
     }
@@ -1605,7 +1559,7 @@ x_color_cells (Display *dpy, int *ncells)
 void
 x_query_colors (struct frame *f, XColor *colors, int ncolors)
 {
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
 
   if (dpyinfo->color_cells)
     {
@@ -1723,7 +1677,7 @@ x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color)
    get color reference counts right.  */
 
 unsigned long
-x_copy_color (struct frame *f, long unsigned int pixel)
+x_copy_color (struct frame *f, unsigned long pixel)
 {
   XColor color;
 
@@ -1761,7 +1715,8 @@ x_copy_color (struct frame *f, long unsigned int pixel)
    Value is non-zero if successful.  */
 
 static bool
-x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap, long unsigned int *pixel, double factor, int delta)
+x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap,
+                      unsigned long *pixel, double factor, int delta)
 {
   XColor color, new;
   long bright;
@@ -1837,7 +1792,8 @@ x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap, long un
    be allocated, use DEFAULT_PIXEL, instead.  */
 
 static void
-x_setup_relief_color (struct frame *f, struct relief *relief, double factor, int delta, long unsigned int default_pixel)
+x_setup_relief_color (struct frame *f, struct relief *relief, double factor,
+                     int delta, unsigned long default_pixel)
 {
   XGCValues xgcv;
   struct x_output *di = f->output_data.x;
@@ -1845,7 +1801,7 @@ x_setup_relief_color (struct frame *f, struct relief *relief, double factor, int
   unsigned long pixel;
   unsigned long background = di->relief_background;
   Colormap cmap = FRAME_X_COLORMAP (f);
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   Display *dpy = FRAME_X_DISPLAY (f);
 
   xgcv.graphics_exposures = False;
@@ -1854,11 +1810,10 @@ x_setup_relief_color (struct frame *f, struct relief *relief, double factor, int
   /* Free previously allocated color.  The color cell will be reused
      when it has been freed as many times as it was allocated, so this
      doesn't affect faces using the same colors.  */
-  if (relief->gc
-      && relief->allocated_p)
+  if (relief->gc && relief->pixel != -1)
     {
       x_free_colors (f, &relief->pixel, 1);
-      relief->allocated_p = 0;
+      relief->pixel = -1;
     }
 
   /* Allocate new color.  */
@@ -1866,10 +1821,7 @@ x_setup_relief_color (struct frame *f, struct relief *relief, double factor, int
   pixel = background;
   if (dpyinfo->n_planes != 1
       && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
-    {
-      relief->allocated_p = 1;
-      xgcv.foreground = relief->pixel = pixel;
-    }
+    xgcv.foreground = relief->pixel = pixel;
 
   if (relief->gc == 0)
     {
@@ -3029,32 +2981,13 @@ XTflash (struct frame *f)
 #endif
     {
       /* Get the height not including a menu bar widget.  */
-      int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
+      int height = FRAME_PIXEL_HEIGHT (f);
       /* Height of each line to flash.  */
       int flash_height = FRAME_LINE_HEIGHT (f);
       /* These will be the left and right margins of the rectangles.  */
       int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
       int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
-
-      int width;
-
-      /* Don't flash the area between a scroll bar and the frame
-        edge it is next to.  */
-      switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
-       {
-       case vertical_scroll_bar_left:
-         flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
-         break;
-
-       case vertical_scroll_bar_right:
-         flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
-         break;
-
-       default:
-         break;
-       }
-
-      width = flash_right - flash_left;
+      int width = flash_right - flash_left;
 
       /* If window is tall, flash top and bottom line.  */
       if (height > 3 * FRAME_LINE_HEIGHT (f))
@@ -3146,9 +3079,9 @@ XTtoggle_invisible_pointer (struct frame *f, int invisible)
   block_input ();
   if (invisible)
     {
-      if (FRAME_X_DISPLAY_INFO (f)->invisible_cursor != 0)
+      if (FRAME_DISPLAY_INFO (f)->invisible_cursor != 0)
         XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                       FRAME_X_DISPLAY_INFO (f)->invisible_cursor);
+                       FRAME_DISPLAY_INFO (f)->invisible_cursor);
     }
   else
     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
@@ -3208,34 +3141,6 @@ x_scroll_run (struct window *w, struct run *run)
      fringe of W.  */
   window_box (w, ANY_AREA, &x, &y, &width, &height);
 
-#ifdef USE_TOOLKIT_SCROLL_BARS
-  /* If the fringe is adjacent to the left (right) scroll bar of a
-     leftmost (rightmost, respectively) window, then extend its
-     background to the gap between the fringe and the bar.  */
-  if ((WINDOW_LEFTMOST_P (w)
-       && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
-      || (WINDOW_RIGHTMOST_P (w)
-         && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
-    {
-      int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
-      if (sb_width > 0)
-       {
-         int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
-         int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
-                               * FRAME_COLUMN_WIDTH (f));
-
-         if (bar_area_x + bar_area_width == x)
-           {
-             x = bar_area_x + sb_width;
-             width += bar_area_width - sb_width;
-           }
-         else if (x + width == bar_area_x)
-           width += bar_area_width - sb_width;
-       }
-    }
-#endif
-
   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
   bottom_y = y + height;
@@ -3341,9 +3246,9 @@ x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame)
        x_lower_frame (old_focus);
 
       if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
-       pending_autoraise_frame = dpyinfo->x_focus_frame;
+       dpyinfo->x_pending_autoraise_frame = dpyinfo->x_focus_frame;
       else
-       pending_autoraise_frame = 0;
+       dpyinfo->x_pending_autoraise_frame = NULL;
     }
 
   x_frame_rehighlight (dpyinfo);
@@ -3366,7 +3271,9 @@ x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct fra
           /* Don't stop displaying the initial startup message
              for a switch-frame event we don't need.  */
           /* When run as a daemon, Vterminal_frame is always NIL.  */
-          bufp->arg = (((NILP (Vterminal_frame) || EQ (Fdaemonp (), Qt))
+          bufp->arg = (((NILP (Vterminal_frame)
+                         || ! FRAME_X_P (XFRAME (Vterminal_frame))
+                         || EQ (Fdaemonp (), Qt))
                        && CONSP (Vframe_list)
                        && !NILP (XCDR (Vframe_list)))
                       ? Qt : Qnil);
@@ -3403,18 +3310,192 @@ x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct fra
     }
 }
 
+/* Return the Emacs frame-object corresponding to an X window.
+   It could be the frame's main window or an icon window.  */
+
+static struct frame *
+x_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
+{
+  Lisp_Object tail, frame;
+  struct frame *f;
+
+  if (wdesc == None)
+    return NULL;
+
+  FOR_EACH_FRAME (tail, frame)
+    {
+      f = XFRAME (frame);
+      if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
+       continue;
+      if (f->output_data.x->hourglass_window == wdesc)
+       return f;
+#ifdef USE_X_TOOLKIT
+      if ((f->output_data.x->edit_widget
+          && XtWindow (f->output_data.x->edit_widget) == wdesc)
+         /* A tooltip frame?  */
+         || (!f->output_data.x->edit_widget
+             && FRAME_X_WINDOW (f) == wdesc)
+          || f->output_data.x->icon_desc == wdesc)
+        return f;
+#else /* not USE_X_TOOLKIT */
+#ifdef USE_GTK
+      if (f->output_data.x->edit_widget)
+      {
+        GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
+        struct x_output *x = f->output_data.x;
+        if (gwdesc != 0 && gwdesc == x->edit_widget)
+          return f;
+      }
+#endif /* USE_GTK */
+      if (FRAME_X_WINDOW (f) == wdesc
+          || f->output_data.x->icon_desc == wdesc)
+        return f;
+#endif /* not USE_X_TOOLKIT */
+    }
+  return 0;
+}
+
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+
+/* Like x_window_to_frame but also compares the window with the widget's
+   windows.  */
+
+static struct frame *
+x_any_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
+{
+  Lisp_Object tail, frame;
+  struct frame *f, *found = NULL;
+  struct x_output *x;
+
+  if (wdesc == None)
+    return NULL;
+
+  FOR_EACH_FRAME (tail, frame)
+    {
+      if (found)
+        break;
+      f = XFRAME (frame);
+      if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo)
+       {
+         /* This frame matches if the window is any of its widgets.  */
+         x = f->output_data.x;
+         if (x->hourglass_window == wdesc)
+           found = f;
+         else if (x->widget)
+           {
+#ifdef USE_GTK
+              GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
+              if (gwdesc != 0
+                  && gtk_widget_get_toplevel (gwdesc) == x->widget)
+                found = f;
+#else
+             if (wdesc == XtWindow (x->widget)
+                 || wdesc == XtWindow (x->column_widget)
+                 || wdesc == XtWindow (x->edit_widget))
+               found = f;
+             /* Match if the window is this frame's menubar.  */
+             else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
+               found = f;
+#endif
+           }
+         else if (FRAME_X_WINDOW (f) == wdesc)
+           /* A tooltip frame.  */
+           found = f;
+       }
+    }
+
+  return found;
+}
+
+/* Likewise, but consider only the menu bar widget.  */
+
+static struct frame *
+x_menubar_window_to_frame (struct x_display_info *dpyinfo,
+                          const XEvent *event)
+{
+  Window wdesc = event->xany.window;
+  Lisp_Object tail, frame;
+  struct frame *f;
+  struct x_output *x;
+
+  if (wdesc == None)
+    return NULL;
+
+  FOR_EACH_FRAME (tail, frame)
+    {
+      f = XFRAME (frame);
+      if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
+       continue;
+      x = f->output_data.x;
+#ifdef USE_GTK
+      if (x->menubar_widget && xg_event_is_for_menubar (f, event))
+        return f;
+#else
+      /* Match if the window is this frame's menubar.  */
+      if (x->menubar_widget
+         && lw_window_is_in_menubar (wdesc, x->menubar_widget))
+       return f;
+#endif
+    }
+  return 0;
+}
+
+/* Return the frame whose principal (outermost) window is WDESC.
+   If WDESC is some other (smaller) window, we return 0.  */
+
+struct frame *
+x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
+{
+  Lisp_Object tail, frame;
+  struct frame *f;
+  struct x_output *x;
+
+  if (wdesc == None)
+    return NULL;
+
+  FOR_EACH_FRAME (tail, frame)
+    {
+      f = XFRAME (frame);
+      if (!FRAME_X_P (f) || FRAME_DISPLAY_INFO (f) != dpyinfo)
+       continue;
+      x = f->output_data.x;
+
+      if (x->widget)
+       {
+         /* This frame matches if the window is its topmost widget.  */
+#ifdef USE_GTK
+          GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
+          if (gwdesc == x->widget)
+            return f;
+#else
+         if (wdesc == XtWindow (x->widget))
+           return f;
+#endif
+       }
+      else if (FRAME_X_WINDOW (f) == wdesc)
+       /* Tooltip frame.  */
+       return f;
+    }
+  return 0;
+}
+
+#else /* !USE_X_TOOLKIT && !USE_GTK */
+
+#define x_any_window_to_frame(d, i) x_window_to_frame (d, i)
+#define x_top_window_to_frame(d, i) x_window_to_frame (d, i)
+
+#endif /* USE_X_TOOLKIT || USE_GTK */
+
 /* The focus may have changed.  Figure out if it is a real focus change,
    by checking both FocusIn/Out and Enter/LeaveNotify events.
 
    Returns FOCUS_IN_EVENT event in *BUFP. */
 
 static void
-x_detect_focus_change (struct x_display_info *dpyinfo, XEvent *event, struct input_event *bufp)
+x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame,
+                      const XEvent *event, struct input_event *bufp)
 {
-  struct frame *frame;
-
-  frame = x_any_window_to_frame (dpyinfo, event->xany.window);
-  if (! frame)
+  if (!frame)
     return;
 
   switch (event->type)
@@ -3455,7 +3536,7 @@ x_detect_focus_change (struct x_display_info *dpyinfo, XEvent *event, struct inp
 }
 
 
-#if defined HAVE_MENUS && !defined USE_X_TOOLKIT && !defined USE_GTK
+#if !defined USE_X_TOOLKIT && !defined USE_GTK
 /* Handle an event saying the mouse has moved out of an Emacs frame.  */
 
 void
@@ -3476,7 +3557,7 @@ x_mouse_leave (struct x_display_info *dpyinfo)
 static void
 XTframe_rehighlight (struct frame *frame)
 {
-  x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
+  x_frame_rehighlight (FRAME_DISPLAY_INFO (frame));
 }
 
 static void
@@ -3692,9 +3773,25 @@ x_get_keysym_name (int keysym)
   return value;
 }
 
+/* Mouse clicks and mouse movement.  Rah.
 
-\f
-/* Mouse clicks and mouse movement.  Rah.  */
+   Formerly, we used PointerMotionHintMask (in standard_event_mask)
+   so that we would have to call XQueryPointer after each MotionNotify
+   event to ask for another such event.  However, this made mouse tracking
+   slow, and there was a bug that made it eventually stop.
+
+   Simply asking for MotionNotify all the time seems to work better.
+
+   In order to avoid asking for motion events and then throwing most
+   of them away or busy-polling the server for mouse positions, we ask
+   the server for pointer motion hints.  This means that we get only
+   one event per group of mouse movements.  "Groups" are delimited by
+   other kinds of events (focus changes and button clicks, for
+   example), or by XQueryPointer calls; when one of these happens, we
+   get another MotionNotify event the next time the mouse moves.  This
+   is at least as efficient as getting motion events when mouse
+   tracking is on, and I suspect only negligibly worse when tracking
+   is off.  */
 
 /* Prepare a mouse-event in *RESULT for placement in the input queue.
 
@@ -3702,14 +3799,16 @@ x_get_keysym_name (int keysym)
    the mouse.  */
 
 static Lisp_Object
-construct_mouse_click (struct input_event *result, XButtonEvent *event, struct frame *f)
+construct_mouse_click (struct input_event *result,
+                      const XButtonEvent *event,
+                      struct frame *f)
 {
   /* Make the event type NO_EVENT; we'll change that when we decide
      otherwise.  */
   result->kind = MOUSE_CLICK_EVENT;
   result->code = event->button - Button1;
   result->timestamp = event->time;
-  result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
+  result->modifiers = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f),
                                               event->state)
                       | (event->type == ButtonRelease
                          ? up_modifier
@@ -3730,65 +3829,49 @@ construct_mouse_click (struct input_event *result, XButtonEvent *event, struct f
    the mainstream emacs code by setting mouse_moved.  If not, ask for
    another motion event, so we can check again the next time it moves.  */
 
-static XMotionEvent last_mouse_motion_event;
-static Lisp_Object last_mouse_motion_frame;
-
 static int
-note_mouse_movement (struct frame *frame, XMotionEvent *event)
+note_mouse_movement (struct frame *frame, const XMotionEvent *event)
 {
-  last_mouse_movement_time = event->time;
-  last_mouse_motion_event = *event;
-  XSETFRAME (last_mouse_motion_frame, frame);
+  XRectangle *r;
+  struct x_display_info *dpyinfo;
 
   if (!FRAME_X_OUTPUT (frame))
     return 0;
 
+  dpyinfo = FRAME_DISPLAY_INFO (frame);
+  dpyinfo->last_mouse_movement_time = event->time;
+  dpyinfo->last_mouse_motion_frame = frame;
+  dpyinfo->last_mouse_motion_x = event->x;
+  dpyinfo->last_mouse_motion_y = event->y;
+
   if (event->window != FRAME_X_WINDOW (frame))
     {
       frame->mouse_moved = 1;
-      last_mouse_scroll_bar = Qnil;
+      dpyinfo->last_mouse_scroll_bar = NULL;
       note_mouse_highlight (frame, -1, -1);
-      last_mouse_glyph_frame = 0;
+      dpyinfo->last_mouse_glyph_frame = NULL;
       return 1;
     }
 
 
   /* Has the mouse moved off the glyph it was on at the last sighting?  */
-  if (frame != last_mouse_glyph_frame
-      || event->x < last_mouse_glyph.x
-      || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
-      || event->y < last_mouse_glyph.y
-      || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
+  r = &dpyinfo->last_mouse_glyph;
+  if (frame != dpyinfo->last_mouse_glyph_frame
+      || event->x < r->x || event->x >= r->x + r->width
+      || event->y < r->y || event->y >= r->y + r->height)
     {
       frame->mouse_moved = 1;
-      last_mouse_scroll_bar = Qnil;
+      dpyinfo->last_mouse_scroll_bar = NULL;
       note_mouse_highlight (frame, event->x, event->y);
       /* Remember which glyph we're now on.  */
-      remember_mouse_glyph (frame, event->x, event->y, &last_mouse_glyph);
-      last_mouse_glyph_frame = frame;
+      remember_mouse_glyph (frame, event->x, event->y, r);
+      dpyinfo->last_mouse_glyph_frame = frame;
       return 1;
     }
 
   return 0;
 }
 
-\f
-/************************************************************************
-                             Mouse Face
- ************************************************************************/
-
-static void
-redo_mouse_highlight (void)
-{
-  if (!NILP (last_mouse_motion_frame)
-      && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
-    note_mouse_highlight (XFRAME (last_mouse_motion_frame),
-                         last_mouse_motion_event.x,
-                         last_mouse_motion_event.y);
-}
-
-
-
 /* Return the current position of the mouse.
    *FP should be a frame which indicates which display to ask about.
 
@@ -3815,10 +3898,11 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
                  Time *timestamp)
 {
   struct frame *f1;
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
 
   block_input ();
 
-  if (! NILP (last_mouse_scroll_bar) && insist == 0)
+  if (dpyinfo->last_mouse_scroll_bar && insist == 0)
     x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
   else
     {
@@ -3836,7 +3920,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
             && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
          XFRAME (frame)->mouse_moved = 0;
 
-      last_mouse_scroll_bar = Qnil;
+      dpyinfo->last_mouse_scroll_bar = NULL;
 
       /* Figure out which root window we're on.  */
       XQueryPointer (FRAME_X_DISPLAY (*fp),
@@ -3874,22 +3958,24 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
 
        x_catch_errors (FRAME_X_DISPLAY (*fp));
 
-       if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
-           && FRAME_LIVE_P (last_mouse_frame))
+       if (x_mouse_grabbed (dpyinfo))
          {
            /* If mouse was grabbed on a frame, give coords for that frame
               even if the mouse is now outside it.  */
            XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
 
-                                  /* From-window, to-window.  */
-                                  root, FRAME_X_WINDOW (last_mouse_frame),
+                                  /* From-window.  */
+                                  root,
+
+                                  /* To-window.  */
+                                  FRAME_X_WINDOW (dpyinfo->last_mouse_frame),
 
                                   /* From-position, to-position.  */
                                   root_x, root_y, &win_x, &win_y,
 
                                   /* Child of win.  */
                                   &child);
-           f1 = last_mouse_frame;
+           f1 = dpyinfo->last_mouse_frame;
          }
        else
          {
@@ -3913,7 +3999,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
                   want the edit window.  For non-Gtk+ the innermost
                   window is the edit window.  For Gtk+ it might not
                   be.  It might be the tool bar for example.  */
-               if (x_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win))
+               if (x_window_to_frame (dpyinfo, win))
                  break;
 #endif
                win = child;
@@ -3935,10 +4021,10 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
 #ifdef USE_GTK
            /* We don't wan't to know the innermost window.  We
               want the edit window.  */
-           f1 = x_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
+           f1 = x_window_to_frame (dpyinfo, win);
 #else
            /* Is win one of our frames?  */
-           f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
+           f1 = x_any_window_to_frame (dpyinfo, win);
 #endif
 
 #ifdef USE_X_TOOLKIT
@@ -3984,15 +4070,17 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
               on it, i.e. into the same rectangles that matrices on
               the frame are divided into.  */
 
-           remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph);
-           last_mouse_glyph_frame = f1;
+           /* FIXME: what if F1 is not an X frame?  */
+           dpyinfo = FRAME_DISPLAY_INFO (f1);
+           remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph);
+           dpyinfo->last_mouse_glyph_frame = f1;
 
            *bar_window = Qnil;
            *part = 0;
            *fp = f1;
            XSETINT (*x, win_x);
            XSETINT (*y, win_y);
-           *timestamp = last_mouse_movement_time;
+           *timestamp = dpyinfo->last_mouse_movement_time;
          }
       }
     }
@@ -4078,23 +4166,13 @@ x_window_to_menu_bar (Window window)
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
 
-static void x_scroll_bar_to_input_event (XEvent *, struct input_event *);
 static void x_send_scroll_bar_event (Lisp_Object, int, int, int);
-static void x_create_toolkit_scroll_bar (struct frame *,
-                                         struct scroll_bar *);
-static void x_set_toolkit_scroll_bar_thumb (struct scroll_bar *,
-                                            int, int, int);
-
 
 /* Lisp window being scrolled.  Set when starting to interact with
    a toolkit scroll bar, reset to nil when ending the interaction.  */
 
 static Lisp_Object window_being_scrolled;
 
-/* Last scroll bar part sent in xm_scroll_callback.  */
-
-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.  */
 
@@ -4136,33 +4214,29 @@ xt_action_hook (Widget widget, XtPointer client_data, String action_name,
       && WINDOWP (window_being_scrolled))
     {
       struct window *w;
+      struct scroll_bar *bar;
 
       x_send_scroll_bar_event (window_being_scrolled,
                               scroll_bar_end_scroll, 0, 0);
       w = XWINDOW (window_being_scrolled);
+      bar = XSCROLL_BAR (w->vertical_scroll_bar);
 
-      if (!NILP (XSCROLL_BAR (w->vertical_scroll_bar)->dragging))
+      if (bar->dragging != -1)
        {
-         XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
+         bar->dragging = -1;
          /* The thumb size is incorrect while dragging: fix it.  */
          set_vertical_scroll_bar (w);
        }
       window_being_scrolled = Qnil;
-      last_scroll_bar_part = -1;
-
+#if defined (USE_LUCID)
+      bar->last_seen_part = scroll_bar_nowhere;
+#endif
       /* Xt timeouts no longer needed.  */
       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.  */
-
-static struct window **scroll_bar_windows;
-static ptrdiff_t scroll_bar_windows_size;
-
-
 /* Send a client message with message type Xatom_Scrollbar for a
    scroll action to the frame of WINDOW.  PART is a value identifying
    the part of the scroll bar that was clicked on.  PORTION is the
@@ -4172,47 +4246,33 @@ static void
 x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole)
 {
   XEvent event;
-  XClientMessageEvent *ev = (XClientMessageEvent *) &event;
+  XClientMessageEvent *ev = &event.xclient;
   struct window *w = XWINDOW (window);
   struct frame *f = XFRAME (w->frame);
-  ptrdiff_t i;
+  intptr_t iw = (intptr_t) w;
+  enum { BITS_PER_INTPTR = CHAR_BIT * sizeof iw };
+  verify (BITS_PER_INTPTR <= 64);
+  int sign_shift = BITS_PER_INTPTR - 32;
 
   block_input ();
 
   /* Construct a ClientMessage event to send to the frame.  */
   ev->type = ClientMessage;
-  ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
+  ev->message_type = FRAME_DISPLAY_INFO (f)->Xatom_Scrollbar;
   ev->display = FRAME_X_DISPLAY (f);
   ev->window = FRAME_X_WINDOW (f);
   ev->format = 32;
 
-  /* We can only transfer 32 bits in the XClientMessageEvent, which is
-     not enough to store a pointer or Lisp_Object on a 64 bit system.
-     So, store the window in scroll_bar_windows and pass the index
-     into that array in the event.  */
-  for (i = 0; i < scroll_bar_windows_size; ++i)
-    if (scroll_bar_windows[i] == NULL)
-      break;
-
-  if (i == scroll_bar_windows_size)
-    {
-      ptrdiff_t old_nbytes =
-       scroll_bar_windows_size * sizeof *scroll_bar_windows;
-      ptrdiff_t nbytes;
-      enum { XClientMessageEvent_MAX = 0x7fffffff };
-      scroll_bar_windows =
-       xpalloc (scroll_bar_windows, &scroll_bar_windows_size, 1,
-                XClientMessageEvent_MAX, sizeof *scroll_bar_windows);
-      nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
-      memset (&scroll_bar_windows[i], 0, nbytes - old_nbytes);
-    }
-
-  scroll_bar_windows[i] = w;
-  ev->data.l[0] = (long) i;
-  ev->data.l[1] = (long) part;
-  ev->data.l[2] = (long) 0;
-  ev->data.l[3] = (long) portion;
-  ev->data.l[4] = (long) whole;
+  /* A 32-bit X client on a 64-bit X server can pass a window pointer
+     as-is.  A 64-bit client on a 32-bit X server is in trouble
+     because a pointer does not fit and would be truncated while
+     passing through the server.  So use two slots and hope that X12
+     will resolve such issues someday.  */
+  ev->data.l[0] = iw >> 31 >> 1;
+  ev->data.l[1] = sign_shift <= 0 ? iw : iw << sign_shift >> sign_shift;
+  ev->data.l[2] = part;
+  ev->data.l[3] = portion;
+  ev->data.l[4] = whole;
 
   /* Make Xt timeouts work while the scroll bar is active.  */
 #ifdef USE_X_TOOLKIT
@@ -4232,14 +4292,18 @@ x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole)
    in *IEVENT.  */
 
 static void
-x_scroll_bar_to_input_event (XEvent *event, struct input_event *ievent)
+x_scroll_bar_to_input_event (const XEvent *event,
+                            struct input_event *ievent)
 {
-  XClientMessageEvent *ev = (XClientMessageEvent *) event;
+  const XClientMessageEvent *ev = &event->xclient;
   Lisp_Object window;
   struct window *w;
 
-  w = scroll_bar_windows[ev->data.l[0]];
-  scroll_bar_windows[ev->data.l[0]] = NULL;
+  /* See the comment in the function above.  */
+  intptr_t iw0 = ev->data.l[0];
+  intptr_t iw1 = ev->data.l[1];
+  intptr_t iw = (iw0 << 31 << 1) + (iw1 & 0xffffffffu);
+  w = (struct window *) iw;
 
   XSETWINDOW (window, w);
 
@@ -4252,10 +4316,10 @@ x_scroll_bar_to_input_event (XEvent *event, struct input_event *ievent)
   ievent->timestamp =
     XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w->frame)));
 #endif
-  ievent->part = ev->data.l[1];
-  ievent->code = ev->data.l[2];
-  ievent->x = make_number ((int) ev->data.l[3]);
-  ievent->y = make_number ((int) ev->data.l[4]);
+  ievent->code = 0;
+  ievent->part = ev->data.l[2];
+  ievent->x = make_number (ev->data.l[3]);
+  ievent->y = make_number (ev->data.l[4]);
   ievent->modifiers = 0;
 }
 
@@ -4281,32 +4345,32 @@ xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
   switch (cs->reason)
     {
     case XmCR_DECREMENT:
-      bar->dragging = Qnil;
+      bar->dragging = -1;
       part = scroll_bar_up_arrow;
       break;
 
     case XmCR_INCREMENT:
-      bar->dragging = Qnil;
+      bar->dragging = -1;
       part = scroll_bar_down_arrow;
       break;
 
     case XmCR_PAGE_DECREMENT:
-      bar->dragging = Qnil;
+      bar->dragging = -1;
       part = scroll_bar_above_handle;
       break;
 
     case XmCR_PAGE_INCREMENT:
-      bar->dragging = Qnil;
+      bar->dragging = -1;
       part = scroll_bar_below_handle;
       break;
 
     case XmCR_TO_TOP:
-      bar->dragging = Qnil;
+      bar->dragging = -1;
       part = scroll_bar_to_top;
       break;
 
     case XmCR_TO_BOTTOM:
-      bar->dragging = Qnil;
+      bar->dragging = -1;
       part = scroll_bar_to_bottom;
       break;
 
@@ -4322,7 +4386,7 @@ xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
        whole = XM_SB_MAX - slider_size;
        portion = min (cs->value, whole);
        part = scroll_bar_handle;
-       bar->dragging = make_number (cs->value);
+       bar->dragging = cs->value;
       }
       break;
 
@@ -4333,7 +4397,6 @@ xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
   if (part >= 0)
     {
       window_being_scrolled = bar->window;
-      last_scroll_bar_part = part;
       x_send_scroll_bar_event (bar->window, part, portion, whole);
     }
 }
@@ -4363,45 +4426,44 @@ xg_scroll_callback (GtkRange     *range,
     {
     case GTK_SCROLL_JUMP:
       /* Buttons 1 2 or 3 must be grabbed.  */
-      if (FRAME_X_DISPLAY_INFO (f)->grabbed != 0
-          && FRAME_X_DISPLAY_INFO (f)->grabbed < (1 << 4))
+      if (FRAME_DISPLAY_INFO (f)->grabbed != 0
+          && FRAME_DISPLAY_INFO (f)->grabbed < (1 << 4))
         {
           part = scroll_bar_handle;
           whole = gtk_adjustment_get_upper (adj) -
             gtk_adjustment_get_page_size (adj);
           portion = min ((int)position, whole);
-          bar->dragging = make_number ((int)portion);
+          bar->dragging = portion;
         }
       break;
     case GTK_SCROLL_STEP_BACKWARD:
       part = scroll_bar_up_arrow;
-      bar->dragging = Qnil;
+      bar->dragging = -1;
       break;
     case GTK_SCROLL_STEP_FORWARD:
       part = scroll_bar_down_arrow;
-      bar->dragging = Qnil;
+      bar->dragging = -1;
       break;
     case GTK_SCROLL_PAGE_BACKWARD:
       part = scroll_bar_above_handle;
-      bar->dragging = Qnil;
+      bar->dragging = -1;
       break;
     case GTK_SCROLL_PAGE_FORWARD:
       part = scroll_bar_below_handle;
-      bar->dragging = Qnil;
+      bar->dragging = -1;
       break;
     }
 
   if (part >= 0)
     {
       window_being_scrolled = bar->window;
-      last_scroll_bar_part = part;
       x_send_scroll_bar_event (bar->window, part, portion, whole);
     }
 
   return FALSE;
 }
 
-/* Callback for button release. Sets dragging to Qnil when dragging is done.  */
+/* Callback for button release. Sets dragging to -1 when dragging is done.  */
 
 static gboolean
 xg_end_scroll_callback (GtkWidget *widget,
@@ -4409,7 +4471,7 @@ xg_end_scroll_callback (GtkWidget *widget,
                         gpointer user_data)
 {
   struct scroll_bar *bar = user_data;
-  bar->dragging = Qnil;
+  bar->dragging = -1;
   if (WINDOWP (window_being_scrolled))
     {
       x_send_scroll_bar_event (window_being_scrolled,
@@ -4436,7 +4498,7 @@ xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data)
   float top = *top_addr;
   float shown;
   int whole, portion, height;
-  int part;
+  enum scroll_bar_part part;
 
   /* Get the size of the thumb, a value between 0 and 1.  */
   block_input ();
@@ -4457,8 +4519,8 @@ xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data)
     part = scroll_bar_handle;
 
   window_being_scrolled = bar->window;
-  bar->dragging = make_number (portion);
-  last_scroll_bar_part = part;
+  bar->dragging = portion;
+  bar->last_seen_part = part;
   x_send_scroll_bar_event (bar->window, part, portion, whole);
 }
 
@@ -4478,7 +4540,7 @@ xaw_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
   /* The position really is stored cast to a pointer.  */
   int position = (intptr_t) call_data;
   Dimension height;
-  int part;
+  enum scroll_bar_part part;
 
   /* Get the height of the scroll bar.  */
   block_input ();
@@ -4496,8 +4558,8 @@ xaw_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
     part = scroll_bar_move_ratio;
 
   window_being_scrolled = bar->window;
-  bar->dragging = Qnil;
-  last_scroll_bar_part = part;
+  bar->dragging = -1;
+  bar->last_seen_part = part;
   x_send_scroll_bar_event (bar->window, part, position, height);
 }
 
@@ -4772,7 +4834,7 @@ x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int positio
       shown = (float) portion / whole;
     }
 
-  if (NILP (bar->dragging))
+  if (bar->dragging == -1)
     {
       int size, value;
 
@@ -4807,19 +4869,28 @@ x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int positio
                   NULL);
 
     /* Massage the top+shown values.  */
-    if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
+    if (bar->dragging == -1 || bar->last_seen_part == scroll_bar_down_arrow)
       top = max (0, min (1, top));
     else
       top = old_top;
+#if ! defined (HAVE_XAW3D)
+    /* With Xaw, 'top' values too closer to 1.0 may
+       cause the thumb to disappear.  Fix that.  */
+    top = min (top, 0.99f);
+#endif
     /* Keep two pixels available for moving the thumb down.  */
     shown = max (0, min (1 - top - (2.0f / height), shown));
+#if ! defined (HAVE_XAW3D)
+    /* Likewise with too small 'shown'.  */
+    shown = max (shown, 0.01f);
+#endif
 
-    /* If the call to XawScrollbarSetThumb below doesn't seem to work,
-       check that your system's configuration file contains a define
-       for `NARROWPROTO'.  See s/freebsd.h for an example.  */
+    /* If the call to XawScrollbarSetThumb below doesn't seem to
+       work, check that 'NARROWPROTO' is defined in src/config.h.
+       If this is not so, most likely you need to fix configure.  */
     if (top != old_top || shown != old_shown)
       {
-       if (NILP (bar->dragging))
+       if (bar->dragging == -1)
          XawScrollbarSetThumb (widget, top, shown);
        else
          {
@@ -4875,25 +4946,22 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
     a.event_mask = (ButtonPressMask | ButtonReleaseMask
                    | ButtonMotionMask | PointerMotionHintMask
                    | ExposureMask);
-    a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
+    a.cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
 
     mask = (CWBackPixel | CWEventMask | CWCursor);
 
     /* Clear the area of W that will serve as a scroll bar.  This is
        for the case that a window has been split horizontally.  In
        this case, no clear_frame is generated to reduce flickering.  */
-    if (width > 0 && height > 0)
+    if (width > 0 && window_box_height (w) > 0)
       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                    left, top, width, window_box_height (w));
 
     window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                            /* Position and size of scroll bar.  */
-                           left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                           top,
-                           width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-                           height,
+                           left, top, width, height,
                            /* Border width, depth, class, and visual.  */
-                            0,
+                           0,
                            CopyFromParent,
                            CopyFromParent,
                            CopyFromParent,
@@ -4910,8 +4978,10 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
   bar->height = height;
   bar->start = 0;
   bar->end = 0;
-  bar->dragging = Qnil;
-  bar->fringe_extended_p = 0;
+  bar->dragging = -1;
+#if defined (USE_TOOLKIT_SCROLL_BARS) && defined (USE_LUCID)
+  bar->last_seen_part = scroll_bar_nowhere;
+#endif
 
   /* Add bar to its frame's list of scroll bars.  */
   bar->next = FRAME_SCROLL_BARS (f);
@@ -4925,19 +4995,11 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
 #ifdef USE_TOOLKIT_SCROLL_BARS
   {
 #ifdef USE_GTK
-    xg_update_scrollbar_pos (f,
-                             bar->x_window,
-                             top,
-                             left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                             width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-                             max (height, 1));
+    xg_update_scrollbar_pos (f, bar->x_window, top,
+                            left,width, max (height, 1));
 #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,
-                      top,
-                      width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-                      max (height, 1), 0);
+    XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0);
     XtMapWidget (scroll_bar);
 #endif /* not USE_GTK */
     }
@@ -4968,7 +5030,7 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
 static void
 x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end, int rebuild)
 {
-  int dragging = ! NILP (bar->dragging);
+  bool dragging = bar->dragging != -1;
   Window w = bar->x_window;
   struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
   GC gc = f->output_data.x->normal_gc;
@@ -5092,44 +5154,17 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
   struct frame *f = XFRAME (w->frame);
   Lisp_Object barobj;
   struct scroll_bar *bar;
-  int top, height, left, sb_left, width, sb_width;
+  int top, height, left, width;
   int window_y, window_height;
-#ifdef USE_TOOLKIT_SCROLL_BARS
-  bool fringe_extended_p;
-#endif
 
   /* Get window dimensions.  */
   window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
   top = window_y;
-  width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
   height = window_height;
 
-  /* Compute the left edge of the scroll bar area.  */
+  /* Compute the left edge and the width of the scroll bar area.  */
   left = WINDOW_SCROLL_BAR_AREA_X (w);
-
-  /* Compute the width of the scroll bar which might be less than
-     the width of the area reserved for the scroll bar.  */
-  if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
-    sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-  else
-    sb_width = width;
-
-  /* Compute the left edge of the scroll bar.  */
-#ifdef USE_TOOLKIT_SCROLL_BARS
-  if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
-    sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
-  else
-    sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
-#else
-  if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
-    sb_left = left + width - sb_width;
-  else
-    sb_left = left;
-#endif
-
-#ifdef USE_TOOLKIT_SCROLL_BARS
-  fringe_extended_p = WINDOW_FRINGE_EXTENDED_P (w);
-#endif
+  width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
 
   /* Does the scroll bar exist yet?  */
   if (NILP (w->vertical_scroll_bar))
@@ -5137,18 +5172,12 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
       if (width > 0 && height > 0)
        {
          block_input ();
-#ifdef USE_TOOLKIT_SCROLL_BARS
-         if (fringe_extended_p)
-           x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                         sb_left, top, sb_width, height);
-         else
-#endif
-           x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                         left, top, width, height);
+         x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                       left, top, width, height);
          unblock_input ();
        }
 
-      bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
+      bar = x_scroll_bar_create (w, top, left, width, max (height, 1));
     }
   else
     {
@@ -5159,11 +5188,11 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
 
       block_input ();
 
-      if (sb_left != bar->left)
+      if (left != bar->left)
        mask |= CWX;
       if (top != bar->top)
        mask |= CWY;
-      if (sb_width != bar->width)
+      if (width != bar->width)
        mask |= CWWidth;
       if (height != bar->height)
        mask |= CWHeight;
@@ -5171,73 +5200,31 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
 #ifdef USE_TOOLKIT_SCROLL_BARS
 
       /* Move/size the scroll bar widget.  */
-      if (mask || bar->fringe_extended_p != fringe_extended_p)
+      if (mask)
        {
          /* Since toolkit scroll bars are smaller than the space reserved
             for them on the frame, we have to clear "under" them.  */
          if (width > 0 && height > 0)
-           {
-             if (fringe_extended_p)
-               x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                             sb_left, top, sb_width, height);
-             else
-               x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                             left, top, width, height);
-           }
+           x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                         left, top, width, height);
 #ifdef USE_GTK
-          xg_update_scrollbar_pos (f,
-                                   bar->x_window,
-                                   top,
-                                   sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                                   sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM *2,
-                                   max (height, 1));
+          xg_update_scrollbar_pos (f, bar->x_window, top,
+                                  left, width, max (height, 1));
 #else /* not USE_GTK */
           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);
+                             left, top, width, max (height, 1), 0);
 #endif /* not USE_GTK */
        }
 #else /* not USE_TOOLKIT_SCROLL_BARS */
 
-      /* Clear areas not covered by the scroll bar because of
-        VERTICAL_SCROLL_BAR_WIDTH_TRIM.  */
-      if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
-       {
-         x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                       left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM, height);
-         x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                       left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                       top, VERTICAL_SCROLL_BAR_WIDTH_TRIM, height);
-       }
-
-      /* Clear areas not covered by the scroll bar because it's not as
-        wide as the area reserved for it.  This makes sure a
-        previous mode line display is cleared after C-x 2 C-x 1, for
-        example.  */
-      {
-       int area_width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
-       int rest = area_width - sb_width;
-       if (rest > 0 && height > 0)
-         {
-           if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
-             x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                           left + area_width - rest, top, rest, height);
-           else
-             x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                           left, top, rest, height);
-         }
-      }
-
       /* Move/size the scroll bar window.  */
       if (mask)
        {
          XWindowChanges wc;
 
-         wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
+         wc.x = left;
          wc.y = top;
-         wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
+         wc.width = width;
          wc.height = height;
          XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
                            mask, &wc);
@@ -5246,22 +5233,20 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
 
       /* Remember new settings.  */
-      bar->left = sb_left;
+      bar->left = left;
       bar->top = top;
-      bar->width = sb_width;
+      bar->width = width;
       bar->height = height;
 
       unblock_input ();
     }
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
-  bar->fringe_extended_p = fringe_extended_p;
-
   x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
 #else /* not USE_TOOLKIT_SCROLL_BARS */
   /* Set the scroll bar's current state, unless we're currently being
      dragged.  */
-  if (NILP (bar->dragging))
+  if (bar->dragging == -1)
     {
       int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
 
@@ -5395,12 +5380,11 @@ XTjudge_scroll_bars (struct frame *f)
    mark bits.  */
 
 static void
-x_scroll_bar_expose (struct scroll_bar *bar, XEvent *event)
+x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event)
 {
   Window w = bar->x_window;
   struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
   GC gc = f->output_data.x->normal_gc;
-  int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
 
   block_input ();
 
@@ -5413,11 +5397,8 @@ x_scroll_bar_expose (struct scroll_bar *bar, XEvent *event)
 
   /* Draw a one-pixel border just inside the edges of the scroll bar.  */
   XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
-
                  /* x, y, width, height */
-                 0, 0,
-                 bar->width - 1 - width_trim - width_trim,
-                 bar->height - 1);
+                 0, 0, bar->width - 1, bar->height - 1);
 
    /* Restore the foreground color of the GC if we changed it above.  */
    if (f->output_data.x->scroll_bar_foreground_pixel != -1)
@@ -5437,7 +5418,9 @@ x_scroll_bar_expose (struct scroll_bar *bar, XEvent *event)
 
 
 static void
-x_scroll_bar_handle_click (struct scroll_bar *bar, XEvent *event, struct input_event *emacs_event)
+x_scroll_bar_handle_click (struct scroll_bar *bar,
+                          const XEvent *event,
+                          struct input_event *emacs_event)
 {
   if (! WINDOWP (bar->window))
     emacs_abort ();
@@ -5445,7 +5428,7 @@ x_scroll_bar_handle_click (struct scroll_bar *bar, XEvent *event, struct input_e
   emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
   emacs_event->code = event->xbutton.button - Button1;
   emacs_event->modifiers
-    = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
+    = (x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO
                               (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
                               event->xbutton.state)
        | (event->type == ButtonRelease
@@ -5471,14 +5454,13 @@ x_scroll_bar_handle_click (struct scroll_bar *bar, XEvent *event, struct input_e
 
 #ifndef USE_TOOLKIT_SCROLL_BARS
     /* If the user has released the handle, set it to its final position.  */
-    if (event->type == ButtonRelease
-       && ! NILP (bar->dragging))
+    if (event->type == ButtonRelease && bar->dragging != -1)
       {
-       int new_start = y - XINT (bar->dragging);
+       int new_start = y - bar->dragging;
        int new_end = new_start + bar->end - bar->start;
 
        x_scroll_bar_set_handle (bar, new_start, new_end, 0);
-       bar->dragging = Qnil;
+       bar->dragging = -1;
       }
 #endif
 
@@ -5495,20 +5477,21 @@ x_scroll_bar_handle_click (struct scroll_bar *bar, XEvent *event, struct input_e
    mark bits.  */
 
 static void
-x_scroll_bar_note_movement (struct scroll_bar *bar, XMotionEvent *event)
+x_scroll_bar_note_movement (struct scroll_bar *bar,
+                           const XMotionEvent *event)
 {
   struct frame *f = XFRAME (XWINDOW (bar->window)->frame);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
 
-  last_mouse_movement_time = event->time;
-
+  dpyinfo->last_mouse_movement_time = event->time;
+  dpyinfo->last_mouse_scroll_bar = bar;
   f->mouse_moved = 1;
-  XSETVECTOR (last_mouse_scroll_bar, bar);
 
   /* If we're dragging the bar, display it.  */
-  if (! NILP (bar->dragging))
+  if (bar->dragging != -1)
     {
       /* Where should the handle be now?  */
-      int new_start = event->y - XINT (bar->dragging);
+      int new_start = event->y - bar->dragging;
 
       if (new_start != bar->start)
        {
@@ -5529,7 +5512,8 @@ x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
                            enum scroll_bar_part *part, Lisp_Object *x,
                            Lisp_Object *y, Time *timestamp)
 {
-  struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
+  struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
   Window w = bar->x_window;
   struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
   int win_x, win_y;
@@ -5541,27 +5525,24 @@ x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
 
   /* Get the mouse's position relative to the scroll bar window, and
      report that.  */
-  if (XQueryPointer (FRAME_X_DISPLAY (f), w,
+  if (XQueryPointer (FRAME_X_DISPLAY (f), w,
 
-                      /* Root, child, root x and root y.  */
-                      &dummy_window, &dummy_window,
-                      &dummy_coord, &dummy_coord,
+                    /* Root, child, root x and root y.  */
+                    &dummy_window, &dummy_window,
+                    &dummy_coord, &dummy_coord,
 
-                      /* Position relative to scroll bar.  */
-                      &win_x, &win_y,
+                    /* Position relative to scroll bar.  */
+                    &win_x, &win_y,
 
-                      /* Mouse buttons and modifier keys.  */
-                      &dummy_mask))
-    ;
-  else
+                    /* Mouse buttons and modifier keys.  */
+                    &dummy_mask))
     {
-      int top_range
-       = VERTICAL_SCROLL_BAR_TOP_RANGE     (f, bar->height);
+      int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
 
       win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
 
-      if (! NILP (bar->dragging))
-       win_y -= XINT (bar->dragging);
+      if (bar->dragging != -1)
+       win_y -= bar->dragging;
 
       if (win_y < 0)
        win_y = 0;
@@ -5571,7 +5552,7 @@ x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
       *fp = f;
       *bar_window = bar->window;
 
-      if (! NILP (bar->dragging))
+      if (bar->dragging != -1)
        *part = scroll_bar_handle;
       else if (win_y < bar->start)
        *part = scroll_bar_above_handle;
@@ -5584,11 +5565,10 @@ x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
       XSETINT (*y, top_range);
 
       f->mouse_moved = 0;
-      last_mouse_scroll_bar = Qnil;
+      dpyinfo->last_mouse_scroll_bar = NULL;
+      *timestamp = dpyinfo->last_mouse_movement_time;
     }
 
-  *timestamp = last_mouse_movement_time;
-
   unblock_input ();
 }
 
@@ -5647,20 +5627,6 @@ static struct x_display_info *XTread_socket_fake_io_error;
 
 static struct x_display_info *next_noop_dpyinfo;
 
-#if defined USE_X_TOOLKIT || defined USE_GTK
-#define SET_SAVED_BUTTON_EVENT                                          \
-     do                                                                        \
-       {                                                               \
-        if (f->output_data.x->saved_menu_event == 0)                   \
-           f->output_data.x->saved_menu_event =                                \
-            xmalloc (sizeof (XEvent));                                 \
-         *f->output_data.x->saved_menu_event = event;                  \
-        inev.ie.kind = MENU_BAR_ACTIVATE_EVENT;                        \
-        XSETFRAME (inev.ie.frame_or_window, f);                        \
-       }                                                               \
-     while (0)
-#endif
-
 enum
 {
   X_EVENT_NORMAL,
@@ -5754,11 +5720,13 @@ static void xembed_send_message (struct frame *f, Time,
    *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.
+   *EVENT is unchanged unless we're processing KeyPress event.
 
-   We return the number of characters stored into the buffer. */
+   We return the number of characters stored into the buffer.  */
 
 static int
-handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
+handle_one_xevent (struct x_display_info *dpyinfo,
+                  const XEvent *event,
                   int *finish, struct input_event *hold_quit)
 {
   union {
@@ -5768,9 +5736,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
   int count = 0;
   int do_help = 0;
   ptrdiff_t nbytes = 0;
-  struct frame *f = NULL;
+  struct frame *any, *f = NULL;
   struct coding_system coding;
-  XEvent event = *eventptr;
   Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
   /* This holds the state XLookupString needs to implement dead keys
      and other tricks known as "compose processing".  _X Window System_
@@ -5786,24 +5753,24 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
   inev.ie.kind = NO_EVENT;
   inev.ie.arg = Qnil;
 
-  if (pending_event_wait.eventtype == event.type)
-    pending_event_wait.eventtype = 0; /* Indicates we got it.  */
+  any = x_any_window_to_frame (dpyinfo, event->xany.window);
+
+  if (any && any->wait_event_type == event->type)
+    any->wait_event_type = 0; /* Indicates we got it.  */
 
-  switch (event.type)
+  switch (event->type)
     {
     case ClientMessage:
       {
-        if (event.xclient.message_type
-            == dpyinfo->Xatom_wm_protocols
-            && event.xclient.format == 32)
+        if (event->xclient.message_type == dpyinfo->Xatom_wm_protocols
+            && event->xclient.format == 32)
           {
-            if (event.xclient.data.l[0]
-                == dpyinfo->Xatom_wm_take_focus)
+            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);
+                /* Use the value returned by x_any_window_to_frame
+                  because this could be the shell widget window
+                  if the frame has no title bar.  */
+                f = any;
 #ifdef HAVE_X_I18N
                 /* Not quite sure this is needed -pd */
                 if (f && FRAME_XIC (f))
@@ -5827,15 +5794,15 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
                    since that might be an event for a deleted frame.  */
                 if (f)
                   {
-                    Display *d = event.xclient.display;
+                    Display *d = event->xclient.display;
                     /* Catch and ignore errors, in case window has been
                        iconified by a window manager such as GWM.  */
                     x_catch_errors (d);
-                    XSetInputFocus (d, event.xclient.window,
+                    XSetInputFocus (d, event->xclient.window,
                                     /* The ICCCM says this is
                                        the only valid choice.  */
                                     RevertToParent,
-                                    event.xclient.data.l[1]);
+                                    event->xclient.data.l[1]);
                     /* This is needed to detect the error
                        if there is an error.  */
                     XSync (d, False);
@@ -5846,8 +5813,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
                goto done;
               }
 
-            if (event.xclient.data.l[0]
-                     == dpyinfo->Xatom_wm_save_yourself)
+            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
@@ -5862,26 +5828,24 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
 #endif
                   {
                     f = x_top_window_to_frame (dpyinfo,
-                                               event.xclient.window);
+                                               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,
+                                   event->xclient.window,
                                    initial_argv, initial_argc);
                     else if (f)
                       XSetCommand (FRAME_X_DISPLAY (f),
-                                   event.xclient.window,
+                                   event->xclient.window,
                                    0, 0);
                   }
                goto done;
               }
 
-            if (event.xclient.data.l[0]
-               == dpyinfo->Xatom_wm_delete_window)
+            if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_delete_window)
               {
-                f = x_any_window_to_frame (dpyinfo,
-                                           event.xclient.window);
+                f = any;
                 if (!f)
                  goto OTHER; /* May be a dialog that is to be removed  */
 
@@ -5893,20 +5857,16 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
            goto done;
           }
 
-        if (event.xclient.message_type
-                 == dpyinfo->Xatom_wm_configure_denied)
-          {
-           goto done;
-          }
+        if (event->xclient.message_type == dpyinfo->Xatom_wm_configure_denied)
+         goto done;
 
-        if (event.xclient.message_type
-           == dpyinfo->Xatom_wm_window_moved)
+        if (event->xclient.message_type == dpyinfo->Xatom_wm_window_moved)
           {
             int new_x, new_y;
-           f = x_window_to_frame (dpyinfo, event.xclient.window);
+           f = x_window_to_frame (dpyinfo, event->xclient.window);
 
-            new_x = event.xclient.data.s[0];
-            new_y = event.xclient.data.s[1];
+            new_x = event->xclient.data.s[0];
+            new_y = event->xclient.data.s[1];
 
             if (f)
               {
@@ -5917,28 +5877,25 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
           }
 
 #ifdef HACK_EDITRES
-        if (event.xclient.message_type
-           == dpyinfo->Xatom_editres)
+        if (event->xclient.message_type == dpyinfo->Xatom_editres)
           {
-           f = x_any_window_to_frame (dpyinfo, event.xclient.window);
+           f = any;
            if (f)
-              _XEditResCheckMessages (f->output_data.x->widget, NULL,
-                                      &event, NULL);
+              _XEditResCheckMessages (f->output_data.x->widget,
+                                     NULL, (XEvent *) event, NULL);
            goto done;
           }
 #endif /* HACK_EDITRES */
 
-        if ((event.xclient.message_type
-            == dpyinfo->Xatom_DONE)
-           || (event.xclient.message_type
-               == dpyinfo->Xatom_PAGE))
+        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];
-           f = x_window_to_frame (dpyinfo, event.xclient.window);
+            Pixmap pixmap = (Pixmap) event->xclient.data.l[1];
+           f = x_window_to_frame (dpyinfo, event->xclient.window);
            if (!f)
              goto OTHER;
             x_kill_gs_process (pixmap, f);
@@ -5949,54 +5906,52 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
 #ifdef USE_TOOLKIT_SCROLL_BARS
         /* Scroll bar callbacks send a ClientMessage from which
            we construct an input_event.  */
-        if (event.xclient.message_type
-           == dpyinfo->Xatom_Scrollbar)
+        if (event->xclient.message_type == dpyinfo->Xatom_Scrollbar)
           {
-            x_scroll_bar_to_input_event (&event, &inev.ie);
+            x_scroll_bar_to_input_event (event, &inev.ie);
            *finish = X_EVENT_GOTO_OUT;
             goto done;
           }
 #endif /* USE_TOOLKIT_SCROLL_BARS */
 
        /* XEmbed messages from the embedder (if any).  */
-        if (event.xclient.message_type
-           == dpyinfo->Xatom_XEMBED)
+        if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
           {
-           enum xembed_message msg = event.xclient.data.l[1];
+           enum xembed_message msg = event->xclient.data.l[1];
            if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT)
-             x_detect_focus_change (dpyinfo, &event, &inev.ie);
+             x_detect_focus_change (dpyinfo, any, event, &inev.ie);
 
            *finish = X_EVENT_GOTO_OUT;
             goto done;
           }
 
-        xft_settings_event (dpyinfo, &event);
+        xft_settings_event (dpyinfo, event);
 
-       f = x_any_window_to_frame (dpyinfo, event.xclient.window);
+       f = any;
        if (!f)
          goto OTHER;
-       if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie))
+       if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie))
          *finish = X_EVENT_DROP;
       }
       break;
 
     case SelectionNotify:
-      last_user_time = event.xselection.time;
+      dpyinfo->last_user_time = event->xselection.time;
 #ifdef USE_X_TOOLKIT
-      if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
+      if (! x_window_to_frame (dpyinfo, event->xselection.requestor))
         goto OTHER;
 #endif /* not USE_X_TOOLKIT */
-      x_handle_selection_notify (&event.xselection);
+      x_handle_selection_notify (&event->xselection);
       break;
 
     case SelectionClear:       /* Someone has grabbed ownership.  */
-      last_user_time = event.xselectionclear.time;
+      dpyinfo->last_user_time = event->xselectionclear.time;
 #ifdef USE_X_TOOLKIT
-      if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
+      if (! x_window_to_frame (dpyinfo, event->xselectionclear.window))
         goto OTHER;
 #endif /* USE_X_TOOLKIT */
       {
-        XSelectionClearEvent *eventp = &(event.xselectionclear);
+        const XSelectionClearEvent *eventp = &event->xselectionclear;
 
         inev.ie.kind = SELECTION_CLEAR_EVENT;
         SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
@@ -6006,29 +5961,29 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
       break;
 
     case SelectionRequest:     /* Someone wants our selection.  */
-      last_user_time = event.xselectionrequest.time;
+      dpyinfo->last_user_time = event->xselectionrequest.time;
 #ifdef USE_X_TOOLKIT
-      if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
+      if (!x_window_to_frame (dpyinfo, event->xselectionrequest.owner))
         goto OTHER;
 #endif /* USE_X_TOOLKIT */
       {
-         XSelectionRequestEvent *eventp = &(event.xselectionrequest);
-
-          inev.ie.kind = SELECTION_REQUEST_EVENT;
-          SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
-          SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
-          SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
-          SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
-          SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
-          SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
+       const XSelectionRequestEvent *eventp = &event->xselectionrequest;
+
+       inev.ie.kind = SELECTION_REQUEST_EVENT;
+       SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
+       SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
+       SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
+       SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
+       SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
+       SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
       }
       break;
 
     case PropertyNotify:
-      last_user_time = event.xproperty.time;
-      f = x_top_window_to_frame (dpyinfo, event.xproperty.window);
-      if (f && event.xproperty.atom == dpyinfo->Xatom_net_wm_state)
-        if (x_handle_net_wm_state (f, &event.xproperty)
+      dpyinfo->last_user_time = event->xproperty.time;
+      f = x_top_window_to_frame (dpyinfo, event->xproperty.window);
+      if (f && event->xproperty.atom == dpyinfo->Xatom_net_wm_state)
+        if (x_handle_net_wm_state (f, &event->xproperty)
            && FRAME_ICONIFIED_P (f)
            && f->output_data.x->net_wm_state_hidden_seen)
           {
@@ -6043,39 +5998,29 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
             XSETFRAME (inev.ie.frame_or_window, f);
           }
 
-      x_handle_property_notify (&event.xproperty);
-      xft_settings_event (dpyinfo, &event);
+      x_handle_property_notify (&event->xproperty);
+      xft_settings_event (dpyinfo, event);
       goto OTHER;
 
     case ReparentNotify:
-      f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
+      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->left_pos = x;
-          f->top_pos = y;
+          f->output_data.x->parent_desc = event->xreparent.parent;
+          x_real_positions (f, &f->left_pos, &f->top_pos);
 
           /* Perhaps reparented due to a WM restart.  Reset this.  */
-          FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
-          FRAME_X_DISPLAY_INFO (f)->net_supported_window = 0;
+          FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
+          FRAME_DISPLAY_INFO (f)->net_supported_window = 0;
 
           x_set_frame_alpha (f);
         }
       goto OTHER;
 
     case Expose:
-      f = x_window_to_frame (dpyinfo, event.xexpose.window);
+      f = x_window_to_frame (dpyinfo, event->xexpose.window);
       if (f)
         {
-#ifdef USE_GTK
-          /* This seems to be needed for GTK 2.6.  */
-         x_clear_area (event.xexpose.display,
-                       event.xexpose.window,
-                       event.xexpose.x, event.xexpose.y,
-                       event.xexpose.width, event.xexpose.height);
-#endif
           if (!FRAME_VISIBLE_P (f))
             {
               SET_FRAME_VISIBLE (f, 1);
@@ -6084,9 +6029,18 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
               SET_FRAME_GARBAGED (f);
             }
           else
-            expose_frame (f,
-                         event.xexpose.x, event.xexpose.y,
-                          event.xexpose.width, event.xexpose.height);
+           {
+#ifdef USE_GTK
+             /* This seems to be needed for GTK 2.6 and later, see
+                http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398.  */
+             x_clear_area (event->xexpose.display,
+                           event->xexpose.window,
+                           event->xexpose.x, event->xexpose.y,
+                           event->xexpose.width, event->xexpose.height);
+#endif
+             expose_frame (f, event->xexpose.x, event->xexpose.y,
+                           event->xexpose.width, event->xexpose.height);
+           }
         }
       else
         {
@@ -6098,8 +6052,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
              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);
+            Widget widget = x_window_to_menu_bar (event->xexpose.window);
             if (widget)
               xlwmenu_redisplay (widget);
           }
@@ -6109,11 +6062,11 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
           /* Dispatch event to the widget.  */
           goto OTHER;
 #else /* not USE_TOOLKIT_SCROLL_BARS */
-          bar = x_window_to_scroll_bar (event.xexpose.display,
-                                        event.xexpose.window);
+          bar = x_window_to_scroll_bar (event->xexpose.display,
+                                        event->xexpose.window);
 
           if (bar)
-            x_scroll_bar_expose (bar, &event);
+            x_scroll_bar_expose (bar, event);
 #ifdef USE_X_TOOLKIT
           else
             goto OTHER;
@@ -6125,14 +6078,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
     case GraphicsExpose:       /* This occurs when an XCopyArea's
                                    source area was obscured or not
                                    available.  */
-      f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
+      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);
-        }
+       expose_frame (f, event->xgraphicsexpose.x,
+                     event->xgraphicsexpose.y,
+                     event->xgraphicsexpose.width,
+                     event->xgraphicsexpose.height);
 #ifdef USE_X_TOOLKIT
       else
         goto OTHER;
@@ -6146,13 +6097,13 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
 
     case UnmapNotify:
       /* Redo the mouse-highlight after the tooltip has gone.  */
-      if (event.xunmap.window == tip_window)
+      if (event->xunmap.window == tip_window)
         {
           tip_window = 0;
-          redo_mouse_highlight ();
+          x_redo_mouse_highlight (dpyinfo);
         }
 
-      f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
+      f = x_top_window_to_frame (dpyinfo, event->xunmap.window);
       if (f)           /* F may no longer exist if
                            the frame was deleted.  */
         {
@@ -6177,7 +6128,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
       goto OTHER;
 
     case MapNotify:
-      if (event.xmap.window == tip_window)
+      if (event->xmap.window == tip_window)
         /* The tooltip has been drawn already.  Avoid
            the SET_FRAME_GARBAGED below.  */
         goto OTHER;
@@ -6185,7 +6136,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
       /* 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);
+      f = x_top_window_to_frame (dpyinfo, event->xmap.window);
       if (f)
         {
          bool iconified = FRAME_ICONIFIED_P (f);
@@ -6199,7 +6150,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
             SET_FRAME_GARBAGED (f);
 
           /* Check if fullscreen was specified before we where mapped the
-             first time, i.e. from the command line. */
+             first time, i.e. from the command line.  */
           if (!f->output_data.x->has_been_visible)
             x_check_fullscreen (f);
 
@@ -6225,7 +6176,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
 
     case KeyPress:
 
-      last_user_time = event.xkey.time;
+      dpyinfo->last_user_time = event->xkey.time;
       ignore_next_mouse_click_timeout = 0;
 
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
@@ -6234,8 +6185,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
         goto OTHER;
 #endif
 
-      f = x_any_window_to_frame (dpyinfo, event.xkey.window);
+      f = any;
 
+#if ! defined (USE_GTK)
       /* If mouse-highlight is an integer, input clears out
         mouse highlighting.  */
       if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
@@ -6245,6 +6197,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
           clear_mouse_face (hlinfo);
           hlinfo->mouse_face_hidden = 1;
         }
+#endif
 
 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
       if (f == 0)
@@ -6252,7 +6205,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
           /* 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);
+                                            event->xkey.window);
           if (widget && XmIsScrollBar (widget))
             {
               widget = XtParent (widget);
@@ -6281,29 +6234,30 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
           int modifiers;
           Lisp_Object coding_system = Qlatin_1;
          Lisp_Object c;
+         /* Event will be modified.  */
+         XKeyEvent xkey = event->xkey;
 
 #ifdef USE_GTK
           /* Don't pass keys to GTK.  A Tab will shift focus to the
              tool bar in GTK 2.4.  Keys will still go to menus and
-             dialogs because in that case popup_activated is TRUE
+             dialogs because in that case popup_activated is nonzero
              (see above).  */
           *finish = X_EVENT_DROP;
 #endif
 
-          event.xkey.state
-            |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                       extra_keyboard_modifiers);
-          modifiers = event.xkey.state;
+          xkey.state |= x_emacs_to_x_modifiers (FRAME_DISPLAY_INFO (f),
+                                               extra_keyboard_modifiers);
+          modifiers = 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);
+          xkey.state &= ~ControlMask;
+          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
@@ -6320,7 +6274,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
 
               coding_system = Vlocale_coding_system;
               nbytes = XmbLookupString (FRAME_XIC (f),
-                                        &event.xkey, (char *) copy_bufptr,
+                                        &xkey, (char *) copy_bufptr,
                                         copy_bufsiz, &keysym,
                                         &status_return);
               if (status_return == XBufferOverflow)
@@ -6328,7 +6282,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
                   copy_bufsiz = nbytes + 1;
                   copy_bufptr = alloca (copy_bufsiz);
                   nbytes = XmbLookupString (FRAME_XIC (f),
-                                            &event.xkey, (char *) copy_bufptr,
+                                            &xkey, (char *) copy_bufptr,
                                             copy_bufsiz, &keysym,
                                             &status_return);
                 }
@@ -6345,11 +6299,11 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
                 emacs_abort ();
             }
           else
-            nbytes = XLookupString (&event.xkey, (char *) copy_bufptr,
+            nbytes = XLookupString (&xkey, (char *) copy_bufptr,
                                     copy_bufsiz, &keysym,
                                     &compose_status);
 #else
-          nbytes = XLookupString (&event.xkey, (char *) copy_bufptr,
+          nbytes = XLookupString (&xkey, (char *) copy_bufptr,
                                   copy_bufsiz, &keysym,
                                   &compose_status);
 #endif
@@ -6365,8 +6319,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
          /* Common for all keysym input events.  */
          XSETFRAME (inev.ie.frame_or_window, f);
          inev.ie.modifiers
-           = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers);
-         inev.ie.timestamp = event.xkey.time;
+           = x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), modifiers);
+         inev.ie.timestamp = xkey.time;
 
          /* First deal with keysyms which have defined
             translations to characters.  */
@@ -6542,6 +6496,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
            if (keysym == NoSymbol)
              break;
          }
+         /* FIXME: check side effects and remove this.  */
+         ((XEvent *) event)->xkey = xkey;
         }
     done_keysym:
 #ifdef HAVE_X_I18N
@@ -6554,7 +6510,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
 #endif
 
     case KeyRelease:
-      last_user_time = event.xkey.time;
+      dpyinfo->last_user_time = event->xkey.time;
 #ifdef HAVE_X_I18N
       /* Don't dispatch this event since XtDispatchEvent calls
          XFilterEvent, and two calls in a row may freeze the
@@ -6565,35 +6521,35 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
 #endif
 
     case EnterNotify:
-      last_user_time = event.xcrossing.time;
-      x_detect_focus_change (dpyinfo, &event, &inev.ie);
+      dpyinfo->last_user_time = event->xcrossing.time;
+      x_detect_focus_change (dpyinfo, any, event, &inev.ie);
 
-      f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
+      f = any;
 
       if (f && x_mouse_click_focus_ignore_position)
-       ignore_next_mouse_click_timeout = event.xmotion.time + 200;
+       ignore_next_mouse_click_timeout = event->xmotion.time + 200;
 
       /* 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);
+       note_mouse_movement (f, &event->xmotion);
 #ifdef USE_GTK
       /* We may get an EnterNotify on the buttons in the toolbar.  In that
          case we moved out of any highlighted area and need to note this.  */
-      if (!f && last_mouse_glyph_frame)
-        note_mouse_movement (last_mouse_glyph_frame, &event.xmotion);
+      if (!f && dpyinfo->last_mouse_glyph_frame)
+        note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &event->xmotion);
 #endif
       goto OTHER;
 
     case FocusIn:
-      x_detect_focus_change (dpyinfo, &event, &inev.ie);
+      x_detect_focus_change (dpyinfo, any, event, &inev.ie);
       goto OTHER;
 
     case LeaveNotify:
-      last_user_time = event.xcrossing.time;
-      x_detect_focus_change (dpyinfo, &event, &inev.ie);
+      dpyinfo->last_user_time = event->xcrossing.time;
+      x_detect_focus_change (dpyinfo, any, event, &inev.ie);
 
-      f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
+      f = x_top_window_to_frame (dpyinfo, event->xcrossing.window);
       if (f)
         {
           if (f == hlinfo->mouse_face_mouse_frame)
@@ -6613,26 +6569,23 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
         }
 #ifdef USE_GTK
       /* See comment in EnterNotify above */
-      else if (last_mouse_glyph_frame)
-        note_mouse_movement (last_mouse_glyph_frame, &event.xmotion);
+      else if (dpyinfo->last_mouse_glyph_frame)
+        note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &event->xmotion);
 #endif
       goto OTHER;
 
     case FocusOut:
-      x_detect_focus_change (dpyinfo, &event, &inev.ie);
+      x_detect_focus_change (dpyinfo, any, event, &inev.ie);
       goto OTHER;
 
     case MotionNotify:
       {
-        last_user_time = event.xmotion.time;
+        dpyinfo->last_user_time = event->xmotion.time;
         previous_help_echo_string = help_echo_string;
         help_echo_string = Qnil;
 
-        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);
+       f = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame
+            : x_window_to_frame (dpyinfo, event->xmotion.window));
 
         if (hlinfo->mouse_face_hidden)
           {
@@ -6641,7 +6594,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
           }
 
 #ifdef USE_GTK
-        if (f && xg_event_is_for_scrollbar (f, &event))
+        if (f && xg_event_is_for_scrollbar (f, event))
           f = 0;
 #endif
         if (f)
@@ -6653,7 +6606,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
              {
                static Lisp_Object last_mouse_window;
                Lisp_Object window = window_from_coordinates
-                 (f, event.xmotion.x, event.xmotion.y, 0, 0);
+                 (f, event->xmotion.x, event->xmotion.y, 0, 0);
 
                /* Window will be selected only when it is not selected now and
                   last mouse movement event was not in it.  Minibuffer window
@@ -6674,18 +6627,18 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
                /* Remember the last window where we saw the mouse.  */
                last_mouse_window = window;
              }
-            if (!note_mouse_movement (f, &event.xmotion))
+            if (!note_mouse_movement (f, &event->xmotion))
              help_echo_string = previous_help_echo_string;
           }
         else
           {
 #ifndef USE_TOOLKIT_SCROLL_BARS
             struct scroll_bar *bar
-              = x_window_to_scroll_bar (event.xmotion.display,
-                                        event.xmotion.window);
+              = x_window_to_scroll_bar (event->xmotion.display,
+                                        event->xmotion.window);
 
             if (bar)
-              x_scroll_bar_note_movement (bar, &event.xmotion);
+              x_scroll_bar_note_movement (bar, &event->xmotion);
 #endif /* USE_TOOLKIT_SCROLL_BARS */
 
             /* If we move outside the frame, then we're
@@ -6702,14 +6655,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
       }
 
     case ConfigureNotify:
-      f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
+      f = x_top_window_to_frame (dpyinfo, event->xconfigure.window);
 #ifdef USE_GTK
       if (!f
-          && (f = x_any_window_to_frame (dpyinfo, event.xconfigure.window))
-          && event.xconfigure.window == FRAME_X_WINDOW (f))
+          && (f = any)
+          && event->xconfigure.window == FRAME_X_WINDOW (f))
         {
-          xg_frame_resized (f, event.xconfigure.width,
-                            event.xconfigure.height);
+          xg_frame_resized (f, event->xconfigure.width,
+                            event->xconfigure.height);
           f = 0;
         }
 #endif
@@ -6717,8 +6670,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
         {
 #ifndef USE_X_TOOLKIT
 #ifndef USE_GTK
-          int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, event.xconfigure.height);
-          int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, event.xconfigure.width);
+          int width = FRAME_PIXEL_TO_TEXT_WIDTH (f, event->xconfigure.width);
+          int height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, event->xconfigure.height);
 
           /* In the toolkit version, change_frame_size
              is called by the code that handles resizing
@@ -6727,18 +6680,19 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
           /* 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 != FRAME_COLS (f)
-              || rows != FRAME_LINES (f)
-              || event.xconfigure.width != FRAME_PIXEL_WIDTH (f)
-              || event.xconfigure.height != FRAME_PIXEL_HEIGHT (f))
+          if (width != FRAME_TEXT_WIDTH (f)
+              || height != FRAME_TEXT_HEIGHT (f)
+              || event->xconfigure.width != FRAME_PIXEL_WIDTH (f)
+              || event->xconfigure.height != FRAME_PIXEL_HEIGHT (f))
             {
-              change_frame_size (f, rows, columns, 0, 1, 0);
-              SET_FRAME_GARBAGED (f);
+              change_frame_size (f, width, height, 0, 1, 0, 1);
+             x_clear_under_internal_border (f);
+             SET_FRAME_GARBAGED (f);
               cancel_mouse_face (f);
             }
 
-          FRAME_PIXEL_WIDTH (f) = event.xconfigure.width;
-          FRAME_PIXEL_HEIGHT (f) = event.xconfigure.height;
+/**           FRAME_PIXEL_WIDTH (f) = event->xconfigure.width; **/
+/**           FRAME_PIXEL_HEIGHT (f) = event->xconfigure.height; **/
 #endif /* not USE_GTK */
 #endif
 
@@ -6748,9 +6702,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
           if (FRAME_GTK_OUTER_WIDGET (f)
               && gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f)))
 #endif
-            {
-             x_real_positions (f, &f->left_pos, &f->top_pos);
-            }
+           x_real_positions (f, &f->left_pos, &f->top_pos);
 
 #ifdef HAVE_X_I18N
           if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
@@ -6767,42 +6719,37 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
            by the rest of Emacs, we put it here.  */
         bool tool_bar_p = 0;
 
-        memset (&compose_status, 0, sizeof (compose_status));
-       last_mouse_glyph_frame = 0;
-        last_user_time = event.xbutton.time;
+       memset (&compose_status, 0, sizeof (compose_status));
+       dpyinfo->last_mouse_glyph_frame = NULL;
+       dpyinfo->last_user_time = event->xbutton.time;
 
-        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);
+        f = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame
+            : x_window_to_frame (dpyinfo, event->xbutton.window));
 
 #ifdef USE_GTK
-        if (f && xg_event_is_for_scrollbar (f, &event))
+        if (f && xg_event_is_for_scrollbar (f, event))
           f = 0;
 #endif
         if (f)
           {
+#if ! defined (USE_GTK)
             /* Is this in the tool-bar?  */
             if (WINDOWP (f->tool_bar_window)
                 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
               {
                 Lisp_Object window;
-                int x = event.xbutton.x;
-                int y = event.xbutton.y;
+                int x = event->xbutton.x;
+                int y = event->xbutton.y;
 
                 window = window_from_coordinates (f, x, y, 0, 1);
                 tool_bar_p = EQ (window, f->tool_bar_window);
 
-                if (tool_bar_p && event.xbutton.button < 4)
-                  {
-                   handle_tool_bar_click (f, x, y,
-                                          event.xbutton.type == ButtonPress,
-                                          x_x_to_emacs_modifiers (dpyinfo,
-                                                                  event.xbutton.state));
-                  }
+                if (tool_bar_p && event->xbutton.button < 4)
+                 handle_tool_bar_click
+                   (f, x, y, event->xbutton.type == ButtonPress,
+                    x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
               }
+#endif /* !USE_GTK */
 
             if (!tool_bar_p)
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
@@ -6811,52 +6758,52 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
                 {
                   if (ignore_next_mouse_click_timeout)
                     {
-                      if (event.type == ButtonPress
-                          && (int)(event.xbutton.time - ignore_next_mouse_click_timeout) > 0)
+                      if (event->type == ButtonPress
+                          && event->xbutton.time > ignore_next_mouse_click_timeout)
                         {
                           ignore_next_mouse_click_timeout = 0;
-                          construct_mouse_click (&inev.ie, &event.xbutton, f);
+                          construct_mouse_click (&inev.ie, &event->xbutton, f);
                         }
-                      if (event.type == ButtonRelease)
+                      if (event->type == ButtonRelease)
                         ignore_next_mouse_click_timeout = 0;
                     }
                   else
-                    construct_mouse_click (&inev.ie, &event.xbutton, f);
+                    construct_mouse_click (&inev.ie, &event->xbutton, f);
                 }
             if (FRAME_X_EMBEDDED_P (f))
-              xembed_send_message (f, event.xbutton.time,
+              xembed_send_message (f, event->xbutton.time,
                                    XEMBED_REQUEST_FOCUS, 0, 0, 0);
           }
         else
           {
             struct scroll_bar *bar
-              = x_window_to_scroll_bar (event.xbutton.display,
-                                        event.xbutton.window);
+              = x_window_to_scroll_bar (event->xbutton.display,
+                                        event->xbutton.window);
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
             /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
                scroll bars.  */
-            if (bar && event.xbutton.state & ControlMask)
+            if (bar && event->xbutton.state & ControlMask)
               {
-                x_scroll_bar_handle_click (bar, &event, &inev.ie);
+                x_scroll_bar_handle_click (bar, event, &inev.ie);
                 *finish = X_EVENT_DROP;
               }
 #else /* not USE_TOOLKIT_SCROLL_BARS */
             if (bar)
-              x_scroll_bar_handle_click (bar, &event, &inev.ie);
+              x_scroll_bar_handle_click (bar, event, &inev.ie);
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
           }
 
-        if (event.type == ButtonPress)
+        if (event->type == ButtonPress)
           {
-            dpyinfo->grabbed |= (1 << event.xbutton.button);
-            last_mouse_frame = f;
+            dpyinfo->grabbed |= (1 << event->xbutton.button);
+            dpyinfo->last_mouse_frame = f;
 
             if (!tool_bar_p)
               last_tool_bar_item = -1;
           }
         else
-          dpyinfo->grabbed &= ~(1 << event.xbutton.button);
+          dpyinfo->grabbed &= ~(1 << event->xbutton.button);
 
        /* Ignore any mouse motion that happened before this event;
           any subsequent mouse-movement Emacs events should reflect
@@ -6865,7 +6812,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
          f->mouse_moved = 0;
 
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
-        f = x_menubar_window_to_frame (dpyinfo, &event);
+        f = x_menubar_window_to_frame (dpyinfo, event);
         /* For a down-event in the menu bar,
            don't pass it to Xt right now.
            Instead, save it away
@@ -6874,19 +6821,23 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
         if (! popup_activated ()
 #ifdef USE_GTK
             /* Gtk+ menus only react to the first three buttons. */
-            && event.xbutton.button < 3
+            && event->xbutton.button < 3
 #endif
-            && f && event.type == ButtonPress
+            && 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 < FRAME_PIXEL_WIDTH (f)
-            && event.xbutton.y >= 0
-            && event.xbutton.y < f->output_data.x->menubar_height
-            && event.xbutton.same_screen)
+            && event->xbutton.x >= 0
+            && event->xbutton.x < FRAME_PIXEL_WIDTH (f)
+            && event->xbutton.y >= 0
+            && event->xbutton.y < f->output_data.x->menubar_height
+            && event->xbutton.same_screen)
           {
-            SET_SAVED_BUTTON_EVENT;
-            *finish = X_EVENT_DROP;
+           if (!f->output_data.x->saved_menu_event)
+             f->output_data.x->saved_menu_event = xmalloc (sizeof *event);
+           *f->output_data.x->saved_menu_event = *event;
+           inev.ie.kind = MENU_BAR_ACTIVATE_EVENT;
+           XSETFRAME (inev.ie.frame_or_window, f);
+           *finish = X_EVENT_DROP;
           }
         else
           goto OTHER;
@@ -6906,18 +6857,18 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
     case MappingNotify:
       /* Someone has changed the keyboard mapping - update the
          local cache.  */
-      switch (event.xmapping.request)
+      switch (event->xmapping.request)
         {
         case MappingModifier:
           x_find_modifier_meanings (dpyinfo);
           /* This is meant to fall through.  */
         case MappingKeyboard:
-          XRefreshKeyboardMapping (&event.xmapping);
+          XRefreshKeyboardMapping ((XMappingEvent *) &event->xmapping);
         }
       goto OTHER;
 
     case DestroyNotify:
-      xft_settings_event (dpyinfo, &event);
+      xft_settings_event (dpyinfo, event);
       break;
 
     default:
@@ -6925,7 +6876,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
 #ifdef USE_X_TOOLKIT
       block_input ();
     if (*finish != X_EVENT_DROP)
-      XtDispatchEvent (&event);
+      XtDispatchEvent ((XEvent *) event);
     unblock_input ();
 #endif /* USE_X_TOOLKIT */
     break;
@@ -6963,12 +6914,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
     }
 
   SAFE_FREE ();
-  *eventptr = event;
   return count;
 }
 
-#if defined USE_GTK || defined USE_X_TOOLKIT
-
 /* 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.
@@ -6987,8 +6935,6 @@ x_dispatch_event (XEvent *event, Display *display)
 
   return finish;
 }
-#endif
-
 
 /* Read events coming from the X server.
    Return as soon as there are no more events to be read.
@@ -7003,43 +6949,38 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
 {
   int count = 0;
   int event_found = 0;
+  struct x_display_info *dpyinfo = terminal->display_info.x;
 
   block_input ();
 
-  /* So people can tell when we have read the available input.  */
-  input_signal_count++;
-
   /* For debugging, this gives a way to fake an I/O error.  */
-  if (terminal->display_info.x == XTread_socket_fake_io_error)
+  if (dpyinfo == XTread_socket_fake_io_error)
     {
       XTread_socket_fake_io_error = 0;
-      x_io_error_quitter (terminal->display_info.x->display);
+      x_io_error_quitter (dpyinfo->display);
     }
 
 #ifndef USE_GTK
-  while (XPending (terminal->display_info.x->display))
+  while (XPending (dpyinfo->display))
     {
       int finish;
       XEvent event;
 
-      XNextEvent (terminal->display_info.x->display, &event);
+      XNextEvent (dpyinfo->display, &event);
 
 #ifdef HAVE_X_I18N
       /* Filter events for the current X input method.  */
-      if (x_filter_event (terminal->display_info.x, &event))
+      if (x_filter_event (dpyinfo, &event))
         continue;
 #endif
       event_found = 1;
 
-      count += handle_one_xevent (terminal->display_info.x,
-                                  &event, &finish, hold_quit);
+      count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit);
 
       if (finish == X_EVENT_GOTO_OUT)
-        goto out;
+       break;
     }
 
- out:;
-
 #else /* USE_GTK */
 
   /* For GTK we must use the GTK event loop.  But XEvents gets passed
@@ -7089,12 +7030,11 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
     }
 
   /* If the focus was just given to an auto-raising frame,
-     raise it now.  */
-  /* ??? This ought to be able to handle more than one such frame.  */
-  if (pending_autoraise_frame)
+     raise it now.  FIXME: handle more than one such frame.  */
+  if (dpyinfo->x_pending_autoraise_frame)
     {
-      x_raise_frame (pending_autoraise_frame);
-      pending_autoraise_frame = 0;
+      x_raise_frame (dpyinfo->x_pending_autoraise_frame);
+      dpyinfo->x_pending_autoraise_frame = NULL;
     }
 
   unblock_input ();
@@ -7142,7 +7082,7 @@ static void
 x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   Display *dpy = FRAME_X_DISPLAY (f);
   int x, y, wd, h;
   XGCValues xgcv;
@@ -7209,7 +7149,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
     {
       Display *dpy = FRAME_X_DISPLAY (f);
       Window window = FRAME_X_WINDOW (f);
-      GC gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
+      GC gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc;
       unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
       struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
       XGCValues xgcv;
@@ -7230,7 +7170,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
       else
        {
          gc = XCreateGC (dpy, window, mask, &xgcv);
-         FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
+         FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
        }
 
       x_clip_to_row (w, row, TEXT_AREA, gc);
@@ -7362,9 +7302,7 @@ x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
 #endif
     }
 
-#ifndef XFlush
   XFlush (FRAME_X_DISPLAY (f));
-#endif
 }
 
 \f
@@ -7399,7 +7337,7 @@ x_bitmap_icon (struct frame *f, Lisp_Object file)
   else
     {
       /* Create the GNU bitmap and mask if necessary.  */
-      if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
+      if (FRAME_DISPLAY_INFO (f)->icon_bitmap_id < 0)
        {
          ptrdiff_t rc = -1;
 
@@ -7413,7 +7351,7 @@ x_bitmap_icon (struct frame *f, Lisp_Object file)
 
          rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
          if (rc != -1)
-           FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
+           FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
 
 #endif
 
@@ -7425,8 +7363,8 @@ x_bitmap_icon (struct frame *f, Lisp_Object file)
              if (rc == -1)
                return 1;
 
-             FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
-             x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
+             FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
+             x_create_bitmap_mask (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id);
            }
        }
 
@@ -7434,9 +7372,9 @@ x_bitmap_icon (struct frame *f, Lisp_Object file)
         this increments the ref-count one extra time.
         As a result, the GNU bitmap and mask are never freed.
         That way, we don't have to worry about allocating it again.  */
-      x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
+      x_reference_bitmap (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id);
 
-      bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
+      bitmap_id = FRAME_DISPLAY_INFO (f)->icon_bitmap_id;
     }
 
   x_wm_set_icon_pixmap (f, bitmap_id);
@@ -7650,7 +7588,7 @@ x_connection_closed (Display *dpy, const char *error_message)
       if (FRAME_X_P (XFRAME (frame))
          && FRAME_X_P (XFRAME (minibuf_frame))
          && ! EQ (frame, minibuf_frame)
-         && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
+         && FRAME_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
        delete_frame (frame, Qnoelisp);
     }
 
@@ -7659,7 +7597,7 @@ x_connection_closed (Display *dpy, const char *error_message)
      for another frame that we need to delete.  */
   FOR_EACH_FRAME (tail, frame)
     if (FRAME_X_P (XFRAME (frame))
-       && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
+       && FRAME_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
       {
        /* Set this to t so that delete_frame won't get confused
           trying to find a replacement.  */
@@ -7806,6 +7744,7 @@ Lisp_Object
 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
 {
   struct font *font = XFONT_OBJECT (font_object);
+  int unit;
 
   if (fontset < 0)
     fontset = fontset_from_font (font_object);
@@ -7820,20 +7759,25 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
   FRAME_COLUMN_WIDTH (f) = font->average_width;
   FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font);
 
+  FRAME_TOOL_BAR_HEIGHT (f) = FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
+  FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
+
   compute_fringe_widths (f, 1);
 
-  /* Compute the scroll bar width in character columns.  */
-  if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
-    {
-      int wid = FRAME_COLUMN_WIDTH (f);
-      FRAME_CONFIG_SCROLL_BAR_COLS (f)
-       = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
-    }
-  else
-    {
-      int wid = FRAME_COLUMN_WIDTH (f);
-      FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
-    }
+  unit = FRAME_COLUMN_WIDTH (f);
+#ifdef USE_TOOLKIT_SCROLL_BARS
+  /* The width of a toolkit scrollbar does not change with the new
+     font but we have to calculate the number of columns it occupies
+     anew.  */
+  FRAME_CONFIG_SCROLL_BAR_COLS (f)
+    = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
+#else
+  /* The width of a non-toolkit scrollbar is at least 14 pixels and a
+     multiple of the frame's character width.  */
+  FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
+  FRAME_CONFIG_SCROLL_BAR_WIDTH (f)
+    = FRAME_CONFIG_SCROLL_BAR_COLS (f) * unit;
+#endif  
 
   if (FRAME_X_WINDOW (f) != 0)
     {
@@ -7841,7 +7785,8 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
         doing it because it's done in Fx_show_tip, and it leads to
         problems because the tip frame has no widget.  */
       if (NILP (tip_frame) || XFRAME (tip_frame) != f)
-        x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+       x_set_window_size (f, 0, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
+                          FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 1);
     }
 
 #ifdef HAVE_X_I18N
@@ -7882,7 +7827,7 @@ xim_destroy_callback (XIM xim, XPointer client_data, XPointer call_data)
   FOR_EACH_FRAME (tail, frame)
     {
       struct frame *f = XFRAME (frame);
-      if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
+      if (FRAME_X_P (f) && FRAME_DISPLAY_INFO (f) == dpyinfo)
        {
          FRAME_XIC (f) = NULL;
           xic_free_xfontset (f);
@@ -7973,7 +7918,7 @@ xim_instantiate_callback (Display *display, XPointer client_data, XPointer call_
          struct frame *f = XFRAME (frame);
 
          if (FRAME_X_P (f)
-              && FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
+              && FRAME_DISPLAY_INFO (f) == xim_inst->dpyinfo)
            if (FRAME_XIC (f) == NULL)
              {
                create_frame_xic (f);
@@ -8071,7 +8016,7 @@ x_calc_absolute_position (struct frame *f)
   /* Treat negative positions as relative to the leftmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
-    f->left_pos = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f))
+    f->left_pos = x_display_pixel_width (FRAME_DISPLAY_INFO (f))
       - FRAME_PIXEL_WIDTH (f) + f->left_pos;
 
   {
@@ -8094,7 +8039,7 @@ x_calc_absolute_position (struct frame *f)
 #endif
 
     if (flags & YNegative)
-      f->top_pos = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))
+      f->top_pos = x_display_pixel_height (FRAME_DISPLAY_INFO (f))
        - height + f->top_pos;
   }
 
@@ -8117,9 +8062,6 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
 
   if (change_gravity > 0)
     {
-      FRAME_X_OUTPUT (f)->left_before_move = f->left_pos;
-      FRAME_X_OUTPUT (f)->top_before_move = f->top_pos;
-
       f->top_pos = yoff;
       f->left_pos = xoff;
       f->size_hint_flags &= ~ (XNegative | YNegative);
@@ -8137,7 +8079,7 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
   modified_left = f->left_pos;
   modified_top = f->top_pos;
 
-  if (change_gravity != 0 && FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
+  if (change_gravity != 0 && FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
     {
       /* Some WMs (twm, wmaker at least) has an offset that is smaller
          than the WM decorations.  So we use the calculated offset instead
@@ -8150,7 +8092,7 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
                modified_left, modified_top);
 
   x_sync_with_move (f, f->left_pos, f->top_pos,
-                    FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
+                    FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
                     ? 1 : 0);
 
   /* change_gravity is non-zero when this function is called from Lisp to
@@ -8164,8 +8106,8 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
      need to compute the top/left offset adjustment for this frame.  */
 
   if (change_gravity != 0 &&
-      (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
-       || (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
+      (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
+       || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
            && (FRAME_X_OUTPUT (f)->move_offset_left == 0
                && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
     x_check_expected_move (f, modified_left, modified_top);
@@ -8186,7 +8128,7 @@ wm_supports (struct frame *f, Atom want_atom)
   unsigned long actual_size, bytes_remaining;
   int i, rc, actual_format;
   Window wmcheck_window;
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   Window target_window = dpyinfo->root_window;
   long max_len = 65536;
   Display *dpy = FRAME_X_DISPLAY (f);
@@ -8267,7 +8209,7 @@ wm_supports (struct frame *f, Atom want_atom)
 static void
 set_wm_state (Lisp_Object frame, int add, Atom atom, Atom value)
 {
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (frame));
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (XFRAME (frame));
 
   x_send_client_event (frame, make_number (0), frame,
                        dpyinfo->Xatom_net_wm_state,
@@ -8286,7 +8228,7 @@ void
 x_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
 {
   Lisp_Object frame;
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
 
   XSETFRAME (frame, f);
 
@@ -8309,7 +8251,7 @@ get_current_wm_state (struct frame *f,
   Atom actual_type;
   unsigned long actual_size, bytes_remaining;
   int i, rc, actual_format, is_hidden = 0;
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   long max_len = 65536;
   Display *dpy = FRAME_X_DISPLAY (f);
   unsigned char *tmp_data = NULL;
@@ -8373,7 +8315,7 @@ get_current_wm_state (struct frame *f,
 static int
 do_ewmh_fullscreen (struct frame *f)
 {
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   int have_net_atom = wm_supports (f, dpyinfo->Xatom_net_wm_state);
   int cur, dummy;
 
@@ -8453,7 +8395,7 @@ XTfullscreen_hook (struct frame *f)
 
 
 static int
-x_handle_net_wm_state (struct frame *f, XPropertyEvent *event)
+x_handle_net_wm_state (struct frame *f, const XPropertyEvent *event)
 {
   int value = FULLSCREEN_NONE;
   Lisp_Object lval;
@@ -8491,7 +8433,7 @@ x_check_fullscreen (struct frame *f)
   if (do_ewmh_fullscreen (f))
     return;
 
-  if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
+  if (f->output_data.x->parent_desc != FRAME_DISPLAY_INFO (f)->root_window)
     return; /* Only fullscreen without WM or with EWM hints (above). */
 
   /* Setting fullscreen to nil doesn't do anything.  We could save the
@@ -8501,7 +8443,7 @@ x_check_fullscreen (struct frame *f)
   if (f->want_fullscreen != FULLSCREEN_NONE)
     {
       int width = FRAME_PIXEL_WIDTH (f), height = FRAME_PIXEL_HEIGHT (f);
-      struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+      struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
 
       switch (f->want_fullscreen)
         {
@@ -8548,7 +8490,7 @@ x_check_expected_move (struct frame *f, int expected_left, int expected_top)
       int adjusted_left;
       int adjusted_top;
 
-        FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
+        FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
       FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left;
       FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top;
 
@@ -8566,7 +8508,7 @@ x_check_expected_move (struct frame *f, int expected_left, int expected_top)
     /* It's a "Type B" window manager.  We don't have to adjust the
        frame's position. */
 
-      FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
+      FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
 }
 
 
@@ -8622,15 +8564,14 @@ x_wait_for_event (struct frame *f, int eventtype)
   struct timespec tmo, tmo_at, time_now;
   int fd = ConnectionNumber (FRAME_X_DISPLAY (f));
 
-  pending_event_wait.f = f;
-  pending_event_wait.eventtype = eventtype;
+  f->wait_event_type = eventtype;
 
   /* Set timeout to 0.1 second.  Hopefully not noticeable.
      Maybe it should be configurable.  */
   tmo = make_timespec (0, 100 * 1000 * 1000);
   tmo_at = timespec_add (current_timespec (), tmo);
 
-  while (pending_event_wait.eventtype)
+  while (f->wait_event_type)
     {
       pending_signals = 1;
       totally_unblock_input ();
@@ -8649,8 +8590,8 @@ x_wait_for_event (struct frame *f, int eventtype)
       if (pselect (fd + 1, &fds, NULL, NULL, &tmo, NULL) == 0)
         break; /* Timeout */
     }
-  pending_event_wait.f = 0;
-  pending_event_wait.eventtype = 0;
+
+  f->wait_event_type = 0;
 }
 
 
@@ -8660,23 +8601,23 @@ x_wait_for_event (struct frame *f, int eventtype)
    size changes.  Otherwise we leave the window gravity unchanged.  */
 
 static void
-x_set_window_size_1 (struct frame *f, int change_gravity, int cols, int rows)
+x_set_window_size_1 (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
 {
   int pixelwidth, pixelheight;
 
-  check_frame_size (f, &rows, &cols);
-  f->scroll_bar_actual_width
-    = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
-       ? 0
-       : FRAME_CONFIG_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f));
+  check_frame_size (f, &width, &height, pixelwise);
 
   compute_fringe_widths (f, 0);
 
-  pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols)
-    + FRAME_TOOLBAR_WIDTH (f);
-  pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows)
-    + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
-
+  pixelwidth = ((pixelwise
+                ? FRAME_TEXT_TO_PIXEL_WIDTH (f, width)
+                : FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width))
+               + FRAME_TOOLBAR_WIDTH (f));
+  pixelheight = ((pixelwise
+                 ? FRAME_TEXT_TO_PIXEL_HEIGHT (f, height)
+                 : FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height))
+                + FRAME_MENUBAR_HEIGHT (f)
+                + FRAME_TOOLBAR_HEIGHT (f));
   if (change_gravity) f->win_gravity = NorthWestGravity;
   x_wm_set_size_hint (f, (long) 0, 0);
   XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
@@ -8710,9 +8651,7 @@ x_set_window_size_1 (struct frame *f, int change_gravity, int cols, int rows)
     x_wait_for_event (f, ConfigureNotify);
   else
     {
-      change_frame_size (f, rows, cols, 0, 1, 0);
-      FRAME_PIXEL_WIDTH (f) = pixelwidth;
-      FRAME_PIXEL_HEIGHT (f) = pixelheight;
+      change_frame_size (f, width, height, 0, 1, 0, 1);
       x_sync (f);
     }
 }
@@ -8724,17 +8663,19 @@ x_set_window_size_1 (struct frame *f, int change_gravity, int cols, int rows)
    Otherwise we leave the window gravity unchanged.  */
 
 void
-x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
+x_set_window_size (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
 {
   block_input ();
 
+  check_frame_size (f, &width, &height, pixelwise);
+
   if (NILP (tip_frame) || XFRAME (tip_frame) != f)
     {
-      int r, c;
+      int text_width, text_height;
 
       /* When the frame is maximized/fullscreen or running under for
          example Xmonad, x_set_window_size_1 will be a no-op.
-         In that case, the right thing to do is extend rows/cols to
+         In that case, the right thing to do is extend rows/width to
          the current frame size.  We do that first if x_set_window_size_1
          turns out to not be a no-op (there is no way to know).
          The size will be adjusted again if the frame gets a
@@ -8745,23 +8686,27 @@ x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
          is however.  */
       pixelh -= FRAME_MENUBAR_HEIGHT (f);
 #endif
-      r = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelh);
-      /* Update f->scroll_bar_actual_width because it is used in
-         FRAME_PIXEL_WIDTH_TO_TEXT_COLS.  */
-      f->scroll_bar_actual_width
-        = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
-      c = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, FRAME_PIXEL_WIDTH (f));
-      change_frame_size (f, r, c, 0, 1, 0);
+      text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, FRAME_PIXEL_WIDTH (f));
+      text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelh);
+
+      change_frame_size (f, text_width, text_height, 0, 1, 0, 1);
     }
 
 #ifdef USE_GTK
   if (FRAME_GTK_WIDGET (f))
-    xg_frame_set_char_size (f, cols, rows);
+    if (! pixelwise)
+      xg_frame_set_char_size (f, width * FRAME_COLUMN_WIDTH (f),
+                             height * FRAME_LINE_HEIGHT (f));
+    else
+      xg_frame_set_char_size (f, width, height);
   else
-    x_set_window_size_1 (f, change_gravity, cols, rows);
+    x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
 #else /* not USE_GTK */
 
-  x_set_window_size_1 (f, change_gravity, cols, rows);
+  x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
+#if !defined USE_X_TOOLKIT
+  x_clear_under_internal_border (f);
+#endif
 
 #endif /* not USE_GTK */
 
@@ -8858,15 +8803,16 @@ x_ewmh_activate_frame (struct frame *f)
   /* See Window Manager Specification/Extended Window Manager Hints at
      http://freedesktop.org/wiki/Specifications/wm-spec  */
 
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
 
   if (FRAME_VISIBLE_P (f) && wm_supports (f, dpyinfo->Xatom_net_active_window))
     {
       Lisp_Object frame;
       XSETFRAME (frame, f);
       x_send_client_event (frame, make_number (0), frame,
-                           dpyinfo->Xatom_net_active_window,
-                           make_number (32), list2i (1, last_user_time));
+                          dpyinfo->Xatom_net_active_window,
+                          make_number (32),
+                          list2i (1, dpyinfo->last_user_time));
     }
 }
 
@@ -8891,7 +8837,7 @@ static void
 xembed_set_info (struct frame *f, enum xembed_info flags)
 {
   unsigned long data[2];
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
 
   data[0] = XEMBED_VERSION;
   data[1] = flags;
@@ -8910,7 +8856,7 @@ xembed_send_message (struct frame *f, Time t, enum xembed_message msg,
 
   event.xclient.type = ClientMessage;
   event.xclient.window = FRAME_X_OUTPUT (f)->parent_desc;
-  event.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_XEMBED;
+  event.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_XEMBED;
   event.xclient.format = 32;
   event.xclient.data.l[0] = t;
   event.xclient.data.l[1] = msg;
@@ -8935,17 +8881,11 @@ xembed_send_message (struct frame *f, Time t, enum xembed_message msg,
 void
 x_make_frame_visible (struct frame *f)
 {
-  Lisp_Object type;
   int original_top, original_left;
-  int retry_count = 2;
-
- retry:
 
   block_input ();
 
-  type = x_icon_type (f);
-  if (!NILP (type))
-    x_bitmap_icon (f, type);
+  x_set_bitmap_icon (f);
 
   if (! FRAME_VISIBLE_P (f))
     {
@@ -8990,7 +8930,6 @@ x_make_frame_visible (struct frame *f)
      so that incoming events are handled.  */
   {
     Lisp_Object frame;
-    int count;
     /* This must be before UNBLOCK_INPUT
        since events that arrive in response to the actions above
        will set it when they are handled.  */
@@ -9044,16 +8983,16 @@ x_make_frame_visible (struct frame *f)
 
     XSETFRAME (frame, f);
 
-    /* Wait until the frame is visible.  Process X events until a
-       MapNotify event has been seen, or until we think we won't get a
-       MapNotify at all..  */
-    for (count = input_signal_count + 10;
-        input_signal_count < count && !FRAME_VISIBLE_P (f);)
+    /* Process X events until a MapNotify event has been seen.  */
+    while (!FRAME_VISIBLE_P (f))
       {
        /* Force processing of queued events.  */
        x_sync (f);
 
-       /* Machines that do polling rather than SIGIO have been
+       /* This hack is still in use at least for Cygwin.  See
+          http://lists.gnu.org/archive/html/emacs-devel/2013-12/msg00351.html.
+
+          Machines that do polling rather than SIGIO have been
           observed to go into a busy-wait here.  So we'll fake an
           alarm signal to let the handler know that there's something
           to be read.  We used to raise a real alarm, but it seems
@@ -9069,21 +9008,14 @@ x_make_frame_visible (struct frame *f)
            poll_for_input_1 ();
            poll_suppress_count = old_poll_suppress_count;
          }
-      }
-
-    /* 2000-09-28: In
 
-       (let ((f (selected-frame)))
-          (iconify-frame f)
-         (raise-frame f))
-
-       the frame is not raised with various window managers on
-       FreeBSD, GNU/Linux and Solaris.  It turns out that, for some
-       unknown reason, the call to XtMapWidget is completely ignored.
-       Mapping the widget a second time works.  */
-
-    if (!FRAME_VISIBLE_P (f) && --retry_count != 0)
-      goto retry;
+       if (XPending (FRAME_X_DISPLAY (f)))
+         {
+           XEvent xev;
+           XNextEvent (FRAME_X_DISPLAY (f), &xev);
+           x_dispatch_event (&xev, FRAME_X_DISPLAY (f));
+         }
+      }
   }
 }
 
@@ -9100,8 +9032,8 @@ x_make_frame_invisible (struct frame *f)
   window = FRAME_OUTER_WINDOW (f);
 
   /* Don't keep the highlight on an invisible frame.  */
-  if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
-    FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
+  if (FRAME_DISPLAY_INFO (f)->x_highlight_frame == f)
+    FRAME_DISPLAY_INFO (f)->x_highlight_frame = 0;
 
   block_input ();
 
@@ -9152,20 +9084,17 @@ x_iconify_frame (struct frame *f)
 #ifdef USE_X_TOOLKIT
   int result;
 #endif
-  Lisp_Object type;
 
   /* Don't keep the highlight on an invisible frame.  */
-  if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
-    FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
+  if (FRAME_DISPLAY_INFO (f)->x_highlight_frame == f)
+    FRAME_DISPLAY_INFO (f)->x_highlight_frame = 0;
 
   if (FRAME_ICONIFIED_P (f))
     return;
 
   block_input ();
 
-  type = x_icon_type (f);
-  if (!NILP (type))
-    x_bitmap_icon (f, type);
+  x_set_bitmap_icon (f);
 
 #if defined (USE_GTK)
   if (FRAME_GTK_OUTER_WIDGET (f))
@@ -9231,7 +9160,7 @@ x_iconify_frame (struct frame *f)
 
     msg.xclient.window = FRAME_X_WINDOW (f);
     msg.xclient.type = ClientMessage;
-    msg.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
+    msg.xclient.message_type = FRAME_DISPLAY_INFO (f)->Xatom_wm_change_state;
     msg.xclient.format = 32;
     msg.xclient.data.l[0] = IconicState;
 
@@ -9270,7 +9199,7 @@ x_iconify_frame (struct frame *f)
 void
 x_free_frame_resources (struct frame *f)
 {
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
 #ifdef USE_X_TOOLKIT
   Lisp_Object bar;
@@ -9286,8 +9215,7 @@ x_free_frame_resources (struct frame *f)
       /* We must free faces before destroying windows because some
         font-driver (e.g. xft) access a window while finishing a
         face.  */
-      if (FRAME_FACE_CACHE (f))
-       free_frame_faces (f);
+      free_frame_faces (f);
 
       if (f->output_data.x->icon_desc)
        XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
@@ -9349,9 +9277,9 @@ x_free_frame_resources (struct frame *f)
       if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
        unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
 #endif /* USE_TOOLKIT_SCROLL_BARS */
-      if (f->output_data.x->white_relief.allocated_p)
+      if (f->output_data.x->white_relief.pixel != -1)
        unload_color (f, f->output_data.x->white_relief.pixel);
-      if (f->output_data.x->black_relief.allocated_p)
+      if (f->output_data.x->black_relief.pixel != -1)
        unload_color (f, f->output_data.x->black_relief.pixel);
 
       x_free_gcs (f);
@@ -9393,7 +9321,7 @@ x_free_frame_resources (struct frame *f)
 static void
 x_destroy_window (struct frame *f)
 {
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
 
   /* If a display connection is dead, don't try sending more
      commands to the X server.  */
@@ -9437,11 +9365,12 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
   size_hints.height = FRAME_PIXEL_HEIGHT (f);
   size_hints.width = FRAME_PIXEL_WIDTH (f);
 
-  size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
-  size_hints.height_inc = FRAME_LINE_HEIGHT (f);
-  size_hints.max_width = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f))
+  size_hints.width_inc = frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f);
+  size_hints.height_inc = frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (f);
+
+  size_hints.max_width = x_display_pixel_width (FRAME_DISPLAY_INFO (f))
     - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
-  size_hints.max_height = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))
+  size_hints.max_height = x_display_pixel_height (FRAME_DISPLAY_INFO (f))
     - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
 
   /* Calculate the base and minimum sizes.  */
@@ -9452,7 +9381,15 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
     base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
     base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
 
-    check_frame_size (f, &min_rows, &min_cols);
+    check_frame_size (f, &min_cols, &min_rows, 0);
+
+    if (frame_resize_pixelwise)
+      /* Needed to prevent a bad protocol error crash when making the
+        frame size very small.  */
+      {
+       min_cols = 2 * min_cols;
+       min_rows = 2 * min_rows;
+      }
 
     /* The window manager uses the base width hints to calculate the
        current number of rows and columns in the frame while
@@ -9467,8 +9404,8 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
     size_hints.flags |= PBaseSize;
     size_hints.base_width = base_width;
     size_hints.base_height = base_height + FRAME_MENUBAR_HEIGHT (f);
-    size_hints.min_width  = base_width + min_cols * size_hints.width_inc;
-    size_hints.min_height = base_height + min_rows * size_hints.height_inc;
+    size_hints.min_width  = base_width + min_cols * FRAME_COLUMN_WIDTH (f);
+    size_hints.min_height = base_height + min_rows * FRAME_LINE_HEIGHT (f);
   }
 
   /* If we don't need the old flags, we don't need the old hint at all.  */
@@ -9701,7 +9638,7 @@ same_x_server (const char *name1, const char *name2)
    get to the first bit.  With MASK 0x7e0, *BITS is set to 6, and *OFFSET
    to 5.  */
 static void
-get_bits_and_offset (long unsigned int mask, int *bits, int *offset)
+get_bits_and_offset (unsigned long mask, int *bits, int *offset)
 {
   int nr = 0;
   int off = 0;
@@ -9898,26 +9835,16 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
 
   {
     struct x_display_info *share;
-    Lisp_Object tail;
 
-    for (share = x_display_list, tail = x_display_name_list; share;
-        share = share->next, tail = XCDR (tail))
-      if (same_x_server (SSDATA (XCAR (XCAR (tail))),
+    for (share = x_display_list; share; share = share->next)
+      if (same_x_server (SSDATA (XCAR (share->name_list_element)),
                         SSDATA (display_name)))
        break;
     if (share)
       terminal->kboard = share->terminal->kboard;
     else
       {
-       terminal->kboard = xmalloc (sizeof *terminal->kboard);
-       init_kboard (terminal->kboard);
-       kset_window_system (terminal->kboard, Qx);
-
-       /* Add the keyboard to the list before running Lisp code (via
-           Qvendor_specific_keysyms below), since these are not traced
-           via terminals but only through all_kboards.  */
-       terminal->kboard->next_kboard = all_kboards;
-       all_kboards = terminal->kboard;
+       terminal->kboard = allocate_kboard (Qx);
 
        if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
          {
@@ -9956,11 +9883,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
   dpyinfo->next = x_display_list;
   x_display_list = dpyinfo;
 
-  /* Put it on x_display_name_list as well, to keep them parallel.  */
-  x_display_name_list = Fcons (Fcons (display_name, Qnil),
-                              x_display_name_list);
-  dpyinfo->name_list_element = XCAR (x_display_name_list);
-
+  dpyinfo->name_list_element = Fcons (display_name, Qnil);
   dpyinfo->display = dpy;
 
   /* Set the name of the terminal. */
@@ -10174,9 +10097,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
   dpyinfo->x_dnd_atoms_size = 8;
   dpyinfo->x_dnd_atoms = xmalloc (sizeof *dpyinfo->x_dnd_atoms
                                   * dpyinfo->x_dnd_atoms_size);
-
-  connection = ConnectionNumber (dpyinfo->display);
-  dpyinfo->connection = connection;
   dpyinfo->gray
     = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
                                   gray_bits, gray_width, gray_height,
@@ -10188,6 +10108,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
 
   xsettings_initialize (dpyinfo);
 
+  connection = ConnectionNumber (dpyinfo->display);
+
   /* This is only needed for distinguishing keyboard and process input.  */
   if (connection != 0)
     add_keyboard_wait_descriptor (connection);
@@ -10244,12 +10166,12 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
     if (STRINGP (value)
        && (!strcmp (SSDATA (value), "false")
            || !strcmp (SSDATA (value), "off")))
-      use_xim = 0;
+      use_xim = false;
 #else
     if (STRINGP (value)
        && (!strcmp (SSDATA (value), "true")
            || !strcmp (SSDATA (value), "on")))
-      use_xim = 1;
+      use_xim = true;
 #endif
   }
 
@@ -10288,29 +10210,6 @@ x_delete_display (struct x_display_info *dpyinfo)
         break;
       }
 
-  delete_keyboard_wait_descriptor (dpyinfo->connection);
-
-  /* Discard this display from x_display_name_list and x_display_list.
-     We can't use Fdelq because that can quit.  */
-  if (! NILP (x_display_name_list)
-      && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
-    x_display_name_list = XCDR (x_display_name_list);
-  else
-    {
-      Lisp_Object tail;
-
-      tail = x_display_name_list;
-      while (CONSP (tail) && CONSP (XCDR (tail)))
-       {
-         if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
-           {
-             XSETCDR (tail, XCDR (XCDR (tail)));
-             break;
-           }
-         tail = XCDR (tail);
-       }
-    }
-
   if (next_noop_dpyinfo == dpyinfo)
     next_noop_dpyinfo = dpyinfo->next;
 
@@ -10391,11 +10290,6 @@ static struct redisplay_interface x_redisplay_interface =
     x_update_window_begin,
     x_update_window_end,
     x_flush,
-#ifdef XFlush
-    x_flush,
-#else
-    0,  /* flush_display_optional */
-#endif
     x_clear_window_mouse_face,
     x_get_glyph_overhangs,
     x_fix_overlapping_area,
@@ -10408,6 +10302,7 @@ static struct redisplay_interface x_redisplay_interface =
     x_clear_frame_area,
     x_draw_window_cursor,
     x_draw_vertical_window_border,
+    x_draw_window_divider,
     x_shift_glyphs_for_insert
   };
 
@@ -10417,6 +10312,7 @@ void
 x_delete_terminal (struct terminal *terminal)
 {
   struct x_display_info *dpyinfo = terminal->display_info.x;
+  int connection = -1;
 
   /* Protect against recursive calls.  delete_frame in
      delete_terminal calls us back when it deletes our last frame.  */
@@ -10435,6 +10331,8 @@ x_delete_terminal (struct terminal *terminal)
      and dpyinfo->display was set to 0 to indicate that.  */
   if (dpyinfo->display)
     {
+      connection = ConnectionNumber (dpyinfo->display);
+
       x_destroy_all_bitmaps (dpyinfo);
       XSetCloseDownMode (dpyinfo->display, DestroyAll);
 
@@ -10475,6 +10373,10 @@ x_delete_terminal (struct terminal *terminal)
 #endif /* ! USE_GTK */
     }
 
+  /* No more input on this descriptor.  */
+  if (connection != -1)
+    delete_keyboard_wait_descriptor (connection);
+
   /* Mark as dead. */
   dpyinfo->display = NULL;
   x_delete_display (dpyinfo);
@@ -10522,12 +10424,6 @@ x_create_terminal (struct x_display_info *dpyinfo)
   terminal->delete_terminal_hook = x_delete_terminal;
 
   terminal->rif = &x_redisplay_interface;
-  terminal->scroll_region_ok = 1;    /* We'll scroll partial frames. */
-  terminal->char_ins_del_ok = 1;
-  terminal->line_ins_del_ok = 1;         /* We'll just blt 'em. */
-  terminal->fast_clear_end_of_line = 1;  /* X does this well. */
-  terminal->memory_below_frame = 0;   /* We don't remember what scrolls
-                                        off the bottom. */
 
   return terminal;
 }
@@ -10572,10 +10468,6 @@ x_initialize (void)
 #endif
 #endif
 
-  pending_autoraise_frame = 0;
-  pending_event_wait.f = 0;
-  pending_event_wait.eventtype = 0;
-
   /* Note that there is no real way portable across R3/R4 to get the
      original error handler.  */
   XSetErrorHandler (x_error_handler);
@@ -10588,12 +10480,6 @@ syms_of_xterm (void)
 {
   x_error_message = NULL;
 
-  staticpro (&x_display_name_list);
-  x_display_name_list = Qnil;
-
-  staticpro (&last_mouse_scroll_bar);
-  last_mouse_scroll_bar = Qnil;
-
   DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
   DEFSYM (Qlatin_1, "latin-1");
 
@@ -10652,17 +10538,14 @@ With MS Windows or Nextstep, the value is t.  */);
   Vx_toolkit_scroll_bars = Qnil;
 #endif
 
-  staticpro (&last_mouse_motion_frame);
-  last_mouse_motion_frame = Qnil;
-
-  Qmodifier_value = intern_c_string ("modifier-value");
-  Qalt = intern_c_string ("alt");
+  DEFSYM (Qmodifier_value, "modifier-value");
+  DEFSYM (Qalt, "alt");
   Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
-  Qhyper = intern_c_string ("hyper");
+  DEFSYM (Qhyper, "hyper");
   Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
-  Qmeta = intern_c_string ("meta");
+  DEFSYM (Qmeta, "meta");
   Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
-  Qsuper = intern_c_string ("super");
+  DEFSYM (Qsuper, "super");
   Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
 
   DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym,
@@ -10700,5 +10583,3 @@ default is nil, which is the same as `super'.  */);
                                     make_float (DEFAULT_REHASH_THRESHOLD),
                                     Qnil);
 }
-
-#endif /* HAVE_X_WINDOWS */