(Ffile_name_completion): Make argument name match its use in docstring.
[bpt/emacs.git] / src / xterm.c
index 0992e1f..fcc4c67 100644 (file)
@@ -1,6 +1,6 @@
 /* X Communication module for terminals which understand the X protocol.
-   Copyright (C) 1989, 93, 94, 95, 96, 97, 98, 1999, 2000, 01, 02, 2003
-   Free Software Foundation, Inc.
+   Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+     2002, 2003, 2004, 2005  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -130,8 +130,7 @@ extern void _XEditResCheckMessages ();
 #ifdef HAVE_XAW3D
 #include <X11/Xaw3d/Simple.h>
 #include <X11/Xaw3d/Scrollbar.h>
-#define ARROW_SCROLLBAR
-#include <X11/Xaw3d/ScrollbarP.h>
+#include <X11/Xaw3d/ThreeD.h>
 #else /* !HAVE_XAW3D */
 #include <X11/Xaw/Simple.h>
 #include <X11/Xaw/Scrollbar.h>
@@ -158,6 +157,13 @@ extern void _XEditResCheckMessages ();
 
 #define abs(x) ((x) < 0 ? -(x) : (x))
 
+/* Default to using XIM if available.  */
+#ifdef USE_XIM
+int use_xim = 1;
+#else
+int use_xim = 0;  /* configure --without-xim */
+#endif
+
 \f
 
 /* Non-nil means Emacs uses toolkit scroll bars.  */
@@ -209,6 +215,17 @@ static String Xt_default_resources[] = {0};
 
 static int toolkit_scroll_bar_interaction;
 
+/* Non-zero means to not move point as a result of clicking on a
+   frame to focus it (when focus-follows-mouse is nil).  */
+
+int x_mouse_click_focus_ignore_position;
+
+/* 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)
@@ -279,7 +296,7 @@ extern Lisp_Object Vcommand_line_args, Vsystem_name;
 
 extern Lisp_Object Vx_no_window_manager;
 
-extern Lisp_Object Qface, Qmouse_face, Qeql;
+extern Lisp_Object Qeql;
 
 extern int errno;
 
@@ -294,10 +311,10 @@ Lisp_Object Vx_keysym_table;
 static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
 
 static Lisp_Object Qvendor_specific_keysyms;
-static Lisp_Object Qlatin_1, Qutf_8;
+static Lisp_Object Qlatin_1;
 
 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
-
+extern int x_bitmap_mask P_ ((FRAME_PTR, int));
 
 static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
 static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
@@ -328,40 +345,30 @@ static void x_clear_frame P_ ((void));
 static void frame_highlight P_ ((struct frame *));
 static void frame_unhighlight P_ ((struct frame *));
 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
-static int  x_focus_changed P_ ((int,
-                                 int,
-                                 struct x_display_info *,
-                                 struct frame *,
-                                 struct input_event *,
-                                 int));
-static int  x_detect_focus_change P_ ((struct x_display_info *,
-                                       XEvent *,
-                                       struct input_event *,
-                                       int));
+static void  x_focus_changed P_ ((int, int, struct x_display_info *,
+                                 struct frame *, struct input_event *));
+static void x_detect_focus_change P_ ((struct x_display_info *,
+                                       XEvent *, struct input_event *));
 static void XTframe_rehighlight P_ ((struct frame *));
 static void x_frame_rehighlight P_ ((struct x_display_info *));
 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
                                   enum text_cursor_kinds));
 
-static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
-                              GC, int));
+static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
 static void x_flush P_ ((struct frame *f));
 static void x_update_begin P_ ((struct frame *));
 static void x_update_window_begin P_ ((struct window *));
 static void x_after_update_window_line P_ ((struct glyph_row *));
-static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
+static struct scroll_bar *x_window_to_scroll_bar P_ ((Display *, Window));
 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
                                            enum scroll_bar_part *,
                                            Lisp_Object *, Lisp_Object *,
                                            unsigned long *));
 static void x_check_fullscreen P_ ((struct frame *));
-static void x_check_fullscreen_move P_ ((struct frame *));
-static int handle_one_xevent P_ ((struct x_display_info *,
-                                  XEvent *,
-                                  struct input_event **,
-                                  int *,
-                                  int *));
+static void x_check_expected_move P_ ((struct frame *));
+static int handle_one_xevent P_ ((struct x_display_info *, XEvent *,
+                                 int *, struct input_event *));
 
 
 /* Flush display of frame F, or of all frames if F is null.  */
@@ -528,7 +535,7 @@ x_draw_vertical_window_border (w, x, y0, y1)
      int x, y0, y1;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  
+
   XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
             f->output_data.x->normal_gc, x, y0, x, y1);
 }
@@ -562,7 +569,9 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
                                output_cursor.vpos,
                                output_cursor.x, output_cursor.y);
 
-      x_draw_vertical_border (w);
+      if (draw_window_fringes (w, 1))
+       x_draw_vertical_border (w);
+
       UNBLOCK_INPUT;
     }
 
@@ -642,11 +651,7 @@ x_after_update_window_line (desired_row)
   xassert (w);
 
   if (!desired_row->mode_line_p && !w->pseudo_window_p)
-    {
-      BLOCK_INPUT;
-      draw_row_fringe_bitmaps (w, desired_row);
-      UNBLOCK_INPUT;
-    }
+    desired_row->redraw_fringe_bitmaps_p = 1;
 
   /* When a window has disappeared, make sure that no rest of
      full-width rows stays visible in the internal border.  Could
@@ -673,7 +678,7 @@ x_after_update_window_line (desired_row)
       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                    0, y, width, height, False);
       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                   f->output_data.x->pixel_width - width,
+                   FRAME_PIXEL_WIDTH (f) - width,
                    y, width, height, False);
       UNBLOCK_INPUT;
     }
@@ -690,11 +695,26 @@ x_draw_fringe_bitmap (w, row, p)
   Window window = FRAME_X_WINDOW (f);
   GC gc = f->output_data.x->normal_gc;
   struct face *face = p->face;
+  int rowY;
 
   /* Must clip because of partially visible lines.  */
-  x_clip_to_row (w, row, gc, 1);
+  rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+  if (p->y < rowY)
+    {
+      /* Adjust position of "bottom aligned" bitmap on partially
+        visible last row.  */
+      int oldY = row->y;
+      int oldVH = row->visible_height;
+      row->visible_height = p->h;
+      row->y -= rowY - p->y;
+      x_clip_to_row (w, row, -1, gc);
+      row->y = oldY;
+      row->visible_height = oldVH;
+    }
+  else
+    x_clip_to_row (w, row, -1, gc);
 
-  if (p->bx >= 0)
+  if (p->bx >= 0 && !p->overlay_p)
     {
       /* In case the same realized face is used for fringes and
         for something displayed in the text (e.g. face `region' on
@@ -712,20 +732,49 @@ x_draw_fringe_bitmap (w, row, p)
        XSetForeground (display, face->gc, face->foreground);
     }
 
-  if (p->which != NO_FRINGE_BITMAP)
+  if (p->which)
     {
-      unsigned char *bits = fringe_bitmaps[p->which].bits + p->dh;
-      Pixmap pixmap;
+      unsigned char *bits;
+      Pixmap pixmap, clipmask = (Pixmap) 0;
       int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
+      XGCValues gcv;
+
+      if (p->wd > 8)
+       bits = (unsigned char *)(p->bits + p->dh);
+      else
+       bits = (unsigned char *)p->bits + p->dh;
 
       /* Draw the bitmap.  I believe these small pixmaps can be cached
         by the server.  */
       pixmap = XCreatePixmapFromBitmapData (display, window, bits, p->wd, p->h,
-                                           face->foreground,
+                                           (p->cursor_p
+                                            ? (p->overlay_p ? face->background
+                                               : f->output_data.x->cursor_pixel)
+                                            : face->foreground),
                                            face->background, depth);
+
+      if (p->overlay_p)
+       {
+         clipmask = XCreatePixmapFromBitmapData (display,
+                                                 FRAME_X_DISPLAY_INFO (f)->root_window,
+                                                 bits, p->wd, p->h,
+                                                 1, 0, 1);
+         gcv.clip_mask = clipmask;
+         gcv.clip_x_origin = p->x;
+         gcv.clip_y_origin = p->y;
+         XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
+       }
+
       XCopyArea (display, pixmap, window, gc, 0, 0,
                 p->wd, p->h, p->x, p->y);
       XFreePixmap (display, pixmap);
+
+      if (p->overlay_p)
+       {
+         gcv.clip_mask = (Pixmap) 0;
+         XChangeGC (display, gc, GCClipMask, &gcv);
+         XFreePixmap (display, clipmask);
+       }
     }
 
   XSetClipMask (display, gc, None);
@@ -929,7 +978,8 @@ static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
                                           int, int, int));
 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
-                                   int, int, int, int, XRectangle *));
+                                   int, int, int, int, int, int,
+                                   XRectangle *));
 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
                                 int, int, int, XRectangle *));
 
@@ -1967,9 +2017,10 @@ x_setup_relief_colors (s)
 
 static void
 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
-                   raised_p, left_p, right_p, clip_rect)
+                   raised_p, top_p, bot_p, left_p, right_p, clip_rect)
      struct frame *f;
-     int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p;
+     int left_x, top_y, right_x, bottom_y, width;
+     int top_p, bot_p, left_p, right_p, raised_p;
      XRectangle *clip_rect;
 {
   Display *dpy = FRAME_X_DISPLAY (f);
@@ -1984,10 +2035,11 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
   XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
 
   /* Top.  */
-  for (i = 0; i < width; ++i)
-    XDrawLine (dpy, window, gc,
-              left_x + i * left_p, top_y + i,
-              right_x + 1 - i * right_p, top_y + i);
+  if (top_p)
+    for (i = 0; i < width; ++i)
+      XDrawLine (dpy, window, gc,
+                left_x + i * left_p, top_y + i,
+                right_x + 1 - i * right_p, top_y + i);
 
   /* Left.  */
   if (left_p)
@@ -2003,10 +2055,11 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
   XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
 
   /* Bottom.  */
-  for (i = 0; i < width; ++i)
-    XDrawLine (dpy, window, gc,
-              left_x + i * left_p, bottom_y - i,
-              right_x + 1 - i * right_p, bottom_y - i);
+  if (bot_p)
+    for (i = 0; i < width; ++i)
+      XDrawLine (dpy, window, gc,
+                left_x + i * left_p, bottom_y - i,
+                right_x + 1 - i * right_p, bottom_y - i);
 
   /* Right.  */
   if (right_p)
@@ -2072,14 +2125,9 @@ x_draw_glyph_string_box (s)
   struct glyph *last_glyph;
   XRectangle clip_rect;
 
-  last_x = window_box_right (s->w, s->area);
-  if (s->row->full_width_p
-      && !s->w->pseudo_window_p)
-    {
-      last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
-      if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
-       last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
-    }
+  last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
+           ? WINDOW_RIGHT_EDGE_X (s->w)
+           : window_box_right (s->w, s->area));
 
   /* The glyph that may have a right box line.  */
   last_glyph = (s->cmp || s->img
@@ -2113,7 +2161,7 @@ x_draw_glyph_string_box (s)
     {
       x_setup_relief_colors (s);
       x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
-                         width, raised_p, left_p, right_p, &clip_rect);
+                         width, raised_p, 1, 1, left_p, right_p, &clip_rect);
     }
 }
 
@@ -2124,21 +2172,22 @@ static void
 x_draw_image_foreground (s)
      struct glyph_string *s;
 {
-  int x;
-  int y = s->ybase - image_ascent (s->img, s->face);
+  int x = s->x;
+  int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = s->x + abs (s->face->box_line_width);
-  else
-    x = s->x;
+      && s->first_glyph->left_box_line_p
+      && s->slice.x == 0)
+    x += abs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
+  if (s->slice.x == 0)
+    x += s->img->hmargin;
+  if (s->slice.y == 0)
+    y += s->img->vmargin;
 
   if (s->img->pixmap)
     {
@@ -2163,11 +2212,12 @@ x_draw_image_foreground (s)
          get_glyph_string_clip_rect (s, &clip_rect);
          image_rect.x = x;
          image_rect.y = y;
-         image_rect.width = s->img->width;
-         image_rect.height = s->img->height;
+         image_rect.width = s->slice.width;
+         image_rect.height = s->slice.height;
          if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
            XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
-                      r.x - x, r.y - y, r.width, r.height, r.x, r.y);
+                      s->slice.x + r.x - x, s->slice.y + r.y - y,
+                      r.width, r.height, r.x, r.y);
        }
       else
        {
@@ -2176,11 +2226,12 @@ x_draw_image_foreground (s)
          get_glyph_string_clip_rect (s, &clip_rect);
          image_rect.x = x;
          image_rect.y = y;
-         image_rect.width = s->img->width;
-         image_rect.height = s->img->height;
+         image_rect.width = s->slice.width;
+         image_rect.height = s->slice.height;
          if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
            XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
-                      r.x - x, r.y - y, r.width, r.height, r.x, r.y);
+                      s->slice.x + r.x - x, s->slice.y + r.y - y,
+                      r.width, r.height, r.x, r.y);
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -2192,15 +2243,17 @@ x_draw_image_foreground (s)
            {
              int r = s->img->relief;
              if (r < 0) r = -r;
-             XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
-                             s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+             XDrawRectangle (s->display, s->window, s->gc,
+                             x - r, y - r,
+                             s->slice.width + r*2 - 1,
+                             s->slice.height + r*2 - 1);
            }
        }
     }
   else
     /* Draw a rectangle if image could not be loaded.  */
     XDrawRectangle (s->display, s->window, s->gc, x, y,
-                   s->img->width - 1, s->img->height - 1);
+                   s->slice.width - 1, s->slice.height - 1);
 }
 
 
@@ -2212,21 +2265,22 @@ x_draw_image_relief (s)
 {
   int x0, y0, x1, y1, thick, raised_p;
   XRectangle r;
-  int x;
-  int y = s->ybase - image_ascent (s->img, s->face);
+  int x = s->x;
+  int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = s->x + abs (s->face->box_line_width);
-  else
-    x = s->x;
+      && s->first_glyph->left_box_line_p
+      && s->slice.x == 0)
+    x += abs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
+  if (s->slice.x == 0)
+    x += s->img->hmargin;
+  if (s->slice.y == 0)
+    y += s->img->vmargin;
 
   if (s->hl == DRAW_IMAGE_SUNKEN
       || s->hl == DRAW_IMAGE_RAISED)
@@ -2242,12 +2296,17 @@ x_draw_image_relief (s)
 
   x0 = x - thick;
   y0 = y - thick;
-  x1 = x + s->img->width + thick - 1;
-  y1 = y + s->img->height + thick - 1;
+  x1 = x + s->slice.width + thick - 1;
+  y1 = y + s->slice.height + thick - 1;
 
   x_setup_relief_colors (s);
   get_glyph_string_clip_rect (s, &r);
-  x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
+  x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
+                     s->slice.y == 0,
+                     s->slice.y + s->slice.height == s->img->height,
+                     s->slice.x == 0,
+                     s->slice.x + s->slice.width == s->img->width,
+                     &r);
 }
 
 
