]> code.delx.au - gnu-emacs/blobdiff - src/xterm.c
Add fullscreen_hook.
[gnu-emacs] / src / xterm.c
index c0941b7cbdb460646681ec48a4b9a45e37e9adaf..564da0d876c4079da31b235289bf2003acf5ee78 100644 (file)
@@ -182,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.  */
 
@@ -321,20 +325,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 int x_io_error_quitter P_ ((Display *));
-void x_catch_errors P_ ((Display *));
-void x_uncatch_errors P_ ((void));
-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 *));
@@ -366,9 +358,11 @@ 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 *));
+static SIGTYPE x_connection_closed P_ ((Display *, char *)) NO_RETURN;
 
 
 /* Flush display of frame F, or of all frames if F is null.  */
@@ -2543,19 +2537,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))
            {
@@ -2586,8 +2589,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;
 }
@@ -2674,32 +2689,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);
            }
        }
@@ -2711,14 +2728,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);
            }
        }
@@ -4074,6 +4091,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
@@ -5803,8 +5823,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 */
@@ -5820,6 +5841,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;
@@ -5838,10 +5861,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 #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.ie))
          *finish = X_EVENT_DROP;
       }
@@ -6083,7 +6104,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;
@@ -6561,7 +6586,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;
 
@@ -6660,11 +6685,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);
             }
@@ -7162,8 +7184,7 @@ x_draw_hollow_cursor (w, row)
     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
@@ -7482,7 +7503,7 @@ struct x_error_message_stack {
 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
@@ -7501,7 +7522,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.
@@ -7533,18 +7554,17 @@ x_uncatch_errors ()
 {
   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 (x_error_message->dpy) != 0)
-    {
-      BLOCK_INPUT;
-      XSync (x_error_message->dpy, False);
-      UNBLOCK_INPUT;
-    }
+    XSync (x_error_message->dpy, False);
 
   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
@@ -7590,6 +7610,23 @@ x_clear_errors (dpy)
   x_error_message->string[0] = 0;
 }
 
+/* Close off all unclosed x_catch_errors calls.  */
+
+void
+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 ()
+{
+  return x_error_message != 0;
+}
+
 #if 0
 static unsigned int x_wire_count;
 x_trace_wire ()
@@ -7745,7 +7782,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.  */
-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.  */
@@ -7790,6 +7827,12 @@ x_error_quitter (display, 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.  */
 
@@ -8195,8 +8238,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);
@@ -8214,7 +8260,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
@@ -8226,13 +8272,26 @@ 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)
-    {
-      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;
-    }
+  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;
 }
@@ -8267,37 +8326,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;
 
-    if (expect_top != f->top_pos || expect_left != f->left_pos)
+  /* 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 (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;
 
-        f->left_pos = expect_left;
-        f->top_pos = expect_top;
-        x_set_offset (f, expect_left, expect_top, 0);
+      /* 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);
+
+      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;
+}
+
 
-    /* Just do this once */
-    FRAME_X_OUTPUT (f)->check_expected_move = 0;
+/* 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;
+
+      /* 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);
 }
 
 
@@ -8489,13 +8607,25 @@ void
 x_raise_frame (f)
      struct frame *f;
 {
+  Lisp_Object frame;
+  const char *atom = "_NET_ACTIVE_WINDOW";
+
+  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));
+
+  XSETFRAME (frame, f);
+  /* See Window Manager Specification/Extended Window Manager Hints at
+     http://freedesktop.org/wiki/Standards_2fwm_2dspec */
+
+  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 (time (NULL) * 1000),
+                                      Qnil)));
+  XFlush (FRAME_X_DISPLAY (f));
+  UNBLOCK_INPUT;
 }
 
 /* Lower frame F.  */
@@ -9955,8 +10085,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)))
+       && (!strcasecmp (dpyinfo->font_table[i].name, fontname)
+           || !strcasecmp (dpyinfo->font_table[i].full_name, fontname)))
       return (dpyinfo->font_table + i);
   return NULL;
 }
@@ -10019,10 +10149,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.  */
@@ -10100,6 +10239,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;
@@ -10169,18 +10323,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);
@@ -10468,6 +10618,11 @@ 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);
+
   connection = ConnectionNumber (dpyinfo->display);
   dpyinfo->connection = connection;
 
@@ -10578,7 +10733,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
 
@@ -10656,12 +10811,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);
 }
 
@@ -10676,13 +10835,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 */
@@ -10763,6 +10948,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;
@@ -10785,17 +10973,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
@@ -10849,6 +11026,14 @@ 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.
+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.