* xdisp.c (init_xdisp): Initialize echo_area_window (Bug#6451).
[bpt/emacs.git] / src / xterm.c
index efd30f4..be7fde0 100644 (file)
@@ -1,6 +1,6 @@
 /* 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, 2006, 2007, 2008, 2009
+                 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
                  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -753,11 +753,6 @@ x_after_update_window_line (desired_row)
     {
       int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
 
-      /* Internal border is drawn below the tool bar.  */
-      if (WINDOWP (f->tool_bar_window)
-         && w == XWINDOW (f->tool_bar_window))
-       y -= width;
-
       BLOCK_INPUT;
       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                    0, y, width, height, False);
@@ -779,24 +774,9 @@ x_draw_fringe_bitmap (w, row, p)
   Window window = FRAME_X_WINDOW (f);
   GC gc = f->output_data.x->normal_gc;
   struct face *face = p->face;
-  int rowY;
 
   /* Must clip because of partially visible lines.  */
-  rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
-  if (p->y < rowY)
-    {
-      /* Adjust position of "bottom aligned" bitmap on partially
-        visible last row.  */
-      int oldY = row->y;
-      int oldVH = row->visible_height;
-      row->visible_height = p->h;
-      row->y -= rowY - p->y;
-      x_clip_to_row (w, row, -1, gc);
-      row->y = oldY;
-      row->visible_height = oldVH;
-    }
-  else
-    x_clip_to_row (w, row, -1, gc);
+  x_clip_to_row (w, row, -1, gc);
 
   if (!p->overlay_p)
     {
@@ -1383,19 +1363,27 @@ x_draw_composite_glyph_string_foreground (s)
              if (j < i)
                {
                  font->driver->draw (s, j, i, x, y, 0);
+                 if (s->face->overstrike)
+                   font->driver->draw (s, j, i, x + 1, y, 0);
                  x += width;
                }
              xoff = LGLYPH_XOFF (glyph);
              yoff = LGLYPH_YOFF (glyph);
              wadjust = LGLYPH_WADJUST (glyph);
              font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
+             if (s->face->overstrike)
+               font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff, 0);
              x += wadjust;
              j = i + 1;
              width = 0;
            }
        }
       if (j < i)
-       font->driver->draw (s, j, i, x, y, 0);
+       {
+         font->driver->draw (s, j, i, x, y, 0);
+         if (s->face->overstrike)
+           font->driver->draw (s, j, i, x + 1, y, 0);
+       }
     }
 }
 
@@ -3012,6 +3000,22 @@ XTflash (f)
   BLOCK_INPUT;
 
   {
+#ifdef USE_GTK
+    /* Use Gdk routines to draw.  This way, we won't draw over scroll bars
+       when the scroll bars and the edit widget share the same X window.  */
+    GdkGCValues vals;
+    GdkGC *gc;
+    vals.foreground.pixel = (FRAME_FOREGROUND_PIXEL (f)
+                             ^ FRAME_BACKGROUND_PIXEL (f));
+    vals.function = GDK_XOR;
+    gc = gdk_gc_new_with_values (FRAME_GTK_WIDGET (f)->window,
+                                 &vals,
+                                 GDK_GC_FUNCTION
+                                 | GDK_GC_FOREGROUND);
+#define XFillRectangle(d, win, gc, x, y, w, h) \
+    gdk_draw_rectangle (FRAME_GTK_WIDGET (f)->window, \
+                        gc, TRUE, x, y, w, h)
+#else
     GC gc;
 
     /* Create a GC that will use the GXxor function to flip foreground
@@ -3026,7 +3030,7 @@ XTflash (f)
       gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                      GCFunction | GCForeground, &values);
     }
-
+#endif
     {
       /* Get the height not including a menu bar widget.  */
       int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
@@ -3062,13 +3066,14 @@ XTflash (f)
          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
                          flash_left,
                          (FRAME_INTERNAL_BORDER_WIDTH (f)
-                          + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
+                          + FRAME_TOP_MARGIN_HEIGHT (f)),
                          width, flash_height);
          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
                          flash_left,
                          (height - flash_height
                           - FRAME_INTERNAL_BORDER_WIDTH (f)),
                          width, flash_height);