@@ -2258,21 +2317,22 @@ x_draw_image_foreground_1 (s, pixmap)
      struct glyph_string *s;
      Pixmap pixmap;
 {
-  int x;
-  int y = s->ybase - s->y - image_ascent (s->img, s->face);
+  int x = 0;
+  int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = abs (s->face->box_line_width);
-  else
-    x = 0;
+      && s->first_glyph->left_box_line_p
+      && s->slice.x == 0)
+    x += abs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
+  if (s->slice.x == 0)
+    x += s->img->hmargin;
+  if (s->slice.y == 0)
+    y += s->img->vmargin;
 
   if (s->img->pixmap)
     {
@@ -2288,19 +2348,21 @@ x_draw_image_foreground_1 (s, pixmap)
          XGCValues xgcv;
 
          xgcv.clip_mask = s->img->mask;
-         xgcv.clip_x_origin = x;
-         xgcv.clip_y_origin = y;
+         xgcv.clip_x_origin = x - s->slice.x;
+         xgcv.clip_y_origin = y - s->slice.y;
          xgcv.function = GXcopy;
          XChangeGC (s->display, s->gc, mask, &xgcv);
 
          XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
-                    0, 0, s->img->width, s->img->height, x, y);
+                    s->slice.x, s->slice.y,
+                    s->slice.width, s->slice.height, x, y);
          XSetClipMask (s->display, s->gc, None);
        }
       else
        {
          XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
-                    0, 0, s->img->width, s->img->height, x, y);
+                    s->slice.x, s->slice.y,
+                    s->slice.width, s->slice.height, x, y);
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -2313,14 +2375,15 @@ x_draw_image_foreground_1 (s, pixmap)
              int r = s->img->relief;
              if (r < 0) r = -r;
              XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
-                             s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+                             s->slice.width + r*2 - 1,
+                             s->slice.height + r*2 - 1);
            }
        }
     }
   else
     /* Draw a rectangle if image could not be loaded.  */
     XDrawRectangle (s->display, pixmap, s->gc, x, y,
-                   s->img->width - 1, s->img->height - 1);
+                   s->slice.width - 1, s->slice.height - 1);
 }
 
 
@@ -2362,33 +2425,28 @@ static void
 x_draw_image_glyph_string (s)
      struct glyph_string *s;
 {
-  int x, y;
   int box_line_hwidth = abs (s->face->box_line_width);
   int box_line_vwidth = max (s->face->box_line_width, 0);
   int height;
   Pixmap pixmap = None;
 
-  height = s->height - 2 * box_line_vwidth;
-
+  height = s->height;
+  if (s->slice.y == 0)
+    height -= box_line_vwidth;
+  if (s->slice.y + s->slice.height >= s->img->height)
+    height -= box_line_vwidth;
 
   /* Fill background with face under the image.  Do it only if row is
      taller than image or if image has a clip mask to reduce
      flickering.  */
   s->stippled_p = s->face->stipple != 0;
-  if (height > s->img->height
+  if (height > s->slice.height
       || s->img->hmargin
       || s->img->vmargin
       || s->img->mask
       || s->img->pixmap == 0
       || s->width != s->background_width)
     {
-      if (box_line_hwidth && s->first_glyph->left_box_line_p)
-       x = s->x + box_line_hwidth;
-      else
-       x = s->x;
-
-      y = s->y + box_line_vwidth;
-
       if (s->img->mask)
        {
          /* Create a pixmap as large as the glyph string.  Fill it
@@ -2427,7 +2485,19 @@ x_draw_image_glyph_string (s)
            }
        }
       else
-       x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
+       {
+         int x = s->x;
+         int y = s->y;
+
+         if (s->first_glyph->left_box_line_p
+             && s->slice.x == 0)
+           x += box_line_hwidth;
+
+         if (s->slice.y == 0)
+           y += box_line_vwidth;
+
+         x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
+       }
 
       s->background_filled_p = 1;
     }
@@ -2466,7 +2536,7 @@ x_draw_stretch_glyph_string (s)
     {
       /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
         as wide as the stretch glyph.  */
-      int width = min (CANON_X_UNIT (s->f), s->background_width);
+      int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
 
       /* Draw cursor.  */
       x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
@@ -2745,10 +2815,6 @@ x_clear_frame ()
 
   XFlush (FRAME_X_DISPLAY (f));
 
-#ifdef USE_GTK
-  xg_frame_cleared (f);
-#endif
-
   UNBLOCK_INPUT;
 }
 
@@ -2819,12 +2885,12 @@ XTflash (f)
 
     {
       /* Get the height not including a menu bar widget.  */
-      int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
+      int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
       /* Height of each line to flash.  */
       int flash_height = FRAME_LINE_HEIGHT (f);
       /* These will be the left and right margins of the rectangles.  */
       int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
-      int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
+      int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
 
       int width;
 
@@ -2852,7 +2918,7 @@ XTflash (f)
          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
                          flash_left,
                          (FRAME_INTERNAL_BORDER_WIDTH (f)
-                          + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
+                          + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
                          width, flash_height);
          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
                          flash_left,
@@ -2906,7 +2972,7 @@ XTflash (f)
          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
                          flash_left,
                          (FRAME_INTERNAL_BORDER_WIDTH (f)
-                          + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
+                          + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
                          width, flash_height);
          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
                          flash_left,
@@ -2998,8 +3064,6 @@ x_scroll_run (w, run)
      without mode lines.  Include in this box the left and right
      fringe of W.  */
   window_box (w, -1, &x, &y, &width, &height);
-  width += FRAME_X_FRINGE_WIDTH (f);
-  x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
 
   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
@@ -3118,20 +3182,16 @@ x_new_focus_frame (dpyinfo, frame)
 
 /* Handle FocusIn and FocusOut state changes for FRAME.
    If FRAME has focus and there exists more than one frame, puts
-   a FOCUS_IN_EVENT into BUFP.
-   Returns number of events inserted into BUFP. */
+   a FOCUS_IN_EVENT into *BUFP.  */
 
-static int
-x_focus_changed (type, state, dpyinfo, frame, bufp, numchars)
+static void
+x_focus_changed (type, state, dpyinfo, frame, bufp)
      int type;
      int state;
      struct x_display_info *dpyinfo;
      struct frame *frame;
      struct input_event *bufp;
-     int numchars;
 {
-  int nr_events = 0;
-
   if (type == FocusIn)
     {
       if (dpyinfo->x_focus_event_frame != frame)
@@ -3141,17 +3201,12 @@ x_focus_changed (type, state, dpyinfo, frame, bufp, numchars)
 
           /* Don't stop displaying the initial startup message
              for a switch-frame event we don't need.  */
-          if (numchars > 0
-              && GC_NILP (Vterminal_frame)
+          if (GC_NILP (Vterminal_frame)
               && GC_CONSP (Vframe_list)
               && !GC_NILP (XCDR (Vframe_list)))
             {
               bufp->kind = FOCUS_IN_EVENT;
               XSETFRAME (bufp->frame_or_window, frame);
-              bufp->arg = Qnil;
-              ++bufp;
-              numchars--;
-              ++nr_events;
             }
         }
 
@@ -3177,57 +3232,51 @@ x_focus_changed (type, state, dpyinfo, frame, bufp, numchars)
         XUnsetICFocus (FRAME_XIC (frame));
 #endif
     }
-
-  return nr_events;
 }
 
 /* The focus may have changed.  Figure out if it is a real focus change,
    by checking both FocusIn/Out and Enter/LeaveNotify events.
 
-   Returns number of events inserted into BUFP. */
+   Returns FOCUS_IN_EVENT event in *BUFP. */
 
-static int
-x_detect_focus_change (dpyinfo, event, bufp, numchars)
+static void
+x_detect_focus_change (dpyinfo, event, bufp)
      struct x_display_info *dpyinfo;
      XEvent *event;
      struct input_event *bufp;
-     int numchars;
 {
   struct frame *frame;
-  int nr_events = 0;
 
   frame = x_any_window_to_frame (dpyinfo, event->xany.window);
-  if (! frame) return nr_events;
+  if (! frame)
+    return;
 
   switch (event->type)
     {
     case EnterNotify:
     case LeaveNotify:
-      if (event->xcrossing.detail != NotifyInferior
-          && event->xcrossing.focus
-          && ! (frame->output_data.x->focus_state & FOCUS_EXPLICIT))
-        nr_events = x_focus_changed ((event->type == EnterNotify
-                                      ? FocusIn : FocusOut),
-                                     FOCUS_IMPLICIT,
-                                     dpyinfo,
-                                     frame,
-                                     bufp,
-                                     numchars);
+      {
+        struct frame *focus_frame = dpyinfo->x_focus_event_frame;
+        int focus_state
+          = focus_frame ? focus_frame->output_data.x->focus_state : 0;
+
+        if (event->xcrossing.detail != NotifyInferior
+            && event->xcrossing.focus
+            && ! (focus_state & FOCUS_EXPLICIT))
+          x_focus_changed ((event->type == EnterNotify ? FocusIn : FocusOut),
+                          FOCUS_IMPLICIT,
+                          dpyinfo, frame, bufp);
+      }
       break;
 
     case FocusIn:
     case FocusOut:
-      nr_events = x_focus_changed (event->type,
-                                   (event->xfocus.detail == NotifyPointer
-                                    ? FOCUS_IMPLICIT : FOCUS_EXPLICIT),
-                                   dpyinfo,
-                                   frame,
-                                   bufp,
-                                   numchars);
+      x_focus_changed (event->type,
+                      (event->xfocus.detail == NotifyPointer ?
+                       FOCUS_IMPLICIT : FOCUS_EXPLICIT),
+                      dpyinfo, frame, bufp);
       break;
     }
-
-  return nr_events;
 }
 
 
@@ -3321,12 +3370,14 @@ x_find_modifier_meanings (dpyinfo)
      Alt keysyms are on.  */
   {
     int row, col;      /* The row and column in the modifier table.  */
+    int found_alt_or_meta;
 
     for (row = 3; row < 8; row++)
+    {
+      found_alt_or_meta = 0;
       for (col = 0; col < mods->max_keypermod; col++)
        {
-         KeyCode code
-           = mods->modifiermap[(row * mods->max_keypermod) + col];
+         KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
 
          /* Zeroes are used for filler.  Skip them.  */
          if (code == 0)
@@ -3344,33 +3395,44 @@ x_find_modifier_meanings (dpyinfo)
                  {
                  case XK_Meta_L:
                  case XK_Meta_R:
+                   found_alt_or_meta = 1;
                    dpyinfo->meta_mod_mask |= (1 << row);
                    break;
 
                  case XK_Alt_L:
                  case XK_Alt_R:
+                   found_alt_or_meta = 1;
                    dpyinfo->alt_mod_mask |= (1 << row);
                    break;
 
                  case XK_Hyper_L:
                  case XK_Hyper_R:
-                   dpyinfo->hyper_mod_mask |= (1 << row);
+                   if (!found_alt_or_meta)
+                     dpyinfo->hyper_mod_mask |= (1 << row);
+                   code_col = syms_per_code;
+                   col = mods->max_keypermod;
                    break;
 
                  case XK_Super_L:
                  case XK_Super_R:
-                   dpyinfo->super_mod_mask |= (1 << row);
+                   if (!found_alt_or_meta)
+                     dpyinfo->super_mod_mask |= (1 << row);
+                   code_col = syms_per_code;
+                   col = mods->max_keypermod;
                    break;
 
                  case XK_Shift_Lock:
                    /* Ignore this if it's not on the lock modifier.  */
-                   if ((1 << row) == LockMask)
+                   if (!found_alt_or_meta && ((1 << row) == LockMask))
                      dpyinfo->shift_lock_mask = LockMask;
+                   code_col = syms_per_code;
+                   col = mods->max_keypermod;
                    break;
                  }
              }
          }
        }
+    }
   }
 
   /* If we couldn't find any meta keys, accept any alt keys as meta keys.  */
@@ -3572,37 +3634,39 @@ glyph_rect (f, x, y, rect)
      XRectangle *rect;
 {
   Lisp_Object window;
-  int found = 0;
-
-  window = window_from_coordinates (f, x, y, 0, 0);
-  if (!NILP (window))
-    {
-      struct window *w = XWINDOW (window);
-      struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-      struct glyph_row *end = r + w->current_matrix->nrows - 1;
+  struct window *w;
+  struct glyph_row *r, *end_row;
 
-      frame_to_window_pixel_xy (w, &x, &y);
+  window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
+  if (NILP (window))
+    return 0;
 
-      for (; !found && r < end && r->enabled_p; ++r)
-       if (r->y >= y)
-         {
-           struct glyph *g = r->glyphs[TEXT_AREA];
-           struct glyph *end = g + r->used[TEXT_AREA];
-           int gx;
+  w = XWINDOW (window);
+  r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  end_row = r + w->current_matrix->nrows - 1;
 
-           for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
-             if (gx >= x)
-               {
-                 rect->width = g->pixel_width;
-                 rect->height = r->height;
-                 rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
-                 rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
-                 found = 1;
-               }
-         }
+  for (; r < end_row && r->enabled_p; ++r)
+    {
+      if (r->y >= y)
+       {
+         struct glyph *g = r->glyphs[TEXT_AREA];
+         struct glyph *end = g + r->used[TEXT_AREA];
+         int gx = r->x;
+         while (g < end && gx < x)
+           gx += g->pixel_width, ++g;
+         if (g < end)
+           {
+             rect->width = g->pixel_width;
+             rect->height = r->height;
+             rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
+             rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
+             return 1;
+           }
+         break;
+       }
     }
 
-  return found;
+  return 0;
 }
 
 
@@ -3767,7 +3831,9 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
        /* If not, is it one of our scroll bars?  */
        if (! f1)
          {
-           struct scroll_bar *bar = x_window_to_scroll_bar (win);
+           struct scroll_bar *bar;
+
+            bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win);
 
            if (bar)
              {
@@ -3802,7 +3868,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
                gx = win_x;
                gy = win_y;
 
-               /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
+               /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
                   round down even for negative values.  */
                if (gx < 0)
                  gx -= width - 1;
@@ -3838,19 +3904,21 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
 
 /* Scroll bar support.  */
 
-/* Given an X window ID, find the struct scroll_bar which manages it.
+/* Given an X window ID and a DISPLAY, find the struct scroll_bar which
+   manages it.
    This can be called in GC, so we have to make sure to strip off mark
    bits.  */
 
 static struct scroll_bar *
-x_window_to_scroll_bar (window_id)
+x_window_to_scroll_bar (display, window_id)
+     Display *display;
      Window window_id;
 {
   Lisp_Object tail;
 
-#ifdef USE_GTK
-  window_id = (Window) xg_get_scroll_id_for_window (window_id);
-#endif /* USE_GTK */
+#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
+  window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
+#endif /* USE_GTK  && USE_TOOLKIT_SCROLL_BARS */
 
   for (tail = Vframe_list;
        XGCTYPE (tail) == Lisp_Cons;
@@ -3873,7 +3941,8 @@ x_window_to_scroll_bar (window_id)
                               condemned = Qnil,
                               ! GC_NILP (bar));
           bar = XSCROLL_BAR (bar)->next)
-       if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
+       if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id &&
+            FRAME_X_DISPLAY (XFRAME (frame)) == display)
          return XSCROLL_BAR (bar);
     }
 
@@ -3985,7 +4054,7 @@ xt_action_hook (widget, client_data, action_name, event, params,
       x_send_scroll_bar_event (window_being_scrolled,
                               scroll_bar_end_scroll, 0, 0);
       w = XWINDOW (window_being_scrolled);
-      
+
       if (!NILP (XSCROLL_BAR (w->vertical_scroll_bar)->dragging))
        {
          XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
@@ -4206,8 +4275,6 @@ xg_scroll_callback (widget, data)
   int part = -1, whole = 0, portion = 0;
   GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (widget));
 
-  if (xg_ignore_gtk_scrollbar) return;
-
   position = gtk_adjustment_get_value (adj);
 
   p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA);
@@ -4221,6 +4288,8 @@ xg_scroll_callback (widget, data)
   previous = *p;
   *p = position;
 
+  if (xg_ignore_gtk_scrollbar) return;
+
   diff = (int) (position - previous);
 
   if (diff == (int) adj->step_increment)
@@ -4476,6 +4545,7 @@ x_create_toolkit_scroll_bar (f, bar)
       f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
     }
 
+#ifdef XtNbeNiceToColormap
   /* Tell the toolkit about them.  */
   if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
       || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
@@ -4499,16 +4569,17 @@ x_create_toolkit_scroll_bar (f, bar)
       pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
       if (pixel != -1)
        {
-         XtSetArg (av[ac], "topShadowPixel", pixel);
+         XtSetArg (av[ac], XtNtopShadowPixel, pixel);
          ++ac;
        }
       pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
       if (pixel != -1)
        {
-         XtSetArg (av[ac], "bottomShadowPixel", pixel);
+         XtSetArg (av[ac], XtNbottomShadowPixel, pixel);
          ++ac;
        }
     }
