(x_draw_image_glyph_string): Adjust stipple origin when
[bpt/emacs.git] / src / xterm.c
index eb54674..512fff3 100644 (file)
@@ -1,12 +1,12 @@
 /* X Communication module for terminals which understand the X protocol.
-   Copyright (C) 1989, 93, 94, 95, 96, 97, 98, 1999, 2000,01,02,03,04
-   Free Software Foundation, Inc.
+   Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+                 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -16,8 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 /* New display code by Gerd Moellmann <gerd@gnu.org>.  */
 /* Xt features made by Fred Pierresteguy.  */
@@ -130,9 +130,7 @@ extern void _XEditResCheckMessages ();
 #ifdef HAVE_XAW3D
 #include <X11/Xaw3d/Simple.h>
 #include <X11/Xaw3d/Scrollbar.h>
-#define ARROW_SCROLLBAR
-#define XAW_ARROW_SCROLLBARS
-#include <X11/Xaw3d/ScrollbarP.h>
+#include <X11/Xaw3d/ThreeD.h>
 #else /* !HAVE_XAW3D */
 #include <X11/Xaw/Simple.h>
 #include <X11/Xaw/Scrollbar.h>
@@ -184,6 +182,10 @@ static Lisp_Object last_window;
 
 int x_use_underline_position_properties;
 
+/* Non-zero means to draw the underline at the same place as the descent line.  */
+
+int x_underline_at_descent_line;
+
 /* This is a chain of structures for all the X displays currently in
    use.  */
 
@@ -251,6 +253,7 @@ static unsigned long ignore_next_mouse_click_timeout;
 /* Where the mouse was last time we reported a mouse event.  */
 
 static XRectangle last_mouse_glyph;
+static FRAME_PTR last_mouse_glyph_frame;
 static Lisp_Object last_mouse_press_frame;
 
 /* The scroll bar in which the last X motion event occurred.
@@ -274,6 +277,10 @@ static Lisp_Object last_mouse_scroll_bar;
 
 static Time last_mouse_movement_time;
 
+/* Time for last user interaction as returned in X events.  */
+
+static Time last_user_time;
+
 /* Incremented by XTread_socket whenever it really tries to read
    events.  */
 
@@ -322,21 +329,8 @@ static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
 static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
 static const XColor *x_color_cells P_ ((Display *, int *));
 static void x_update_window_end P_ ((struct window *, int, int));
-void x_delete_display P_ ((struct x_display_info *));
-static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
-                                               unsigned));
+
 static int x_io_error_quitter P_ ((Display *));
-int x_catch_errors P_ ((Display *));
-void x_uncatch_errors P_ ((Display *, int));
-void x_lower_frame P_ ((struct frame *));
-void x_scroll_bar_clear P_ ((struct frame *));
-int x_had_errors_p P_ ((Display *));
-void x_wm_set_size_hint P_ ((struct frame *, long, int));
-void x_raise_frame P_ ((struct frame *));
-void x_set_window_size P_ ((struct frame *, int, int, int));
-void x_wm_set_window_state P_ ((struct frame *, int));
-void x_wm_set_icon_pixmap P_ ((struct frame *, int));
-void x_initialize P_ ((void));
 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
 static int x_compute_min_glyph_bounds P_ ((struct frame *));
 static void x_update_end P_ ((struct frame *));
@@ -368,9 +362,13 @@ static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
                                            Lisp_Object *, Lisp_Object *,
                                            unsigned long *));
 static void x_check_fullscreen P_ ((struct frame *));
-static void x_check_expected_move P_ ((struct frame *));
+static void x_check_expected_move P_ ((struct frame *, int, int));
+static void x_sync_with_move P_ ((struct frame *, int, int, int));
 static int handle_one_xevent P_ ((struct x_display_info *, XEvent *,
                                  int *, struct input_event *));
+/* Don't declare this NO_RETURN because we want no
+   interference with debugging failing X calls.  */
+static SIGTYPE x_connection_closed P_ ((Display *, char *));
 
 
 /* Flush display of frame F, or of all frames if F is null.  */
@@ -537,6 +535,12 @@ x_draw_vertical_window_border (w, x, y0, y1)
      int x, y0, y1;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
+  struct face *face;
+
+  face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
+  if (face)
+    XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
+                   face->foreground);
 
   XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
             f->output_data.x->normal_gc, x, y0, x, y1);
@@ -906,6 +910,7 @@ x_encode_char (c, char2b, font_info, two_byte_p)
       /* It's a program.  */
       struct ccl_program *ccl = font_info->font_encoder;
 
+      check_ccl_update (ccl);
       if (CHARSET_DIMENSION (charset) == 1)
        {
          ccl->reg[0] = charset;
@@ -1294,7 +1299,7 @@ x_draw_glyph_string_foreground (s)
         XDrawImageString is usually faster than XDrawString.)  Always
         use XDrawImageString when drawing the cursor so that there is
         no chance that characters under a box cursor are invisible.  */