+
        }
       else
        /* If it is short, flash it all.  */
@@ -3116,7 +3121,7 @@ XTflash (f)
          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
                          flash_left,
                          (FRAME_INTERNAL_BORDER_WIDTH (f)
-                          + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
+                          + FRAME_TOP_MARGIN_HEIGHT (f)),
                          width, flash_height);
          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
                          flash_left,
@@ -3130,7 +3135,12 @@ XTflash (f)
                        flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
                        width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
 
+#ifdef USE_GTK
+      g_object_unref (G_OBJECT (gc));
+#undef XFillRectangle
+#else
       XFreeGC (FRAME_X_DISPLAY (f), gc);
+#endif
       x_flush (f);
     }
   }
@@ -4064,7 +4074,7 @@ x_window_to_scroll_bar (display, window_id)
          return XSCROLL_BAR (bar);
     }
 
-  return 0;
+  return NULL;
 }
 
 
@@ -5794,6 +5804,7 @@ event_handler_gdk (gxev, ev, data)
 {
   XEvent *xev = (XEvent *) gxev;
 
+  BLOCK_INPUT;
   if (current_count >= 0)
     {
       struct x_display_info *dpyinfo;
@@ -5804,23 +5815,27 @@ event_handler_gdk (gxev, ev, data)
       /* Filter events for the current X input method.
          GTK calls XFilterEvent but not for key press and release,
          so we do it here.  */
-      if (xev->type == KeyPress || xev->type == KeyRelease)
-        if (dpyinfo && x_filter_event (dpyinfo, xev))
-          return GDK_FILTER_REMOVE;
+      if ((xev->type == KeyPress || xev->type == KeyRelease)
+         && dpyinfo
+         && x_filter_event (dpyinfo, xev))
+       {
+         UNBLOCK_INPUT;
+         return GDK_FILTER_REMOVE;
+       }
 #endif
 
       if (! dpyinfo)
         current_finish = X_EVENT_NORMAL;
       else
-       {
-         current_count +=
-           handle_one_xevent (dpyinfo, xev, &current_finish,
-                              current_hold_quit);
-       }
+       current_count +=
+         handle_one_xevent (dpyinfo, xev, &current_finish,
+                            current_hold_quit);
     }
   else
     current_finish = x_dispatch_event (xev, xev->xany.display);
 
+  UNBLOCK_INPUT;
+
   if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
     return GDK_FILTER_REMOVE;
 
@@ -6071,7 +6086,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         goto OTHER;
 #endif /* USE_X_TOOLKIT */
       {
-        XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
+        XSelectionClearEvent *eventp = &(event.xselectionclear);
 
         inev.ie.kind = SELECTION_CLEAR_EVENT;
         SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
@@ -6088,8 +6103,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         goto OTHER;
 #endif /* USE_X_TOOLKIT */
       {
-          XSelectionRequestEvent *eventp
-            = (XSelectionRequestEvent *) &event;
+         XSelectionRequestEvent *eventp = &(event.xselectionrequest);
 
           inev.ie.kind = SELECTION_REQUEST_EVENT;
           SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
@@ -6936,7 +6950,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
          f->mouse_moved = 0;
 
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
-        f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
+        f = x_menubar_window_to_frame (dpyinfo, &event);
         /* For a down-event in the menu bar,
            don't pass it to Xt right now.
            Instead, save it away
@@ -7438,6 +7452,11 @@ x_clear_frame_area (f, x, y, width, height)
 {
   x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                x, y, width, height, False);
+#ifdef USE_GTK
+  /* Must queue a redraw, because scroll bars might have been cleared.  */
+  if (FRAME_GTK_WIDGET (f))
+    gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
+#endif
 }
 
 
@@ -7862,45 +7881,44 @@ x_connection_closed (dpy, error_message)
        delete_frame (frame, Qnoelisp);
       }
 
-  /* 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
-     events from the display.  As a consequence, a sequence of
-
-     M-x make-frame-on-display RET :1 RET
-     ...kill the new frame, so that we get an IO error...
-     M-x make-frame-on-display RET :1 RET
-
-     will indefinitely wait in Xt for events for display `:1', opened
-     in the first call to make-frame-on-display.
-
-     Closing the display is reported to lead to a bus error on
-     OpenWindows in certain situations.  I suspect that is a bug
-     in OpenWindows.  I don't know how to circumvent it here.  */
-
+  /* If DPYINFO is null, this means we didn't open the display in the
+     first place, so don't try to close it.  */
   if (dpyinfo)
     {
 #ifdef USE_X_TOOLKIT
-      /* If DPYINFO is null, this means we didn't open the display
-        in the first place, so don't try to close it.  */
-      {
-       extern void (*fatal_error_signal_hook) P_ ((void));
-       fatal_error_signal_hook = x_fatal_error_signal;
-       XtCloseDisplay (dpy);
-       fatal_error_signal_hook = NULL;
-      }
-#endif
+      /* 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
+        events from the display.  As a consequence, a sequence of
+
+        M-x make-frame-on-display RET :1 RET
+        ...kill the new frame, so that we get an IO error...
+        M-x make-frame-on-display RET :1 RET
+
+        will indefinitely wait in Xt for events for display `:1',
+        opened in the first call to make-frame-on-display.
+
+        Closing the display is reported to lead to a bus error on
+        OpenWindows in certain situations.  I suspect that is a bug
+        in OpenWindows.  I don't know how to circumvent it here.  */
+      extern void (*fatal_error_signal_hook) P_ ((void));
+      fatal_error_signal_hook = x_fatal_error_signal;
+      XtCloseDisplay (dpy);
+      fatal_error_signal_hook = NULL;
+#endif /* USE_X_TOOLKIT */
 
 #ifdef USE_GTK
-      /* Due to bugs in some Gtk+ versions, just exit here if this
-         is the last display/terminal. */
-      if (terminal_list->next_terminal == NULL)
-        {
-          fprintf (stderr, "%s\n", error_msg);
-          shut_down_emacs (0, 0, Qnil);
-          exit (70);
-        }
-      xg_display_close (dpyinfo->display);
-#endif
+      /* A long-standing GTK bug prevents proper disconnect handling
+        (https://bugzilla.gnome.org/show_bug.cgi?id=85715).  Once,
+        the resulting Glib error message loop filled a user's disk.
+        To avoid this, kill Emacs unconditionally on disconnect.  */
+      shut_down_emacs (0, 0, Qnil);
+      fprintf (stderr, "%s\n\
+When compiled with GTK, Emacs cannot recover from X disconnects.\n\
+This is a GTK bug: https://bugzilla.gnome.org/show_bug.cgi?id=85715\n\
+For details, see etc/PROBLEMS.\n",
+              error_msg);
+      abort ();
+#endif /* USE_GTK */
 
       /* Indicate that this display is dead.  */
       dpyinfo->display = 0;
@@ -8552,6 +8570,72 @@ x_set_sticky (f, new_value, old_value)
                 "_NET_WM_STATE_STICKY", NULL);
 }
 
