A simpler, centralized INLINE.
[bpt/emacs.git] / src / xterm.c
index 7038de7..2633bf1 100644 (file)
@@ -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"
@@ -69,7 +67,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "atimer.h"
 #include "keymap.h"
 #include "font.h"
-#include "fontset.h"
 #include "xsettings.h"
 #include "xgselect.h"
 #include "sysselect.h"
@@ -87,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
 
@@ -141,15 +138,10 @@ int use_xim = 1;
 int use_xim = 0;  /* configure --without-xim */
 #endif
 
-\f
-
 /* Non-zero means that a HELP_EVENT has been generated since Emacs
    start.  */
 
-static int any_help_event_p;
-
-/* Last window where we saw the mouse.  Used by mouse-autoselect-window.  */
-static Lisp_Object last_window;
+static bool any_help_event_p;
 
 /* This is a chain of structures for all the X displays currently in
    use.  */
@@ -163,83 +155,22 @@ struct x_display_info *x_display_list;
 
 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 FRAME_PTR last_mouse_glyph_frame;
-static Lisp_Object last_mouse_press_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;
+static Time ignore_next_mouse_click_timeout;
 
 /* Incremented by XTread_socket whenever it really tries to read
    events.  */
@@ -289,22 +220,16 @@ enum xembed_message
     XEMBED_ACTIVATE_ACCELERATOR   = 14
   };
 
-/* Used in x_flush.  */
-
 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_raise_frame (struct frame *);
 static void x_lower_frame (struct frame *);
 static const XColor *x_color_cells (Display *, int *);
-static void x_update_window_end (struct window *, int, int);
-
 static int x_io_error_quitter (Display *);
 static struct terminal *x_create_terminal (struct x_display_info *);
 void x_delete_terminal (struct terminal *);
 static void x_update_end (struct frame *);
 static void XTframe_up_to_date (struct frame *);
-static void XTset_terminal_modes (struct terminal *);
-static void XTreset_terminal_modes (struct terminal *);
 static void x_clear_frame (struct frame *);
 static _Noreturn void x_ins_del_lines (struct frame *, int, int);
 static void frame_highlight (struct frame *);
@@ -312,30 +237,29 @@ 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 *);
 static void x_draw_bar_cursor (struct window *, struct glyph_row *, int,
                                enum text_cursor_kinds);
 
-static void x_clip_to_row (struct window *, struct glyph_row *, int, GC);
+static void x_clip_to_row (struct window *, struct glyph_row *,
+                          enum glyph_row_area, GC);
 static void x_flush (struct frame *f);
 static void x_update_begin (struct frame *);
 static void x_update_window_begin (struct window *);
-static void x_after_update_window_line (struct glyph_row *);
 static struct scroll_bar *x_window_to_scroll_bar (Display *, Window);
 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 *);
+static int handle_one_xevent (struct x_display_info *,
+                             const XEvent *, int *,
+                             struct input_event *);
 #ifdef USE_GTK
 static int x_dispatch_event (XEvent *, Display *);
 #endif
@@ -347,26 +271,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 == NULL)
-    {
-      Lisp_Object rest, frame;
-      FOR_EACH_FRAME (rest, frame)
-        if (FRAME_X_P (XFRAME (frame)))
-          x_flush (XFRAME (frame));
-    }
-  else if (FRAME_X_P (f))
-    XFlush (FRAME_X_DISPLAY (f));
+  XFlush (FRAME_X_DISPLAY (f));
   unblock_input ();
 }
 
@@ -436,7 +353,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;
@@ -455,7 +372,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;
@@ -555,9 +472,7 @@ x_update_begin (struct frame *f)
 }
 
 
-/* Start update of window W.  Set the global variable updated_window
-   to the window being updated and set output_cursor to the cursor
-   position of W.  */
+/* Start update of window W.  */
 
 static void
 x_update_window_begin (struct window *w)
@@ -565,8 +480,7 @@ x_update_window_begin (struct window *w)
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
 
-  updated_window = w;
-  set_output_cursor (&w->cursor);
+  w->output_cursor = w->cursor;
 
   block_input ();
 
@@ -602,7 +516,7 @@ x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
             f->output_data.x->normal_gc, x, y0, x, y1);
 }
 
-/* End update of window W (which is equal to updated_window).
+/* End update of window W.
 
    Draw vertical borders between horizontally adjacent windows, and
    display W's cursor if CURSOR_ON_P is non-zero.
@@ -616,18 +530,17 @@ x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
    here.  */
 
 static void
-x_update_window_end (struct window *w, int cursor_on_p, int mouse_face_overwritten_p)
+x_update_window_end (struct window *w, bool cursor_on_p,
+                    bool mouse_face_overwritten_p)
 {
-  Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
-
   if (!w->pseudo_window_p)
     {
       block_input ();
 
       if (cursor_on_p)
-       display_and_set_cursor (w, 1, output_cursor.hpos,
-                               output_cursor.vpos,
-                               output_cursor.x, output_cursor.y);
+       display_and_set_cursor (w, 1,
+                               w->output_cursor.hpos, w->output_cursor.vpos,
+                               w->output_cursor.x, w->output_cursor.y);
 
       if (draw_window_fringes (w, 1))
        x_draw_vertical_border (w);
@@ -638,13 +551,7 @@ x_update_window_end (struct window *w, int cursor_on_p, int mouse_face_overwritt
   /* If a row with mouse-face was overwritten, arrange for
      XTframe_up_to_date to redisplay the mouse highlight.  */
   if (mouse_face_overwritten_p)
-    {
-      hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
-      hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
-      hlinfo->mouse_face_window = Qnil;
-    }
-
-  updated_window = NULL;
+    reset_mouse_highlight (MOUSE_HL_INFO (XFRAME (w->frame)));
 }
 
 
@@ -665,9 +572,8 @@ x_update_end (struct frame *f)
 }
 
 
-/* This function is called from various places in xdisp.c whenever a
-   complete update has been performed.  The global variable
-   updated_window is not available here.  */
+/* This function is called from various places in xdisp.c
+   whenever a complete update has been performed.  */
 
 static void
 XTframe_up_to_date (struct frame *f)
@@ -679,15 +585,13 @@ XTframe_up_to_date (struct frame *f)
 
 /* 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.  The window being updated is
-   found in updated_window.  This function It is called from
+   before DESIRED_ROW is made current.  This function is called from
    update_window_line only if it is known that there are differences
    between bitmaps to be drawn between current row and DESIRED_ROW.  */
 
 static void
-x_after_update_window_line (struct glyph_row *desired_row)
+x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
 {
-  struct window *w = updated_window;
   struct frame *f;
   int width, height;
 
@@ -698,7 +602,7 @@ x_after_update_window_line (struct glyph_row *desired_row)
 
   /* 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,
+     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.  */
@@ -714,10 +618,10 @@ x_after_update_window_line (struct glyph_row *desired_row)
 
       block_input ();
       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                   0, y, width, height, False);
+                   0, y, width, height);
       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                    FRAME_PIXEL_WIDTH (f) - width,
-                   y, width, height, False);
+                   y, width, height);
       unblock_input ();
     }
 }
@@ -732,7 +636,7 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
   struct face *face = p->face;
 
   /* Must clip because of partially visible lines.  */
-  x_clip_to_row (w, row, -1, gc);
+  x_clip_to_row (w, row, ANY_AREA, gc);
 
   if (!p->overlay_p)
     {
@@ -825,7 +729,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;
@@ -849,27 +753,6 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
   XSetClipMask (display, gc, None);
 }
 