-      if (s->for_overlaps_p
+      if (s->for_overlaps
          || (s->background_filled_p && s->hl != DRAW_CURSOR))
        {
          /* Draw characters with 16-bit or 8-bit functions.  */
@@ -2127,15 +2132,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 += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
-      if (s->area != RIGHT_MARGIN_AREA
-         || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
-       last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
-    }
+  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
@@ -2477,9 +2476,11 @@ x_draw_image_glyph_string (s)
            {
              /* Fill background with a stipple pattern.  */
              XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
+             XSetTSOrigin (s->display, s->gc, - s->x, - s->y);
              XFillRectangle (s->display, pixmap, s->gc,
                              0, 0, s->background_width, s->height);
              XSetFillStyle (s->display, s->gc, FillSolid);
+             XSetTSOrigin (s->display, s->gc, 0, 0);
            }
          else
            {
@@ -2544,19 +2545,28 @@ 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 (FRAME_COLUMN_WIDTH (s->f), s->background_width);
+      int width, background_width = s->background_width;
+      int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
+
+      if (x < left_x)
+       {
+         background_width -= left_x - x;
+         x = left_x;
+       }
+      width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
 
       /* Draw cursor.  */
-      x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
+      x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
 
       /* Clear rest using the GC of the original non-cursor face.  */
-      if (width < s->background_width)
+      if (width < background_width)
        {
-         int x = s->x + width, y = s->y;
-         int w = s->background_width - width, h = s->height;
+         int y = s->y;
+         int w = background_width - width, h = s->height;
          XRectangle r;
          GC gc;
 
+         x += width;
          if (s->row->mouse_face_p
              && cursor_in_mouse_face_p (s->w))
            {
@@ -2587,8 +2597,20 @@ x_draw_stretch_glyph_string (s)
        }
     }
   else if (!s->background_filled_p)
-    x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
-                                s->height);
+    {
+      int background_width = s->background_width;
+      int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
+
+      /* Don't draw into left margin, fringe or scrollbar area
+         except for header line and mode line.  */
+      if (x < left_x && !s->row->mode_line_p)
+       {
+         background_width -= left_x - x;
+         x = left_x;
+       }
+      if (background_width > 0)
+       x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
+    }
 
   s->background_filled_p = 1;
 }
@@ -2605,7 +2627,7 @@ x_draw_glyph_string (s)
   /* If S draws into the background of its successor, draw the
      background of the successor first so that S can draw into it.
      This makes S->next use XDrawString instead of XDrawImageString.  */
-  if (s->next && s->right_overhang && !s->for_overlaps_p)
+  if (s->next && s->right_overhang && !s->for_overlaps)
     {
       xassert (s->next->img == NULL);
       x_set_glyph_string_gc (s->next);
@@ -2618,7 +2640,7 @@ x_draw_glyph_string (s)
 
   /* Draw relief (if any) in advance for char/composition so that the
      glyph string can be drawn over it.  */
-  if (!s->for_overlaps_p
+  if (!s->for_overlaps
       && s->face->box != FACE_NO_BOX
       && (s->first_glyph->type == CHAR_GLYPH
          || s->first_glyph->type == COMPOSITE_GLYPH))
@@ -2644,7 +2666,7 @@ x_draw_glyph_string (s)
       break;
 
     case CHAR_GLYPH:
-      if (s->for_overlaps_p)
+      if (s->for_overlaps)
        s->background_filled_p = 1;
       else
        x_draw_glyph_string_background (s, 0);
@@ -2652,7 +2674,7 @@ x_draw_glyph_string (s)
       break;
 
     case COMPOSITE_GLYPH:
-      if (s->for_overlaps_p || s->gidx > 0)
+      if (s->for_overlaps || s->gidx > 0)
        s->background_filled_p = 1;
       else
        x_draw_glyph_string_background (s, 1);
@@ -2663,7 +2685,7 @@ x_draw_glyph_string (s)
       abort ();
     }
 
-  if (!s->for_overlaps_p)
+  if (!s->for_overlaps)
     {
       /* Draw underline.  */
       if (s->face->underline_p)
@@ -2675,32 +2697,34 @@ x_draw_glyph_string (s)
          if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
            h = 1;
 
-         /* Get the underline position.  This is the recommended
-            vertical offset in pixels from the baseline to the top of
-            the underline.  This is a signed value according to the
-            specs, and its default is
-
-            ROUND ((maximum descent) / 2), with
-            ROUND(x) = floor (x + 0.5)  */
-
-         if (x_use_underline_position_properties
-             && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
-           y = s->ybase + (long) tem;
-         else if (s->face->font)
-           y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
-         else
-           y = s->y + s->height - h;
+         y = s->y + s->height - h;
+         if (!x_underline_at_descent_line)
+            {
+             /* Get the underline position.  This is the recommended
+                 vertical offset in pixels from the baseline to the top of
+                 the underline.  This is a signed value according to the
+                 specs, and its default is
+
+                ROUND ((maximum descent) / 2), with
+                ROUND(x) = floor (x + 0.5)  */
+
+              if (x_use_underline_position_properties
+                  && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
+                y = s->ybase + (long) tem;
+              else if (s->face->font)
+                y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
+            }
 
          if (s->face->underline_defaulted_p)
            XFillRectangle (s->display, s->window, s->gc,
-                           s->x, y, s->width, h);
+                           s->x, y, s->background_width, h);
          else
            {
              XGCValues xgcv;
              XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
              XSetForeground (s->display, s->gc, s->face->underline_color);
              XFillRectangle (s->display, s->window, s->gc,
-                             s->x, y, s->width, h);
+                             s->x, y, s->background_width, h);
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
@@ -2712,14 +2736,14 @@ x_draw_glyph_string (s)
 
          if (s->face->overline_color_defaulted_p)
            XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                           s->width, h);
+                           s->background_width, h);
          else
            {
              XGCValues xgcv;
              XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
              XSetForeground (s->display, s->gc, s->face->overline_color);
              XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                             s->width, h);
+                             s->background_width, h);
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
@@ -3464,7 +3488,7 @@ x_find_modifier_meanings (dpyinfo)
 /* Convert between the modifier bits X uses and the modifier bits
    Emacs uses.  */
 
-static unsigned int
+unsigned int
 x_x_to_emacs_modifiers (dpyinfo, state)
      struct x_display_info *dpyinfo;
      unsigned int state;
@@ -3583,7 +3607,7 @@ construct_mouse_click (result, event, f)
 static XMotionEvent last_mouse_motion_event;
 static Lisp_Object last_mouse_motion_frame;
 
-static void
+static int
 note_mouse_movement (frame, event)
      FRAME_PTR frame;
      XMotionEvent *event;
@@ -3592,23 +3616,36 @@ note_mouse_movement (frame, event)
   last_mouse_motion_event = *event;
   XSETFRAME (last_mouse_motion_frame, frame);
 
+  if (!FRAME_X_OUTPUT (frame))
+    return 0;
+
   if (event->window != FRAME_X_WINDOW (frame))
     {
       frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
       note_mouse_highlight (frame, -1, -1);
+      last_mouse_glyph_frame = 0;
+      return 1;
     }
 
+
   /* Has the mouse moved off the glyph it was on at the last sighting?  */
-  else if (event->x < last_mouse_glyph.x
-          || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
-          || event->y < last_mouse_glyph.y
-          || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
+  if (frame != last_mouse_glyph_frame
+      || event->x < last_mouse_glyph.x
+      || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
+      || event->y < last_mouse_glyph.y
+      || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
     {
       frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
       note_mouse_highlight (frame, event->x, event->y);
+      /* Remember which glyph we're now on.  */
+      remember_mouse_glyph (frame, event->x, event->y, &last_mouse_glyph);
+      last_mouse_glyph_frame = frame;
+      return 1;
     }
+
+  return 0;
 }
 
 \f
@@ -3627,56 +3664,6 @@ redo_mouse_highlight ()
 }
 
 
-static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
-
-
-/* Try to determine frame pixel position and size of the glyph under
-   frame pixel coordinates X/Y on frame F .  Return the position and
-   size in *RECT.  Value is non-zero if we could compute these
-   values.  */
-
-static int
-glyph_rect (f, x, y, rect)
-     struct frame *f;
-     int x, y;
-     XRectangle *rect;
-{
-  Lisp_Object window;
-  struct window *w;
-  struct glyph_row *r, *end_row;
-
-  window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
-  if (NILP (window))
-    return 0;
-
-  w = XWINDOW (window);
-  r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-  end_row = r + w->current_matrix->nrows - 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 0;
-}
-
 
 /* Return the current position of the mouse.
    *FP should be a frame which indicates which display to ask about.
@@ -3757,7 +3744,6 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
        Window win, child;
        int win_x, win_y;
        int parent_x = 0, parent_y = 0;
-       int count;
 
        win = root;
 
@@ -3765,7 +3751,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
           structure is changing at the same time this function
           is running.  So at least we must not crash from them.  */
 
-       count = x_catch_errors (FRAME_X_DISPLAY (*fp));
+       x_catch_errors (FRAME_X_DISPLAY (*fp));
 
        if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
            && FRAME_LIVE_P (last_mouse_frame))
@@ -3834,7 +3820,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
        if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
          f1 = 0;
 
-       x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
+       x_uncatch_errors ();
 
        /* If not, is it one of our scroll bars?  */
        if (! f1)
@@ -3864,32 +3850,8 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
               on it, i.e. into the same rectangles that matrices on
               the frame are divided into.  */
 
-           int width, height, gx, gy;
-           XRectangle rect;
-
-           if (glyph_rect (f1, win_x, win_y, &rect))
-             last_mouse_glyph = rect;
-           else
-             {
-               width = FRAME_SMALLEST_CHAR_WIDTH (f1);
-               height = FRAME_SMALLEST_FONT_HEIGHT (f1);
-               gx = win_x;
-               gy = win_y;
-
-               /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
-                  round down even for negative values.  */
-               if (gx < 0)
-                 gx -= width - 1;
-               if (gy < 0)
-                 gy -= height - 1;
-               gx = (gx + width - 1) / width * width;
-               gy = (gy + height - 1) / height * height;
-
-               last_mouse_glyph.width  = width;
-               last_mouse_glyph.height = height;
-               last_mouse_glyph.x = gx;
-               last_mouse_glyph.y = gy;
-             }
+           remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph);
+           last_mouse_glyph_frame = f1;
 
            *bar_window = Qnil;
            *part = 0;
@@ -4025,8 +3987,6 @@ static Boolean xaw3d_arrow_scroll;
 
 static Boolean xaw3d_pick_top;
 
-extern void set_vertical_scroll_bar P_ ((struct window *));
-
 /* Action hook installed via XtAppAddActionHook when toolkit scroll
    bars are used..  The hook is responsible for detecting when
    the user ends an interaction with the scroll bar, and generates
@@ -4139,6 +4099,9 @@ x_send_scroll_bar_event (window, part, portion, whole)
 
   /* Make Xt timeouts work while the scroll bar is active.  */
   toolkit_scroll_bar_interaction = 1;
+#ifdef USE_X_TOOLKIT
+  x_activate_timeout_atimer ();
+#endif
 
   /* Setting the event mask to zero means that the message will
      be sent to the client that created the window, and if that
@@ -4329,7 +4292,7 @@ xg_scroll_callback (widget, data)
     }
 
   if (part >= 0)
-    { 
+    {
       window_being_scrolled = bar->window;
       last_scroll_bar_part = part;
       x_send_scroll_bar_event (bar->window, part, portion, whole);
@@ -4553,6 +4516,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)
@@ -4576,16 +4540,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);
@@ -4594,11 +4559,14 @@ x_create_toolkit_scroll_bar (f, bar)
     char *initial = "";
     char *val = initial;
     XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
+#ifdef XtNarrowScrollbars
+                  XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
+#endif
                   XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
-    if (val == initial)
+    if (xaw3d_arrow_scroll || val == initial)
       {        /* ARROW_SCROLL */
        xaw3d_arrow_scroll = True;
-       /* Isn't that just a personal preference ?   -sm */
+       /* Isn't that just a personal preference ?   --Stef */
        XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
       }
   }
@@ -4731,30 +4699,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
          }
       }
   }
@@ -5334,6 +5283,11 @@ x_scroll_bar_expose (bar, event)
 
   x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
 
+  /* Switch to scroll bar foreground color.  */
+  if (f->output_data.x->scroll_bar_foreground_pixel != -1)
+    XSetForeground (FRAME_X_DISPLAY (f), gc,
+                   f->output_data.x->scroll_bar_foreground_pixel);
+
   /* Draw a one-pixel border just inside the edges of the scroll bar.  */
   XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
 
@@ -5342,7 +5296,12 @@ x_scroll_bar_expose (bar, event)
                  XINT (bar->width) - 1 - width_trim - width_trim,
                  XINT (bar->height) - 1);
 