+/* Return the current _NET_WM_STATE.
+   SIZE_STATE is set to one of the FULLSCREEN_* values.
+   STICKY is set to 1 if the sticky state is set, 0 if not.  */
+
+static void
+get_current_vm_state (struct frame *f,
+                      Window window,
+                      int *size_state,
+                      int *sticky)
+{
+  Atom actual_type;
+  unsigned long actual_size, bytes_remaining;
+  int i, rc, actual_format;
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  long max_len = 65536;
+  Display *dpy = FRAME_X_DISPLAY (f);
+  unsigned char *tmp_data = NULL;
+  Atom target_type = XA_ATOM;
+
+  *sticky = 0;
+  *size_state = FULLSCREEN_NONE;
+
+  BLOCK_INPUT;
+  x_catch_errors (dpy);
+  rc = XGetWindowProperty (dpy, window, dpyinfo->Xatom_net_wm_state,
+                           0, max_len, False, target_type,
+                           &actual_type, &actual_format, &actual_size,
+                           &bytes_remaining, &tmp_data);
+
+  if (rc != Success || actual_type != target_type || x_had_errors_p (dpy))
+    {
+      if (tmp_data) XFree (tmp_data);
+      x_uncatch_errors ();
+      UNBLOCK_INPUT;
+      return;
+    }
+
+  x_uncatch_errors ();
+
+  for (i = 0; i < actual_size; ++i)
+    {
+      Atom a = ((Atom*)tmp_data)[i];
+      if (a == dpyinfo->Xatom_net_wm_state_maximized_horz) 
+        {
+          if (*size_state == FULLSCREEN_HEIGHT)
+            *size_state = FULLSCREEN_MAXIMIZED;
+          else
+            *size_state = FULLSCREEN_WIDTH;
+        }
+      else if (a == dpyinfo->Xatom_net_wm_state_maximized_vert)
+        {
+          if (*size_state == FULLSCREEN_WIDTH)
+            *size_state = FULLSCREEN_MAXIMIZED;
+          else
+            *size_state = FULLSCREEN_HEIGHT;
+        }
+      else if (a == dpyinfo->Xatom_net_wm_state_fullscreen_atom)
+        *size_state = FULLSCREEN_BOTH;
+      else if (a == dpyinfo->Xatom_net_wm_state_sticky)
+        *sticky = 1;
+    }
+
+  if (tmp_data) XFree (tmp_data);
+  UNBLOCK_INPUT;
+}
+
 /* Do fullscreen as specified in extended window manager hints */
 
 static int