-\f
-
-/* This is called when starting Emacs and when restarting after
-   suspend.  When starting Emacs, no X window is mapped.  And nothing
-   must be done to Emacs's own window if it is suspended (though that
-   rarely happens).  */
-
-static void
-XTset_terminal_modes (struct terminal *terminal)
-{
-}
-
-/* This is called when exiting or suspending Emacs.  Exiting will make
-   the X-windows go away, and suspending requires no action.  */
-
-static void
-XTreset_terminal_modes (struct terminal *terminal)
-{
-}
-
-\f
 /***********************************************************************
                            Glyph display
  ***********************************************************************/
@@ -878,8 +761,6 @@ XTreset_terminal_modes (struct terminal *terminal)
 
 static void x_set_glyph_string_clipping (struct glyph_string *);
 static void x_set_glyph_string_gc (struct glyph_string *);
-static void x_draw_glyph_string_background (struct glyph_string *,
-                                            int);
 static void x_draw_glyph_string_foreground (struct glyph_string *);
 static void x_draw_composite_glyph_string_foreground (struct glyph_string *);
 static void x_draw_glyph_string_box (struct glyph_string *);
@@ -952,14 +833,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;
     }
 }
 
@@ -999,14 +880,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);
@@ -1164,7 +1045,7 @@ x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h)
    contains the first component of a composition.  */
 
 static void
-x_draw_glyph_string_background (struct glyph_string *s, int force_p)
+x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
 {
   /* Nothing to do if background has already been drawn or if it
      shouldn't be drawn in the first place.  */
@@ -1377,7 +1258,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
        }
       else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
        {
-         sprintf ((char *) buf, "%0*X",
+         sprintf (buf, "%0*X",
                   glyph->u.glyphless.ch < 0x10000 ? 4 : 6,
                   glyph->u.glyphless.ch);
          str = buf;
@@ -1414,11 +1295,6 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
 
 #ifdef USE_X_TOOLKIT
 
-static Boolean cvt_string_to_pixel (Display *, XrmValue *, Cardinal *,
-                                    XrmValue *, XrmValue *, XtPointer *);
-static void cvt_pixel_dtor (XtAppContext, XrmValue *, XtPointer,
-                            XrmValue *, Cardinal *);
-
 #ifdef USE_LUCID
 
 /* Return the frame on which widget WIDGET is used.. Abort if frame
@@ -1447,7 +1323,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;
     }
@@ -1656,7 +1532,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)
     {
@@ -1896,7 +1772,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;
@@ -2648,7 +2524,10 @@ x_draw_underwave (struct glyph_string *s)
 
   /* Find and set clipping rectangle */
 
-  wave_clip = (XRectangle){ x0, y0, width, wave_height };
+  wave_clip.x = x0;
+  wave_clip.y = y0;
+  wave_clip.width = width;
+  wave_clip.height = wave_height;
   get_glyph_string_clip_rect (s, &string_clip);
 
   if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
@@ -2689,7 +2568,7 @@ x_draw_underwave (struct glyph_string *s)
 static void
 x_draw_glyph_string (struct glyph_string *s)
 {
-  int relief_drawn_p = 0;
+  bool relief_drawn_p = 0;
 
   /* If S draws into the background of its successors, draw the
      background of the successors first so that S can draw into it.
@@ -2988,10 +2867,10 @@ x_delete_glyphs (struct frame *f, register int n)
    If they are <= 0, this is probably an error.  */
 
 void
-x_clear_area (Display *dpy, Window window, int x, int y, int width, int height, int exposures)
+x_clear_area (Display *dpy, Window window, int x, int y, int width, int height)
 {
   eassert (width > 0 && height > 0);
-  XClearArea (dpy, window, x, y, width, height, exposures);
+  XClearArea (dpy, window, x, y, width, height, False);
 }
 
 
@@ -3003,11 +2882,7 @@ x_clear_frame (struct frame *f)
   /* Clearing the frame will erase any cursor, so mark them all as no
      longer visible.  */
   mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
-  output_cursor.hpos = output_cursor.vpos = 0;
-  output_cursor.x = -1;
 
-  /* We don't set the output cursor here because there will always
-     follow an explicit cursor_to.  */
   block_input ();
 
   XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
@@ -3087,26 +2962,7 @@ XTflash (struct frame *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))
@@ -3132,22 +2988,22 @@ XTflash (struct frame *f)
       x_flush (f);
 
       {
-       EMACS_TIME delay = make_emacs_time (0, 150 * 1000 * 1000);
-       EMACS_TIME wakeup = add_emacs_time (current_emacs_time (), delay);
+       struct timespec delay = make_timespec (0, 150 * 1000 * 1000);
+       struct timespec wakeup = timespec_add (current_timespec (), delay);
 
        /* Keep waiting until past the time wakeup or any input gets
           available.  */
        while (! detect_input_pending ())
          {
-           EMACS_TIME current = current_emacs_time ();
-           EMACS_TIME timeout;
+           struct timespec current = current_timespec ();
+           struct timespec timeout;
 
            /* Break if result would not be positive.  */
-           if (EMACS_TIME_LE (wakeup, current))
+           if (timespec_cmp (wakeup, current) <= 0)
              break;
 
            /* How long `select' should wait.  */
-           timeout = make_emacs_time (0, 10 * 1000 * 1000);
+           timeout = make_timespec (0, 10 * 1000 * 1000);
 
            /* Try to wait that long--but we might wake up sooner.  */
            pselect (0, NULL, NULL, NULL, &timeout, NULL);
@@ -3193,14 +3049,14 @@ XTflash (struct frame *f)
 
 
 static void
-XTtoggle_invisible_pointer (FRAME_PTR f, int invisible)
+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),
@@ -3233,20 +3089,6 @@ XTring_bell (struct frame *f)
     }
 }
 
-\f
-/* Specify how many text lines, from the top of the window,
-   should be affected by insert-lines and delete-lines operations.
-   This, and those operations, are used only within an update
-   that is bounded by calls to x_update_begin and x_update_end.  */
-
-static void
-XTset_terminal_window (struct frame *f, int n)
-{
-  /* This function intentionally left blank.  */
-}
-
-
-\f
 /***********************************************************************
                              Line Dance
  ***********************************************************************/
@@ -3272,7 +3114,7 @@ x_scroll_run (struct window *w, struct run *run)
   /* Get frame-relative bounding box of the text display area of W,
      without mode lines.  Include in this box the left and right
      fringe of W.  */
-  window_box (w, -1, &x, &y, &width, &height);
+  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
@@ -3328,7 +3170,6 @@ x_scroll_run (struct window *w, struct run *run)
   block_input ();
 
   /* Cursor off.  Will be switched on again in x_update_window_end.  */
-  updated_window = w;
   x_clear_cursor (w);
 
   XCopyArea (FRAME_X_DISPLAY (f),
@@ -3408,9 +3249,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);
@@ -3433,13 +3274,12 @@ 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.  */
-          if ((NILP (Vterminal_frame) || EQ (Fdaemonp(), Qt))
-              && CONSP (Vframe_list)
-              && !NILP (XCDR (Vframe_list)))
-            {
-              bufp->kind = FOCUS_IN_EVENT;
-              XSETFRAME (bufp->frame_or_window, frame);
-            }
+          bufp->arg = (((NILP (Vterminal_frame) || EQ (Fdaemonp (), Qt))
+                       && CONSP (Vframe_list)
+                       && !NILP (XCDR (Vframe_list)))
+                      ? Qt : Qnil);
+          bufp->kind = FOCUS_IN_EVENT;
+          XSETFRAME (bufp->frame_or_window, frame);
         }
 
       frame->output_data.x->focus_state |= state;