-  UNBLOCK_INPUT;
+   /* Restore the foreground color of the GC if we changed it above.  */
+   if (f->output_data.x->scroll_bar_foreground_pixel != -1)
+     XSetForeground (FRAME_X_DISPLAY (f), gc,
+                   f->output_data.x->foreground_pixel);
+
+   UNBLOCK_INPUT;
 
 }
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
@@ -5625,8 +5584,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);     \
-        inev.kind = MENU_BAR_ACTIVATE_EVENT;                           \
-        XSETFRAME (inev.frame_or_window, f);                           \
+        inev.ie.kind = MENU_BAR_ACTIVATE_EVENT;                        \
+        XSETFRAME (inev.ie.frame_or_window, f);                        \
        }                                                               \
      while (0)
 
@@ -5733,7 +5692,10 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
      int *finish;
      struct input_event *hold_quit;
 {
-  struct input_event inev;
+  union {
+    struct input_event ie;
+    struct selection_input_event sie;
+  } inev;
   int count = 0;
   int do_help = 0;
   int nbytes = 0;
@@ -5743,9 +5705,9 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
   *finish = X_EVENT_NORMAL;
 
-  EVENT_INIT (inev);
-  inev.kind = NO_EVENT;
-  inev.arg = Qnil;
+  EVENT_INIT (inev.ie);
+  inev.ie.kind = NO_EVENT;
+  inev.ie.arg = Qnil;
 
   switch (event.type)
     {
@@ -5788,7 +5750,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                     Display *d = event.xclient.display;
                     /* Catch and ignore errors, in case window has been
                        iconified by a window manager such as GWM.  */
-                    int count = x_catch_errors (d);
+                    x_catch_errors (d);
                     XSetInputFocus (d, event.xclient.window,
                                     /* The ICCCM says this is
                                        the only valid choice.  */
@@ -5797,7 +5759,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                     /* This is needed to detect the error
                        if there is an error.  */
                     XSync (d, False);
-                    x_uncatch_errors (d, count);
+                    x_uncatch_errors ();
                   }
                 /* Not certain about handling scroll bars here */
 #endif /* 0 */
@@ -5843,8 +5805,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                 if (!f)
                  goto OTHER; /* May be a dialog that is to be removed  */
 
-               inev.kind = DELETE_WINDOW_EVENT;
-               XSETFRAME (inev.frame_or_window, f);
+               inev.ie.kind = DELETE_WINDOW_EVENT;
+               XSETFRAME (inev.ie.frame_or_window, f);
                goto done;
               }
 
@@ -5879,8 +5841,9 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
            == dpyinfo->Xatom_editres)
           {
            f = x_any_window_to_frame (dpyinfo, event.xclient.window);
-            _XEditResCheckMessages (f->output_data.x->widget, NULL,
-                                    &event, NULL);
+           if (f)
+              _XEditResCheckMessages (f->output_data.x->widget, NULL,
+                                      &event, NULL);
            goto done;
           }
 #endif /* HACK_EDITRES */
@@ -5896,6 +5859,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                images, only, which should have 1 page.  */
             Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
            f = x_window_to_frame (dpyinfo, event.xclient.window);
+           if (!f)
+             goto OTHER;
             x_kill_gs_process (pixmap, f);
             expose_frame (f, 0, 0, 0, 0);
            goto done;
@@ -5907,23 +5872,22 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         if (event.xclient.message_type
            == dpyinfo->Xatom_Scrollbar)
           {
-            x_scroll_bar_to_input_event (&event, &inev);
+            x_scroll_bar_to_input_event (&event, &inev.ie);
            *finish = X_EVENT_GOTO_OUT;
             goto done;
           }
 #endif /* USE_TOOLKIT_SCROLL_BARS */
 
        f = x_any_window_to_frame (dpyinfo, event.xclient.window);
-
        if (!f)
          goto OTHER;
-
-       if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev))
+       if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie))
          *finish = X_EVENT_DROP;
       }
       break;
 
     case SelectionNotify:
+      last_user_time = event.xselection.time;
 #ifdef USE_X_TOOLKIT
       if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
         goto OTHER;
@@ -5932,6 +5896,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
       break;
 
     case SelectionClear:       /* Someone has grabbed ownership.  */
+      last_user_time = event.xselectionclear.time;
 #ifdef USE_X_TOOLKIT
       if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
         goto OTHER;
@@ -5939,15 +5904,16 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
       {
         XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
 
-        inev.kind = SELECTION_CLEAR_EVENT;
-        SELECTION_EVENT_DISPLAY (&inev) = eventp->display;
-        SELECTION_EVENT_SELECTION (&inev) = eventp->selection;
-        SELECTION_EVENT_TIME (&inev) = eventp->time;
-        inev.frame_or_window = Qnil;
+        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;
 
     case SelectionRequest:     /* Someone wants our selection.  */
+      last_user_time = event.xselectionrequest.time;
 #ifdef USE_X_TOOLKIT
       if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
         goto OTHER;
@@ -5956,18 +5922,19 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
           XSelectionRequestEvent *eventp
             = (XSelectionRequestEvent *) &event;
 
-          inev.kind = SELECTION_REQUEST_EVENT;
-          SELECTION_EVENT_DISPLAY (&inev) = eventp->display;
-          SELECTION_EVENT_REQUESTOR (&inev) = eventp->requestor;
-          SELECTION_EVENT_SELECTION (&inev) = eventp->selection;
-          SELECTION_EVENT_TARGET (&inev) = eventp->target;
-          SELECTION_EVENT_PROPERTY (&inev) = eventp->property;
-          SELECTION_EVENT_TIME (&inev) = eventp->time;
-          inev.frame_or_window = Qnil;
+          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:
+      last_user_time = event.xproperty.time;
 #if 0 /* This is plain wrong.  In the case that we are waiting for a
         PropertyNotify used as an ACK in incremental selection
         transfer, the property will be on the receiver's window.  */
@@ -5991,6 +5958,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
           /* Perhaps reparented due to a WM restart.  Reset this.  */
           FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
+          FRAME_X_DISPLAY_INFO (f)->net_supported_window = 0;
         }
       goto OTHER;
 
@@ -6000,6 +5968,14 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         {
           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;
@@ -6094,8 +6070,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
             {
               f->async_iconified = 1;
 
-              inev.kind = ICONIFY_EVENT;
-              XSETFRAME (inev.frame_or_window, f);
+              inev.ie.kind = ICONIFY_EVENT;
+              XSETFRAME (inev.ie.frame_or_window, f);
             }
         }
       goto OTHER;
@@ -6127,8 +6103,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
           if (f->iconified)
             {
-              inev.kind = DEICONIFY_EVENT;
-              XSETFRAME (inev.frame_or_window, f);
+              inev.ie.kind = DEICONIFY_EVENT;
+              XSETFRAME (inev.ie.frame_or_window, f);
             }
           else if (! NILP (Vframe_list)
                    && ! NILP (XCDR (Vframe_list)))
@@ -6141,6 +6117,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
     case KeyPress:
 
+      last_user_time = event.xkey.time;
       ignore_next_mouse_click_timeout = 0;
 
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
@@ -6151,7 +6128,11 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
       f = x_any_window_to_frame (dpyinfo, event.xkey.window);
 
-      if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+      /* If mouse-highlight is an integer, input clears out
+        mouse highlighting.  */
+      if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+         && (f == 0
+             || !EQ (f->tool_bar_window, dpyinfo->mouse_face_window)))
         {
           clear_mouse_face (dpyinfo);
           dpyinfo->mouse_face_hidden = 1;
@@ -6237,7 +6218,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
               if (status_return == XBufferOverflow)
                 {
                   copy_bufsiz = nbytes + 1;
-                  copy_bufptr = (char *) alloca (copy_bufsiz);
+                  copy_bufptr = (unsigned char *) alloca (copy_bufsiz);
                   nbytes = XmbLookupString (FRAME_XIC (f),
                                             &event.xkey, copy_bufptr,
                                             copy_bufsiz, &keysym,
@@ -6255,7 +6236,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                   if (status_return == XBufferOverflow)
                     {
                       copy_bufsiz = nbytes + 1;
-                      copy_bufptr = (char *) alloca (copy_bufsiz);
+                      copy_bufptr = (unsigned char *) alloca (copy_bufsiz);
                       nbytes = Xutf8LookupString (FRAME_XIC (f),
                                                   &event.xkey,
                                                   copy_bufptr,
@@ -6291,21 +6272,60 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
           if (compose_status.chars_matched > 0 && nbytes == 0)
             break;
 
+          bzero (&compose_status, sizeof (compose_status));
           orig_keysym = keysym;
 
          /* Common for all keysym input events.  */
-         XSETFRAME (inev.frame_or_window, f);
-         inev.modifiers
+         XSETFRAME (inev.ie.frame_or_window, f);
+         inev.ie.modifiers
            = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers);
-         inev.timestamp = event.xkey.time;
+         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.  */
            {
-             inev.kind = ASCII_KEYSTROKE_EVENT;
-             inev.code = keysym;
+             inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+             inev.ie.code = keysym;
+             goto done_keysym;
+           }
+
+         /* Keysyms directly mapped to supported Unicode characters.  */
+         if ((keysym >= 0x01000000 && keysym <= 0x010033ff)
+             || (keysym >= 0x0100e000 && keysym <= 0x0100ffff))
+           {
+             int code = keysym & 0xFFFF, charset_id, c1, c2;
+
+             if (code < 0x80)
+               {
+                 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+                 inev.ie.code = code;
+               }
+             else if (code < 0x100)
+               {
+                 if (code < 0xA0)
+                   charset_id = CHARSET_8_BIT_CONTROL;
+                 else
+                   charset_id = charset_latin_iso8859_1;
+                 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+                 inev.ie.code = MAKE_CHAR (charset_id, code, 0);
+               }
+             else
+               {
+                 if (code < 0x2500)
+                   charset_id = charset_mule_unicode_0100_24ff,
+                     code -= 0x100;
+                 else if (code < 0xE000)
+                   charset_id = charset_mule_unicode_2500_33ff,
+                     code -= 0x2500;
+                 else
+                   charset_id = charset_mule_unicode_e000_ffff,
+                     code -= 0xE000;
+                 c1 = (code / 96) + 32, c2 = (code % 96) + 32;
+                 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+                 inev.ie.code = MAKE_CHAR (charset_id, c1, c2);
+               }
              goto done_keysym;
            }
 
@@ -6315,10 +6335,10 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                                         Vx_keysym_table,
                                         Qnil))))
            {
-             inev.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
-                           ? ASCII_KEYSTROKE_EVENT
-                           : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-             inev.code = XFASTINT (c);
+             inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
+                             ? ASCII_KEYSTROKE_EVENT
+                             : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+             inev.ie.code = XFASTINT (c);
              goto done_keysym;
            }
 