+#endif
 
   widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
                           f->output_data.x->edit_widget, av, ac);
@@ -4588,7 +4659,7 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
      its size, the update will often happen too late.
      If you don't believe it, check out revision 1.650 of xterm.c to see
      what hoops we were going through and the still poor behavior we got.  */
-  portion = XFASTINT (XWINDOW (bar->window)->height) * 30;
+  portion = WINDOW_TOTAL_LINES (XWINDOW (bar->window)) * 30;
   /* When the thumb is at the bottom, position == whole.
      So we need to increase `whole' to make space for the thumb.  */
   whole += portion;
@@ -4654,30 +4725,11 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
          XawScrollbarSetThumb (widget, top, shown);
        else
          {
-#ifdef HAVE_XAW3D
-           ScrollbarWidget sb = (ScrollbarWidget) widget;
-           int scroll_mode = 0;
-
-           /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR.  */
-           if (xaw3d_arrow_scroll)
-             {
-               /* Xaw3d stupidly ignores resize requests while dragging
-                  so we have to make it believe it's not in dragging mode.  */
-               scroll_mode = sb->scrollbar.scroll_mode;
-               if (scroll_mode == 2)
-                 sb->scrollbar.scroll_mode = 0;
-             }
-#endif
            /* Try to make the scrolling a tad smoother.  */
            if (!xaw3d_pick_top)
              shown = min (shown, old_shown);
 
            XawScrollbarSetThumb (widget, top, shown);
-
-#ifdef HAVE_XAW3D
-           if (xaw3d_arrow_scroll && scroll_mode == 2)
-             sb->scrollbar.scroll_mode = scroll_mode;
-#endif
          }
       }
   }
@@ -4780,9 +4832,7 @@ x_scroll_bar_create (w, top, left, width, height)
                              top,
                              left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
                              width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-                             max (height, 1),
-                             left,
-                             width);
+                             max (height, 1));
     xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar));
 #else /* not USE_GTK */
     Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
@@ -4956,37 +5006,38 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
   struct frame *f = XFRAME (w->frame);
   struct scroll_bar *bar;
   int top, height, left, sb_left, width, sb_width;
-  int window_x, window_y, window_width, window_height;
+  int window_y, window_height;
 
   /* Get window dimensions.  */
-  window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
+  window_box (w, -1, 0, &window_y, 0, &window_height);
   top = window_y;
-  width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
+  width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
   height = window_height;
 
   /* Compute the left edge of the scroll bar area.  */
-  if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
-    left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
-  else
-    left = XFASTINT (w->left);
-  left *= CANON_X_UNIT (f);
-  left += FRAME_INTERNAL_BORDER_WIDTH (f);
+  left = WINDOW_SCROLL_BAR_AREA_X (w);
 
   /* Compute the width of the scroll bar which might be less than
      the width of the area reserved for the scroll bar.  */
-  if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
-    sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
+  if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
+    sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
   else
     sb_width = width;
 
   /* Compute the left edge of the scroll bar.  */
 #ifdef USE_TOOLKIT_SCROLL_BARS
-  if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
-    sb_left = left + width - sb_width - (width - sb_width) / 2;
+  if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
+    sb_left = (left +
+              (WINDOW_RIGHTMOST_P (w)
+               ? width - sb_width - (width - sb_width) / 2
+               : 0));
   else
-    sb_left = left + (width - sb_width) / 2;
+    sb_left = (left +
+              (WINDOW_LEFTMOST_P (w)
+               ? (width - sb_width) / 2
+               : width - sb_width));
 #else
-  if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
+  if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
     sb_left = left + width - sb_width;
   else
     sb_left = left;
@@ -5025,32 +5076,29 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
 
-#ifdef USE_GTK
-      if (mask)
-        xg_update_scrollbar_pos (f,
-                                 SCROLL_BAR_X_WINDOW (bar),
-                                 top,
-                                 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                                 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-                                 max (height, 1),
-                                 left,
-                                 width);
-#else /* not USE_GTK */
-
-      /* Since toolkit scroll bars are smaller than the space reserved
-         for them on the frame, we have to clear "under" them.  */
-      if (width > 0 && height > 0)
-        x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                          left, top, width, height, False);
       /* Move/size the scroll bar widget.  */
       if (mask)
+       {
+         /* Since toolkit scroll bars are smaller than the space reserved
+            for them on the frame, we have to clear "under" them.  */
+         if (width > 0 && height > 0)
+           x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                          left, top, width, height, False);
+#ifdef USE_GTK
+          xg_update_scrollbar_pos (f,
+                                   SCROLL_BAR_X_WINDOW (bar),
+                                   top,
+                                   sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                                   sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM *2,
+                                   max (height, 1));
+#else /* not USE_GTK */
           XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
                              sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
                              top,
                              sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
                              max (height, 1), 0);
-
 #endif /* not USE_GTK */
+       }
 #else /* not USE_TOOLKIT_SCROLL_BARS */
 
       /* Clear areas not covered by the scroll bar because of
@@ -5071,11 +5119,11 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
         previous mode line display is cleared after C-x 2 C-x 1, for
         example.  */
       {
-       int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
+       int area_width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
        int rest = area_width - sb_width;
        if (rest > 0 && height > 0)
          {
-           if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
+           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);
@@ -5502,73 +5550,6 @@ x_scroll_bar_clear (f)
 }
 
 \f
-/* Define a queue to save up SelectionRequest events for later handling.  */
-
-struct selection_event_queue
-  {
-    XEvent event;
-    struct selection_event_queue *next;
-  };
-
-static struct selection_event_queue *queue;
-
-/* Nonzero means queue up certain events--don't process them yet.  */
-
-static int x_queue_selection_requests;
-
-/* Queue up an X event *EVENT, to be processed later.  */
-
-static void
-x_queue_event (f, event)
-     FRAME_PTR f;
-     XEvent *event;
-{
-  struct selection_event_queue *queue_tmp
-    = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
-
-  if (queue_tmp != NULL)
-    {
-      queue_tmp->event = *event;
-      queue_tmp->next = queue;
-      queue = queue_tmp;
-    }
-}
-
-/* Take all the queued events and put them back
-   so that they get processed afresh.  */
-
-static void
-x_unqueue_events (display)
-     Display *display;
-{
-  while (queue != NULL)
-    {
-      struct selection_event_queue *queue_tmp = queue;
-      XPutBackEvent (display, &queue_tmp->event);
-      queue = queue_tmp->next;
-      xfree ((char *)queue_tmp);
-    }
-}
-
-/* Start queuing SelectionRequest events.  */
-
-void
-x_start_queuing_selection_requests (display)
-     Display *display;
-{
-  x_queue_selection_requests++;
-}
-
-/* Stop queuing SelectionRequest events.  */
-
-void
-x_stop_queuing_selection_requests (display)
-     Display *display;
-{
-  x_queue_selection_requests--;
-  x_unqueue_events (display);
-}
-\f
 /* The main X event-reading loop - XTread_socket.  */
 
 #if 0
@@ -5595,6 +5576,11 @@ static XComposeStatus compose_status;
 static int temp_index;
 static short temp_buffer[100];
 
+#define STORE_KEYSYM_FOR_DEBUG(keysym)                         \
+  if (temp_index == sizeof temp_buffer / sizeof (short))       \
+    temp_index = 0;                                            \
+  temp_buffer[temp_index++] = (keysym)
+
 /* Set this to nonzero to fake an "X I/O error"
    on a particular display.  */
 
@@ -5614,15 +5600,8 @@ static struct x_display_info *next_noop_dpyinfo;
            f->output_data.x->saved_menu_event                          \
             = (XEvent *) xmalloc (sizeof (XEvent));                    \
          bcopy (&event, f->output_data.x->saved_menu_event, size);     \
-         if (numchars >= 1)                                            \
-           {                                                           \
-             bufp->kind = MENU_BAR_ACTIVATE_EVENT;                     \
-             XSETFRAME (bufp->frame_or_window, f);                     \
-             bufp->arg = Qnil;                                         \
-             bufp++;                                                   \
-             count++;                                                  \
-             numchars--;                                               \
-           }                                                           \
+        inev.ie.kind = MENU_BAR_ACTIVATE_EVENT;                        \
+        XSETFRAME (inev.ie.frame_or_window, f);                        \
        }                                                               \
      while (0)
 
@@ -5664,41 +5643,47 @@ x_filter_event (dpyinfo, event)
 #endif
 
 #ifdef USE_GTK
-static struct x_display_info *current_dpyinfo;
-static struct input_event **current_bufp;
-static int *current_numcharsp;
 static int current_count;
 static int current_finish;
+static struct input_event *current_hold_quit;
 
 /* This is the filter function invoked by the GTK event loop.
    It is invoked before the XEvent is translated to a GdkEvent,
-   so we have a chanse to act on the event before GTK. */
+   so we have a chance to act on the event before GTK. */
 static GdkFilterReturn
 event_handler_gdk (gxev, ev, data)
      GdkXEvent *gxev;
      GdkEvent *ev;
      gpointer data;
 {
-  XEvent *xev = (XEvent*)gxev;
+  XEvent *xev = (XEvent *) gxev;
 
-  if (current_numcharsp)
+  if (current_count >= 0)
     {
+      struct x_display_info *dpyinfo;
+
+      dpyinfo = x_display_info_for_display (xev->xany.display);
+
 #ifdef HAVE_X_I18N
       /* Filter events for the current X input method.
          GTK calls XFilterEvent but not for key press and release,
          so we do it here.  */
       if (xev->type == KeyPress || xev->type == KeyRelease)
-        if (x_filter_event (current_dpyinfo, xev))
+        if (dpyinfo && x_filter_event (dpyinfo, xev))
           return GDK_FILTER_REMOVE;
 #endif
-      current_count += handle_one_xevent (current_dpyinfo,
-                                          xev,
-                                          current_bufp,
-                                          current_numcharsp,
-                                          &current_finish);
+
+      if (! dpyinfo)
+        current_finish = X_EVENT_NORMAL;
+      else
+       {
+         current_count +=
+           handle_one_xevent (dpyinfo, xev, &current_finish,
+                              current_hold_quit);
+       }
     }
   else
-    current_finish = x_dispatch_event (xev, GDK_DISPLAY ());
+    current_finish = x_dispatch_event (xev, xev->xany.display);
 
   if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
     return GDK_FILTER_REMOVE;
@@ -5714,28 +5699,32 @@ event_handler_gdk (gxev, ev, data)
    *FINISH is zero if caller should continue reading events.
    *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
 
-   Events representing keys are stored in buffer *BUFP_R,
-   which can hold up to *NUMCHARSP characters.
    We return the number of characters stored into the buffer. */
 
 static int
-handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
+handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
      struct x_display_info *dpyinfo;
      XEvent *eventp;
-     /* register */ struct input_event **bufp_r;
-     /* register */ int *numcharsp;
      int *finish;
+     struct input_event *hold_quit;
 {
+  union {
+    struct input_event ie;
+    struct selection_input_event sie;
+  } inev;
   int count = 0;
+  int do_help = 0;
   int nbytes = 0;
   struct frame *f;
   struct coding_system coding;
-  struct input_event *bufp = *bufp_r;
-  int numchars = *numcharsp;
   XEvent event = *eventp;
 
   *finish = X_EVENT_NORMAL;
 
+  EVENT_INIT (inev.ie);
+  inev.ie.kind = NO_EVENT;
+  inev.ie.arg = Qnil;
+
   switch (event.type)
     {
     case ClientMessage:
@@ -5790,8 +5779,10 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                   }
                 /* Not certain about handling scroll bars here */
 #endif /* 0 */
+               goto done;
               }
-            else if (event.xclient.data.l[0]
+
+            if (event.xclient.data.l[0]
                      == dpyinfo->Xatom_wm_save_yourself)
               {
                 /* Save state modify the WM_COMMAND property to
@@ -5802,11 +5793,9 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                 /* If we have a session manager, don't set this.
                    KDE will then start two Emacsen, one for the
                    session manager and one for this. */
-                if (numchars > 0
 #ifdef HAVE_X_SM
-                    && ! x_session_have_connection ()
+                if (! x_session_have_connection ())
 #endif
-                    )
                   {
                     f = x_top_window_to_frame (dpyinfo,
                                                event.xclient.window);
@@ -5821,89 +5810,94 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                                    event.xclient.window,
                                    0, 0);
                   }
+               goto done;
               }
-            else if (event.xclient.data.l[0]
-                     == dpyinfo->Xatom_wm_delete_window)
+
+            if (event.xclient.data.l[0]
+               == dpyinfo->Xatom_wm_delete_window)
               {
-                struct frame *f
-                  = x_any_window_to_frame (dpyinfo,
+                f = x_any_window_to_frame (dpyinfo,
                                            event.xclient.window);
+                if (!f)
+                 goto OTHER; /* May be a dialog that is to be removed  */
 
-                if (f)
-                  {
-                    if (numchars == 0)
-                      abort ();
-
-                    bufp->kind = DELETE_WINDOW_EVENT;
-                    XSETFRAME (bufp->frame_or_window, f);
-                    bufp->arg = Qnil;
-                    bufp++;
-
-                    count += 1;
-                    numchars -= 1;
-                  }
-                else
-                  goto OTHER; /* May be a dialog that is to be removed  */
+               inev.ie.kind = DELETE_WINDOW_EVENT;
+               XSETFRAME (inev.ie.frame_or_window, f);
+               goto done;
               }
+
+           goto done;
           }
-        else if (event.xclient.message_type
+
+        if (event.xclient.message_type
                  == dpyinfo->Xatom_wm_configure_denied)
           {
+           goto done;
           }
-        else 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;
-            struct frame *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];
 
             if (f)
               {
-                f->output_data.x->left_pos = new_x;
-                f->output_data.x->top_pos = new_y;
+                f->left_pos = new_x;
+                f->top_pos = new_y;
               }
+           goto done;
           }
+
 #ifdef HACK_EDITRES
-        else if (event.xclient.message_type
-                 == dpyinfo->Xatom_editres)
+        if (event.xclient.message_type
+           == dpyinfo->Xatom_editres)
           {
-            struct frame *f
-              = x_any_window_to_frame (dpyinfo, event.xclient.window);
+           f = x_any_window_to_frame (dpyinfo, event.xclient.window);
             _XEditResCheckMessages (f->output_data.x->widget, NULL,
                                     &event, NULL);
+           goto done;
           }
 #endif /* HACK_EDITRES */
-        else 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];
-            struct frame *f
-              = x_window_to_frame (dpyinfo, event.xclient.window);
+           f = x_window_to_frame (dpyinfo, event.xclient.window);
             x_kill_gs_process (pixmap, f);
             expose_frame (f, 0, 0, 0, 0);
+           goto done;
           }
+
 #ifdef USE_TOOLKIT_SCROLL_BARS
         /* Scroll bar callbacks send a ClientMessage from which
            we construct an input_event.  */
