(x_draw_image_glyph_string): Adjust stipple origin when
[bpt/emacs.git] / src / xterm.c
index 2528348..512fff3 100644 (file)
@@ -1,12 +1,12 @@
 /* X Communication module for terminals which understand the X protocol.
    Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
 /* X Communication module for terminals which understand the X protocol.
    Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-                 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+                 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
 
 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,
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -182,6 +182,10 @@ static Lisp_Object last_window;
 
 int x_use_underline_position_properties;
 
 
 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.  */
 
 /* This is a chain of structures for all the X displays currently in
    use.  */
 
@@ -249,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;
 /* 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.
 static Lisp_Object last_mouse_press_frame;
 
 /* The scroll bar in which the last X motion event occurred.
@@ -272,6 +277,10 @@ static Lisp_Object last_mouse_scroll_bar;
 
 static Time last_mouse_movement_time;
 
 
 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.  */
 
 /* Incremented by XTread_socket whenever it really tries to read
    events.  */
 
@@ -320,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));
 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 *));
 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 *));
 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 *));
@@ -366,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 *));
                                            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 *));
 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.  */
 
 
 /* Flush display of frame F, or of all frames if F is null.  */
@@ -2476,9 +2476,11 @@ x_draw_image_glyph_string (s)
            {
              /* Fill background with a stipple pattern.  */
              XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
            {
              /* 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);
              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
            {
            }
          else
            {
@@ -2543,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.  */
     {
       /* 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.  */
 
       /* 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.  */
 
       /* 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;
 
          XRectangle r;
          GC gc;
 
+         x += width;
          if (s->row->mouse_face_p
              && cursor_in_mouse_face_p (s->w))
            {
          if (s->row->mouse_face_p
              && cursor_in_mouse_face_p (s->w))
            {
@@ -2586,8 +2597,20 @@ x_draw_stretch_glyph_string (s)
        }
     }
   else if (!s->background_filled_p)
        }
     }
   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;
 }
 
   s->background_filled_p = 1;
 }
@@ -2674,32 +2697,34 @@ x_draw_glyph_string (s)
          if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
            h = 1;
 
          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,
 
          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,
          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);
            }
        }
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
@@ -2711,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,
 
          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,
          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);
            }
        }
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
@@ -3463,7 +3488,7 @@ x_find_modifier_meanings (dpyinfo)
 /* Convert between the modifier bits X uses and the modifier bits
    Emacs uses.  */
 
 /* 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;
 x_x_to_emacs_modifiers (dpyinfo, state)
      struct x_display_info *dpyinfo;
      unsigned int state;
@@ -3591,26 +3616,32 @@ note_mouse_movement (frame, event)
   last_mouse_motion_event = *event;
   XSETFRAME (last_mouse_motion_frame, frame);
 
   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);
   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;
     }
 
       return 1;
     }
 
-  note_mouse_highlight (frame, event->x, event->y);
 
   /* Has the mouse moved off the glyph it was on at the last sighting?  */
 
   /* Has the mouse moved off the glyph it was on at the last sighting?  */
-  if (event->x < last_mouse_glyph.x
+  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;
       || 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);
       /* 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 1;
     }
 
@@ -3713,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;
        Window win, child;
        int win_x, win_y;
        int parent_x = 0, parent_y = 0;
-       int count;
 
        win = root;
 
 
        win = root;
 
@@ -3721,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.  */
 
           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))
 
        if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
            && FRAME_LIVE_P (last_mouse_frame))
@@ -3790,7 +3820,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
        if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
          f1 = 0;
 
        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)
 
        /* If not, is it one of our scroll bars?  */
        if (! f1)
@@ -3821,6 +3851,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
               the frame are divided into.  */
 
            remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph);
               the frame are divided into.  */
 
            remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph);
+           last_mouse_glyph_frame = f1;
 
            *bar_window = Qnil;
            *part = 0;
 
            *bar_window = Qnil;
            *part = 0;
@@ -4068,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;
 
   /* 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
 
   /* Setting the event mask to zero means that the message will
      be sent to the client that created the window, and if that
@@ -5249,6 +5283,11 @@ x_scroll_bar_expose (bar, event)
 
   x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
 
 
   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,
 
   /* Draw a one-pixel border just inside the edges of the scroll bar.  */
   XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
 