@@ -6408,8 +6428,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
              STORE_KEYSYM_FOR_DEBUG (keysym);
              /* make_lispy_event will convert this to a symbolic
                 key.  */
-             inev.kind = NON_ASCII_KEYSTROKE_EVENT;
-             inev.code = keysym;
+             inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
+             inev.ie.code = keysym;
              goto done_keysym;
            }
 
@@ -6460,18 +6480,18 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                else
                  c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
                                              nbytes - i, len);
-               inev.kind = (SINGLE_BYTE_CHAR_P (c)
+               inev.ie.kind = (SINGLE_BYTE_CHAR_P (c)
                              ? ASCII_KEYSTROKE_EVENT
                              : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-               inev.code = c;
-               kbd_buffer_store_event_hold (&inev, hold_quit);
+               inev.ie.code = c;
+               kbd_buffer_store_event_hold (&inev.ie, hold_quit);
              }
 
            /* Previous code updated count by nchars rather than nbytes,
               but that seems bogus to me.  ++kfs  */
            count += nbytes;
 
-           inev.kind = NO_EVENT;  /* Already stored above.  */
+           inev.ie.kind = NO_EVENT;  /* Already stored above.  */
 
            if (keysym == NoSymbol)
              break;
@@ -6488,6 +6508,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 #endif
 
     case KeyRelease:
+      last_user_time = event.xkey.time;
 #ifdef HAVE_X_I18N
       /* Don't dispatch this event since XtDispatchEvent calls
          XFilterEvent, and two calls in a row may freeze the
@@ -6498,7 +6519,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 #endif
 
     case EnterNotify:
-      x_detect_focus_change (dpyinfo, &event, &inev);
+      last_user_time = event.xcrossing.time;
+      x_detect_focus_change (dpyinfo, &event, &inev.ie);
 
       f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
 
@@ -6525,14 +6547,21 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         so update things that depend on mouse position.  */
       if (f && !f->output_data.x->hourglass_p)
        note_mouse_movement (f, &event.xmotion);
+#ifdef USE_GTK
+      /* We may get an EnterNotify on the buttons in the toolbar.  In that
+         case we moved out of any highlighted area and need to note this.  */
+      if (!f && last_mouse_glyph_frame)
+        note_mouse_movement (last_mouse_glyph_frame, &event);
+#endif
       goto OTHER;
 
     case FocusIn:
-      x_detect_focus_change (dpyinfo, &event, &inev);
+      x_detect_focus_change (dpyinfo, &event, &inev.ie);
       goto OTHER;
 
     case LeaveNotify:
-      x_detect_focus_change (dpyinfo, &event, &inev);
+      last_user_time = event.xcrossing.time;
+      x_detect_focus_change (dpyinfo, &event, &inev.ie);
 
       f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
       if (f)
@@ -6552,17 +6581,22 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
           if (any_help_event_p)
            do_help = -1;
         }
+#ifdef USE_GTK
+      /* See comment in EnterNotify above */
+      else if (last_mouse_glyph_frame)
+        note_mouse_movement (last_mouse_glyph_frame, &event);
+#endif
       goto OTHER;
 
     case FocusOut:
-      x_detect_focus_change (dpyinfo, &event, &inev);
+      x_detect_focus_change (dpyinfo, &event, &inev.ie);
       goto OTHER;
 
     case MotionNotify:
       {
+        last_user_time = event.xmotion.time;
         previous_help_echo_string = help_echo_string;
-        help_echo_string = help_echo_object = help_echo_window = Qnil;
-        help_echo_pos = -1;
+        help_echo_string = Qnil;
 
         if (dpyinfo->grabbed && last_mouse_frame
             && FRAME_LIVE_P (last_mouse_frame))
@@ -6580,7 +6614,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
           {
 
             /* Generate SELECT_WINDOW_EVENTs when needed.  */
-            if (mouse_autoselect_window)
+            if (!NILP (Vmouse_autoselect_window))
               {
                 Lisp_Object window;
 
@@ -6590,18 +6624,19 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
                 /* 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.  */
+                   will be selected only when it is active.  */
                 if (WINDOWP (window)
                     && !EQ (window, last_window)
                     && !EQ (window, selected_window))
                   {
-                    inev.kind = SELECT_WINDOW_EVENT;
-                    inev.frame_or_window = window;
+                    inev.ie.kind = SELECT_WINDOW_EVENT;
+                    inev.ie.frame_or_window = window;
                   }
 
                 last_window=window;
               }
-            note_mouse_movement (f, &event.xmotion);
+            if (!note_mouse_movement (f, &event.xmotion))
+             help_echo_string = previous_help_echo_string;
           }
         else
           {
@@ -6678,11 +6713,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
               && 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->left_pos, &f->top_pos);
 
-             x_check_expected_move (f);
              if (f->want_fullscreen & FULLSCREEN_WAIT)
                f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
             }
@@ -6710,6 +6742,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         int tool_bar_p = 0;
 
         bzero (&compose_status, sizeof (compose_status));
+       last_mouse_glyph_frame = 0;
+        last_user_time = event.xbutton.time;
 
         if (dpyinfo->grabbed
             && last_mouse_frame
@@ -6729,15 +6763,16 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                 int y = event.xbutton.y;
 
                 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
-                if (EQ (window, f->tool_bar_window))
+                tool_bar_p = EQ (window, f->tool_bar_window);
+
+                if (tool_bar_p && event.xbutton.button < 4)
                   {
-                   if (event.xbutton.type == ButtonPress)
-                     handle_tool_bar_click (f, x, y, 1, 0);
-                   else
-                     handle_tool_bar_click (f, x, y, 0,
-                                            x_x_to_emacs_modifiers (dpyinfo,
+                    if (event.xbutton.type == ButtonPress)
+                      handle_tool_bar_click (f, x, y, 1, 0);
+                    else
+                      handle_tool_bar_click (f, x, y, 0,
+                                             x_x_to_emacs_modifiers (dpyinfo,
                                                                     event.xbutton.state));
-                   tool_bar_p = 1;
                   }
               }
 
@@ -6755,13 +6790,13 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                              && (int)(event.xbutton.time - ignore_next_mouse_click_timeout) > 0)
                            {
                              ignore_next_mouse_click_timeout = 0;
-                             construct_mouse_click (&inev, &event, f);
+                             construct_mouse_click (&inev.ie, &event.xbutton, f);
                            }
                          if (event.type == ButtonRelease)
                            ignore_next_mouse_click_timeout = 0;
                        }
                      else
-                       construct_mouse_click (&inev, &event, f);
+                       construct_mouse_click (&inev.ie, &event.xbutton, f);
                    }
                 }
           }
@@ -6776,12 +6811,12 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                scroll bars.  */
             if (bar && event.xbutton.state & ControlMask)
               {
-                x_scroll_bar_handle_click (bar, &event, &inev);
+                x_scroll_bar_handle_click (bar, &event, &inev.ie);
                 *finish = X_EVENT_DROP;
               }
 #else /* not USE_TOOLKIT_SCROLL_BARS */
             if (bar)
-              x_scroll_bar_handle_click (bar, &event, &inev);
+              x_scroll_bar_handle_click (bar, &event, &inev.ie);
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
           }
 