@@ -8559,13 +8643,17 @@ do_ewmh_fullscreen (f)
      struct frame *f;
 {
   int have_net_atom = wm_supports (f, "_NET_WM_STATE");
+  Lisp_Object lval = get_frame_param (f, Qfullscreen);
+  int cur, dummy;
+
+  get_current_vm_state (f, FRAME_OUTER_WINDOW (f), &cur, &dummy);
 
   /* 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)
+  if (have_net_atom && cur != f->want_fullscreen)
     {
       Lisp_Object frame;
       const char *fs = "_NET_WM_STATE_FULLSCREEN";
@@ -8574,26 +8662,41 @@ do_ewmh_fullscreen (f)
 
       XSETFRAME (frame, f);
 
-      set_wm_state (frame, 0, fs, NULL);
-      set_wm_state (frame, 0, fh, NULL);
-      set_wm_state (frame, 0, fw, NULL);
-      
-      /* If there are _NET_ atoms we assume we have extended window manager
-         hints.  */
+      /* Keep number of calls to set_wm_state as low as possible.
+         Some window managers, or possible Gtk+, hangs when too many
+         are sent at once.  */
       switch (f->want_fullscreen)
         {
         case FULLSCREEN_BOTH:
+          if (cur == FULLSCREEN_WIDTH || cur == FULLSCREEN_MAXIMIZED
+              || cur == FULLSCREEN_HEIGHT)
+            set_wm_state (frame, 0, fw, fh);
           set_wm_state (frame, 1, fs, NULL);
           break;
         case FULLSCREEN_WIDTH:
-          set_wm_state (frame, 1, fw, NULL);
+          if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_HEIGHT
+              || cur == FULLSCREEN_MAXIMIZED)
+            set_wm_state (frame, 0, fs, fh);
+          if (cur != FULLSCREEN_MAXIMIZED)
+            set_wm_state (frame, 1, fw, NULL);
           break;
         case FULLSCREEN_HEIGHT:
-          set_wm_state (frame, 1, fh, NULL);
+          if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_WIDTH
+              || cur == FULLSCREEN_MAXIMIZED)
+            set_wm_state (frame, 0, fs, fw);
+          if (cur != FULLSCREEN_MAXIMIZED)
+            set_wm_state (frame, 1, fh, NULL);
           break;
         case FULLSCREEN_MAXIMIZED:
+          if (cur == FULLSCREEN_BOTH)
+            set_wm_state (frame, 0, fs, NULL);
           set_wm_state (frame, 1, fw, fh);
           break;
+        case FULLSCREEN_NONE:
+          if (cur == FULLSCREEN_BOTH)
+            set_wm_state (frame, 0, fs, NULL);
+          else
+            set_wm_state (frame, 0, fw, fh);
         }
 
       f->want_fullscreen = FULLSCREEN_NONE;
@@ -8622,57 +8725,11 @@ x_handle_net_wm_state (f, event)
      struct frame *f;
      XPropertyEvent *event;
 {
-  Atom actual_type;
-  unsigned long actual_size, bytes_remaining;
-  int i, rc, actual_format, value = FULLSCREEN_NONE;
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  long max_len = 65536;
-  Display *dpy = FRAME_X_DISPLAY (f);
-  unsigned char *tmp_data = NULL;
-  Atom target_type = XA_ATOM;
+  int value = FULLSCREEN_NONE;
   Lisp_Object lval;
   int sticky = 0;
 
-  BLOCK_INPUT;
-  x_catch_errors (dpy);
-  rc = XGetWindowProperty (dpy, event->window,
-                           event->atom, 0, max_len, False, target_type,
-                           &actual_type, &actual_format, &actual_size,
-                           &bytes_remaining, &tmp_data);
-
-  if (rc != Success || actual_type != target_type || x_had_errors_p (dpy))
-    {
-      if (tmp_data) XFree (tmp_data);
-      x_uncatch_errors ();
-      UNBLOCK_INPUT;
-      return;
-    }
-
-  x_uncatch_errors ();
-
-  for (i = 0; i < actual_size; ++i)
-    {
-      Atom a = ((Atom*)tmp_data)[i];
-      if (a == dpyinfo->Xatom_net_wm_state_maximized_horz) 
-        {
-          if (value == FULLSCREEN_HEIGHT)
-            value = FULLSCREEN_MAXIMIZED;
-          else
-            value = FULLSCREEN_WIDTH;
-        }
-      else if (a == dpyinfo->Xatom_net_wm_state_maximized_vert)
-        {
-          if (value == FULLSCREEN_WIDTH)
-            value = FULLSCREEN_MAXIMIZED;
-          else
-            value = FULLSCREEN_HEIGHT;
-        }
-      else if (a == dpyinfo->Xatom_net_wm_state_fullscreen_atom)
-        value = FULLSCREEN_BOTH;
-      else if (a == dpyinfo->Xatom_net_wm_state_sticky)
-        sticky = 1;
-    }
-
+  get_current_vm_state (f, event->window, &value, &sticky);
   lval = Qnil;
   switch (value) 
     {
@@ -8692,9 +8749,6 @@ x_handle_net_wm_state (f, event)
       
   store_frame_param (f, Qfullscreen, lval);
   store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
-
-  if (tmp_data) XFree (tmp_data);
-  UNBLOCK_INPUT;
 }
 
 /* Check if we need to resize the frame due to a fullscreen request.
@@ -8709,9 +8763,13 @@ x_check_fullscreen (f)
   if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
     return; /* Only fullscreen without WM or with EWM hints (above). */
 
+  /* Setting fullscreen to nil doesn't do anything.  We could save the
+     last non-fullscreen size and restore it, but it seems like a
+     lot of work for this unusual case (no window manager running).  */
+
   if (f->want_fullscreen != FULLSCREEN_NONE)
     {
-      int width = FRAME_COLS (f), height = FRAME_LINES (f);
+      int width = FRAME_PIXEL_WIDTH (f), height = FRAME_PIXEL_HEIGHT (f);
       struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
       switch (f->want_fullscreen)
@@ -8728,13 +8786,9 @@ x_check_fullscreen (f)
         case FULLSCREEN_HEIGHT:
           height = x_display_pixel_height (dpyinfo);
         }
-      
-      if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
-        {
-          change_frame_size (f, height, width, 0, 1, 0);
-          SET_FRAME_GARBAGED (f);
-          cancel_mouse_face (f);
-        }
+
+      XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+                     width, height);
     }
 }
 