-        else if (event.xclient.message_type
-                 == dpyinfo->Xatom_Scrollbar)
+        if (event.xclient.message_type
+           == dpyinfo->Xatom_Scrollbar)
           {
-            x_scroll_bar_to_input_event (&event, bufp);
-            ++bufp, ++count, --numchars;
-            goto out;
+            x_scroll_bar_to_input_event (&event, &inev.ie);
+           *finish = X_EVENT_GOTO_OUT;
+            goto done;
           }
 #endif /* USE_TOOLKIT_SCROLL_BARS */
-        else
-          goto OTHER;
+
+       f = x_any_window_to_frame (dpyinfo, event.xclient.window);
+
+       if (!f)
+         goto OTHER;
+
+       if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie))
+         *finish = X_EVENT_DROP;
       }
       break;
 
@@ -5923,19 +5917,11 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
       {
         XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
 
-        if (numchars == 0)
-          abort ();
-
-        bufp->kind = SELECTION_CLEAR_EVENT;
-        SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
-        SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
-        SELECTION_EVENT_TIME (bufp) = eventp->time;
-        bufp->frame_or_window = Qnil;
-        bufp->arg = Qnil;
-        bufp++;
-
-        count += 1;
-        numchars -= 1;
+        inev.ie.kind = SELECTION_CLEAR_EVENT;
+        SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
+        SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
+        SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
+        inev.ie.frame_or_window = Qnil;
       }
       break;
 
@@ -5944,31 +5930,19 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
       if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
         goto OTHER;
 #endif /* USE_X_TOOLKIT */
-      if (x_queue_selection_requests)
-        x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
-                       &event);
-      else
-        {
+      {
           XSelectionRequestEvent *eventp
             = (XSelectionRequestEvent *) &event;
 
-          if (numchars == 0)
-            abort ();
-
-          bufp->kind = SELECTION_REQUEST_EVENT;
-          SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
-          SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
-          SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
-          SELECTION_EVENT_TARGET (bufp) = eventp->target;
-          SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
-          SELECTION_EVENT_TIME (bufp) = eventp->time;
-          bufp->frame_or_window = Qnil;
-          bufp->arg = Qnil;
-          bufp++;
-
-          count += 1;
-          numchars -= 1;
-        }
+          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;
+          inev.ie.frame_or_window = Qnil;
+      }
       break;
 
     case PropertyNotify:
@@ -5990,11 +5964,13 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           int x, y;
           f->output_data.x->parent_desc = event.xreparent.parent;
           x_real_positions (f, &x, &y);
-          f->output_data.x->left_pos = x;
-          f->output_data.x->top_pos = y;
+          f->left_pos = x;
+          f->top_pos = y;
+
+          /* Perhaps reparented due to a WM restart.  Reset this.  */
+          FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
         }
       goto OTHER;
-      break;
 
     case Expose:
       f = x_window_to_frame (dpyinfo, event.xexpose.window);
@@ -6002,6 +5978,14 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
         {
           x_check_fullscreen (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 (f->async_visible == 0)
             {
               f->async_visible = 1;
@@ -6010,9 +5994,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
               SET_FRAME_GARBAGED (f);
             }
           else
-            expose_frame (x_window_to_frame (dpyinfo,
-                                             event.xexpose.window),
-                          event.xexpose.x, event.xexpose.y,
+            expose_frame (f,
+                         event.xexpose.x, event.xexpose.y,
                           event.xexpose.width, event.xexpose.height);
         }
       else
@@ -6036,7 +6019,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           /* Dispatch event to the widget.  */
           goto OTHER;
 #else /* not USE_TOOLKIT_SCROLL_BARS */
-          bar = x_window_to_scroll_bar (event.xexpose.window);
+          bar = x_window_to_scroll_bar (event.xexpose.display,
+                                        event.xexpose.window);
 
           if (bar)
             x_scroll_bar_expose (bar, &event);
@@ -6096,12 +6080,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
             {
               f->async_iconified = 1;
 
-              bufp->kind = ICONIFY_EVENT;
-              XSETFRAME (bufp->frame_or_window, f);
-              bufp->arg = Qnil;
-              bufp++;
-              count++;
-              numchars--;
+              inev.ie.kind = ICONIFY_EVENT;
+              XSETFRAME (inev.ie.frame_or_window, f);
             }
         }
       goto OTHER;
@@ -6118,7 +6098,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
       f = x_top_window_to_frame (dpyinfo, event.xmap.window);
       if (f)
         {
-          /* wait_reading_process_input will notice this and update
+          /* wait_reading_process_output will notice this and update
              the frame's display structures.
              If we where iconified, we should not set garbaged,
              because that stops redrawing on Expose events.  This looks
@@ -6133,12 +6113,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 
           if (f->iconified)
             {
-              bufp->kind = DEICONIFY_EVENT;
-              XSETFRAME (bufp->frame_or_window, f);
-              bufp->arg = Qnil;
-              bufp++;
-              count++;
-              numchars--;
+              inev.ie.kind = DEICONIFY_EVENT;
+              XSETFRAME (inev.ie.frame_or_window, f);
             }
           else if (! NILP (Vframe_list)
                    && ! NILP (XCDR (Vframe_list)))
@@ -6151,6 +6127,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 
     case KeyPress:
 
+      ignore_next_mouse_click_timeout = 0;
+
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
       /* Dispatch KeyPress events when in menu.  */
       if (popup_activated ())
@@ -6161,8 +6139,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 
       if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
         {
-          dpyinfo->mouse_face_hidden = 1;
           clear_mouse_face (dpyinfo);
+          dpyinfo->mouse_face_hidden = 1;
         }
 
 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
@@ -6199,6 +6177,15 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           int copy_bufsiz = sizeof (copy_buffer);
           int modifiers;
           Lisp_Object coding_system = Qlatin_1;
+         Lisp_Object c;
+
+#ifdef USE_GTK
+          /* Don't pass keys to GTK.  A Tab will shift focus to the
+             tool bar in GTK 2.4.  Keys will still go to menus and
+             dialogs because in that case popup_activated is TRUE
+             (see above).  */
+          *finish = X_EVENT_DROP;
+#endif
 
           event.xkey.state
             |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
@@ -6285,51 +6272,44 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                                   &compose_status);
 #endif
 
+          /* If not using XIM/XIC, and a compose sequence is in progress,
+             we break here.  Otherwise, chars_matched is always 0.  */
+          if (compose_status.chars_matched > 0 && nbytes == 0)
+            break;
+
           orig_keysym = keysym;
 
-          if (numchars > 1)
-            {
-              Lisp_Object c;
+         /* 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;
 
-              /* First deal with keysyms which have defined
-                 translations to characters.  */
-              if (keysym >= 32 && keysym < 128)
-                /* Avoid explicitly decoding each ASCII character.  */
-                {
-                  bufp->kind = ASCII_KEYSTROKE_EVENT;
-                  bufp->code = keysym;
-                  XSETFRAME (bufp->frame_or_window, f);
-                  bufp->arg = Qnil;
-                  bufp->modifiers
-                    = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                              modifiers);
-                  bufp->timestamp = event.xkey.time;
-                  bufp++;
-                  count++;
-                  numchars--;
-                }
-              /* Now non-ASCII.  */
-              else if (HASH_TABLE_P (Vx_keysym_table)
-                       && (NATNUMP (c = Fgethash (make_number (keysym),
-                                                  Vx_keysym_table,
-                                                  Qnil))))
-                {
-                  bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
-                                ? ASCII_KEYSTROKE_EVENT
-                                : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-                  bufp->code = XFASTINT (c);
-                  XSETFRAME (bufp->frame_or_window, f);
-                  bufp->arg = Qnil;
-                  bufp->modifiers
-                    = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                              modifiers);
-                  bufp->timestamp = event.xkey.time;
-                  bufp++;
-                  count++;
-                  numchars--;
-                }
-              /* Random non-modifier sorts of keysyms.  */
-              else if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
+         /* First deal with keysyms which have defined
+            translations to characters.  */
+         if (keysym >= 32 && keysym < 128)
+           /* Avoid explicitly decoding each ASCII character.  */
+           {
+             inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+             inev.ie.code = keysym;
+             goto done_keysym;
+           }
+
+         /* Now non-ASCII.  */
+         if (HASH_TABLE_P (Vx_keysym_table)
+             && (NATNUMP (c = Fgethash (make_number (keysym),
+                                        Vx_keysym_table,
+                                        Qnil))))
+           {
+             inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
+                             ? ASCII_KEYSTROKE_EVENT
+                             : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+             inev.ie.code = XFASTINT (c);
+             goto done_keysym;
+           }
+
+         /* Random non-modifier sorts of keysyms.  */
+         if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
                         || keysym == XK_Delete
 #ifdef XK_ISO_Left_Tab
                         || (keysym >= XK_ISO_Left_Tab
@@ -6410,104 +6390,80 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                                  <= XK_ISO_Last_Group_Lock)
 #endif
                              ))
-                {
-                  if (temp_index == sizeof temp_buffer / sizeof (short))
-                    temp_index = 0;
-                  temp_buffer[temp_index++] = keysym;
-                  /* make_lispy_event will convert this to a symbolic
-                     key.  */
-                  bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
-                  bufp->code = keysym;
-                  XSETFRAME (bufp->frame_or_window, f);
-                  bufp->arg = Qnil;
-                  bufp->modifiers
-                    = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                              modifiers);
-                  bufp->timestamp = event.xkey.time;
-                  bufp++;
-                  count++;
-                  numchars--;
-                }
-              else if (numchars > nbytes)
-                {      /* Raw bytes, not keysym.  */
-                  register int i;
-                  register int c;
-                  int nchars, len;
-
-                  /* The input should be decoded with `coding_system'
-                     which depends on which X*LookupString function
-                     we used just above and the locale.  */
-                  setup_coding_system (coding_system, &coding);
-                  coding.src_multibyte = 0;
-                  coding.dst_multibyte = 1;
-                  /* The input is converted to events, thus we can't
-                     handle composition.  Anyway, there's no XIM that
-                     gives us composition information.  */
-                  coding.composing = COMPOSITION_DISABLED;
-
-                  for (i = 0; i < nbytes; i++)
-                    {
-                      if (temp_index == (sizeof temp_buffer
-                                         / sizeof (short)))
-                        temp_index = 0;
-                      temp_buffer[temp_index++] = copy_bufptr[i];
-                    }
+           {
+             STORE_KEYSYM_FOR_DEBUG (keysym);
+             /* make_lispy_event will convert this to a symbolic
+                key.  */
+             inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
+             inev.ie.code = keysym;
+             goto done_keysym;
+           }
 
-                  {
-                    /* Decode the input data.  */
-                    int require;
-                    unsigned char *p;
-
-                    require = decoding_buffer_size (&coding, nbytes);
-                    p = (unsigned char *) alloca (require);
-                    coding.mode |= CODING_MODE_LAST_BLOCK;
-                    /* We explicitely disable composition
-                       handling because key data should
-                       not contain any composition
-                       sequence.  */
-                    coding.composing = COMPOSITION_DISABLED;
-                    decode_coding (&coding, copy_bufptr, p,
-                                   nbytes, require);
-                    nbytes = coding.produced;
-                    nchars = coding.produced_char;
-                    copy_bufptr = p;
-                  }
+         {     /* Raw bytes, not keysym.  */
+           register int i;
+           register int c;
+           int nchars, len;
+
+           /* The input should be decoded with `coding_system'
+              which depends on which X*LookupString function
+              we used just above and the locale.  */
+           setup_coding_system (coding_system, &coding);
+           coding.src_multibyte = 0;
+           coding.dst_multibyte = 1;
+           /* The input is converted to events, thus we can't
+              handle composition.  Anyway, there's no XIM that
+              gives us composition information.  */
+           coding.composing = COMPOSITION_DISABLED;
+
+           for (i = 0; i < nbytes; i++)
+             {
+               STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
+             }
 
-                  /* Convert the input data to a sequence of
-                     character events.  */
-                  for (i = 0; i < nbytes; i += len)
-                    {
-                      if (nchars == nbytes)
-                        c = copy_bufptr[i], len = 1;
-                      else
-                        c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
-                                                    nbytes - i, len);
-
-                      bufp->kind = (SINGLE_BYTE_CHAR_P (c)
-                                    ? ASCII_KEYSTROKE_EVENT
-                                    : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-                      bufp->code = c;
-                      XSETFRAME (bufp->frame_or_window, f);
-                      bufp->arg = Qnil;
-                      bufp->modifiers
-                        = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                                  modifiers);
-                      bufp->timestamp = event.xkey.time;
-                      bufp++;
-                    }
+           {
+             /* Decode the input data.  */
+             int require;
+             unsigned char *p;
+
+             require = decoding_buffer_size (&coding, nbytes);
+             p = (unsigned char *) alloca (require);
+             coding.mode |= CODING_MODE_LAST_BLOCK;
+             /* We explicitly disable composition handling because
+                key data should not contain any composition sequence.  */
+             coding.composing = COMPOSITION_DISABLED;
+             decode_coding (&coding, copy_bufptr, p, nbytes, require);
+             nbytes = coding.produced;
+             nchars = coding.produced_char;
+             copy_bufptr = p;
+           }
 
-                  count += nchars;
-                  numchars -= nchars;
+           /* Convert the input data to a sequence of
+              character events.  */
+           for (i = 0; i < nbytes; i += len)
+             {
+               if (nchars == nbytes)
+                 c = copy_bufptr[i], len = 1;
+               else
+                 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
+                                             nbytes - i, len);
+               inev.ie.kind = (SINGLE_BYTE_CHAR_P (c)
+                             ? ASCII_KEYSTROKE_EVENT
+                             : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+               inev.ie.code = c;
+               kbd_buffer_store_event_hold (&inev.ie, hold_quit);
+             }
 
-                  if (keysym == NoSymbol)
-                    break;
-                }
-              else
-                abort ();
-            }
-          else
-            abort ();
+           /* Previous code updated count by nchars rather than nbytes,
+              but that seems bogus to me.  ++kfs  */
+           count += nbytes;
+
+           inev.ie.kind = NO_EVENT;  /* Already stored above.  */
+
+           if (keysym == NoSymbol)
+             break;
+         }
         }
+    done_keysym:
 #ifdef HAVE_X_I18N
       /* Don't dispatch this event since XtDispatchEvent calls
          XFilterEvent, and two calls in a row may freeze the
@@ -6528,63 +6484,41 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 #endif
 
     case EnterNotify:
-      {
-        int n;
+      x_detect_focus_change (dpyinfo, &event, &inev.ie);
 
-        n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
-        if (n > 0)
-          {
-            bufp += n, count += n, numchars -= n;
-          }
+      f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
 
-        f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
+      if (f && x_mouse_click_focus_ignore_position)
+       ignore_next_mouse_click_timeout = event.xmotion.time + 200;
 
 #if 0
-        if (event.xcrossing.focus)
-          {
-            /* Avoid nasty pop/raise loops.  */
-            if (f && (!(f->auto_raise)
-                      || !(f->auto_lower)
-                      || (event.xcrossing.time - enter_timestamp) > 500))
-              {
-                x_new_focus_frame (dpyinfo, f);
-                enter_timestamp = event.xcrossing.time;
-              }
-          }
-        else if (f == dpyinfo->x_focus_frame)
-          x_new_focus_frame (dpyinfo, 0);
+      if (event.xcrossing.focus)
+       {
+         /* Avoid nasty pop/raise loops.  */
+         if (f && (!(f->auto_raise)
+                   || !(f->auto_lower)
+                   || (event.xcrossing.time - enter_timestamp) > 500))
+           {
+             x_new_focus_frame (dpyinfo, f);
+             enter_timestamp = event.xcrossing.time;
+           }
+       }
+      else if (f == dpyinfo->x_focus_frame)
+       x_new_focus_frame (dpyinfo, 0);
 #endif
 