@@ -3457,6 +3297,9 @@ x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct fra
         {
           dpyinfo->x_focus_event_frame = 0;
           x_new_focus_frame (dpyinfo, 0);
+
+          bufp->kind = FOCUS_OUT_EVENT;
+          XSETFRAME (bufp->frame_or_window, frame);
         }
 
 #ifdef HAVE_X_I18N
@@ -3468,18 +3311,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)
@@ -3541,7 +3558,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
@@ -3757,9 +3774,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.
 
@@ -3767,14 +3800,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
@@ -3787,7 +3822,6 @@ construct_mouse_click (struct input_event *result, XButtonEvent *event, struct f
   return Qnil;
 }
 
-\f
 /* Function to report a mouse movement to the mainstream Emacs code.
    The input handler calls this.
 
@@ -3796,65 +3830,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 (FRAME_PTR 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.
 
@@ -3876,15 +3894,16 @@ redo_mouse_highlight (void)
    movement.  */
 
 static void
-XTmouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
+XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
                  enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
                  Time *timestamp)
 {
-  FRAME_PTR f1;
+  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
     {
@@ -3902,7 +3921,7 @@ XTmouse_position (FRAME_PTR *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),
@@ -3940,22 +3959,24 @@ XTmouse_position (FRAME_PTR *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
          {
@@ -3979,7 +4000,7 @@ XTmouse_position (FRAME_PTR *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;
@@ -4001,10 +4022,10 @@ XTmouse_position (FRAME_PTR *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
@@ -4050,15 +4071,17 @@ XTmouse_position (FRAME_PTR *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;
          }
       }
     }
@@ -4144,23 +4167,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.  */
 
@@ -4202,33 +4215,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
@@ -4238,47 +4247,43 @@ 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;
 
   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;
+  /* 32-bit X client on a 64-bit X server can pass window pointer
+     as is.  64-bit client on a 32-bit X server is in trouble
+     because pointer does not fit and will be truncated while
+     passing through the server.  So we should use two slots
+     and hope that X12 will resolve such an issues someday.  */
 
-  if (i == scroll_bar_windows_size)
+  if (BITS_PER_LONG > 32)
     {
-      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);
+      union {
+       int i[2];
+       void *v;
+      } val;
+      val.v = w;
+      ev->data.l[0] = val.i[0];
+      ev->data.l[1] = val.i[1];
     }
-
-  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;
+  else
+    {
+      ev->data.l[0] = 0;
+      ev->data.l[1] = (long) w;
+    }
+  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
@@ -4298,14 +4303,27 @@ 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.  */
+
+  if (BITS_PER_LONG > 32)
+    {
+      union {
+       int i[2];
+       void *v;
+      } val;
+      val.i[0] = ev->data.l[0];
+      val.i[1] = ev->data.l[1];
+      w = val.v;
+    }
+  else
+    w = (void *) ev->data.l[1];
 
   XSETWINDOW (window, w);
 
@@ -4318,10 +4336,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;
 }
 
@@ -4340,39 +4358,39 @@ x_scroll_bar_to_input_event (XEvent *event, struct input_event *ievent)
 static void
 xm_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
 {
-  struct scroll_bar *bar = (struct scroll_bar *) client_data;
-  XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
+  struct scroll_bar *bar = client_data;
+  XmScrollBarCallbackStruct *cs = call_data;
   int part = -1, whole = 0, portion = 0;
 
   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;
 
@@ -4388,7 +4406,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;
 
@@ -4399,7 +4417,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);
     }
 }
@@ -4415,11 +4432,11 @@ xg_scroll_callback (GtkRange     *range,
                     gdouble       value,
                     gpointer      user_data)
 {
-  struct scroll_bar *bar = (struct scroll_bar *) user_data;
+  struct scroll_bar *bar = user_data;
   gdouble position;
   int part = -1, whole = 0, portion = 0;
   GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range));
-  FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (range), XG_FRAME_DATA);
+  struct frame *f = g_object_get_data (G_OBJECT (range), XG_FRAME_DATA);
 
   if (xg_ignore_gtk_scrollbar) return FALSE;
   position = gtk_adjustment_get_value (adj);
@@ -4429,53 +4446,52 @@ 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,
                         GdkEventButton *event,
                         gpointer user_data)
 {
-  struct scroll_bar *bar = (struct scroll_bar *) user_data;
-  bar->dragging = Qnil;
+  struct scroll_bar *bar = user_data;
+  bar->dragging = -1;
   if (WINDOWP (window_being_scrolled))
     {
       x_send_scroll_bar_event (window_being_scrolled,
@@ -4497,11 +4513,12 @@ xg_end_scroll_callback (GtkWidget *widget,
 static void
 xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data)
 {
-  struct scroll_bar *bar = (struct scroll_bar *) client_data;
-  float top = *(float *) call_data;
+  struct scroll_bar *bar = client_data;
+  float *top_addr = 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 ();
@@ -4522,8 +4539,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);
 }
 
@@ -4539,11 +4556,11 @@ xaw_jump_callback (Widget widget, XtPointer client_data, XtPointer call_data)
 static void
 xaw_scroll_callback (Widget widget, XtPointer client_data, XtPointer call_data)
 {
-  struct scroll_bar *bar = (struct scroll_bar *) client_data;
+  struct scroll_bar *bar = client_data;
   /* The position really is stored cast to a pointer.  */
-  int position = (long) call_data;
+  int position = (intptr_t) call_data;
   Dimension height;
-  int part;
+  enum scroll_bar_part part;
 
   /* Get the height of the scroll bar.  */
   block_input ();
@@ -4561,8 +4578,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);
 }
 
@@ -4837,7 +4854,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;
 
@@ -4872,19 +4889,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
          {
@@ -4940,7 +4966,7 @@ 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);
 
@@ -4949,17 +4975,13 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
        this case, no clear_frame is generated to reduce flickering.  */
     if (width > 0 && height > 0)
       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                   left, top, width,
-                   window_box_height (w), False);
+                   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,
@@ -4976,8 +4998,11 @@ 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->dragging = -1;
   bar->fringe_extended_p = 0;
+#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);
@@ -4991,19 +5016,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 */
     }
@@ -5034,9 +5051,9 @@ 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;
-  FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
+  struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
   GC gc = f->output_data.x->normal_gc;
 
   /* If the display is already accurate, do nothing.  */
@@ -5086,11 +5103,9 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end, int rebuild
        zero-height areas; that means "clear to end of window."  */
     if (start > 0)
       x_clear_area (FRAME_X_DISPLAY (f), w,
-                   /* x, y, width, height, and exposures.  */
                    VERTICAL_SCROLL_BAR_LEFT_BORDER,
                    VERTICAL_SCROLL_BAR_TOP_BORDER,
-                   inside_width, start,
-                   False);
+                   inside_width, start);
 
     /* Change to proper foreground color if one is specified.  */
     if (f->output_data.x->scroll_bar_foreground_pixel != -1)
@@ -5113,12 +5128,9 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end, int rebuild
        clear zero-height areas; that means "clear to end of window." */
     if (end < inside_height)
       x_clear_area (FRAME_X_DISPLAY (f), w,
-                   /* x, y, width, height, and exposures.  */
                    VERTICAL_SCROLL_BAR_LEFT_BORDER,
                    VERTICAL_SCROLL_BAR_TOP_BORDER + end,
-                   inside_width, inside_height - end,
-                   False);
-
+                   inside_width, inside_height - end);
   }
 
   unblock_input ();