@@ -6789,12 +6824,6 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
           {
             dpyinfo->grabbed |= (1 << event.xbutton.button);
             last_mouse_frame = f;
-            /* Ignore any mouse motion that happened
-               before this event; any subsequent mouse-movement
-               Emacs events should reflect only motion after
-               the ButtonPress.  */
-            if (f != 0)
-              f->mouse_moved = 0;
 
             if (!tool_bar_p)
               last_tool_bar_item = -1;
@@ -6802,6 +6831,12 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         else
           dpyinfo->grabbed &= ~(1 << event.xbutton.button);
 
+       /* Ignore any mouse motion that happened before this event;
+          any subsequent mouse-movement Emacs events should reflect
+          only motion after the ButtonPress/Release.  */
+       if (f != 0)
+         f->mouse_moved = 0;
+
 #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,
@@ -6889,9 +6924,9 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
     }
 
  done:
-  if (inev.kind != NO_EVENT)
+  if (inev.ie.kind != NO_EVENT)
     {
-      kbd_buffer_store_event_hold (&inev, hold_quit);
+      kbd_buffer_store_event_hold (&inev.ie, hold_quit);
       count++;
     }
 
@@ -7148,7 +7183,7 @@ x_clip_to_row (w, row, area, gc)
   window_box (w, area, &window_x, &window_y, &window_width, 0);
 
   clip_rect.x = window_x;
-  clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+  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;
@@ -7178,29 +7213,9 @@ x_draw_hollow_cursor (w, row)
   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 (FRAME_COLUMN_WIDTH (f), wd);
-  w->phys_cursor_width = wd;
-
-  /* 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);
-
-  /* Compute the proper height and ascent of the rectangle, based
-     on the actual glyph.  Using the full height of the row looks
-     bad when there are tall images on that row.  */
-  h = max (min (FRAME_LINE_HEIGHT (f), row->height),
-          cursor_glyph->ascent + cursor_glyph->descent);
-  if (h < row->height)
-    y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
-  h--;
+  /* Compute frame-relative coordinates for phys cursor.  */
+  get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &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.  */
@@ -7214,7 +7229,7 @@ x_draw_hollow_cursor (w, row)
 
   /* Set clipping, draw the rectangle, and reset clipping again.  */
   x_clip_to_row (w, row, TEXT_AREA, gc);
-  XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
+  XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h - 1);
   XSetClipMask (dpy, gc, None);
 }
 
@@ -7427,10 +7442,30 @@ x_bitmap_icon (f, file)
       /* 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);
-         x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
+         int rc = -1;
+
+#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
+#ifdef USE_GTK
+         if (xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
+           return 0;
+#else
+         rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
+         if (rc != -1)
+           FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
+#endif /* USE_GTK */
+#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
+
+         /* If all else fails, use the (black and white) xbm image. */
+         if (rc == -1)
+           {
+             rc = x_create_bitmap_from_data (f, gnu_xbm_bits,
+                                             gnu_xbm_width, gnu_xbm_height);
+             if (rc == -1)
+               return 1;
+
+             FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
+             x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
+           }
        }
 
       /* The first time we create the GNU bitmap and mask,
@@ -7484,12 +7519,21 @@ x_text_icon (f, icon_name)
 #define X_ERROR_MESSAGE_SIZE 200
 
 /* If non-nil, this should be a string.
-   It means catch X errors  and store the error message in this string.  */
+   It means catch X errors  and store the error message in this string.
 
-static Lisp_Object x_error_message_string;
+   The reason we use a stack is that x_catch_error/x_uncatch_error can
+   be called from a signal handler.
+*/
+
+struct x_error_message_stack {
+  char string[X_ERROR_MESSAGE_SIZE];
+  Display *dpy;
+  struct x_error_message_stack *prev;
+};
+static struct x_error_message_stack *x_error_message;
 
 /* An X error handler which stores the error message in
-   x_error_message_string.  This is called from x_error_handler if
+   *x_error_message.  This is called from x_error_handler if
    x_catch_errors is in effect.  */
 
 static void
@@ -7498,7 +7542,7 @@ x_error_catcher (display, error)
      XErrorEvent *error;
 {
   XGetErrorText (display, error->error_code,
-                SDATA (x_error_message_string),
+                x_error_message->string,
                 X_ERROR_MESSAGE_SIZE);
 }
 
@@ -7508,7 +7552,7 @@ x_error_catcher (display, error)
 
    After calling this function, X protocol errors no longer cause
    Emacs to exit; instead, they are recorded in the string
-   stored in x_error_message_string.
+   stored in *x_error_message.
 
    Calling x_check_errors signals an Emacs error if an X error has
    occurred since the last call to x_catch_errors or x_check_errors.
@@ -7516,47 +7560,41 @@ x_error_catcher (display, error)
    Calling x_uncatch_errors resumes the normal error handling.  */
 
 void x_check_errors ();
-static Lisp_Object x_catch_errors_unwind ();
 
-int
+void
 x_catch_errors (dpy)
      Display *dpy;
 {
-  int count = SPECPDL_INDEX ();
+  struct x_error_message_stack *data = xmalloc (sizeof (*data));
 
   /* Make sure any errors from previous requests have been dealt with.  */
   XSync (dpy, False);
 
-  record_unwind_protect (x_catch_errors_unwind,
-                        Fcons (make_save_value (dpy, 0),
-                               x_error_message_string));
-
-  x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
-  SSET (x_error_message_string, 0, 0);
-
-  return count;
+  data->dpy = dpy;
+  data->string[0] = 0;
+  data->prev = x_error_message;
+  x_error_message = data;
 }
 
-/* Unbind the binding that we made to check for X errors.  */
+/* Undo the last x_catch_errors call.
+   DPY should be the display that was passed to x_catch_errors.  */
 
-static Lisp_Object
-x_catch_errors_unwind (old_val)
-     Lisp_Object old_val;
+void
+x_uncatch_errors ()
 {
-  Lisp_Object first = XCAR (old_val);
-  Display *dpy = XSAVE_VALUE (first)->pointer;
+  struct x_error_message_stack *tmp;
+
+  BLOCK_INPUT;
 
   /* 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;
-    }
+  if (x_display_info_for_display (x_error_message->dpy) != 0)
+    XSync (x_error_message->dpy, False);
 
-  x_error_message_string = XCDR (old_val);
-  return Qnil;
+  tmp = x_error_message;
+  x_error_message = x_error_message->prev;
+  xfree (tmp);
+  UNBLOCK_INPUT;
 }
 
 /* If any X protocol errors have arrived since the last call to
@@ -7571,8 +7609,13 @@ x_check_errors (dpy, format)
   /* Make sure to catch any errors incurred so far.  */
   XSync (dpy, False);
 
-  if (SREF (x_error_message_string, 0))
-    error (format, SDATA (x_error_message_string));
+  if (x_error_message->string[0])
+    {
+      char string[X_ERROR_MESSAGE_SIZE];
+      bcopy (x_error_message->string, string, X_ERROR_MESSAGE_SIZE);
+      x_uncatch_errors ();
+      error (format, string);
+    }
 }
 
 /* Nonzero if we had any X protocol errors
@@ -7585,7 +7628,7 @@ x_had_errors_p (dpy)
   /* Make sure to catch any errors incurred so far.  */
   XSync (dpy, False);
 
-  return SREF (x_error_message_string, 0) != 0;
+  return x_error_message->string[0] != 0;
 }
 
 /* Forget about any errors we have had, since we did x_catch_errors on DPY.  */
@@ -7594,20 +7637,24 @@ void
 x_clear_errors (dpy)
      Display *dpy;
 {
-  SSET (x_error_message_string, 0, 0);
+  x_error_message->string[0] = 0;
 }
 
-/* Stop catching X protocol errors and let them make Emacs die.
-   DPY should be the display that was passed to x_catch_errors.
-   COUNT should be the value that was returned by
-   the corresponding call to x_catch_errors.  */
+/* Close off all unclosed x_catch_errors calls.  */
 
 void
-x_uncatch_errors (dpy, count)
-     Display *dpy;
-     int count;
+x_fully_uncatch_errors ()
+{
+  while (x_error_message)
+    x_uncatch_errors ();
+}
+
+/* Nonzero if x_catch_errors has been done and not yet canceled.  */
+
+int
+x_catching_errors ()
 {
-  unbind_to (count, Qnil);
+  return x_error_message != 0;
 }
 
 #if 0