-        /* EnterNotify counts as mouse movement,
-           so update things that depend on mouse position.  */
-        if (f && !f->output_data.x->hourglass_p)
-          note_mouse_movement (f, &event.xmotion);
-        goto OTHER;
-      }
+      /* EnterNotify counts as mouse movement,
+        so update things that depend on mouse position.  */
+      if (f && !f->output_data.x->hourglass_p)
+       note_mouse_movement (f, &event.xmotion);
+      goto OTHER;
 
     case FocusIn:
-      {
-        int n;
-
-        n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
-        if (n > 0)
-          {
-            bufp += n, count += n, numchars -= n;
-          }
-      }
-
-      goto OTHER;
+      x_detect_focus_change (dpyinfo, &event, &inev.ie);
+      goto OTHER;
 
     case LeaveNotify:
-      {
-        int n;
-
-        n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
-        if (n > 0)
-          {
-            bufp += n, count += n, numchars -= n;
-          }
-      }
+      x_detect_focus_change (dpyinfo, &event, &inev.ie);
 
       f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
       if (f)
@@ -6602,31 +6536,12 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
              Otherwise, the startup message is cleared when
              the mouse leaves the frame.  */
           if (any_help_event_p)
-            {
-              Lisp_Object frame;
-              int n;
-
-              XSETFRAME (frame, f);
-              help_echo_string = Qnil;
-              n = gen_help_event (bufp, numchars,
-                                  Qnil, frame, Qnil, Qnil, 0);
-              bufp += n, count += n, numchars -= n;
-            }
-
+           do_help = -1;
         }
       goto OTHER;
 
     case FocusOut:
-      {
-        int n;
-
-        n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
-        if (n > 0)
-          {
-            bufp += n, count += n, numchars -= n;
-          }
-      }
-
+      x_detect_focus_change (dpyinfo, &event, &inev.ie);
       goto OTHER;
 
     case MotionNotify:
@@ -6657,20 +6572,17 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 
                 window = window_from_coordinates (f,
                                                   event.xmotion.x, event.xmotion.y,
-                                                  0, 0);
+                                                  0, 0, 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 iff it is active.  */
-                if (WINDOWP(window)
+                if (WINDOWP (window)
                     && !EQ (window, last_window)
-                    && !EQ (window, selected_window)
-                    && numchars > 0)
+                    && !EQ (window, selected_window))
                   {
-                    bufp->kind = SELECT_WINDOW_EVENT;
-                    bufp->frame_or_window = window;
-                    bufp->arg = Qnil;
-                    ++bufp, ++count, --numchars;
+                    inev.ie.kind = SELECT_WINDOW_EVENT;
+                    inev.ie.frame_or_window = window;
                   }
 
                 last_window=window;
@@ -6681,7 +6593,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           {
 #ifndef USE_TOOLKIT_SCROLL_BARS
             struct scroll_bar *bar
-              = x_window_to_scroll_bar (event.xmotion.window);
+              = x_window_to_scroll_bar (event.xmotion.display,
+                                        event.xmotion.window);
 
             if (bar)
               x_scroll_bar_note_movement (bar, &event);
@@ -6696,22 +6609,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
            has changed, generate a HELP_EVENT.  */
         if (!NILP (help_echo_string)
             || !NILP (previous_help_echo_string))
-          {
-            Lisp_Object frame;
-            int n;
-
-            if (f)
-              XSETFRAME (frame, f);
-            else
-              frame = Qnil;
-
-            any_help_event_p = 1;
-            n = gen_help_event (bufp, numchars, help_echo_string, frame,
-                                help_echo_window, help_echo_object,
-                                help_echo_pos);
-            bufp += n, count += n, numchars -= n;
-          }
-
+         do_help = 1;
         goto OTHER;
       }
 
@@ -6728,11 +6626,12 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
              do this one, the right one will come later.
              The toolkit version doesn't seem to need this, but we
              need to reset it below.  */
-          int dont_resize =
-            ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
-             && FRAME_NEW_WIDTH (f) != 0);
-          int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
-          int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
+          int dont_resize
+           = ((f->want_fullscreen & FULLSCREEN_WAIT)
+              && f->new_text_cols != 0);
+          int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, event.xconfigure.height);
+          int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, event.xconfigure.width);
+
           if (dont_resize)
             goto OTHER;
 
@@ -6743,10 +6642,10 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           /* Even if the number of character rows and columns has
              not changed, the font size may have changed, so we need
              to check the pixel dimensions as well.  */
-          if (columns != f->width
-              || rows != f->height
-              || event.xconfigure.width != f->output_data.x->pixel_width
-              || event.xconfigure.height != f->output_data.x->pixel_height)
+          if (columns != FRAME_COLS (f)
+              || rows != FRAME_LINES (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);
@@ -6755,28 +6654,25 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 #endif /* not USE_GTK */
 #endif
 
-          f->output_data.x->pixel_width = event.xconfigure.width;
-          f->output_data.x->pixel_height = event.xconfigure.height;
+          FRAME_PIXEL_WIDTH (f) = event.xconfigure.width;
+          FRAME_PIXEL_HEIGHT (f) = event.xconfigure.height;
 
 #ifdef USE_GTK
           /* GTK creates windows but doesn't map them.
              Only get real positions and check fullscreen when mapped. */
           if (FRAME_GTK_OUTER_WIDGET (f)
               && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f)))
-            {
 #endif
-          /* What we have now is the position of Emacs's own window.
-             Convert that to the position of the window manager window.  */
-          x_real_positions (f, &f->output_data.x->left_pos,
-                            &f->output_data.x->top_pos);
-
-          x_check_fullscreen_move (f);
-          if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
-            f->output_data.x->want_fullscreen &=
-              ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
-#ifdef USE_GTK
+            {
+             /* What we have now is the position of Emacs's own window.
+                Convert that to the position of the window manager window.  */
+             x_real_positions (f, &f->left_pos, &f->top_pos);
+
+             x_check_expected_move (f);
+             if (f->want_fullscreen & FULLSCREEN_WAIT)
+               f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
             }
-#endif
+
 #ifdef HAVE_X_I18N
           if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
             xic_set_statusarea (f);
@@ -6786,7 +6682,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
             {
               /* Since the WM decorations come below top_pos now,
                  we must put them below top_pos in the future.  */
-              f->output_data.x->win_gravity = NorthWestGravity;
+              f->win_gravity = NorthWestGravity;
               x_wm_set_size_hint (f, (long) 0, 0);
             }
         }
@@ -6797,10 +6693,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
       {
         /* If we decide we want to generate an event to be seen
            by the rest of Emacs, we put it here.  */
-        struct input_event emacs_event;
         int tool_bar_p = 0;
 
-        emacs_event.kind = NO_EVENT;
         bzero (&compose_status, sizeof (compose_status));
 
         if (dpyinfo->grabbed
@@ -6814,13 +6708,13 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           {
             /* Is this in the tool-bar?  */
             if (WINDOWP (f->tool_bar_window)
-                && XFASTINT (XWINDOW (f->tool_bar_window)->height))
+                && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
               {
                 Lisp_Object window;
                 int x = event.xbutton.x;
                 int y = event.xbutton.y;
 
-                window = window_from_coordinates (f, x, y, 0, 1);
+                window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
                 if (EQ (window, f->tool_bar_window))
                   {
                    if (event.xbutton.type == ButtonPress)
@@ -6840,25 +6734,40 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
                   if (! popup_activated ())
 #endif
-                    construct_mouse_click (&emacs_event, &event, f);
+                   {
+                     if (ignore_next_mouse_click_timeout)
+                       {
+                         if (event.type == ButtonPress
+                             && (int)(event.xbutton.time - ignore_next_mouse_click_timeout) > 0)
+                           {
+                             ignore_next_mouse_click_timeout = 0;
+                             construct_mouse_click (&inev.ie, &event, f);
+                           }
+                         if (event.type == ButtonRelease)
+                           ignore_next_mouse_click_timeout = 0;
+                       }
+                     else
+                       construct_mouse_click (&inev.ie, &event, f);
+                   }
                 }
           }
         else
           {
             struct scroll_bar *bar
-              = x_window_to_scroll_bar (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)
               {
-                x_scroll_bar_handle_click (bar, &event, &emacs_event);
+                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, &emacs_event);
+              x_scroll_bar_handle_click (bar, &event, &inev.ie);
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
           }
 
@@ -6879,14 +6788,6 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
         else
           dpyinfo->grabbed &= ~(1 << event.xbutton.button);
 
-        if (numchars >= 1 && emacs_event.kind != NO_EVENT)
-          {
-            bcopy (&emacs_event, bufp, sizeof (struct input_event));
-            bufp++;
-            count++;
-            numchars--;
-          }
-
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
         f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
         /* For a down-event in the menu bar,
@@ -6903,7 +6804,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
             /* Verify the event is really within the menu bar
                and not just sent to it due to grabbing.  */
             && event.xbutton.x >= 0
-            && event.xbutton.x < f->output_data.x->pixel_width
+            && event.xbutton.x < FRAME_PIXEL_WIDTH (f)
             && event.xbutton.y >= 0
             && event.xbutton.y < f->output_data.x->menubar_height
             && event.xbutton.same_screen)
@@ -6973,16 +6874,38 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
     break;
     }
 
-  goto ret;
+ done:
+  if (inev.ie.kind != NO_EVENT)
+    {
+      kbd_buffer_store_event_hold (&inev.ie, hold_quit);
+      count++;
+    }
 
- out:
-  *finish = X_EVENT_GOTO_OUT;
+  if (do_help
+      && !(hold_quit && hold_quit->kind != NO_EVENT))
+    {
+      Lisp_Object frame;
 
- ret:
-  *bufp_r = bufp;
-  *numcharsp = numchars;
-  *eventp = event;
+      if (f)
+       XSETFRAME (frame, f);
+      else
+       frame = Qnil;
 
+      if (do_help > 0)
+       {
+         any_help_event_p = 1;
+         gen_help_event (help_echo_string, frame, help_echo_window,
+                         help_echo_object, help_echo_pos);
+       }
+      else
+       {
+         help_echo_string = Qnil;
+         gen_help_event (Qnil, frame, Qnil, Qnil, 0);
+       }
+      count++;
+    }
+
+  *eventp = event;
   return count;
 }
 
@@ -6998,26 +6921,12 @@ x_dispatch_event (event, display)
      Display *display;
 {
   struct x_display_info *dpyinfo;
-  struct input_event bufp[10];
-  struct input_event *bufpp = bufp;
-  int numchars = 10;
   int finish = X_EVENT_NORMAL;
 
-  for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
-    if (dpyinfo->display == display)
-      break;
+  dpyinfo = x_display_info_for_display (display);
 
   if (dpyinfo)
-    {
-      int i, events;
-      events = handle_one_xevent (dpyinfo,
-                                  event,
-                                  &bufpp,
-                                  &numchars,
-                                  &finish);
-      for (i = 0; i < events; ++i)
-        kbd_buffer_store_event (&bufp[i]);
-    }
+    handle_one_xevent (dpyinfo, event, &finish, 0);
 
   return finish;
 }
@@ -7027,19 +6936,16 @@ x_dispatch_event (event, display)
    This routine is called by the SIGIO handler.
    We return as soon as there are no more events to be read.
 
-   Events representing keys are stored in buffer BUFP,
-   which can hold up to NUMCHARS characters.
    We return the number of characters stored into the buffer,
    thus pretending to be `read'.
 
    EXPECTED is nonzero if the caller knows input is available.  */
 
 static int
-XTread_socket (sd, bufp, numchars, expected)
+XTread_socket (sd, expected, hold_quit)
      register int sd;
-     /* register */ struct input_event *bufp;
-     /* register */ int numchars;
      int expected;
+     struct input_event *hold_quit;
 {
   int count = 0;
   XEvent event;
@@ -7058,9 +6964,6 @@ XTread_socket (sd, bufp, numchars, expected)
   /* So people can tell when we have read the available input.  */
   input_signal_count++;
 
-  if (numchars <= 0)
-    abort ();                  /* Don't think this happens.  */
-
   ++handling_signal;
 
   /* Find the display we are supposed to read input for.
@@ -7102,36 +7005,21 @@ XTread_socket (sd, bufp, numchars, expected)
        }
 
 #ifdef HAVE_X_SM
-      BLOCK_INPUT;
-      count += x_session_check_input (bufp, &numchars);
-      UNBLOCK_INPUT;
+      {
+       struct input_event inev;
+       BLOCK_INPUT;
+       /* We don't need to EVENT_INIT (inev) here, as
+          x_session_check_input copies an entire input_event.  */
+       if (x_session_check_input (&inev))
+         {
+           kbd_buffer_store_event_hold (&inev, hold_quit);
+           count++;
+         }
+       UNBLOCK_INPUT;
+      }
 #endif
 
-#ifdef USE_GTK
-      /* For GTK we must use the GTK event loop.  But XEvents gets passed
-         to our filter function above, and then to the big event switch.
-         We use a bunch of globals to communicate with our filter function,
-         that is kind of ugly, but it works. */
-      current_dpyinfo = dpyinfo;
-
-      while (gtk_events_pending ())
-        {
-          static int nr = 0;
-          current_count = count;
-          current_numcharsp = &numchars;
-          current_bufp = &bufp;
-
-          gtk_main_iteration ();
-
-          count = current_count;
-          current_bufp = 0;
-          current_numcharsp = 0;
-
-          if (current_finish == X_EVENT_GOTO_OUT)
-            goto out;
-        }
-
-#else /* not USE_GTK */
+#ifndef USE_GTK
       while (XPending (dpyinfo->display))
        {
           int finish;
@@ -7145,17 +7033,39 @@ XTread_socket (sd, bufp, numchars, expected)
 #endif
          event_found = 1;
 
-          count += handle_one_xevent (dpyinfo,
-                                      &event,
-                                      &bufp,
-                                      &numchars,
-                                      &finish);
+          count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit);
 
           if (finish == X_EVENT_GOTO_OUT)
             goto out;
         }
-#endif /* USE_GTK */
+#endif /* not USE_GTK */
+    }
+
+#ifdef USE_GTK
+
+  /* For GTK we must use the GTK event loop.  But XEvents gets passed
+     to our filter function above, and then to the big event switch.
+     We use a bunch of globals to communicate with our filter function,
+     that is kind of ugly, but it works.
+
+     There is no way to do one display at the time, GTK just does events
+     from all displays.  */
+
+  while (gtk_events_pending ())
+    {
+      current_count = count;
+      current_hold_quit = hold_quit;
+
+      gtk_main_iteration ();
+
+      count = current_count;
+      current_count = -1;
+      current_hold_quit = 0;
+
+      if (current_finish == X_EVENT_GOTO_OUT)
+        break;
     }
+#endif /* USE_GTK */
 
  out:;
 
@@ -7190,8 +7100,9 @@ XTread_socket (sd, bufp, numchars, expected)
       pending_autoraise_frame = 0;
     }
 
-  UNBLOCK_INPUT;
   --handling_signal;
+  UNBLOCK_INPUT;
+
   return count;
 }
 
@@ -7204,40 +7115,30 @@ XTread_socket (sd, bufp, numchars, expected)
 
 /* Set clipping for output in glyph row ROW.  W is the window in which
    we operate.  GC is the graphics context to set clipping in.
-   WHOLE_LINE_P non-zero means include the areas used for truncation
-   mark display and alike in the clipping rectangle.
 
    ROW may be a text row or, e.g., a mode line.  Text rows must be
    clipped to the interior of the window dedicated to text display,
    mode lines must be clipped to the whole window.  */
 
 static void
-x_clip_to_row (w, row, gc, whole_line_p)
+x_clip_to_row (w, row, area, gc)
      struct window *w;
      struct glyph_row *row;
+     int area;
      GC gc;
-     int whole_line_p;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   XRectangle clip_rect;
-  int window_x, window_y, window_width, window_height;
+  int window_x, window_y, window_width;
 
-  window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
+  window_box (w, area, &window_x, &window_y, &window_width, 0);
 
-  clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
-  clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+  clip_rect.x = window_x;
+  clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
   clip_rect.y = max (clip_rect.y, window_y);
   clip_rect.width = window_width;
   clip_rect.height = row->visible_height;
 
-  /* If clipping to the whole line, including trunc marks, extend
-     the rectangle to the left and increase its width.  */
-  if (whole_line_p)
-    {
-      clip_rect.x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
-      clip_rect.width += FRAME_X_FRINGE_WIDTH (f);
-    }
-
   XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
 }
 
@@ -7257,28 +7158,16 @@ x_draw_hollow_cursor (w, row)
   struct glyph *cursor_glyph;
   GC gc;
 
-  /* Compute frame-relative coordinates from window-relative
-     coordinates.  */
-  x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
-  y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
-       + row->ascent - w->phys_cursor_ascent);
-  h = row->height - 1;
-
   /* Get the glyph the cursor is on.  If we can't tell because
      the current matrix is invalid or such, give up.  */
   cursor_glyph = get_phys_cursor_glyph (w);
   if (cursor_glyph == NULL)
     return;
 
-  /* Compute the width of the rectangle to draw.  If on a stretch
-     glyph, and `x-stretch-block-cursor' is nil, don't draw a
-     rectangle as wide as the glyph, but use a canonical character
-     width instead.  */
-  wd = cursor_glyph->pixel_width - 1;
-  if (cursor_glyph->type == STRETCH_GLYPH
-      && !x_stretch_cursor_p)
-    wd = min (CANON_X_UNIT (f), wd);
-  w->phys_cursor_width = wd;
+  /* Compute frame-relative coordinates for phys cursor.  */
+  x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+  y = get_phys_cursor_geometry (w, row, cursor_glyph, &h);
+  wd = w->phys_cursor_width;
 
   /* The foreground of cursor_gc is typically the same as the normal
      background color, which can cause the cursor box to be invisible.  */