@@ -5257,7 +5296,12 @@ x_scroll_bar_expose (bar, event)
                  XINT (bar->width) - 1 - width_trim - width_trim,
                  XINT (bar->height) - 1);
 
                  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 */
 
 }
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
@@ -5706,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.  */
                     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.  */
                     XSetInputFocus (d, event.xclient.window,
                                     /* The ICCCM says this is
                                        the only valid choice.  */
@@ -5715,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);
                     /* 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 */
                   }
                 /* Not certain about handling scroll bars here */
 #endif /* 0 */
@@ -5797,8 +5841,9 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
            == dpyinfo->Xatom_editres)
           {
            f = x_any_window_to_frame (dpyinfo, event.xclient.window);
            == 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 */
            goto done;
           }
 #endif /* HACK_EDITRES */
@@ -5814,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);
                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;
             x_kill_gs_process (pixmap, f);
             expose_frame (f, 0, 0, 0, 0);
            goto done;
@@ -5832,16 +5879,15 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 #endif /* USE_TOOLKIT_SCROLL_BARS */
 
        f = x_any_window_to_frame (dpyinfo, event.xclient.window);
 #endif /* USE_TOOLKIT_SCROLL_BARS */
 
        f = x_any_window_to_frame (dpyinfo, event.xclient.window);
-
        if (!f)
          goto OTHER;
        if (!f)
          goto OTHER;
-
        if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie))
          *finish = X_EVENT_DROP;
       }
       break;
 
     case SelectionNotify:
        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;
 #ifdef USE_X_TOOLKIT
       if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
         goto OTHER;
@@ -5850,6 +5896,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
       break;
 
     case SelectionClear:       /* Someone has grabbed ownership.  */
       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;
 #ifdef USE_X_TOOLKIT
       if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
         goto OTHER;
@@ -5866,6 +5913,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
       break;
 
     case SelectionRequest:     /* Someone wants our selection.  */
       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;
 #ifdef USE_X_TOOLKIT
       if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
         goto OTHER;
@@ -5886,6 +5934,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
       break;
 
     case PropertyNotify:
       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.  */
 #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.  */
@@ -5909,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;
 
           /* 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;
 
         }
       goto OTHER;
 
@@ -6067,6 +6117,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
     case KeyPress:
 
 
     case KeyPress:
 
+      last_user_time = event.xkey.time;
       ignore_next_mouse_click_timeout = 0;
 
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
       ignore_next_mouse_click_timeout = 0;
 
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
@@ -6077,7 +6128,11 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
       f = x_any_window_to_frame (dpyinfo, event.xkey.window);
 
 
       f = x_any_window_to_frame (dpyinfo, event.xkey.window);
 
-      if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+      /* 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;
         {
           clear_mouse_face (dpyinfo);
           dpyinfo->mouse_face_hidden = 1;
@@ -6237,23 +6292,40 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
            }
 
          /* Keysyms directly mapped to supported Unicode characters.  */
            }
 
          /* Keysyms directly mapped to supported Unicode characters.  */
-         if ((keysym >= 0x01000100 && keysym <= 0x010033ff)
+         if ((keysym >= 0x01000000 && keysym <= 0x010033ff)
              || (keysym >= 0x0100e000 && keysym <= 0x0100ffff))
            {
              || (keysym >= 0x0100e000 && keysym <= 0x0100ffff))
            {
-             int code, charset_id, c1, c2;
-
-             if (keysym < 0x01002500)
-               charset_id = charset_mule_unicode_0100_24ff,
-                 code = (keysym & 0xFFFF) - 0x100;
-             else if (keysym < 0x0100e000)
-               charset_id = charset_mule_unicode_2500_33ff,
-                 code = (keysym & 0xFFFF) - 0x2500;
+             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
              else
-               charset_id = charset_mule_unicode_e000_ffff,
-                 code = (keysym & 0xFFFF) - 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);
+               {
+                 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;
            }
 
              goto done_keysym;
            }
 