@@ -7666,7 +7713,6 @@ x_connection_closed (dpy, error_message)
 {
   struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
   Lisp_Object frame, tail;
-  int count;
 
   error_msg = (char *) alloca (strlen (error_message) + 1);
   strcpy (error_msg, error_message);
@@ -7676,7 +7722,7 @@ x_connection_closed (dpy, error_message)
      below.  Otherwise, we might end up with printing ``can't find per
      display information'' in the recursive call instead of printing
      the original message here.  */
-  count = x_catch_errors (dpy);
+  x_catch_errors (dpy);
 
   /* We have to close the display to inform Xt that it doesn't
      exist anymore.  If we don't, Xt will continue to wait for
@@ -7744,7 +7790,7 @@ x_connection_closed (dpy, error_message)
   if (dpyinfo)
     x_delete_display (dpyinfo);
 
-  x_uncatch_errors (dpy, count);
+  x_uncatch_errors ();
 
   if (x_display_list == 0)
     {
@@ -7764,18 +7810,59 @@ 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 P_ ((Display *, XErrorEvent *));
+
+/* 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 (x_error_message)
+    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
+
+/* Some versions of GNU/Linux define noinline in their headers.  */
+
+#ifdef noinline
+#undef noinline
+#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;
 {
   char buf[256], buf1[356];
 
+  /* Ignore BadName errors.  They can happen because of fonts
+     or colors that are not defined.  */
+
+  if (error->error_code == BadName)
+    return;
+
   /* Note that there is no real way portable across R3/R4 to get the
      original error handler.  */
 
@@ -7786,21 +7873,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.  */
@@ -8140,7 +8212,6 @@ void
 x_calc_absolute_position (f)
      struct frame *f;
 {
-  int win_x = 0, win_y = 0;
   int flags = f->size_hint_flags;
 
   /* We have nothing to do if the current position
@@ -8197,8 +8268,11 @@ x_set_offset (f, xoff, yoff, change_gravity)
 {
   int modified_top, modified_left;
 
-  if (change_gravity > 0)
+  if (change_gravity != 0)
     {
+      FRAME_X_OUTPUT (f)->left_before_move = f->left_pos;
+      FRAME_X_OUTPUT (f)->top_before_move = f->top_pos;
+
       f->top_pos = yoff;
       f->left_pos = xoff;
       f->size_hint_flags &= ~ (XNegative | YNegative);
@@ -8216,7 +8290,7 @@ x_set_offset (f, xoff, yoff, change_gravity)
   modified_left = f->left_pos;
   modified_top = f->top_pos;
 
-  if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
+  if (change_gravity != 0 && FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
     {
       /* Some WMs (twm, wmaker at least) has an offset that is smaller
          than the WM decorations.  So we use the calculated offset instead
@@ -8228,17 +8302,222 @@ x_set_offset (f, xoff, yoff, change_gravity)
   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)
+  x_sync_with_move (f, f->left_pos, f->top_pos,
+                    FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
+                    ? 1 : 0);
+
+  /* change_gravity is non-zero when this function is called from Lisp to
+     programmatically move a frame.  In that case, we call
+     x_check_expected_move to discover if we have a "Type A" or "Type B"
+     window manager, and, for a "Type A" window manager, adjust the position
+     of the frame.
+
+     We call x_check_expected_move if a programmatic move occurred, and
+     either the window manager type (A/B) is unknown or it is Type A but we
+     need to compute the top/left offset adjustment for this frame.  */
+
+  if (change_gravity != 0 &&
+      (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
+       || (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
+           && (FRAME_X_OUTPUT (f)->move_offset_left == 0
+               && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
+    x_check_expected_move (f, modified_left, modified_top);
+
+  UNBLOCK_INPUT;
+}
+
+/* Return non-zero if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
+   on the root window for frame F contains ATOMNAME.
+   This is how a WM check shall be done according to the Window Manager
+   Specification/Extended Window Manager Hints at
+   http://freedesktop.org/wiki/Standards_2fwm_2dspec.  */
+
+static int
+wm_supports (f, atomname)
+     struct frame *f;
+     const char *atomname;
+{
+  Atom actual_type;
+  unsigned long actual_size, bytes_remaining;
+  int i, rc, actual_format;
+  Atom prop_atom;
+  Window wmcheck_window;
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  Window target_window = dpyinfo->root_window;
+  long max_len = 65536;
+  Display *dpy = FRAME_X_DISPLAY (f);
+  unsigned char *tmp_data = NULL;
+  Atom target_type = XA_WINDOW;
+  Atom want_atom;
+
+  BLOCK_INPUT;
+
+  prop_atom = XInternAtom (dpy, "_NET_SUPPORTING_WM_CHECK", False);
+
+  x_catch_errors (dpy);
+  rc = XGetWindowProperty (dpy, target_window,
+                           prop_atom, 0, max_len, False, target_type,
+                           &actual_type, &actual_format, &actual_size,
+                           &bytes_remaining, &tmp_data);
+  
+  if (rc != Success || actual_type != XA_WINDOW || x_had_errors_p (dpy))
     {
-      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;
+      if (tmp_data) XFree (tmp_data);
+      x_uncatch_errors ();
+      UNBLOCK_INPUT;
+      return 0;
+    }
+
+  wmcheck_window = *(Window *) tmp_data;
+  XFree (tmp_data);
+
+  /* Check if window exists. */
+  XSelectInput (dpy, wmcheck_window, StructureNotifyMask);
+  x_sync (f);
+  if (x_had_errors_p (dpy))
+    {
+      x_uncatch_errors ();
+      UNBLOCK_INPUT;
+      return 0;
+    }
+
+  if (dpyinfo->net_supported_window != wmcheck_window)
+    {
+      /* Window changed, reload atoms */
+      if (dpyinfo->net_supported_atoms != NULL)
+        XFree (dpyinfo->net_supported_atoms);
+      dpyinfo->net_supported_atoms = NULL;
+      dpyinfo->nr_net_supported_atoms = 0;
+      dpyinfo->net_supported_window = 0;
+
+      target_type = XA_ATOM;
+      prop_atom = XInternAtom (dpy, "_NET_SUPPORTED", False);
+      tmp_data = NULL;
+      rc = XGetWindowProperty (dpy, target_window,
+                               prop_atom, 0, max_len, False, target_type,
+                               &actual_type, &actual_format, &actual_size,
+                               &bytes_remaining, &tmp_data);
+
+      if (rc != Success || actual_type != XA_ATOM || x_had_errors_p (dpy))
+        {
+          if (tmp_data) XFree (tmp_data);
+          x_uncatch_errors ();
+          UNBLOCK_INPUT;
+          return 0;
+        }
+
+      dpyinfo->net_supported_atoms = (Atom *)tmp_data;
+      dpyinfo->nr_net_supported_atoms = actual_size;
+      dpyinfo->net_supported_window = wmcheck_window;
     }
 
+  rc = 0;
+  want_atom = XInternAtom (dpy, atomname, False);
+
+  for (i = 0; rc == 0 && i < dpyinfo->nr_net_supported_atoms; ++i) 
+    rc = dpyinfo->net_supported_atoms[i] == want_atom;
+
+  x_uncatch_errors ();
   UNBLOCK_INPUT;
+
+  return rc;
+}
+
+/* Do fullscreen as specified in extended window manager hints */
+
+static int
+do_ewmh_fullscreen (f)
+     struct frame *f;
+{
+  int have_net_atom = wm_supports (f, "_NET_WM_STATE");
+
+  /* Some window managers don't say they support _NET_WM_STATE, but they do say
+     they support _NET_WM_STATE_FULLSCREEN.  Try that also.  */
+  if (!have_net_atom)
+      have_net_atom = wm_supports (f, "_NET_WM_STATE_FULLSCREEN");
+
+  if (have_net_atom)
+    {
+      Lisp_Object frame;
+      const char *atom = "_NET_WM_STATE";
+      const char *fs = "_NET_WM_STATE_FULLSCREEN";
+      const char *fw = "_NET_WM_STATE_MAXIMIZED_HORZ";
+      const char *fh = "_NET_WM_STATE_MAXIMIZED_VERT";
+      const char *what = NULL;
+
+      XSETFRAME (frame, f);
+
+      /* If there are _NET_ atoms we assume we have extended window manager
+         hints.  */
+      switch (f->want_fullscreen)
+        {
+        case FULLSCREEN_BOTH:
+          what = fs;
+          break;
+        case FULLSCREEN_WIDTH:
+          what = fw;
+          break;
+        case FULLSCREEN_HEIGHT:
+          what = fh;
+          break;
+        }
+
+      if (what != NULL && !wm_supports (f, what)) return 0;
+
+
+      Fx_send_client_event (frame, make_number (0), frame,
+                            make_unibyte_string (atom, strlen (atom)),
+                            make_number (32),
+                            Fcons (make_number (0), /* Remove */
+                                   Fcons
+                                   (make_unibyte_string (fs,
+                                                         strlen (fs)),
+                                    Qnil)));
+      Fx_send_client_event (frame, make_number (0), frame,
+                            make_unibyte_string (atom, strlen (atom)),
+                            make_number (32),
+                            Fcons (make_number (0), /* Remove */
+                                   Fcons
+                                   (make_unibyte_string (fh,
+                                                         strlen (fh)),
+                                    Qnil)));
+      Fx_send_client_event (frame, make_number (0), frame,
+                            make_unibyte_string (atom, strlen (atom)),
+                            make_number (32),
+                            Fcons (make_number (0), /* Remove */
+                                   Fcons
+                                   (make_unibyte_string (fw,
+                                                         strlen (fw)),
+                                    Qnil)));
+      f->want_fullscreen = FULLSCREEN_NONE;
+      if (what != NULL)
+        Fx_send_client_event (frame, make_number (0), frame,
+                              make_unibyte_string (atom, strlen (atom)),
+                              make_number (32),
+                              Fcons (make_number (1), /* Add */
+                                     Fcons
+                                     (make_unibyte_string (what,
+                                                           strlen (what)),
+                                      Qnil)));
+    }
+
+  return have_net_atom;
 }
 
+static void
+XTfullscreen_hook (f)
+     FRAME_PTR f;
+{
+  if (f->async_visible)
+    {
+      BLOCK_INPUT;
+      do_ewmh_fullscreen (f);
+      x_sync (f);
+      UNBLOCK_INPUT;
+    }
+}
+
+
 /* Check if we need to resize the frame due to a fullscreen request.
    If so needed, resize the frame. */
 static void
@@ -8249,6 +8528,9 @@ x_check_fullscreen (f)
     {
       int width, height, ign;
 
+      if (do_ewmh_fullscreen (f))
+        return;
+
       x_real_positions (f, &f->left_pos, &f->top_pos);
 
       x_fullscreen_adjust (f, &width, &height, &ign, &ign);
@@ -8269,37 +8551,96 @@ x_check_fullscreen (f)
     }
 }
 
-/* If frame parameters are set after the frame is mapped, we need to move
-   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. */
+/* This function is called by x_set_offset to determine whether the window
+   manager interfered with the positioning of the frame.  Type A window
+   managers position the surrounding window manager decorations a small
+   amount above and left of the user-supplied position.  Type B window
+   managers position the surrounding window manager decorations at the
+   user-specified position.  If we detect a Type A window manager, we
+   compensate by moving the window right and down by the proper amount.  */
+
 static void
-x_check_expected_move (f)
+x_check_expected_move (f, expected_left, expected_top)
      struct frame *f;
+     int expected_left;
+     int expected_top;
 {
-  if (FRAME_X_OUTPUT (f)->check_expected_move)
-  {
-    int expect_top = FRAME_X_OUTPUT (f)->expected_top;
-    int expect_left = FRAME_X_OUTPUT (f)->expected_left;
+  int current_left = 0, current_top = 0;
+
+  /* x_real_positions returns the left and top offsets of the outermost
+     window manager window around the frame.  */
+
+  x_real_positions (f, &current_left, &current_top);
 
-    if (expect_top != f->top_pos || expect_left != f->left_pos)
+  if (current_left != expected_left || current_top != expected_top)
       {
+      /* It's a "Type A" window manager. */
+
+      int adjusted_left;
+      int adjusted_top;
+
         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;
+      FRAME_X_OUTPUT (f)->move_offset_left = expected_left - current_left;
+      FRAME_X_OUTPUT (f)->move_offset_top = expected_top - current_top;
+
+      /* Now fix the mispositioned frame's location. */
+
+      adjusted_left = expected_left + FRAME_X_OUTPUT (f)->move_offset_left;
+      adjusted_top = expected_top + FRAME_X_OUTPUT (f)->move_offset_top;
+
+      XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+                   adjusted_left, adjusted_top);
 
-        f->left_pos = expect_left;
-        f->top_pos = expect_top;
-        x_set_offset (f, expect_left, expect_top, 0);
+      x_sync_with_move (f, expected_left, expected_top, 0);
       }
-    else if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN)
+  else
+    /* It's a "Type B" window manager.  We don't have to adjust the
+       frame's position. */
+
       FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
+}
+
+
+/* Wait for XGetGeometry to return up-to-date position information for a
+   recently-moved frame.  Call this immediately after calling XMoveWindow.
+   If FUZZY is non-zero, then LEFT and TOP are just estimates of where the
+   frame has been moved to, so we use a fuzzy position comparison instead
+   of an exact comparison.  */
+
+static void
+x_sync_with_move (f, left, top, fuzzy)
+    struct frame *f;
+    int left, top, fuzzy;
+{
+  int count = 0;
+
+  while (count++ < 50)
+    {
+      int current_left = 0, current_top = 0;
 
-    /* Just do this once */
-    FRAME_X_OUTPUT (f)->check_expected_move = 0;
+      /* In theory, this call to XSync only needs to happen once, but in
+         practice, it doesn't seem to work, hence the need for the surrounding
+         loop.  */
+
+      XSync (FRAME_X_DISPLAY (f), False);
+      x_real_positions (f, &current_left, &current_top);
+
+      if (fuzzy)
+        {
+          /* The left fuzz-factor is 10 pixels.  The top fuzz-factor is 40
+             pixels.  */
+
+          if (abs (current_left - left) <= 10 && abs (current_top - top) <= 40)
+            return;
   }
+      else if (current_left == left && current_top == top)
+        return;
+    }
+
+  /* As a last resort, just wait 0.5 seconds and hope that XGetGeometry
+     will then return up-to-date position info. */
+
+  wait_reading_process_output (0, 500000, 0, 0, Qnil, NULL, 0);
 }
 
 
@@ -8491,13 +8832,12 @@ void
 x_raise_frame (f)
      struct frame *f;
 {
+  BLOCK_INPUT;
   if (f->async_visible)
-    {
-      BLOCK_INPUT;
-      XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
-      XFlush (FRAME_X_DISPLAY (f));
-      UNBLOCK_INPUT;
-    }
+    XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
+
+  XFlush (FRAME_X_DISPLAY (f));
+  UNBLOCK_INPUT;
 }
 
 /* Lower frame F.  */
@@ -8521,7 +8861,32 @@ XTframe_raise_lower (f, raise_flag)
      int raise_flag;
 {
   if (raise_flag)
-    x_raise_frame (f);
+    {
+      /* The following code is needed for `raise-frame' to work on
+        some versions of metacity; see Window Manager
+        Specification/Extended Window Manager Hints at
+        http://freedesktop.org/wiki/Standards_2fwm_2dspec  */
+
+#if 0
+      /* However, on other versions (metacity 2.17.2-1.fc7), it
+        reportedly causes hangs when resizing frames.  */
+
+      const char *atom = "_NET_ACTIVE_WINDOW";
+      if (f->async_visible && wm_supports (f, atom))
+        {
+          Lisp_Object frame;
+          XSETFRAME (frame, f);
+          Fx_send_client_event (frame, make_number (0), frame,
+                                make_unibyte_string (atom, strlen (atom)),
+                                make_number (32),
+                                Fcons (make_number (1),
+                                       Fcons (make_number (last_user_time),
+                                              Qnil)));
+        }
+      else
+#endif
+        x_raise_frame (f);
+    }
   else
     x_lower_frame (f);
 }
@@ -9252,7 +9617,14 @@ x_wm_set_icon_pixmap (f, pixmap_id)
 #endif
     }
 
-#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state.  */
+
+#ifdef USE_GTK
+  {
+    xg_set_frame_icon (f, icon_pixmap, icon_mask);
+    return;
+  }
+
+#elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state.  */
 
   {
     Arg al[1];
@@ -9262,12 +9634,12 @@ x_wm_set_icon_pixmap (f, pixmap_id)
     XtSetValues (f->output_data.x->widget, al, 1);
   }
 
-#else /* not USE_X_TOOLKIT */
+#else /* not USE_X_TOOLKIT && not USE_GTK */
 
   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 */
+#endif /* not USE_X_TOOLKIT && not USE_GTK */
 }
 
 void
@@ -9324,7 +9696,6 @@ x_list_fonts (f, pattern, size, maxnames)
     = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
   Display *dpy = dpyinfo->display;
   int try_XLoadQueryFont = 0;
-  int count;
   int allow_auto_scaled_font = 0;
 
   if (size < 0)
@@ -9364,7 +9735,7 @@ x_list_fonts (f, pattern, size, maxnames)
       /* At first, put PATTERN in the cache.  */
 
       BLOCK_INPUT;
-      count = x_catch_errors (dpy);
+      x_catch_errors (dpy);
 
       if (try_XLoadQueryFont)
        {
@@ -9445,7 +9816,7 @@ x_list_fonts (f, pattern, size, maxnames)
            }
        }
 
-      x_uncatch_errors (dpy, count);
+      x_uncatch_errors ();
       UNBLOCK_INPUT;
 
       if (names)
@@ -9536,7 +9907,7 @@ x_list_fonts (f, pattern, size, maxnames)
              XFontStruct *thisinfo;
 
              BLOCK_INPUT;
-             count = x_catch_errors (dpy);
+             x_catch_errors (dpy);
              thisinfo = XLoadQueryFont (dpy,
                                         SDATA (XCAR (tem)));
              if (x_had_errors_p (dpy))
@@ -9546,7 +9917,7 @@ x_list_fonts (f, pattern, size, maxnames)
                  thisinfo = NULL;
                  x_clear_errors (dpy);
                }