@@ -7291,7 +7180,7 @@ x_draw_hollow_cursor (w, row)
   gc = dpyinfo->scratch_cursor_gc;
 
   /* Set clipping, draw the rectangle, and reset clipping again.  */
-  x_clip_to_row (w, row, gc, 0);
+  x_clip_to_row (w, row, TEXT_AREA, gc);
   XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
   XSetClipMask (dpy, gc, None);
 }
@@ -7363,7 +7252,7 @@ x_draw_bar_cursor (w, row, width, kind)
       width = min (cursor_glyph->pixel_width, width);
 
       w->phys_cursor_width = width;
-      x_clip_to_row (w, row, gc, 0);
+      x_clip_to_row (w, row, TEXT_AREA, gc);
 
       if (kind == BAR_CURSOR)
          XFillRectangle (dpy, window, gc,
@@ -7423,6 +7312,13 @@ x_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, activ
       w->phys_cursor_type = cursor_type;
       w->phys_cursor_on_p = 1;
 
+      if (glyph_row->exact_window_width_line_p
+         && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
+       {
+         glyph_row->cursor_in_fringe_p = 1;
+         draw_fringe_bitmap (w, glyph_row, 0);
+       }
+      else
       switch (cursor_type)
        {
        case HOLLOW_BOX_CURSOR:
@@ -7477,24 +7373,36 @@ x_bitmap_icon (f, file)
   if (FRAME_X_WINDOW (f) == 0)
     return 1;
 
-  /* Free up our existing icon bitmap if any.  */
+  /* Free up our existing icon bitmap and mask if any.  */
   if (f->output_data.x->icon_bitmap > 0)
     x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
   f->output_data.x->icon_bitmap = 0;
 
   if (STRINGP (file))
-    bitmap_id = x_create_bitmap_from_file (f, file);
+    {
+#ifdef USE_GTK
+      /* Use gtk_window_set_icon_from_file () if available,
+        It's not restricted to bitmaps */
+      if (xg_set_icon (f, file))
+       return 0;
+#endif /* USE_GTK */
+      bitmap_id = x_create_bitmap_from_file (f, file);
+      x_create_bitmap_mask (f, bitmap_id);
+    }
   else
     {
-      /* Create the GNU bitmap if necessary.  */
+      /* Create the GNU bitmap and mask if necessary.  */
       if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
-       FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
-         = x_create_bitmap_from_data (f, gnu_bits,
-                                      gnu_width, gnu_height);
+       {
+         FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
+           = x_create_bitmap_from_data (f, gnu_bits,
+                                        gnu_width, gnu_height);
+         x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
+       }
 
-      /* The first time we create the GNU bitmap,
+      /* The first time we create the GNU bitmap and mask,
         this increments the ref-count one extra time.
-        As a result, the GNU bitmap is never freed.
+        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);
 
@@ -7602,11 +7510,17 @@ static Lisp_Object
 x_catch_errors_unwind (old_val)
      Lisp_Object old_val;
 {
-  Lisp_Object first;
-
-  first = XCAR (old_val);
+  Lisp_Object first = XCAR (old_val);
+  Display *dpy = XSAVE_VALUE (first)->pointer;
 
-  XSync (XSAVE_VALUE (first)->pointer, False);
+  /* The display may have been closed before this function is called.
+     Check if it is still open before calling XSync.  */
+  if (x_display_info_for_display (dpy) != 0)
+    {
+      BLOCK_INPUT;
+      XSync (dpy, False);
+      UNBLOCK_INPUT;
+    }
 
   x_error_message_string = XCDR (old_val);
   return Qnil;
@@ -7758,6 +7672,11 @@ x_connection_closed (dpy, error_message)
     }
 #endif
 
+#ifdef USE_GTK
+  if (dpyinfo)
+    xg_display_close (dpyinfo->display);
+#endif
+
   /* Indicate that this display is dead.  */
   if (dpyinfo)
     dpyinfo->display = 0;
@@ -7812,12 +7731,41 @@ x_connection_closed (dpy, error_message)
   error ("%s", error_msg);
 }
 
+/* We specifically use it before defining it, so that gcc doesn't inline it,
+   otherwise gdb doesn't know how to properly put a breakpoint on it.  */
+static void x_error_quitter (Display *display, XErrorEvent *error);
+
+/* This is the first-level handler for X protocol errors.
+   It calls x_error_quitter or x_error_catcher.  */
+
+static int
+x_error_handler (display, error)
+     Display *display;
+     XErrorEvent *error;
+{
+  if (! NILP (x_error_message_string))
+    x_error_catcher (display, error);
+  else
+    x_error_quitter (display, error);
+  return 0;
+}
 
 /* This is the usual handler for X protocol errors.
    It kills all frames on the display that we got the error for.
    If that was the only one, it prints an error message and kills Emacs.  */
 
-static void
+/* .gdbinit puts a breakpoint here, so make sure it is not inlined.  */
+
+#if __GNUC__ >= 3  /* On GCC 3.0 we might get a warning.  */
+#define NO_INLINE __attribute__((noinline))
+#else
+#define NO_INLINE
+#endif
+
+/* On older GCC versions, just putting x_error_quitter
+   after x_error_handler prevents inlining into the former.  */
+
+static void NO_INLINE
 x_error_quitter (display, error)
      Display *display;
      XErrorEvent *error;
@@ -7834,21 +7782,6 @@ x_error_quitter (display, error)
 }
 
 
-/* This is the first-level handler for X protocol errors.
-   It calls x_error_quitter or x_error_catcher.  */
-
-static int
-x_error_handler (display, error)
-     Display *display;
-     XErrorEvent *error;
-{
-  if (! NILP (x_error_message_string))
-    x_error_catcher (display, error);
-  else
-    x_error_quitter (display, error);
-  return 0;
-}
-
 /* This is the handler for X IO errors, always.
    It kills all frames on the display that we lost touch with.
    If that was the only one, it prints an error message and kills Emacs.  */
@@ -7882,46 +7815,45 @@ x_new_font (f, fontname)
   if (!fontp)
     return Qnil;
 
-  f->output_data.x->font = (XFontStruct *) (fontp->font);
-  f->output_data.x->baseline_offset = fontp->baseline_offset;
-  f->output_data.x->fontset = -1;
+  FRAME_FONT (f) = (XFontStruct *) (fontp->font);
+  FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
+  FRAME_FONTSET (f) = -1;
+
+  FRAME_COLUMN_WIDTH (f) = fontp->average_width;
+  FRAME_SPACE_WIDTH (f) = fontp->space_width;
+  FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
 
   compute_fringe_widths (f, 1);
 
   /* Compute the scroll bar width in character columns.  */
-  if (f->scroll_bar_pixel_width > 0)
+  if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
     {
-      int wid = FONT_WIDTH (f->output_data.x->font);
-      f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
+      int wid = FRAME_COLUMN_WIDTH (f);
+      FRAME_CONFIG_SCROLL_BAR_COLS (f)
+       = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
     }
   else
     {
-      int wid = FONT_WIDTH (f->output_data.x->font);
-      f->scroll_bar_cols = (14 + wid - 1) / wid;
+      int wid = FRAME_COLUMN_WIDTH (f);
+      FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
     }
 
   /* Now make the frame display the given font.  */
   if (FRAME_X_WINDOW (f) != 0)
     {
       XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
-               f->output_data.x->font->fid);
+               FRAME_FONT (f)->fid);
       XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
-               f->output_data.x->font->fid);
+               FRAME_FONT (f)->fid);
       XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
-               f->output_data.x->font->fid);
-
-      frame_update_line_height (f);
+               FRAME_FONT (f)->fid);
 
       /* Don't change the size of a tip frame; there's no point in
         doing it because it's done in Fx_show_tip, and it leads to
         problems because the tip frame has no widget.  */
       if (NILP (tip_frame) || XFRAME (tip_frame) != f)
-       x_set_window_size (f, 0, f->width, f->height);
+       x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
     }
-  else
-    /* If we are setting a new frame's font for the first time,
-       there are no faces yet, so this font's height is the line height.  */
-    f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
 
   return build_string (fontp->full_name);
 }
@@ -7942,7 +7874,7 @@ x_new_fontset (f, fontsetname)
   if (fontset < 0)
     return Qnil;
 
-  if (f->output_data.x->fontset == fontset)
+  if (FRAME_FONTSET (f) == fontset)
     /* This fontset is already set in frame F.  There's nothing more
        to do.  */
     return fontset_name (fontset);
@@ -7954,7 +7886,7 @@ x_new_fontset (f, fontsetname)
     return Qnil;
 
   /* Since x_new_font doesn't update any fontset information, do it now.  */
-  f->output_data.x->fontset = fontset;
+  FRAME_FONTSET (f) = fontset;
 
 #ifdef HAVE_X_I18N
   if (FRAME_XIC (f)
@@ -7996,11 +7928,7 @@ xim_destroy_callback (xim, client_data, call_data)
       if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
        {
          FRAME_XIC (f) = NULL;
-         if (FRAME_XIC_FONTSET (f))
-           {
-             XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
-             FRAME_XIC_FONTSET (f) = NULL;
-           }
+          xic_free_xfontset (f);
        }
     }
 
@@ -8025,31 +7953,35 @@ xim_open_dpy (dpyinfo, resource_name)
      struct x_display_info *dpyinfo;
      char *resource_name;
 {
-#ifdef USE_XIM
   XIM xim;
 
-  xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
-  dpyinfo->xim = xim;
-
-  if (xim)
+#ifdef HAVE_XIM
+  if (use_xim)
     {
+      xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name,
+                    EMACS_CLASS);
+      dpyinfo->xim = xim;
+
+      if (xim)
+       {
 #ifdef HAVE_X11R6
-      XIMCallback destroy;
+         XIMCallback destroy;
 #endif
 
-      /* Get supported styles and XIM values.  */
-      XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
+         /* Get supported styles and XIM values.  */
+         XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
 
 #ifdef HAVE_X11R6
-      destroy.callback = xim_destroy_callback;
-      destroy.client_data = (XPointer)dpyinfo;
-      XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
+         destroy.callback = xim_destroy_callback;
+         destroy.client_data = (XPointer)dpyinfo;
+         XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
 #endif
+       }
     }
 
-#else /* not USE_XIM */
-  dpyinfo->xim = NULL;
-#endif /* not USE_XIM */
+  else
+#endif /* HAVE_XIM */
+    dpyinfo->xim = NULL;
 }
 
 
@@ -8123,32 +8055,35 @@ xim_initialize (dpyinfo, resource_name)
      struct x_display_info *dpyinfo;
      char *resource_name;
 {
-#ifdef USE_XIM
+#ifdef HAVE_XIM
+  if (use_xim)
+    {
 #ifdef HAVE_X11R6_XIM
-  struct xim_inst_t *xim_inst;
-  int len;
-
-  dpyinfo->xim = NULL;
-  xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
-  xim_inst->dpyinfo = dpyinfo;
-  len = strlen (resource_name);
-  xim_inst->resource_name = (char *) xmalloc (len + 1);
-  bcopy (resource_name, xim_inst->resource_name, len + 1);
-  XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
-                                 resource_name, EMACS_CLASS,
-                                 xim_instantiate_callback,
-                                 /* Fixme: This is XPointer in
-                                    XFree86 but (XPointer *) on
-                                    Tru64, at least.  */
-                                 (XPointer) xim_inst);
+      struct xim_inst_t *xim_inst;
+      int len;
+
+      dpyinfo->xim = NULL;
+      xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
+      xim_inst->dpyinfo = dpyinfo;
+      len = strlen (resource_name);
+      xim_inst->resource_name = (char *) xmalloc (len + 1);
+      bcopy (resource_name, xim_inst->resource_name, len + 1);
+      XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
+                                     resource_name, EMACS_CLASS,
+                                     xim_instantiate_callback,
+                                     /* This is XPointer in XFree86
+                                        but (XPointer *) on Tru64, at
+                                        least, hence the configure test.  */
+                                     (XRegisterIMInstantiateCallback_arg6) xim_inst);
 #else /* not HAVE_X11R6_XIM */
-  dpyinfo->xim = NULL;
-  xim_open_dpy (dpyinfo, resource_name);
+      dpyinfo->xim = NULL;
+      xim_open_dpy (dpyinfo, resource_name);
 #endif /* not HAVE_X11R6_XIM */
 
-#else /* not USE_XIM */
-  dpyinfo->xim = NULL;
-#endif /* not USE_XIM */
+    }
+  else
+#endif /* HAVE_XIM */
+    dpyinfo->xim = NULL;
 }
 
 
@@ -8158,18 +8093,21 @@ static void
 xim_close_dpy (dpyinfo)
      struct x_display_info *dpyinfo;
 {
-#ifdef USE_XIM
+#ifdef HAVE_XIM
+  if (use_xim)
+    {
 #ifdef HAVE_X11R6_XIM
-  if (dpyinfo->display)
-    XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
-                                     NULL, EMACS_CLASS,
-                                     xim_instantiate_callback, NULL);
+      if (dpyinfo->display)
+       XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
+                                         NULL, EMACS_CLASS,
+                                         xim_instantiate_callback, NULL);
 #endif /* not HAVE_X11R6_XIM */
-  if (dpyinfo->display)
-    XCloseIM (dpyinfo->xim);
-  dpyinfo->xim = NULL;
-  XFree (dpyinfo->xim_styles);
-#endif /* USE_XIM */
+      if (dpyinfo->display)
+       XCloseIM (dpyinfo->xim);
+      dpyinfo->xim = NULL;
+      XFree (dpyinfo->xim_styles);
+    }
+#endif /* HAVE_XIM */
 }
 
 #endif /* not HAVE_X11R6_XIM */