@@ -5166,11 +5178,11 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
   int top, height, left, sb_left, width, sb_width;
   int window_y, window_height;
 #ifdef USE_TOOLKIT_SCROLL_BARS
-  int fringe_extended_p;
+  bool fringe_extended_p;
 #endif
 
   /* Get window dimensions.  */
-  window_box (w, -1, 0, &window_y, 0, &window_height);
+  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;
@@ -5199,16 +5211,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
 #endif
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
-  if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
-    fringe_extended_p = (WINDOW_LEFTMOST_P (w)
-                        && WINDOW_LEFT_FRINGE_WIDTH (w)
-                        && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
-                            || WINDOW_LEFT_MARGIN_COLS (w) == 0));
-  else
-    fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
-                        && WINDOW_RIGHT_FRINGE_WIDTH (w)
-                        && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
-                            || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
+  fringe_extended_p = WINDOW_FRINGE_EXTENDED_P (w);
 #endif
 
   /* Does the scroll bar exist yet?  */
@@ -5220,11 +5223,11 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
 #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, False);
+                         sb_left, top, sb_width, height);
          else
 #endif
            x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                         left, top, width, height, False);
+                         left, top, width, height);
          unblock_input ();
        }
 
@@ -5259,41 +5262,21 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
            {
              if (fringe_extended_p)
                x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                             sb_left, top, sb_width, height, False);
+                             sb_left, top, sb_width, height);
              else
                x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                             left, top, width, height, False);
+                             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,
+                                  sb_left, sb_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);
+                             sb_left, top, sb_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, False);
-         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, False);
-       }
-
       /* 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
@@ -5305,11 +5288,10 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
          {
            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, False);
+                           left + area_width - rest, top, rest, height);
            else
              x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                           left, top, rest, height, False);
+                           left, top, rest, height);
          }
       }
 
@@ -5318,9 +5300,9 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
        {
          XWindowChanges wc;
 
-         wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
+         wc.x = sb_left;
          wc.y = top;
-         wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
+         wc.width = sb_width;
          wc.height = height;
          XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
                            mask, &wc);
@@ -5344,7 +5326,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
 #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);
 
@@ -5377,7 +5359,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
    `*redeem_scroll_bar_hook' is applied to its window before the judgment.  */
 
 static void