-             x_uncatch_errors (dpy, count);
+             x_uncatch_errors ();
              UNBLOCK_INPUT;
 
              if (thisinfo)
@@ -9702,7 +10073,6 @@ x_load_font (f, fontname, size)
 {
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   Lisp_Object font_names;
-  int count;
 
   /* Get a list of all the fonts that match this name.  Once we
      have a list of matching fonts, we compare them against the fonts
@@ -9741,7 +10111,7 @@ x_load_font (f, fontname, size)
       fontname = (char *) SDATA (XCAR (font_names));
 
     BLOCK_INPUT;
-    count = x_catch_errors (FRAME_X_DISPLAY (f));
+    x_catch_errors (FRAME_X_DISPLAY (f));
     font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
     if (x_had_errors_p (FRAME_X_DISPLAY (f)))
       {
@@ -9750,7 +10120,7 @@ x_load_font (f, fontname, size)
        font = NULL;
        x_clear_errors (FRAME_X_DISPLAY (f));
       }
-    x_uncatch_errors (FRAME_X_DISPLAY (f), count);
+    x_uncatch_errors ();
     UNBLOCK_INPUT;
     if (!font)
       return NULL;
@@ -9952,8 +10322,8 @@ x_query_font (f, fontname)
 
   for (i = 0; i < dpyinfo->n_fonts; i++)
     if (dpyinfo->font_table[i].name
-       && (!strcmp (dpyinfo->font_table[i].name, fontname)
-           || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
+       && (!xstricmp (dpyinfo->font_table[i].name, fontname)
+           || !xstricmp (dpyinfo->font_table[i].full_name, fontname)))
       return (dpyinfo->font_table + i);
   return NULL;
 }
@@ -10016,10 +10386,19 @@ static XrmOptionDescRec emacs_options[] = {
   {"-mc",      "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
   {"-cr",      "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
 };
+
+/* Whether atimer for Xt timeouts is activated or not.  */
+
+static int x_timeout_atimer_activated_flag;
+
 #endif /* USE_X_TOOLKIT */
 
 static int x_initialized;
 
+#ifdef HAVE_X_SM
+static int x_session_initialized;
+#endif
+
 #ifdef MULTI_KBOARD
 /* Test whether two display-name strings agree up to the dot that separates
    the screen number from the server number.  */
@@ -10097,6 +10476,21 @@ get_bits_and_offset (mask, bits, offset)
   *bits = nr;
 }
 