@@ -8183,73 +8121,22 @@ void
 x_calc_absolute_position (f)
      struct frame *f;
 {
-  Window child;
   int win_x = 0, win_y = 0;
-  int flags = f->output_data.x->size_hint_flags;
-  int this_window;
+  int flags = f->size_hint_flags;
 
   /* We have nothing to do if the current position
      is already for the top-left corner.  */
   if (! ((flags & XNegative) || (flags & YNegative)))
     return;
 
-  this_window = FRAME_OUTER_WINDOW (f);
-
-  /* Find the position of the outside upper-left corner of
-     the inner window, with respect to the outer window.
-     But do this only if we will need the results.  */
-  if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
-    {
-      int count;
-
-      BLOCK_INPUT;
-      count = x_catch_errors (FRAME_X_DISPLAY (f));
-      while (1)
-       {
-         x_clear_errors (FRAME_X_DISPLAY (f));
-         XTranslateCoordinates (FRAME_X_DISPLAY (f),
-
-                                /* From-window, to-window.  */
-                                this_window,
-                                f->output_data.x->parent_desc,
-
-                                /* From-position, to-position.  */
-                                0, 0, &win_x, &win_y,
-
-                                /* Child of win.  */
-                                &child);
-         if (x_had_errors_p (FRAME_X_DISPLAY (f)))
-           {
-             Window newroot, newparent = 0xdeadbeef;
-             Window *newchildren;
-             unsigned int nchildren;
-
-             if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
-                               &newparent, &newchildren, &nchildren))
-               break;
-
-             XFree ((char *) newchildren);
-
-             f->output_data.x->parent_desc = newparent;
-           }
-         else
-           break;
-       }
-
-      x_uncatch_errors (FRAME_X_DISPLAY (f), count);
-      UNBLOCK_INPUT;
-    }
-
   /* Treat negative positions as relative to the leftmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
-    f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
-                                 - 2 * f->output_data.x->border_width - win_x
-                                 - PIXEL_WIDTH (f)
-                                 + f->output_data.x->left_pos);
+    f->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
+                   - FRAME_PIXEL_WIDTH (f) + f->left_pos);
 
   {
-    int height = PIXEL_HEIGHT (f);
+    int height = FRAME_PIXEL_HEIGHT (f);
 
 #if defined USE_X_TOOLKIT && defined USE_MOTIF
     /* Something is fishy here.  When using Motif, starting Emacs with
@@ -8268,17 +8155,13 @@ x_calc_absolute_position (f)
 #endif
 
   if (flags & YNegative)
-    f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
-                                - 2 * f->output_data.x->border_width
-                                - win_y
-                                - height
-                                + f->output_data.x->top_pos);
+    f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height - height + f->top_pos);
   }
 
   /* The left_pos and top_pos
      are now relative to the top and left screen edges,
      so the flags should correspond.  */
-  f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
+  f->size_hint_flags &= ~ (XNegative | YNegative);
 }
 
 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
@@ -8297,35 +8180,43 @@ x_set_offset (f, xoff, yoff, change_gravity)
 
   if (change_gravity > 0)
     {
-      f->output_data.x->top_pos = yoff;
-      f->output_data.x->left_pos = xoff;
-      f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
+      f->top_pos = yoff;
+      f->left_pos = xoff;
+      f->size_hint_flags &= ~ (XNegative | YNegative);
       if (xoff < 0)
-       f->output_data.x->size_hint_flags |= XNegative;
+       f->size_hint_flags |= XNegative;
       if (yoff < 0)
-       f->output_data.x->size_hint_flags |= YNegative;
-      f->output_data.x->win_gravity = NorthWestGravity;
+       f->size_hint_flags |= YNegative;
+      f->win_gravity = NorthWestGravity;
     }
   x_calc_absolute_position (f);
 
   BLOCK_INPUT;
   x_wm_set_size_hint (f, (long) 0, 0);
 
-  modified_left = f->output_data.x->left_pos;
-  modified_top = f->output_data.x->top_pos;
-#if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
-        this seems to be unnecessary and incorrect.  rms, 4/17/97.  */
-  /* It is a mystery why we need to add the border_width here
-     when the frame is already visible, but experiment says we do.  */
-  if (change_gravity != 0)
+  modified_left = f->left_pos;
+  modified_top = f->top_pos;
+
+  if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
     {
-      modified_left += f->output_data.x->border_width;
-      modified_top += f->output_data.x->border_width;
+      /* Some WMs (twm, wmaker at least) has an offset that is smaller
+         than the WM decorations.  So we use the calculated offset instead
+         of the WM decoration sizes here (x/y_pixels_outer_diff).  */
+      modified_left += FRAME_X_OUTPUT (f)->move_offset_left;
+      modified_top += FRAME_X_OUTPUT (f)->move_offset_top;
     }
-#endif
 
   XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
                modified_left, modified_top);
+
+  if (FRAME_VISIBLE_P (f)
+      && FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN)
+    {
+      FRAME_X_OUTPUT (f)->check_expected_move = 1;
+      FRAME_X_OUTPUT (f)->expected_top = f->top_pos;
+      FRAME_X_OUTPUT (f)->expected_left = f->left_pos;
+    }
+
   UNBLOCK_INPUT;
 }
 
@@ -8335,57 +8226,60 @@ static void
 x_check_fullscreen (f)
      struct frame *f;
 {
-  if (f->output_data.x->want_fullscreen & FULLSCREEN_BOTH)
+  if (f->want_fullscreen & FULLSCREEN_BOTH)
     {
       int width, height, ign;
 
-      x_real_positions (f, &f->output_data.x->left_pos,
-                        &f->output_data.x->top_pos);
+      x_real_positions (f, &f->left_pos, &f->top_pos);
 
       x_fullscreen_adjust (f, &width, &height, &ign, &ign);
 
       /* We do not need to move the window, it shall be taken care of
          when setting WM manager hints.
          If the frame is visible already, the position is checked by
-         x_check_fullscreen_move. */
-      if (f->width != width || f->height != height)
+         x_check_expected_move. */
+      if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
         {
           change_frame_size (f, height, width, 0, 1, 0);
           SET_FRAME_GARBAGED (f);
           cancel_mouse_face (f);
 
           /* Wait for the change of frame size to occur */
-          f->output_data.x->want_fullscreen |= FULLSCREEN_WAIT;
+          f->want_fullscreen |= FULLSCREEN_WAIT;
         }
     }
 }
 
 /* If frame parameters are set after the frame is mapped, we need to move
-   the window.  This is done in xfns.c.
+   the window.
    Some window managers moves the window to the right position, some
    moves the outer window manager window to the specified position.
    Here we check that we are in the right spot.  If not, make a second
    move, assuming we are dealing with the second kind of window manager. */
 static void
-x_check_fullscreen_move (f)
+x_check_expected_move (f)
      struct frame *f;
 {
-  if (f->output_data.x->want_fullscreen & FULLSCREEN_MOVE_WAIT)
+  if (FRAME_X_OUTPUT (f)->check_expected_move)
   {
-    int expect_top = f->output_data.x->top_pos;
-    int expect_left = f->output_data.x->left_pos;
+    int expect_top = FRAME_X_OUTPUT (f)->expected_top;
+    int expect_left = FRAME_X_OUTPUT (f)->expected_left;
 
-    if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
-      expect_top = 0;
-    if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
-      expect_left = 0;
+    if (expect_top != f->top_pos || expect_left != f->left_pos)
+      {
+        FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
+        FRAME_X_OUTPUT (f)->move_offset_left = expect_left - f->left_pos;
+        FRAME_X_OUTPUT (f)->move_offset_top = expect_top - f->top_pos;
 
-    if (expect_top != f->output_data.x->top_pos
-        || expect_left != f->output_data.x->left_pos)
-      x_set_offset (f, expect_left, expect_top, 1);
+        f->left_pos = expect_left;
+        f->top_pos = expect_top;
+        x_set_offset (f, expect_left, expect_top, 0);
+      }
+    else if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN)
+      FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
 
     /* Just do this once */
-    f->output_data.x->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
+    FRAME_X_OUTPUT (f)->check_expected_move = 0;
   }
 }
 
@@ -8404,19 +8298,19 @@ x_set_window_size_1 (f, change_gravity, cols, rows)
   int pixelwidth, pixelheight;
 
   check_frame_size (f, &rows, &cols);
-  f->output_data.x->vertical_scroll_bar_extra
+  f->scroll_bar_actual_width
     = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
        ? 0
-       : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
-       ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
-       : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
+       : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
+       ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f)
+       : (FRAME_CONFIG_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f)));
 
   compute_fringe_widths (f, 0);
 
-  pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
-  pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
+  pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
+  pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
 
-  f->output_data.x->win_gravity = NorthWestGravity;
+  f->win_gravity = NorthWestGravity;
   x_wm_set_size_hint (f, (long) 0, 0);
 
   XSync (FRAME_X_DISPLAY (f), False);
@@ -8437,8 +8331,8 @@ x_set_window_size_1 (f, change_gravity, cols, rows)
      We pass 1 for DELAY since we can't run Lisp code inside of
      a BLOCK_INPUT.  */
   change_frame_size (f, rows, cols, 0, 1, 0);
-  PIXEL_WIDTH (f) = pixelwidth;
-  PIXEL_HEIGHT (f) = pixelheight;
+  FRAME_PIXEL_WIDTH (f) = pixelwidth;
+  FRAME_PIXEL_HEIGHT (f) = pixelheight;
 
   /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
      receive in the ConfigureNotify event; if we get what we asked
@@ -8512,14 +8406,14 @@ x_set_mouse_position (f, x, y)
 {
   int pix_x, pix_y;
 
-  pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH  (f->output_data.x->font) / 2;
-  pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
+  pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
+  pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
 
   if (pix_x < 0) pix_x = 0;
-  if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
+  if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
 
   if (pix_y < 0) pix_y = 0;
-  if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
+  if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
 
   BLOCK_INPUT;
 
@@ -8646,7 +8540,7 @@ x_make_frame_visible (f)
         before the window gets really visible.  */
       if (! FRAME_ICONIFIED_P (f)
          && ! f->output_data.x->asked_for_visible)
-       x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
+       x_set_offset (f, f->left_pos, f->top_pos, 0);
 
       f->output_data.x->asked_for_visible = 1;
 
@@ -8684,8 +8578,8 @@ x_make_frame_visible (f)
        will set it when they are handled.  */
     int previously_visible = f->output_data.x->has_been_visible;
 
-    original_left = f->output_data.x->left_pos;
-    original_top = f->output_data.x->top_pos;
+    original_left = f->left_pos;
+    original_top = f->top_pos;
 
     /* This must come after we set COUNT.  */
     UNBLOCK_INPUT;
@@ -8702,7 +8596,7 @@ x_make_frame_visible (f)
        and we don't want to override it.  */
 
     if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
-       && f->output_data.x->win_gravity == NorthWestGravity
+       && f->win_gravity == NorthWestGravity
        && previously_visible)
       {
        Drawable rootw;
@@ -8768,7 +8662,7 @@ x_make_frame_visible (f)
          (raise-frame f))
 
        the frame is not raised with various window managers on
-       FreeBSD, Linux and Solaris.  It turns out that, for some
+       FreeBSD, GNU/Linux and Solaris.  It turns out that, for some
        unknown reason, the call to XtMapWidget is completely ignored.
        Mapping the widget a second time works.  */
 
@@ -8943,7 +8837,7 @@ x_iconify_frame (f)
   /* Make sure the X server knows where the window should be positioned,
      in case the user deiconifies with the window manager.  */
   if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
-    x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
+    x_set_offset (f, f->left_pos, f->top_pos, 0);
 
   /* Since we don't know which revision of X we're running, we'll use both
      the X11R3 and X11R4 techniques.  I don't know if this is a good idea.  */
@@ -9158,8 +9052,8 @@ x_wm_set_size_hint (f, flags, user_position)
   /* Setting PMaxSize caused various problems.  */
   size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
 
-  size_hints.x = f->output_data.x->left_pos;
-  size_hints.y = f->output_data.x->top_pos;
+  size_hints.x = f->left_pos;
+  size_hints.y = f->top_pos;
 
 #ifdef USE_X_TOOLKIT
   XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
@@ -9168,16 +9062,16 @@ x_wm_set_size_hint (f, flags, user_position)
   size_hints.height = widget_height;
   size_hints.width = widget_width;
 #else /* not USE_X_TOOLKIT */
-  size_hints.height = PIXEL_HEIGHT (f);
-  size_hints.width = PIXEL_WIDTH (f);
+  size_hints.height = FRAME_PIXEL_HEIGHT (f);
+  size_hints.width = FRAME_PIXEL_WIDTH (f);
 #endif /* not USE_X_TOOLKIT */
 
-  size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
-  size_hints.height_inc = f->output_data.x->line_height;
+  size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
+  size_hints.height_inc = FRAME_LINE_HEIGHT (f);
   size_hints.max_width
-    = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
+    = FRAME_X_DISPLAY_INFO (f)->width - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
   size_hints.max_height
-    = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
+    = FRAME_X_DISPLAY_INFO (f)->height - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
 
   /* Calculate the base and minimum sizes.
 
@@ -9188,8 +9082,8 @@ x_wm_set_size_hint (f, flags, user_position)
     int base_width, base_height;
     int min_rows = 0, min_cols = 0;
 
-    base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
-    base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
+    base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
+    base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
 
     check_frame_size (f, &min_rows, &min_cols);
 
@@ -9264,7 +9158,7 @@ x_wm_set_size_hint (f, flags, user_position)
 #endif
 
 #ifdef PWinGravity
-  size_hints.win_gravity = f->output_data.x->win_gravity;
+  size_hints.win_gravity = f->win_gravity;
   size_hints.flags |= PWinGravity;
 
   if (user_position)
@@ -9309,7 +9203,7 @@ x_wm_set_icon_pixmap (f, pixmap_id)
      struct frame *f;
      int pixmap_id;
 {
-  Pixmap icon_pixmap;
+  Pixmap icon_pixmap, icon_mask;
 
 #ifndef USE_X_TOOLKIT
   Window window = FRAME_OUTER_WINDOW (f);
@@ -9319,6 +9213,8 @@ x_wm_set_icon_pixmap (f, pixmap_id)
     {
       icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
       f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
+      icon_mask = x_bitmap_mask (f, pixmap_id);
+      f->output_data.x->wm_hints.icon_mask = icon_mask;
     }
   else
     {
@@ -9331,6 +9227,7 @@ x_wm_set_icon_pixmap (f, pixmap_id)
         best to explicitly give up.  */
 #if 0
       f->output_data.x->wm_hints.icon_pixmap = None;
+      f->output_data.x->wm_hints.icon_mask = None;
 #else
       return;
 #endif
@@ -9342,11 +9239,13 @@ x_wm_set_icon_pixmap (f, pixmap_id)
     Arg al[1];
     XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
     XtSetValues (f->output_data.x->widget, al, 1);
+    XtSetArg (al[0], XtNiconMask, icon_mask);
+    XtSetValues (f->output_data.x->widget, al, 1);
   }
 
 #else /* not USE_X_TOOLKIT */
 
-  f->output_data.x->wm_hints.flags |= IconPixmapHint;
+  f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint);
   XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
 
 #endif /* not USE_X_TOOLKIT */
@@ -9407,11 +9306,11 @@ x_list_fonts (f, pattern, size, maxnames)
   Display *dpy = dpyinfo->display;
   int try_XLoadQueryFont = 0;
   int count;
-  int allow_scalable_fonts_p = 0;
+  int allow_auto_scaled_font = 0;
 
   if (size < 0)
     {
-      allow_scalable_fonts_p = 1;
+      allow_auto_scaled_font = 1;
       size = 0;
     }
 