-XTcondemn_scroll_bars (FRAME_PTR frame)
+XTcondemn_scroll_bars (struct frame *frame)
 {
   /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS.  */
   while (! NILP (FRAME_SCROLL_BARS (frame)))
@@ -5445,7 +5427,7 @@ XTredeem_scroll_bar (struct window *window)
    last call to `*condemn_scroll_bars_hook'.  */
 
 static void
-XTjudge_scroll_bars (FRAME_PTR f)
+XTjudge_scroll_bars (struct frame *f)
 {
   Lisp_Object bar, next;
 
@@ -5478,12 +5460,11 @@ XTjudge_scroll_bars (FRAME_PTR 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;
-  FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->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 ();
 
@@ -5496,11 +5477,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)
@@ -5520,7 +5498,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 ();
@@ -5528,7 +5508,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
@@ -5554,14 +5534,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
 
@@ -5578,20 +5557,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, XEvent *event)
+x_scroll_bar_note_movement (struct scroll_bar *bar,
+                           const XMotionEvent *event)
 {
-  FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
-
-  last_mouse_movement_time = event->xmotion.time;
+  struct frame *f = XFRAME (XWINDOW (bar->window)->frame);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
 
+  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->xmotion.y - XINT (bar->dragging);
+      int new_start = event->y - bar->dragging;
 
       if (new_start != bar->start)
        {
@@ -5608,13 +5588,14 @@ x_scroll_bar_note_movement (struct scroll_bar *bar, XEvent *event)
    on the scroll bar.  */
 
 static void
-x_scroll_bar_report_motion (FRAME_PTR *fp, Lisp_Object *bar_window,
+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;
-  FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
+  struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
   int win_x, win_y;
   Window dummy_window;
   int dummy_coord;
@@ -5624,27 +5605,24 @@ x_scroll_bar_report_motion (FRAME_PTR *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;
@@ -5654,7 +5632,7 @@ x_scroll_bar_report_motion (FRAME_PTR *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;
@@ -5667,11 +5645,10 @@ x_scroll_bar_report_motion (FRAME_PTR *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 ();
 }
 
@@ -5682,7 +5659,7 @@ x_scroll_bar_report_motion (FRAME_PTR *fp, Lisp_Object *bar_window,
    redraw them.  */
 
 static void
-x_scroll_bar_clear (FRAME_PTR f)
+x_scroll_bar_clear (struct frame *f)
 {
 #ifndef USE_TOOLKIT_SCROLL_BARS
   Lisp_Object bar;
@@ -5699,18 +5676,7 @@ x_scroll_bar_clear (FRAME_PTR f)
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
 }
 
-\f
-/* The main X event-reading loop - XTread_socket.  */
-
-/* This holds the state XLookupString needs to implement dead keys
-   and other tricks known as "compose processing".  _X Window System_
-   says that a portable program can't use this, but Stephen Gildea assures
-   me that letting the compiler initialize it to zeros will work okay.
-
-   This must be defined outside of XTread_socket, for the same reasons
-   given for enter_timestamp, above.  */
-
-static XComposeStatus compose_status;
+#ifdef ENABLE_CHECKING
 
 /* Record the last 100 characters stored
    to help debug the loss-of-chars-during-GC problem.  */
@@ -5723,6 +5689,12 @@ static short temp_buffer[100];
     temp_index = 0;                                            \
   temp_buffer[temp_index++] = (keysym)
 
+#else /* not ENABLE_CHECKING */
+
+#define STORE_KEYSYM_FOR_DEBUG(keysym) ((void)0)
+
+#endif /* ENABLE_CHECKING */
+
 /* Set this to nonzero to fake an "X I/O error"
    on a particular display.  */
 
@@ -5735,20 +5707,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,
@@ -5842,11 +5800,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. */
 
 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 {
@@ -5856,10 +5816,15 @@ 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_
+     says that a portable program can't use this, but Stephen Gildea assures
+     me that letting the compiler initialize it to zeros will work okay.  */
+  static XComposeStatus compose_status;
+
   USE_SAFE_ALLOCA;
 
   *finish = X_EVENT_NORMAL;
@@ -5868,24 +5833,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);
 
-  switch (event.type)
+  if (any && any->wait_event_type == event->type)
+    any->wait_event_type = 0; /* Indicates we got it.  */
+
+  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))
@@ -5909,15 +5874,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);
@@ -5928,8 +5893,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
@@ -5944,26 +5908,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  */
 
@@ -5975,20 +5937,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)
               {
@@ -5999,28 +5957,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);
@@ -6031,54 +5986,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;
@@ -6088,29 +6041,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)
           {
@@ -6125,40 +6078,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,
-                        FALSE);
-#endif
           if (!FRAME_VISIBLE_P (f))
             {
               SET_FRAME_VISIBLE (f, 1);
@@ -6167,9 +6109,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
         {
@@ -6181,8 +6132,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);
           }
@@ -6192,11 +6142,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;
@@ -6208,14 +6158,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;
@@ -6229,13 +6177,13 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
 
     case UnmapNotify:
       /* Redo the mouse-highlight after the tooltip has gone.  */
-      if (event.xmap.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.  */
         {
@@ -6260,7 +6208,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;
@@ -6268,7 +6216,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);
@@ -6308,7 +6256,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)
@@ -6317,8 +6265,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)
@@ -6328,6 +6277,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)
@@ -6335,7 +6285,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);
@@ -6364,6 +6314,8 @@ 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
@@ -6373,20 +6325,19 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
           *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
@@ -6403,7 +6354,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)
@@ -6411,7 +6362,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);
                 }
@@ -6428,11 +6379,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
@@ -6448,8 +6399,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.  */
@@ -6625,6 +6576,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
@@ -6637,7 +6590,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
@@ -6648,35 +6601,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)
@@ -6696,26 +6649,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)
           {
@@ -6724,7 +6674,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)
@@ -6733,18 +6683,16 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
             /* Generate SELECT_WINDOW_EVENTs when needed.
                Don't let popup menus influence things (bug#1261).  */
             if (!NILP (Vmouse_autoselect_window) && !popup_activated ())
-              {
-                Lisp_Object window;
-
-                window = window_from_coordinates (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
-                   will be selected only when it is active.  */
-                if (WINDOWP (window)
-                    && !EQ (window, last_window)
+             {
+               static Lisp_Object last_mouse_window;
+               Lisp_Object window = window_from_coordinates
+                 (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
+                  will be selected only when it is active.  */
+               if (WINDOWP (window)
+                   && !EQ (window, last_mouse_window)
                    && !EQ (window, selected_window)
                    /* For click-to-focus window managers
                       create event iff we don't leave the
@@ -6752,25 +6700,25 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
                    && (focus_follows_mouse
                        || (EQ (XWINDOW (window)->frame,
                                XWINDOW (selected_window)->frame))))
-                  {
-                    inev.ie.kind = SELECT_WINDOW_EVENT;
-                    inev.ie.frame_or_window = window;
-                  }
-
-                last_window=window;
-              }
-            if (!note_mouse_movement (f, &event.xmotion))
+                 {
+                   inev.ie.kind = SELECT_WINDOW_EVENT;
+                   inev.ie.frame_or_window = window;
+                 }
+               /* Remember the last window where we saw the mouse.  */
+               last_mouse_window = window;
+             }
+            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);
+              x_scroll_bar_note_movement (bar, &event->xmotion);
 #endif /* USE_TOOLKIT_SCROLL_BARS */
 
             /* If we move outside the frame, then we're
@@ -6787,14 +6735,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
@@ -6802,8 +6750,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 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, event->xconfigure.height);
+          int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, event->xconfigure.width);
 
           /* In the toolkit version, change_frame_size
              is called by the code that handles resizing
@@ -6814,16 +6762,16 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
              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))
+              || 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);
               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
 
@@ -6833,9 +6781,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))
@@ -6850,44 +6796,39 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
       {
         /* If we decide we want to generate an event to be seen
            by the rest of Emacs, we put it here.  */
-        int tool_bar_p = 0;
+        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)
@@ -6896,52 +6837,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
@@ -6950,7 +6891,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
@@ -6959,25 +6900,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)
-          {
-            SET_SAVED_BUTTON_EVENT;
-            XSETFRAME (last_mouse_press_frame, f);
-            *finish = X_EVENT_DROP;
-          }
-        else if (event.type == ButtonPress)
+            && 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)
           {
-            last_mouse_press_frame = Qnil;
-            goto OTHER;
+           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;
@@ -6997,18 +6936,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:
@@ -7016,7 +6955,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;
@@ -7054,7 +6993,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
     }
 
   SAFE_FREE ();
-  *eventptr = event;
   return count;
 }
 
@@ -7094,6 +7032,7 @@ 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 ();
 
@@ -7101,36 +7040,33 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
   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
@@ -7180,12 +7116,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 ();
@@ -7208,7 +7143,8 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
    mode lines must be clipped to the whole window.  */
 
 static void
-x_clip_to_row (struct window *w, struct glyph_row *row, int area, GC gc)
+x_clip_to_row (struct window *w, struct glyph_row *row,
+              enum glyph_row_area area, GC gc)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   XRectangle clip_rect;
@@ -7232,7 +7168,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;
@@ -7299,7 +7235,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;
@@ -7320,7 +7256,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);
@@ -7385,8 +7321,7 @@ x_define_frame_cursor (struct frame *f, Cursor cursor)
 static void
 x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
 {
-  x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-               x, y, width, height, False);
+  x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), x, y, width, height);
 #ifdef USE_GTK
   /* Must queue a redraw, because scroll bars might have been cleared.  */
   if (FRAME_GTK_WIDGET (f))
@@ -7398,7 +7333,9 @@ x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
 /* RIF: Draw cursor on window W.  */
 
 static void
-x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, int y, int cursor_type, int cursor_width, int on_p, int active_p)
+x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
+                     int y, enum text_cursor_kinds cursor_type,
+                     int cursor_width, bool on_p, bool active_p)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
 
@@ -7451,9 +7388,7 @@ x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, int
 #endif
     }
 
-#ifndef XFlush
   XFlush (FRAME_X_DISPLAY (f));
-#endif
 }
 
 \f
@@ -7488,7 +7423,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;
 
@@ -7502,7 +7437,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
 
@@ -7514,8 +7449,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);
            }
        }
 
@@ -7523,9 +7458,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);
@@ -7659,7 +7594,7 @@ x_check_errors (Display *dpy, const char *format)
 /* Nonzero if we had any X protocol errors
    since we did x_catch_errors on DPY.  */
 
-int
+bool
 x_had_errors_p (Display *dpy)
 {
   /* Make sure to catch any errors incurred so far.  */
@@ -7739,7 +7674,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);
     }
 
@@ -7748,7 +7683,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.  */
@@ -7824,10 +7759,9 @@ static void x_error_quitter (Display *, XErrorEvent *);
 static int
 x_error_handler (Display *display, XErrorEvent *event)
 {
-#ifdef HAVE_GTK3
-  if (event->error_code == BadMatch
-      && event->request_code == X_SetInputFocus
-      && event->minor_code == 0)
+#if defined USE_GTK && defined HAVE_GTK3
+  if ((event->error_code == BadMatch || event->error_code == BadWindow)
+      && event->request_code == X_SetInputFocus)
     {
       return 0;
     }
@@ -7972,7 +7906,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);
@@ -8063,7 +7997,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);
@@ -8098,13 +8032,10 @@ xim_initialize (struct x_display_info *dpyinfo, char *resource_name)
     {
 #ifdef HAVE_X11R6_XIM
       struct xim_inst_t *xim_inst = xmalloc (sizeof *xim_inst);
-      ptrdiff_t len;
 
       dpyinfo->xim_callback_data = xim_inst;
       xim_inst->dpyinfo = dpyinfo;
-      len = strlen (resource_name);
-      xim_inst->resource_name = xmalloc (len + 1);
-      memcpy (xim_inst->resource_name, resource_name, len + 1);
+      xim_inst->resource_name = xstrdup (resource_name);
       XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
                                      resource_name, emacs_class,
                                      xim_instantiate_callback,
@@ -8164,7 +8095,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;
 
   {
@@ -8187,7 +8118,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;
   }
 
@@ -8210,9 +8141,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);
@@ -8230,7 +8158,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
@@ -8243,7 +8171,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
@@ -8257,8 +8185,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);
@@ -8279,7 +8207,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);
@@ -8360,7 +8288,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,
@@ -8370,16 +8298,16 @@ set_wm_state (Lisp_Object frame, int add, Atom atom, Atom value)
                        (make_number (add ? 1 : 0),
                         Fcons
                         (make_fixnum_or_float (atom),
-                         value != 0
-                         ? Fcons (make_fixnum_or_float (value), Qnil)
-                         : Qnil)));
+                         (value != 0
+                         ? list1 (make_fixnum_or_float (value))
+                         : Qnil))));
 }
 
 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);
 
@@ -8402,7 +8330,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;
@@ -8466,7 +8394,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;
 
@@ -8533,7 +8461,7 @@ do_ewmh_fullscreen (struct frame *f)
 }
 
 static void
-XTfullscreen_hook (FRAME_PTR f)
+XTfullscreen_hook (struct frame *f)
 {
   if (FRAME_VISIBLE_P (f))
     {
@@ -8546,7 +8474,7 @@ XTfullscreen_hook (FRAME_PTR 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;
@@ -8584,7 +8512,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
@@ -8594,7 +8522,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)
         {
@@ -8641,7 +8569,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;
 
@@ -8659,7 +8587,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;
 }
 
 
@@ -8711,19 +8639,18 @@ x_wait_for_event (struct frame *f, int eventtype)
 {
   int level = interrupt_input_blocked;
 
-  SELECT_TYPE fds;
-  EMACS_TIME tmo, tmo_at, time_now;
+  fd_set fds;
+  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_emacs_time (0, 100 * 1000 * 1000);
-  tmo_at = add_emacs_time (current_emacs_time (), tmo);
+  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 ();
@@ -8734,16 +8661,16 @@ x_wait_for_event (struct frame *f, int eventtype)
       FD_ZERO (&fds);
       FD_SET (fd, &fds);
 
-      time_now = current_emacs_time ();
-      if (EMACS_TIME_LT (tmo_at, time_now))
+      time_now = current_timespec ();
+      if (timespec_cmp (tmo_at, time_now) < 0)
        break;
 
-      tmo = sub_emacs_time (tmo_at, time_now);
+      tmo = timespec_sub (tmo_at, time_now);
       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;
 }
 
 
@@ -8934,7 +8861,7 @@ x_lower_frame (struct frame *f)
 /* Request focus with XEmbed */
 
 void
-xembed_request_focus (FRAME_PTR f)
+xembed_request_focus (struct frame *f)
 {
   /* See XEmbed Protocol Specification at
      http://freedesktop.org/wiki/Specifications/xembed-spec  */
@@ -8946,25 +8873,26 @@ xembed_request_focus (FRAME_PTR f)
 /* Activate frame with Extended Window Manager Hints */
 
 void
-x_ewmh_activate_frame (FRAME_PTR f)
+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));
     }
 }
 
 static void
-XTframe_raise_lower (FRAME_PTR f, int raise_flag)
+XTframe_raise_lower (struct frame *f, int raise_flag)
 {
   if (raise_flag)
     x_raise_frame (f);
@@ -8984,7 +8912,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;
@@ -9003,7 +8931,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;
@@ -9028,7 +8956,6 @@ 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;
 
@@ -9036,9 +8963,7 @@ x_make_frame_visible (struct frame *f)
 
   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))
     {
@@ -9193,8 +9118,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 ();
 
@@ -9245,20 +9170,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))
@@ -9324,7 +9246,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;
 
@@ -9363,7 +9285,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;
@@ -9448,6 +9370,19 @@ x_free_frame_resources (struct frame *f)
        unload_color (f, f->output_data.x->black_relief.pixel);
 
       x_free_gcs (f);
+
+      /* Free extra GCs allocated by x_setup_relief_colors.  */
+      if (f->output_data.x->white_relief.gc)
+       {
+         XFreeGC (dpyinfo->display, f->output_data.x->white_relief.gc);
+         f->output_data.x->white_relief.gc = 0;
+       }
+      if (f->output_data.x->black_relief.gc)
+       {
+         XFreeGC (dpyinfo->display, f->output_data.x->black_relief.gc);
+         f->output_data.x->black_relief.gc = 0;
+       }
+
       XFlush (FRAME_X_DISPLAY (f));
     }
 
@@ -9461,16 +9396,8 @@ x_free_frame_resources (struct frame *f)
     dpyinfo->x_focus_event_frame = 0;
   if (f == dpyinfo->x_highlight_frame)
     dpyinfo->x_highlight_frame = 0;
-
   if (f == hlinfo->mouse_face_mouse_frame)
-    {
-      hlinfo->mouse_face_beg_row
-       = hlinfo->mouse_face_beg_col = -1;
-      hlinfo->mouse_face_end_row
-       = hlinfo->mouse_face_end_col = -1;
-      hlinfo->mouse_face_window = Qnil;
-      hlinfo->mouse_face_mouse_frame = 0;
-    }
+    reset_mouse_highlight (hlinfo);
 
   unblock_input ();
 }
@@ -9481,7 +9408,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.  */
@@ -9527,9 +9454,9 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
 
   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.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.  */
@@ -9813,18 +9740,11 @@ get_bits_and_offset (long unsigned int mask, int *bits, int *offset)
 /* Return 1 if display DISPLAY is available for use, 0 otherwise.
    But don't permanently open it, just test its availability.  */
 
-int
+bool
 x_display_ok (const char *display)
 {
-    int dpy_ok = 1;
-    Display *dpy;
-
-    dpy = XOpenDisplay (display);
-    if (dpy)
-      XCloseDisplay (dpy);
-    else
-      dpy_ok = 0;
-    return dpy_ok;
+  Display *dpy = XOpenDisplay (display);
+  return dpy ? (XCloseDisplay (dpy), 1) : 0;
 }
 
 #ifdef USE_GTK
@@ -9849,7 +9769,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
   struct terminal *terminal;
   struct x_display_info *dpyinfo;
   XrmDatabase xrdb;
-  Mouse_HLInfo *hlinfo;
   ptrdiff_t lim;
 
   block_input ();
@@ -9897,13 +9816,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
 
         XSetLocaleModifiers ("");
 
-       /* If D-Bus is not already configured, inhibit D-Bus autolaunch,
-          as autolaunch can mess up Emacs's SIGCHLD handler.
-          FIXME: Rewrite subprocess handlers to use glib's child watchers.
-          See Bug#14474.  */
-       if (! egetenv ("DBUS_SESSION_BUS_ADDRESS"))
-         xputenv ("DBUS_SESSION_BUS_ADDRESS=unix:path=/dev/null");
-
         /* Emacs can only handle core input events, so make sure
            Gtk doesn't use Xinput or Xinput2 extensions.  */
        xputenv ("GDK_CORE_DEVICE_EVENTS=1");
@@ -9997,8 +9909,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
   /* We have definitely succeeded.  Record the new connection.  */
 
   dpyinfo = xzalloc (sizeof *dpyinfo);
-  hlinfo = &dpyinfo->mouse_highlight;
-
   terminal = x_create_terminal (dpyinfo);
 
   {
@@ -10069,9 +9979,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
   dpyinfo->display = dpy;
 
   /* Set the name of the terminal. */
-  terminal->name = xmalloc (SBYTES (display_name) + 1);
-  memcpy (terminal->name, SSDATA (display_name), SBYTES (display_name));
-  terminal->name[SBYTES (display_name)] = 0;
+  terminal->name = xlispstrdup (display_name);
 
 #if 0
   XSetAfterFunction (x_current_display, x_trace_wire);
@@ -10113,33 +10021,12 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
   select_visual (dpyinfo);
   dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
   dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
-  dpyinfo->client_leader_window = 0;
-  dpyinfo->grabbed = 0;
-  dpyinfo->reference_count = 0;
   dpyinfo->icon_bitmap_id = -1;
-  dpyinfo->n_fonts = 0;
-  dpyinfo->bitmaps = 0;
-  dpyinfo->bitmaps_size = 0;
-  dpyinfo->bitmaps_last = 0;
-  dpyinfo->scratch_cursor_gc = 0;
-  hlinfo->mouse_face_mouse_frame = 0;
-  hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
-  hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
-  hlinfo->mouse_face_face_id = DEFAULT_FACE_ID;
-  hlinfo->mouse_face_window = Qnil;
-  hlinfo->mouse_face_overlay = Qnil;
-  hlinfo->mouse_face_mouse_x = hlinfo->mouse_face_mouse_y = 0;
-  hlinfo->mouse_face_defer = 0;
-  hlinfo->mouse_face_hidden = 0;
-  dpyinfo->x_focus_frame = 0;
-  dpyinfo->x_focus_event_frame = 0;
-  dpyinfo->x_highlight_frame = 0;
   dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
 
-  /* See if we can construct pixel values from RGB values.  */
-  dpyinfo->red_bits = dpyinfo->blue_bits = dpyinfo->green_bits = 0;
-  dpyinfo->red_offset = dpyinfo->blue_offset = dpyinfo->green_offset = 0;
+  reset_mouse_highlight (&dpyinfo->mouse_highlight);
 
+  /* See if we can construct pixel values from RGB values.  */
   if (dpyinfo->visual->class == TrueColor)
     {
       get_bits_and_offset (dpyinfo->visual->red_mask,
@@ -10199,71 +10086,73 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
     }
 
   {
-    const struct
+    static const struct
     {
       const char *name;
-      Atom *atom;
+      int offset;
     } atom_refs[] = {
-      { "WM_PROTOCOLS", &dpyinfo->Xatom_wm_protocols  },
-      { "WM_TAKE_FOCUS", &dpyinfo->Xatom_wm_take_focus },
-      { "WM_SAVE_YOURSELF", &dpyinfo->Xatom_wm_save_yourself },
-      { "WM_DELETE_WINDOW", &dpyinfo->Xatom_wm_delete_window },
-      { "WM_CHANGE_STATE", &dpyinfo->Xatom_wm_change_state },
-      { "WM_CONFIGURE_DENIED", &dpyinfo->Xatom_wm_configure_denied },
-      { "WM_MOVED", &dpyinfo->Xatom_wm_window_moved },
-      { "WM_CLIENT_LEADER", &dpyinfo->Xatom_wm_client_leader },
-      { "Editres", &dpyinfo->Xatom_editres },
-      { "CLIPBOARD", &dpyinfo->Xatom_CLIPBOARD },
-      { "TIMESTAMP", &dpyinfo->Xatom_TIMESTAMP },
-      { "TEXT", &dpyinfo->Xatom_TEXT },
-      { "COMPOUND_TEXT", &dpyinfo->Xatom_COMPOUND_TEXT },
-      { "UTF8_STRING", &dpyinfo->Xatom_UTF8_STRING },
-      { "DELETE", &dpyinfo->Xatom_DELETE },
-      { "MULTIPLE", &dpyinfo->Xatom_MULTIPLE },
-      { "INCR", &dpyinfo->Xatom_INCR },
-      { "_EMACS_TMP_",  &dpyinfo->Xatom_EMACS_TMP },
-      { "TARGETS", &dpyinfo->Xatom_TARGETS },
-      { "NULL", &dpyinfo->Xatom_NULL },
-      { "ATOM", &dpyinfo->Xatom_ATOM },
-      { "ATOM_PAIR", &dpyinfo->Xatom_ATOM_PAIR },
-      { "CLIPBOARD_MANAGER", &dpyinfo->Xatom_CLIPBOARD_MANAGER },
-      { "_XEMBED_INFO", &dpyinfo->Xatom_XEMBED_INFO },
+#define ATOM_REFS_INIT(string, member) \
+      { string, offsetof (struct x_display_info, member) },
+      ATOM_REFS_INIT ("WM_PROTOCOLS", Xatom_wm_protocols)
+      ATOM_REFS_INIT ("WM_TAKE_FOCUS", Xatom_wm_take_focus)
+      ATOM_REFS_INIT ("WM_SAVE_YOURSELF", Xatom_wm_save_yourself)
+      ATOM_REFS_INIT ("WM_DELETE_WINDOW", Xatom_wm_delete_window)
+      ATOM_REFS_INIT ("WM_CHANGE_STATE", Xatom_wm_change_state)
+      ATOM_REFS_INIT ("WM_CONFIGURE_DENIED", Xatom_wm_configure_denied)
+      ATOM_REFS_INIT ("WM_MOVED", Xatom_wm_window_moved)
+      ATOM_REFS_INIT ("WM_CLIENT_LEADER", Xatom_wm_client_leader)
+      ATOM_REFS_INIT ("Editres", Xatom_editres)
+      ATOM_REFS_INIT ("CLIPBOARD", Xatom_CLIPBOARD)
+      ATOM_REFS_INIT ("TIMESTAMP", Xatom_TIMESTAMP)
+      ATOM_REFS_INIT ("TEXT", Xatom_TEXT)
+      ATOM_REFS_INIT ("COMPOUND_TEXT", Xatom_COMPOUND_TEXT)
+      ATOM_REFS_INIT ("UTF8_STRING", Xatom_UTF8_STRING)
+      ATOM_REFS_INIT ("DELETE", Xatom_DELETE)
+      ATOM_REFS_INIT ("MULTIPLE", Xatom_MULTIPLE)
+      ATOM_REFS_INIT ("INCR", Xatom_INCR)
+      ATOM_REFS_INIT ("_EMACS_TMP_",  Xatom_EMACS_TMP)
+      ATOM_REFS_INIT ("TARGETS", Xatom_TARGETS)
+      ATOM_REFS_INIT ("NULL", Xatom_NULL)
+      ATOM_REFS_INIT ("ATOM", Xatom_ATOM)
+      ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR)
+      ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER)
+      ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO)
       /* For properties of font.  */
-      { "PIXEL_SIZE", &dpyinfo->Xatom_PIXEL_SIZE },
-      { "AVERAGE_WIDTH", &dpyinfo->Xatom_AVERAGE_WIDTH },
-      { "_MULE_BASELINE_OFFSET", &dpyinfo->Xatom_MULE_BASELINE_OFFSET },
-      { "_MULE_RELATIVE_COMPOSE", &dpyinfo->Xatom_MULE_RELATIVE_COMPOSE },
-      { "_MULE_DEFAULT_ASCENT", &dpyinfo->Xatom_MULE_DEFAULT_ASCENT },
+      ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE)
+      ATOM_REFS_INIT ("AVERAGE_WIDTH", Xatom_AVERAGE_WIDTH)
+      ATOM_REFS_INIT ("_MULE_BASELINE_OFFSET", Xatom_MULE_BASELINE_OFFSET)
+      ATOM_REFS_INIT ("_MULE_RELATIVE_COMPOSE", Xatom_MULE_RELATIVE_COMPOSE)
+      ATOM_REFS_INIT ("_MULE_DEFAULT_ASCENT", Xatom_MULE_DEFAULT_ASCENT)
       /* Ghostscript support.  */
-      { "DONE", &dpyinfo->Xatom_DONE },
-      { "PAGE", &dpyinfo->Xatom_PAGE },
-      { "SCROLLBAR", &dpyinfo->Xatom_Scrollbar },
-      { "_XEMBED", &dpyinfo->Xatom_XEMBED },
+      ATOM_REFS_INIT ("DONE", Xatom_DONE)
+      ATOM_REFS_INIT ("PAGE", Xatom_PAGE)
+      ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar)
+      ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED)
       /* EWMH */
-      { "_NET_WM_STATE", &dpyinfo->Xatom_net_wm_state },
-      { "_NET_WM_STATE_FULLSCREEN", &dpyinfo->Xatom_net_wm_state_fullscreen },
-      "_NET_WM_STATE_MAXIMIZED_HORZ",
-        &dpyinfo->Xatom_net_wm_state_maximized_horz },
-      "_NET_WM_STATE_MAXIMIZED_VERT",
-        &dpyinfo->Xatom_net_wm_state_maximized_vert },
-      { "_NET_WM_STATE_STICKY", &dpyinfo->Xatom_net_wm_state_sticky },
-      { "_NET_WM_STATE_HIDDEN", &dpyinfo->Xatom_net_wm_state_hidden },
-      { "_NET_WM_WINDOW_TYPE", &dpyinfo->Xatom_net_window_type },
-      "_NET_WM_WINDOW_TYPE_TOOLTIP",
-        &dpyinfo->Xatom_net_window_type_tooltip },
-      { "_NET_WM_ICON_NAME", &dpyinfo->Xatom_net_wm_icon_name },
-      { "_NET_WM_NAME", &dpyinfo->Xatom_net_wm_name },
-      { "_NET_SUPPORTED",  &dpyinfo->Xatom_net_supported },
-      { "_NET_SUPPORTING_WM_CHECK", &dpyinfo->Xatom_net_supporting_wm_check },
-      { "_NET_WM_WINDOW_OPACITY", &dpyinfo->Xatom_net_wm_window_opacity },
-      { "_NET_ACTIVE_WINDOW", &dpyinfo->Xatom_net_active_window },
-      { "_NET_FRAME_EXTENTS", &dpyinfo->Xatom_net_frame_extents },
-      { "_NET_CURRENT_DESKTOP", &dpyinfo->Xatom_net_current_desktop },
-      { "_NET_WORKAREA", &dpyinfo->Xatom_net_workarea },
+      ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state)
+      ATOM_REFS_INIT ("_NET_WM_STATE_FULLSCREEN", Xatom_net_wm_state_fullscreen)
+      ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_HORZ",
+                     Xatom_net_wm_state_maximized_horz)
+      ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_VERT",
+                     Xatom_net_wm_state_maximized_vert)
+      ATOM_REFS_INIT ("_NET_WM_STATE_STICKY", Xatom_net_wm_state_sticky)
+      ATOM_REFS_INIT ("_NET_WM_STATE_HIDDEN", Xatom_net_wm_state_hidden)
+      ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE", Xatom_net_window_type)
+      ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE_TOOLTIP",
+                     Xatom_net_window_type_tooltip)
+      ATOM_REFS_INIT ("_NET_WM_ICON_NAME", Xatom_net_wm_icon_name)
+      ATOM_REFS_INIT ("_NET_WM_NAME", Xatom_net_wm_name)
+      ATOM_REFS_INIT ("_NET_SUPPORTED",  Xatom_net_supported)
+      ATOM_REFS_INIT ("_NET_SUPPORTING_WM_CHECK", Xatom_net_supporting_wm_check)
+      ATOM_REFS_INIT ("_NET_WM_WINDOW_OPACITY", Xatom_net_wm_window_opacity)
+      ATOM_REFS_INIT ("_NET_ACTIVE_WINDOW", Xatom_net_active_window)
+      ATOM_REFS_INIT ("_NET_FRAME_EXTENTS", Xatom_net_frame_extents)
+      ATOM_REFS_INIT ("_NET_CURRENT_DESKTOP", Xatom_net_current_desktop)
+      ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea)
       /* Session management */
-      { "SM_CLIENT_ID", &dpyinfo->Xatom_SM_CLIENT_ID },
-      { "_XSETTINGS_SETTINGS", &dpyinfo->Xatom_xsettings_prop },
-      { "MANAGER", &dpyinfo->Xatom_xsettings_mgr },
+      ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID)
+      ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop)
+      ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr)
     };
 
     int i;
@@ -10288,7 +10177,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
                   False, atoms_return);
 
     for (i = 0; i < atom_count; i++)
-      *atom_refs[i].atom = atoms_return[i];
+      *(Atom *) ((char *) dpyinfo + atom_refs[i].offset) = atoms_return[i];
 
     /* Manual copy of last atom */
     dpyinfo->Xatom_xsettings_sel = atoms_return[i];
@@ -10298,16 +10187,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
   }
 
   dpyinfo->x_dnd_atoms_size = 8;
-  dpyinfo->x_dnd_atoms_length = 0;
   dpyinfo->x_dnd_atoms = xmalloc (sizeof *dpyinfo->x_dnd_atoms
                                   * dpyinfo->x_dnd_atoms_size);
-
-  dpyinfo->net_supported_atoms = NULL;
-  dpyinfo->nr_net_supported_atoms = 0;
-  dpyinfo->net_supported_window = 0;
-
-  connection = ConnectionNumber (dpyinfo->display);
-  dpyinfo->connection = connection;
   dpyinfo->gray
     = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
                                   gray_bits, gray_width, gray_height,
@@ -10319,6 +10200,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);
@@ -10419,8 +10302,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)
@@ -10498,7 +10379,7 @@ x_activate_timeout_atimer (void)
   block_input ();
   if (!x_timeout_atimer_activated_flag)
     {
-      EMACS_TIME interval = make_emacs_time (0, 100 * 1000 * 1000);
+      struct timespec interval = make_timespec (0, 100 * 1000 * 1000);
       start_atimer (ATIMER_RELATIVE, interval, x_process_timeouts, 0);
       x_timeout_atimer_activated_flag = 1;
     }
@@ -10521,13 +10402,7 @@ static struct redisplay_interface x_redisplay_interface =
     x_after_update_window_line,
     x_update_window_begin,
     x_update_window_end,
-    x_cursor_to,
     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,
@@ -10549,6 +10424,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.  */
@@ -10567,6 +10443,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);
 
@@ -10607,6 +10485,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);
@@ -10634,11 +10516,11 @@ x_create_terminal (struct x_display_info *dpyinfo)
   terminal->delete_glyphs_hook = x_delete_glyphs;
   terminal->ring_bell_hook = XTring_bell;
   terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer;
-  terminal->reset_terminal_modes_hook = XTreset_terminal_modes;
-  terminal->set_terminal_modes_hook = XTset_terminal_modes;
+  terminal->reset_terminal_modes_hook = NULL;
+  terminal->set_terminal_modes_hook = NULL;
   terminal->update_begin_hook = x_update_begin;
   terminal->update_end_hook = x_update_end;
-  terminal->set_terminal_window_hook = XTset_terminal_window;
+  terminal->set_terminal_window_hook = NULL;
   terminal->read_socket_hook = XTread_socket;
   terminal->frame_up_to_date_hook = XTframe_up_to_date;
   terminal->mouse_position_hook = XTmouse_position;
@@ -10704,10 +10586,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);
@@ -10723,15 +10601,9 @@ syms_of_xterm (void)
   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");
 
-  staticpro (&last_mouse_press_frame);
-  last_mouse_press_frame = Qnil;
-
 #ifdef USE_GTK
   xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
   staticpro (&xg_default_icon_file);
@@ -10787,9 +10659,6 @@ 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");
   Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
@@ -10835,5 +10704,3 @@ default is nil, which is the same as `super'.  */);
                                     make_float (DEFAULT_REHASH_THRESHOLD),
                                     Qnil);
 }
-
-#endif /* HAVE_X_WINDOWS */