+int
+x_display_ok (display)
+    const char * display;
+{
+    int dpy_ok = 1;
+    Display *dpy;
+
+    dpy = XOpenDisplay (display);
+    if (dpy)
+      XCloseDisplay (dpy);
+    else
+      dpy_ok = 0;
+    return dpy_ok;
+}
+
 struct x_display_info *
 x_term_init (display_name, xrm_option, resource_name)
      Lisp_Object display_name;
@@ -10166,18 +10560,14 @@ x_term_init (display_name, xrm_option, resource_name)
 
         /* 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);
 
           if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
             gtk_rc_parse (SDATA (abs_file));
-
-          UNGCPRO;
         }
 
         XSetErrorHandler (x_error_handler);
@@ -10465,6 +10855,15 @@ x_term_init (display_name, xrm_option, resource_name)
 
   dpyinfo->cut_buffers_initialized = 0;
 
+  dpyinfo->x_dnd_atoms_size = 8;
+  dpyinfo->x_dnd_atoms_length = 0;
+  dpyinfo->x_dnd_atoms = xmalloc (sizeof (*dpyinfo->x_dnd_atoms)
+                                  * dpyinfo->x_dnd_atoms_size);
+
+  dpyinfo->net_supported_atoms = NULL;
+  dpyinfo->nr_net_supported_atoms = 0;
+  dpyinfo->net_supported_window = 0;
+
   connection = ConnectionNumber (dpyinfo->display);
   dpyinfo->connection = connection;
 
@@ -10523,7 +10922,6 @@ x_term_init (display_name, xrm_option, resource_name)
     Display *dpy = dpyinfo->display;
     XrmValue d, fr, to;
     Font font;
-    int count;
 
     d.addr = (XPointer)&dpy;
     d.size = sizeof (Display *);
@@ -10531,12 +10929,12 @@ x_term_init (display_name, xrm_option, resource_name)
     fr.size = sizeof (XtDefaultFont);
     to.size = sizeof (Font *);
     to.addr = (XPointer)&font;
-    count = x_catch_errors (dpy);
+    x_catch_errors (dpy);
     if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
       abort ();
     if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
       XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
-    x_uncatch_errors (dpy, count);
+    x_uncatch_errors ();
   }
 #endif
 #endif
@@ -10576,7 +10974,7 @@ x_term_init (display_name, xrm_option, resource_name)
 
 #ifdef HAVE_X_SM
   /* Only do this for the first display.  */
-  if (x_initialized == 1)
+  if (!x_session_initialized++)
     x_session_initialize (dpyinfo);
 #endif
 
@@ -10654,12 +11052,16 @@ x_delete_display (dpyinfo)
        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);
+  if (dpyinfo->font_table)
+    {
+      if (dpyinfo->font_table->font_encoder)
+       xfree (dpyinfo->font_table->font_encoder);
+      xfree (dpyinfo->font_table);
+    }
+  if (dpyinfo->x_id_name)
+    xfree (dpyinfo->x_id_name);
+  if (dpyinfo->color_cells)
+    xfree (dpyinfo->color_cells);
   xfree (dpyinfo);
 }
 
@@ -10674,13 +11076,39 @@ static void
 x_process_timeouts (timer)
      struct atimer *timer;
 {
+  BLOCK_INPUT;
+  x_timeout_atimer_activated_flag = 0;
   if (toolkit_scroll_bar_interaction || popup_activated ())
     {
-      BLOCK_INPUT;
       while (XtAppPending (Xt_app_con) & XtIMTimer)
        XtAppProcessEvent (Xt_app_con, XtIMTimer);
-      UNBLOCK_INPUT;
+      /* Reactivate the atimer for next time.  */
+      x_activate_timeout_atimer ();
     }
+  UNBLOCK_INPUT;
+}
+
+/* Install an asynchronous timer that processes Xt timeout events
+   every 0.1s as long as either `toolkit_scroll_bar_interaction' or
+   `popup_activated_flag' (in xmenu.c) is set.  Make sure to call this
+   function whenever these variables are set.  This is necessary
+   because some widget sets use timeouts internally, for example the
+   LessTif menu bar, or the Xaw3d scroll bar.  When Xt timeouts aren't
+   processed, these widgets don't behave normally.  */
+
+void
+x_activate_timeout_atimer ()
+{
+  BLOCK_INPUT;
+  if (!x_timeout_atimer_activated_flag)
+    {
+      EMACS_TIME interval;
+
+      EMACS_SET_SECS_USECS (interval, 0, 100000);
+      start_atimer (ATIMER_RELATIVE, interval, x_process_timeouts, 0);
+      x_timeout_atimer_activated_flag = 1;
+    }
+  UNBLOCK_INPUT;
 }
 
 #endif /* USE_X_TOOLKIT */
@@ -10748,6 +11176,7 @@ x_initialize ()
   condemn_scroll_bars_hook = XTcondemn_scroll_bars;
   redeem_scroll_bar_hook = XTredeem_scroll_bar;
   judge_scroll_bars_hook = XTjudge_scroll_bars;
+  fullscreen_hook = XTfullscreen_hook;
 
   scroll_region_ok = 1;                /* we'll scroll partial frames */
   char_ins_del_ok = 1;
@@ -10761,6 +11190,9 @@ x_initialize ()
   last_tool_bar_item = -1;
   any_help_event_p = 0;
   ignore_next_mouse_click_timeout = 0;
+#ifdef HAVE_X_SM
+  x_session_initialized = 0;
+#endif
 
 #ifdef USE_GTK
   current_count = -1;
@@ -10783,17 +11215,6 @@ x_initialize ()
                         XtCacheByDisplay, cvt_pixel_dtor);
 
   XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
-
-  /* Install an asynchronous timer that processes Xt timeout events
-     every 0.1s.  This is necessary because some widget sets use
-     timeouts internally, for example the LessTif menu bar, or the
-     Xaw3d scroll bar.  When Xt timouts aren't processed, these
-     widgets don't behave normally.  */
-  {
-    EMACS_TIME interval;
-    EMACS_SET_SECS_USECS (interval, 0, 100000);
-    start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
-  }
 #endif
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
@@ -10820,8 +11241,7 @@ x_initialize ()
 void
 syms_of_xterm ()
 {
-  staticpro (&x_error_message_string);
-  x_error_message_string = Qnil;
+  x_error_message = NULL;
 
   staticpro (&x_display_name_list);
   x_display_name_list = Qnil;
@@ -10843,11 +11263,19 @@ syms_of_xterm ()
   DEFVAR_BOOL ("x-use-underline-position-properties",
               &x_use_underline_position_properties,
      doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
-nil means ignore them.  If you encounter fonts with bogus
+A value of nil means ignore them.  If you encounter fonts with bogus
 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-underline-at-descent-line",
+              &x_underline_at_descent_line,
+     doc: /* *Non-nil means to draw the underline at the same place as the descent line.
+A value of nil means to draw the underline according to the value of the
+variable `x-use-underline-position-properties', which is usually at the
+baseline level.  The default value is nil.  */);
+  x_underline_at_descent_line = 0;
+
   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.