@@ -9434,7 +9333,7 @@ x_list_fonts (f, pattern, size, maxnames)
         ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...)  */
       tem = XCDR (dpyinfo->name_list_element);
       key = Fcons (Fcons (pattern, make_number (maxnames)),
-                  allow_scalable_fonts_p ? Qt : Qnil);
+                  allow_auto_scaled_font ? Qt : Qnil);
       list = Fassoc (key, tem);
       if (!NILP (list))
        {
@@ -9540,25 +9439,28 @@ x_list_fonts (f, pattern, size, maxnames)
            {
              int width = 0;
              char *p = names[i];
-             int average_width = -1, dashes = 0;
+             int average_width = -1, resx = 0, dashes = 0;
 
              /* Count the number of dashes in NAMES[I].  If there are
-                14 dashes, and the field value following 12th dash
-                (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
-                is usually too ugly to be used for editing.  Let's
-                ignore it.  */
+                14 dashes, the field value following 9th dash
+                (RESOLUTION_X) is nonzero, and the field value
+                following 12th dash (AVERAGE_WIDTH) is 0, this is a
+                auto-scaled font which is usually too ugly to be used
+                for editing.  Let's ignore it.  */
              while (*p)
                if (*p++ == '-')
                  {
                    dashes++;
                    if (dashes == 7) /* PIXEL_SIZE field */
                      width = atoi (p);
+                   else if (dashes == 9)
+                     resx = atoi (p);
                    else if (dashes == 12) /* AVERAGE_WIDTH field */
                      average_width = atoi (p);
                  }
 
-             if (allow_scalable_fonts_p
-                 || dashes < 14 || average_width != 0)
+             if (allow_auto_scaled_font
+                 || dashes < 14 || average_width != 0 || resx == 0)
                {
                  tem = build_string (names[i]);
                  if (NILP (Fassoc (tem, list)))
@@ -9856,11 +9758,49 @@ x_load_font (f, fontname, size)
 
     /* Now fill in the slots of *FONTP.  */
     BLOCK_INPUT;
+    bzero (fontp, sizeof (*fontp));
     fontp->font = font;
     fontp->font_idx = i;
     fontp->name = (char *) xmalloc (strlen (fontname) + 1);
     bcopy (fontname, fontp->name, strlen (fontname) + 1);
 
+    if (font->min_bounds.width == font->max_bounds.width)
+      {
+       /* Fixed width font.  */
+       fontp->average_width = fontp->space_width = font->min_bounds.width;
+      }
+    else
+      {
+       XChar2b char2b;
+       XCharStruct *pcm;
+
+       char2b.byte1 = 0x00, char2b.byte2 = 0x20;
+       pcm = x_per_char_metric (font, &char2b, 0);
+       if (pcm)
+         fontp->space_width = pcm->width;
+       else
+         fontp->space_width = FONT_WIDTH (font);
+
+       fontp->average_width
+         = (XGetFontProperty (font, dpyinfo->Xatom_AVERAGE_WIDTH, &value)
+            ? (long) value / 10 : 0);
+       if (fontp->average_width < 0)
+         fontp->average_width = - fontp->average_width;
+       if (fontp->average_width == 0)
+         {
+           if (pcm)
+             {
+               int width = pcm->width;
+               for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
+                 if ((pcm = x_per_char_metric (font, &char2b, 0)) != NULL)
+                   width += pcm->width;
+               fontp->average_width = width / 95;
+             }
+           else
+             fontp->average_width = FONT_WIDTH (font);
+         }
+      }
+
     /* Try to get the full name of FONT.  Put it in FULL_NAME.  */
     full_name = 0;
     if (XGetFontProperty (font, XA_FONT, &value))
@@ -10110,6 +10050,34 @@ same_x_server (name1, name2)
 }
 #endif
 
+/* Count number of set bits in mask and number of bits to shift to
+   get to the first bit.  With MASK 0x7e0, *BITS is set to 6, and *OFFSET
+   to 5.  */
+static void
+get_bits_and_offset (mask, bits, offset)
+     unsigned long mask;
+     int *bits;
+     int *offset;
+{
+  int nr = 0;
+  int off = 0;
+
+  while (!(mask & 1))
+    {
+      off++;
+      mask >>= 1;
+    }
+
+  while (mask & 1)
+    {
+      nr++;
+      mask >>= 1;
+    }
+
+  *offset = off;
+  *bits = nr;
+}
+
 struct x_display_info *
 x_term_init (display_name, xrm_option, resource_name)
      Lisp_Object display_name;
@@ -10126,7 +10094,7 @@ x_term_init (display_name, xrm_option, resource_name)
   if (!x_initialized)
     {
       x_initialize ();
-      x_initialized = 1;
+      ++x_initialized;
     }
 
 #ifdef USE_GTK
@@ -10137,61 +10105,65 @@ x_term_init (display_name, xrm_option, resource_name)
     char **argv2 = argv;
     GdkAtom atom;
 
-    /* GTK 2.0 can only handle one display, GTK 2.2 can handle more
-       than one, but this remains to be implemented.  */
-    if (x_initialized > 1)
-      return 0;
-
-    x_initialized++;
-
-    for (argc = 0; argc < NUM_ARGV; ++argc)
-      argv[argc] = 0;
+    if (x_initialized++ > 1)
+      {
+        /* Opening another display.  If xg_display_open returns less
+           than zero, we are probably on GTK 2.0, which can only handle
+           one display.  GTK 2.2 or later can handle more than one.  */
+        if (xg_display_open (SDATA (display_name), &dpy) < 0)
+          error ("Sorry, this version of GTK can only handle one display");
+     }
+    else
+      {
+        for (argc = 0; argc < NUM_ARGV; ++argc)
+          argv[argc] = 0;
 
-    argc = 0;
-    argv[argc++] = initial_argv[0];
+        argc = 0;
+        argv[argc++] = initial_argv[0];
 
-    if (! NILP (display_name))
-      {
-        argv[argc++] = "--display";
-        argv[argc++] = SDATA (display_name);
-      }
+        if (! NILP (display_name))
+          {
+            argv[argc++] = "--display";
+            argv[argc++] = SDATA (display_name);
+          }
 
-    argv[argc++] = "--name";
-    argv[argc++] = resource_name;
+        argv[argc++] = "--name";
+        argv[argc++] = resource_name;
 
 #ifdef HAVE_X11R5
-    XSetLocaleModifiers ("");
+        XSetLocaleModifiers ("");
 #endif
 
-    gtk_init (&argc, &argv2);
+        gtk_init (&argc, &argv2);
 
-    /* gtk_init does set_locale.  We must fix locale after calling it.  */
-    fixup_locale ();
-    xg_initialize ();
+        /* gtk_init does set_locale.  We must fix locale after calling it.  */
+        fixup_locale ();
+        xg_initialize ();
 
-    dpy = GDK_DISPLAY ();
+        dpy = GDK_DISPLAY ();
 
-    /* NULL window -> events for all windows go to our function */
-    gdk_window_add_filter (NULL, event_handler_gdk, NULL);
+        /* NULL window -> events for all windows go to our function */
+        gdk_window_add_filter (NULL, event_handler_gdk, NULL);
 
-    /* Load our own gtkrc if it exists.  */
-    {
-      struct gcpro gcpro1, gcpro2;
-      char *file = "~/.emacs.d/gtkrc";
-      Lisp_Object s, abs_file;
+        /* Load our own gtkrc if it exists.  */
+        {
+          struct gcpro gcpro1, gcpro2;
+          char *file = "~/.emacs.d/gtkrc";
+          Lisp_Object s, abs_file;
 
-      GCPRO2 (s, abs_file);
-      s = make_string (file, strlen (file));
-      abs_file = Fexpand_file_name(s, Qnil);
+          GCPRO2 (s, abs_file);
+          s = make_string (file, strlen (file));
+          abs_file = Fexpand_file_name (s, Qnil);
 
-      if (! NILP (abs_file) && Ffile_readable_p (abs_file))
-        gtk_rc_parse (SDATA (abs_file));
+          if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
+            gtk_rc_parse (SDATA (abs_file));
 
-      UNGCPRO;
-    }
+          UNGCPRO;
+        }
 
-    XSetErrorHandler (x_error_handler);
-    XSetIOErrorHandler (x_io_error_quitter);
+        XSetErrorHandler (x_error_handler);
+        XSetIOErrorHandler (x_io_error_quitter);
+      }
   }
 #else /* not USE_GTK */
 #ifdef USE_X_TOOLKIT
@@ -10312,6 +10284,11 @@ x_term_init (display_name, xrm_option, resource_name)
   x_find_modifier_meanings (dpyinfo);
 
   /* Get the scroll bar cursor.  */
+#ifdef USE_GTK
+  /* We must create a GTK cursor, it is required for GTK widgets.  */
+  dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->display);
+#endif /* USE_GTK */
+
   dpyinfo->vertical_scroll_bar_cursor
     = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
 
@@ -10333,6 +10310,7 @@ x_term_init (display_name, xrm_option, resource_name)
   dpyinfo->height = HeightOfScreen (dpyinfo->screen);
   dpyinfo->width = WidthOfScreen (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;
@@ -10357,6 +10335,21 @@ x_term_init (display_name, xrm_option, resource_name)
   dpyinfo->x_focus_event_frame = 0;
   dpyinfo->x_highlight_frame = 0;
   dpyinfo->image_cache = make_image_cache ();
+  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;
+
+  if (dpyinfo->visual->class == TrueColor)
+    {
+      get_bits_and_offset (dpyinfo->visual->red_mask,
+                           &dpyinfo->red_bits, &dpyinfo->red_offset);
+      get_bits_and_offset (dpyinfo->visual->blue_mask,
+                           &dpyinfo->blue_bits, &dpyinfo->blue_offset);
+      get_bits_and_offset (dpyinfo->visual->green_mask,
+                           &dpyinfo->green_bits, &dpyinfo->green_offset);
+    }
 
   /* See if a private colormap is requested.  */
   if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
@@ -10382,10 +10375,12 @@ x_term_init (display_name, xrm_option, resource_name)
     int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
     double pixels = DisplayHeight (dpyinfo->display, screen_number);
     double mm = DisplayHeightMM (dpyinfo->display, screen_number);
-    dpyinfo->resy = pixels * 25.4 / mm;
+    /* Mac OS X 10.3's Xserver sometimes reports 0.0mm.  */
+    dpyinfo->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
     pixels = DisplayWidth (dpyinfo->display, screen_number);
+    /* Mac OS X 10.3's Xserver sometimes reports 0.0mm.  */
     mm = DisplayWidthMM (dpyinfo->display, screen_number);
-    dpyinfo->resx = pixels * 25.4 / mm;
+    dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
   }
 
   dpyinfo->Xatom_wm_protocols
@@ -10402,6 +10397,8 @@ x_term_init (display_name, xrm_option, resource_name)
     = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
   dpyinfo->Xatom_wm_window_moved
     = XInternAtom (dpyinfo->display, "WM_MOVED", False);
+  dpyinfo->Xatom_wm_client_leader
+    = XInternAtom (dpyinfo->display, "WM_CLIENT_LEADER", False);
   dpyinfo->Xatom_editres
     = XInternAtom (dpyinfo->display, "Editres", False);
   dpyinfo->Xatom_CLIPBOARD
@@ -10431,6 +10428,8 @@ x_term_init (display_name, xrm_option, resource_name)
   /* For properties of font.  */
   dpyinfo->Xatom_PIXEL_SIZE
     = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
+  dpyinfo->Xatom_AVERAGE_WIDTH
+    = XInternAtom (dpyinfo->display, "AVERAGE_WIDTH", False);
   dpyinfo->Xatom_MULE_BASELINE_OFFSET
     = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
   dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
@@ -10537,6 +10536,31 @@ x_term_init (display_name, xrm_option, resource_name)
       XSynchronize (dpyinfo->display, True);
   }
 
+  {
+    Lisp_Object value;
+    value = display_x_get_resource (dpyinfo,
+                                   build_string ("useXIM"),
+                                   build_string ("UseXIM"),
+                                   Qnil, Qnil);
+#ifdef USE_XIM
+    if (STRINGP (value)
+       && (!strcmp (XSTRING (value)->data, "false")
+           || !strcmp (XSTRING (value)->data, "off")))
+      use_xim = 0;
+#else
+    if (STRINGP (value)
+       && (!strcmp (XSTRING (value)->data, "true")
+           || !strcmp (XSTRING (value)->data, "on")))
+      use_xim = 1;
+#endif
+  }
+
+#ifdef HAVE_X_SM
+  /* Only do this for the first display.  */
+  if (x_initialized == 1)
+    x_session_initialize (dpyinfo);
+#endif
+
   UNBLOCK_INPUT;
 
   return dpyinfo;
@@ -10549,6 +10573,8 @@ void
 x_delete_display (dpyinfo)
      struct x_display_info *dpyinfo;
 {
+  int i;
+
   delete_keyboard_wait_descriptor (dpyinfo->connection);
 
   /* Discard this display from x_display_name_list and x_display_list.
@@ -10600,6 +10626,18 @@ x_delete_display (dpyinfo)
     xim_close_dpy (dpyinfo);
 #endif
 
+  /* Free the font names in the font table.  */
+  for (i = 0; i < dpyinfo->n_fonts; i++)
+    if (dpyinfo->font_table[i].name)
+      {
+       if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
+         xfree (dpyinfo->font_table[i].full_name);
+       xfree (dpyinfo->font_table[i].name);
+      }
+
+  if (dpyinfo->font_table->font_encoder)
+    xfree (dpyinfo->font_table->font_encoder);
+
   xfree (dpyinfo->font_table);
   xfree (dpyinfo->x_id_name);
   xfree (dpyinfo->color_cells);
@@ -10646,7 +10684,7 @@ static struct redisplay_interface x_redisplay_interface =
   x_update_window_end,
   x_cursor_to,
   x_flush,
-#ifndef XFlush
+#ifdef XFlush
   x_flush,
 #else
   0,  /* flush_display_optional */
@@ -10655,6 +10693,8 @@ static struct redisplay_interface x_redisplay_interface =
   x_get_glyph_overhangs,
   x_fix_overlapping_area,
   x_draw_fringe_bitmap,
+  0, /* define_fringe_bitmap */
+  0, /* destroy_fringe_bitmap */
   x_per_char_metric,
   x_encode_char,
   x_compute_glyph_string_overhangs,
@@ -10701,6 +10741,11 @@ x_initialize ()
   x_noop_count = 0;
   last_tool_bar_item = -1;
   any_help_event_p = 0;
+  ignore_next_mouse_click_timeout = 0;
+
+#ifdef USE_GTK
+  current_count = -1;
+#endif
 
   /* Try to use interrupt input; if we can't, then start polling.  */
   Fset_input_mode (Qt, Qnil, Qt, Qnil);
@@ -10750,10 +10795,6 @@ x_initialize ()
 #endif /* SIGWINCH */
 
   signal (SIGPIPE, x_connection_signal);
-
-#ifdef HAVE_X_SM
-  x_session_initialize ();
-#endif
 }
 
 
@@ -10788,6 +10829,16 @@ UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
 to 4.1, set this to nil.  */);
   x_use_underline_position_properties = 1;
 
+  DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
+              &x_mouse_click_focus_ignore_position,
+    doc: /* Non-nil means that a mouse click to focus a frame does not move point.
+This variable is only used when the window manager requires that you
+click on a frame to select it (give it focus).  In that case, a value
+of nil, means that the selected window and cursor position changes to
+reflect the mouse click position, while a non-nil value means that the
+selected window or cursor position is preserved.  */);
+  x_mouse_click_focus_ignore_position = 0;
+
   DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
     doc: /* What X toolkit scroll bars Emacs uses.
 A value of nil means Emacs doesn't use X toolkit scroll bars.
@@ -10856,3 +10907,6 @@ default is nil, which is the same as `super'.  */);
 }
 
 #endif /* HAVE_X_WINDOWS */
+
+/* arch-tag: 6d4e4cb7-abc1-4302-9585-d84dcfb09d0f
+   (do not change this comment) */