@@ -8898,11 +8952,9 @@ x_set_window_size_1 (f, change_gravity, cols, rows)
 
   compute_fringe_widths (f, 0);
 
-  pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols)
-    + 2*f->border_width;
+  pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
   pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows)
-    + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f)
-    + 2*f->border_width;
+    + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
 
   if (change_gravity) f->win_gravity = NorthWestGravity;
   x_wm_set_size_hint (f, (long) 0, 0);
@@ -9818,7 +9870,7 @@ x_wm_set_icon_pixmap (f, pixmap_id)
 {
   Pixmap icon_pixmap, icon_mask;
 
-#ifndef USE_X_TOOLKIT
+#if !defined USE_X_TOOLKIT && !defined USE_GTK
   Window window = FRAME_OUTER_WINDOW (f);
 #endif
 
@@ -10073,7 +10125,6 @@ x_term_init (display_name, xrm_option, resource_name)
     int argc;
     char *argv[NUM_ARGV];
     char **argv2 = argv;
-    GdkAtom atom;
     guint id;
 #ifndef HAVE_GTK_MULTIDISPLAY
     if (!EQ (Vinitial_window_system, Qx))
@@ -10212,10 +10263,25 @@ x_term_init (display_name, xrm_option, resource_name)
        terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
        init_kboard (terminal->kboard);
        terminal->kboard->Vwindow_system = Qx;
+
+       /* Add the keyboard to the list before running Lisp code (via
+           Qvendor_specific_keysyms below), since these are not traced
+           via terminals but only through all_kboards.  */
+       terminal->kboard->next_kboard = all_kboards;
+       all_kboards = terminal->kboard;
+
        if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
          {
            char *vendor = ServerVendor (dpy);
-           /* Temporarily hide the partially initialized terminal */
+
+           /* Protect terminal from GC before removing it from the
+              list of terminals.  */
+           struct gcpro gcpro1;
+           Lisp_Object gcpro_term;
+           XSETTERMINAL (gcpro_term, terminal);
+           GCPRO1 (gcpro_term);
+
+           /* Temporarily hide the partially initialized terminal.  */
            terminal_list = terminal->next_terminal;
            UNBLOCK_INPUT;
            terminal->kboard->Vsystem_key_alist
@@ -10224,10 +10290,9 @@ x_term_init (display_name, xrm_option, resource_name)
            BLOCK_INPUT;
            terminal->next_terminal = terminal_list;
            terminal_list = terminal;
+           UNGCPRO;
          }
 
-       terminal->kboard->next_kboard = all_kboards;
-       all_kboards = terminal->kboard;
        /* Don't let the initial kboard remain current longer than necessary.
           That would cause problems if a file loaded on startup tries to
           prompt in the mini-buffer.  */
@@ -10456,7 +10521,8 @@ x_term_init (display_name, xrm_option, resource_name)
     = XInternAtom (dpyinfo->display, "_NET_WM_WINDOW_TYPE", False);
   dpyinfo->Xatom_net_window_type_tooltip
     = XInternAtom (dpyinfo->display, "_NET_WM_WINDOW_TYPE_TOOLTIP", False);
-  
+  dpyinfo->Xatom_net_frame_extents  
+    = XInternAtom (dpyinfo->display, "_NET_FRAME_EXTENTS", False);
   dpyinfo->cut_buffers_initialized = 0;
 
   dpyinfo->x_dnd_atoms_size = 8;
@@ -10576,7 +10642,6 @@ void
 x_delete_display (dpyinfo)
      struct x_display_info *dpyinfo;
 {
-  int i;
   struct terminal *t;
 
   /* Close all frames and delete the generic struct terminal for this
@@ -10728,7 +10793,6 @@ void
 x_delete_terminal (struct terminal *terminal)
 {
   struct x_display_info *dpyinfo = terminal->display_info.x;
-  int i;
 
   /* Protect against recursive calls.  delete_frame in
      delete_terminal calls us back when it deletes our last frame.  */