@@ -6436,6 +6508,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 #endif
 
     case KeyRelease:
 #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
 #ifdef HAVE_X_I18N
       /* Don't dispatch this event since XtDispatchEvent calls
          XFilterEvent, and two calls in a row may freeze the
@@ -6446,6 +6519,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 #endif
 
     case EnterNotify:
 #endif
 
     case EnterNotify:
+      last_user_time = event.xcrossing.time;
       x_detect_focus_change (dpyinfo, &event, &inev.ie);
 
       f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
       x_detect_focus_change (dpyinfo, &event, &inev.ie);
 
       f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
@@ -6473,6 +6547,12 @@ 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);
         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:
       goto OTHER;
 
     case FocusIn:
@@ -6480,6 +6560,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
       goto OTHER;
 
     case LeaveNotify:
       goto OTHER;
 
     case LeaveNotify:
+      last_user_time = event.xcrossing.time;
       x_detect_focus_change (dpyinfo, &event, &inev.ie);
 
       f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
       x_detect_focus_change (dpyinfo, &event, &inev.ie);
 
       f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
@@ -6500,6 +6581,11 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
           if (any_help_event_p)
            do_help = -1;
         }
           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:
       goto OTHER;
 
     case FocusOut:
@@ -6508,6 +6594,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
     case MotionNotify:
       {
 
     case MotionNotify:
       {
+        last_user_time = event.xmotion.time;
         previous_help_echo_string = help_echo_string;
         help_echo_string = Qnil;
 
         previous_help_echo_string = help_echo_string;
         help_echo_string = Qnil;
 
@@ -6527,7 +6614,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
           {
 
             /* Generate SELECT_WINDOW_EVENTs when needed.  */
           {
 
             /* Generate SELECT_WINDOW_EVENTs when needed.  */
-            if (mouse_autoselect_window)
+            if (!NILP (Vmouse_autoselect_window))
               {
                 Lisp_Object window;
 
               {
                 Lisp_Object window;
 
@@ -6537,7 +6624,7 @@ 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
 
                 /* 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))
                 if (WINDOWP (window)
                     && !EQ (window, last_window)
                     && !EQ (window, selected_window))
@@ -6626,11 +6713,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
               && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f)))
 #endif
             {
               && 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_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);
             }
              if (f->want_fullscreen & FULLSCREEN_WAIT)
                f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
             }
@@ -6658,7 +6742,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         int tool_bar_p = 0;
 
         bzero (&compose_status, sizeof (compose_status));
         int tool_bar_p = 0;
 
         bzero (&compose_status, sizeof (compose_status));
-       bzero (&last_mouse_glyph, sizeof (last_mouse_glyph));
+       last_mouse_glyph_frame = 0;
+        last_user_time = event.xbutton.time;
 
         if (dpyinfo->grabbed
             && last_mouse_frame
 
         if (dpyinfo->grabbed
             && last_mouse_frame
@@ -6678,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);
                 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));
                                                                     event.xbutton.state));
-                   tool_bar_p = 1;
                   }
               }
 
                   }
               }
 
@@ -7128,8 +7214,7 @@ x_draw_hollow_cursor (w, row)
     return;
 
   /* Compute frame-relative coordinates for phys cursor.  */
     return;
 
   /* 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);
+  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
   wd = w->phys_cursor_width;
 
   /* The foreground of cursor_gc is typically the same as the normal
@@ -7144,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);
 
   /* 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);
 }
 
   XSetClipMask (dpy, gc, None);
 }
 
@@ -7357,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)
        {
       /* 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,
        }
 
       /* The first time we create the GNU bitmap and mask,
@@ -7414,12 +7519,21 @@ x_text_icon (f, icon_name)
 #define X_ERROR_MESSAGE_SIZE 200
 
 /* If non-nil, this should be a string.
 #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.
+
+   The reason we use a stack is that x_catch_error/x_uncatch_error can
+   be called from a signal handler.
+*/
 
 
-static Lisp_Object x_error_message_string;
+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
 
 /* 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
    x_catch_errors is in effect.  */
 
 static void
@@ -7428,7 +7542,7 @@ x_error_catcher (display, error)
      XErrorEvent *error;
 {
   XGetErrorText (display, error->error_code,
      XErrorEvent *error;
 {
   XGetErrorText (display, error->error_code,
-                SDATA (x_error_message_string),
+                x_error_message->string,
                 X_ERROR_MESSAGE_SIZE);
 }
 
                 X_ERROR_MESSAGE_SIZE);
 }
 
@@ -7438,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
 
    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.
 
    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.
@@ -7446,47 +7560,41 @@ x_error_catcher (display, error)
    Calling x_uncatch_errors resumes the normal error handling.  */
 
 void x_check_errors ();
    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;
 {
 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);
 
 
   /* 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.  */
 
   /* 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
 }
 
 /* If any X protocol errors have arrived since the last call to
@@ -7501,8 +7609,13 @@ x_check_errors (dpy, format)
   /* Make sure to catch any errors incurred so far.  */
   XSync (dpy, False);
 
   /* 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
 }
 
 /* Nonzero if we had any X protocol errors
@@ -7515,7 +7628,7 @@ x_had_errors_p (dpy)
   /* Make sure to catch any errors incurred so far.  */
   XSync (dpy, False);
 
   /* 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.  */
 }
 
 /* Forget about any errors we have had, since we did x_catch_errors on DPY.  */
@@ -7524,20 +7637,24 @@ void
 x_clear_errors (dpy)
      Display *dpy;
 {
 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
 
 void
-x_uncatch_errors (dpy, count)
-     Display *dpy;
-     int count;
+x_fully_uncatch_errors ()
 {
 {
-  unbind_to (count, Qnil);
+  while (x_error_message)
+    x_uncatch_errors ();
+}
+
+/* Nonzero if x_catch_errors has been done and not yet canceled.  */
+
+int
+x_catching_errors ()
+{
+  return x_error_message != 0;
 }
 
 #if 0
 }
 
 #if 0
@@ -7596,7 +7713,6 @@ x_connection_closed (dpy, error_message)
 {
   struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
   Lisp_Object frame, tail;
 {
   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);
 
   error_msg = (char *) alloca (strlen (error_message) + 1);
   strcpy (error_msg, error_message);
@@ -7606,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.  */
      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
 
   /* 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
@@ -7674,7 +7790,7 @@ x_connection_closed (dpy, error_message)
   if (dpyinfo)
     x_delete_display (dpyinfo);
 
   if (dpyinfo)
     x_delete_display (dpyinfo);
 
-  x_uncatch_errors (dpy, count);
+  x_uncatch_errors ();
 
   if (x_display_list == 0)
     {
 
   if (x_display_list == 0)
     {
@@ -7696,7 +7812,7 @@ x_connection_closed (dpy, error_message)
 
 /* 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.  */
 
 /* 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);
+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.  */
 
 /* This is the first-level handler for X protocol errors.
    It calls x_error_quitter or x_error_catcher.  */
@@ -7706,7 +7822,7 @@ x_error_handler (display, error)
      Display *display;
      XErrorEvent *error;
 {
      Display *display;
      XErrorEvent *error;
 {
-  if (! NILP (x_error_message_string))
+  if (x_error_message)
     x_error_catcher (display, error);
   else
     x_error_quitter (display, error);
     x_error_catcher (display, error);
   else
     x_error_quitter (display, error);
@@ -7741,6 +7857,12 @@ x_error_quitter (display, error)
 {
   char buf[256], buf1[356];
 
 {
   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.  */
 
   /* Note that there is no real way portable across R3/R4 to get the
      original error handler.  */
 
@@ -8146,8 +8268,11 @@ x_set_offset (f, xoff, yoff, change_gravity)
 {
   int modified_top, modified_left;
 
 {
   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);
       f->top_pos = yoff;
       f->left_pos = xoff;
       f->size_hint_flags &= ~ (XNegative | YNegative);
@@ -8165,7 +8290,7 @@ x_set_offset (f, xoff, yoff, change_gravity)
   modified_left = f->left_pos;
   modified_top = f->top_pos;
 
   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
     {
       /* Some WMs (twm, wmaker at least) has an offset that is smaller
          than the WM decorations.  So we use the calculated offset instead
@@ -8177,17 +8302,222 @@ x_set_offset (f, xoff, yoff, change_gravity)
   XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
                modified_left, modified_top);
 
   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))
+    {
+      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)
     {
     {
-      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;
+      /* 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;
   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
 /* Check if we need to resize the frame due to a fullscreen request.
    If so needed, resize the frame. */
 static void
@@ -8198,6 +8528,9 @@ x_check_fullscreen (f)
     {
       int width, height, ign;
 
     {
       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);
       x_real_positions (f, &f->left_pos, &f->top_pos);
 
       x_fullscreen_adjust (f, &width, &height, &ign, &ign);
@@ -8218,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
 static void
-x_check_expected_move (f)
+x_check_expected_move (f, expected_left, expected_top)
      struct frame *f;
      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.  */
 
 
-    if (expect_top != f->top_pos || expect_left != f->left_pos)
+  x_real_positions (f, &current_left, &current_top);
+
+  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_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. */
 
 
-        f->left_pos = expect_left;
-        f->top_pos = expect_top;
-        x_set_offset (f, expect_left, expect_top, 0);
+      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);
+
+      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;
       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.  */
 
 
-    /* Just do this once */
-    FRAME_X_OUTPUT (f)->check_expected_move = 0;
+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;
+
+      /* 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);
 }
 
 
 }
 
 
@@ -8440,13 +8832,12 @@ void
 x_raise_frame (f)
      struct frame *f;
 {
 x_raise_frame (f)
      struct frame *f;
 {
+  BLOCK_INPUT;
   if (f->async_visible)
   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.  */
 }
 
 /* Lower frame F.  */
@@ -8470,7 +8861,32 @@ XTframe_raise_lower (f, raise_flag)
      int raise_flag;
 {
   if (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);
 }
   else
     x_lower_frame (f);
 }
@@ -9280,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;
     = 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)
   int allow_auto_scaled_font = 0;
 
   if (size < 0)
@@ -9320,7 +9735,7 @@ x_list_fonts (f, pattern, size, maxnames)
       /* At first, put PATTERN in the cache.  */
 
       BLOCK_INPUT;
       /* At first, put PATTERN in the cache.  */
 
       BLOCK_INPUT;
-      count = x_catch_errors (dpy);
+      x_catch_errors (dpy);
 
       if (try_XLoadQueryFont)
        {
 
       if (try_XLoadQueryFont)
        {
@@ -9401,7 +9816,7 @@ x_list_fonts (f, pattern, size, maxnames)
            }
        }
 
            }
        }
 
-      x_uncatch_errors (dpy, count);
+      x_uncatch_errors ();
       UNBLOCK_INPUT;
 
       if (names)
       UNBLOCK_INPUT;
 
       if (names)
@@ -9492,7 +9907,7 @@ x_list_fonts (f, pattern, size, maxnames)
              XFontStruct *thisinfo;
 
              BLOCK_INPUT;
              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))
              thisinfo = XLoadQueryFont (dpy,
                                         SDATA (XCAR (tem)));
              if (x_had_errors_p (dpy))
@@ -9502,7 +9917,7 @@ x_list_fonts (f, pattern, size, maxnames)
                  thisinfo = NULL;
                  x_clear_errors (dpy);
                }
                  thisinfo = NULL;
                  x_clear_errors (dpy);
                }
-             x_uncatch_errors (dpy, count);
+             x_uncatch_errors ();
              UNBLOCK_INPUT;
 
              if (thisinfo)
              UNBLOCK_INPUT;
 
              if (thisinfo)
@@ -9658,7 +10073,6 @@ x_load_font (f, fontname, size)
 {
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   Lisp_Object font_names;
 {
   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
 
   /* 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
@@ -9697,7 +10111,7 @@ x_load_font (f, fontname, size)
       fontname = (char *) SDATA (XCAR (font_names));
 
     BLOCK_INPUT;
       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)))
       {
     font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
     if (x_had_errors_p (FRAME_X_DISPLAY (f)))
       {
@@ -9706,7 +10120,7 @@ x_load_font (f, fontname, size)
        font = NULL;
        x_clear_errors (FRAME_X_DISPLAY (f));
       }
        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;
     UNBLOCK_INPUT;
     if (!font)
       return NULL;
@@ -9908,8 +10322,8 @@ x_query_font (f, fontname)
 
   for (i = 0; i < dpyinfo->n_fonts; i++)
     if (dpyinfo->font_table[i].name
 
   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;
 }
       return (dpyinfo->font_table + i);
   return NULL;
 }
@@ -9972,10 +10386,19 @@ static XrmOptionDescRec emacs_options[] = {
   {"-mc",      "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
   {"-cr",      "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
 };
   {"-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;
 
 #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.  */
 #ifdef MULTI_KBOARD
 /* Test whether two display-name strings agree up to the dot that separates
    the screen number from the server number.  */
@@ -10053,6 +10476,21 @@ get_bits_and_offset (mask, bits, offset)
   *bits = nr;
 }
 
   *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;
 struct x_display_info *
 x_term_init (display_name, xrm_option, resource_name)
      Lisp_Object display_name;
@@ -10122,18 +10560,14 @@ x_term_init (display_name, xrm_option, resource_name)
 
         /* Load our own gtkrc if it exists.  */
         {
 
         /* Load our own gtkrc if it exists.  */
         {
-          struct gcpro gcpro1, gcpro2;
           char *file = "~/.emacs.d/gtkrc";
           Lisp_Object s, abs_file;
 
           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));
           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);
         }
 
         XSetErrorHandler (x_error_handler);
@@ -10421,6 +10855,15 @@ x_term_init (display_name, xrm_option, resource_name)
 
   dpyinfo->cut_buffers_initialized = 0;
 
 
   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;
 
   connection = ConnectionNumber (dpyinfo->display);
   dpyinfo->connection = connection;
 
@@ -10479,7 +10922,6 @@ x_term_init (display_name, xrm_option, resource_name)
     Display *dpy = dpyinfo->display;
     XrmValue d, fr, to;
     Font font;
     Display *dpy = dpyinfo->display;
     XrmValue d, fr, to;
     Font font;
-    int count;
 
     d.addr = (XPointer)&dpy;
     d.size = sizeof (Display *);
 
     d.addr = (XPointer)&dpy;
     d.size = sizeof (Display *);
@@ -10487,12 +10929,12 @@ x_term_init (display_name, xrm_option, resource_name)
     fr.size = sizeof (XtDefaultFont);
     to.size = sizeof (Font *);
     to.addr = (XPointer)&font;
     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");
     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
   }
 #endif
 #endif
@@ -10532,7 +10974,7 @@ x_term_init (display_name, xrm_option, resource_name)
 
 #ifdef HAVE_X_SM
   /* Only do this for the first display.  */
 
 #ifdef HAVE_X_SM
   /* Only do this for the first display.  */
-  if (x_initialized == 1)
+  if (!x_session_initialized++)
     x_session_initialize (dpyinfo);
 #endif
 
     x_session_initialize (dpyinfo);
 #endif
 
@@ -10610,12 +11052,16 @@ x_delete_display (dpyinfo)
        xfree (dpyinfo->font_table[i].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);
+  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);
 }
 
   xfree (dpyinfo);
 }
 
@@ -10630,13 +11076,39 @@ static void
 x_process_timeouts (timer)
      struct atimer *timer;
 {
 x_process_timeouts (timer)
      struct atimer *timer;
 {
+  BLOCK_INPUT;
+  x_timeout_atimer_activated_flag = 0;
   if (toolkit_scroll_bar_interaction || popup_activated ())
     {
   if (toolkit_scroll_bar_interaction || popup_activated ())
     {
-      BLOCK_INPUT;
       while (XtAppPending (Xt_app_con) & XtIMTimer)
        XtAppProcessEvent (Xt_app_con, XtIMTimer);
       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 */
 }
 
 #endif /* USE_X_TOOLKIT */
@@ -10704,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;
   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;
 
   scroll_region_ok = 1;                /* we'll scroll partial frames */
   char_ins_del_ok = 1;
@@ -10717,6 +11190,9 @@ x_initialize ()
   last_tool_bar_item = -1;
   any_help_event_p = 0;
   ignore_next_mouse_click_timeout = 0;
   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;
 
 #ifdef USE_GTK
   current_count = -1;
@@ -10739,17 +11215,6 @@ x_initialize ()
                         XtCacheByDisplay, cvt_pixel_dtor);
 
   XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
                         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
 #endif
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
@@ -10776,8 +11241,7 @@ x_initialize ()
 void
 syms_of_xterm ()
 {
 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;
 
   staticpro (&x_display_name_list);
   x_display_name_list = Qnil;
@@ -10799,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.
   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;
 
 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.
   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.