* coding.c (make_conversion_work_buffer): Disable buffer modification
[bpt/emacs.git] / src / gtkutil.c
index 140796a..ce8308a 100644 (file)
@@ -53,13 +53,11 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #ifdef HAVE_GTK_MULTIDISPLAY
 
-/* Gtk does not work well without any display open.  Emacs may close
-   all its displays.  In that case, keep a display around just for
-   the purpose of having one.  */
+/* Keep track of the default display, or NULL if there is none.  Emacs
+   may close all its displays.  */
 
 static GdkDisplay *gdpy_def;
 
-
 /* Return the GdkDisplay that corresponds to the X display DPY.  */
 
 static GdkDisplay *
@@ -121,8 +119,11 @@ xg_display_open (display_name, dpy)
   GdkDisplay *gdpy;
 
   gdpy = gdk_display_open (display_name);
-  *dpy = gdpy ? GDK_DISPLAY_XDISPLAY (gdpy) : NULL;
+  if (!gdpy_def)
+    gdk_display_manager_set_default_display (gdk_display_manager_get (),
+                                            gdpy);
 
+  *dpy = gdpy ? GDK_DISPLAY_XDISPLAY (gdpy) : NULL;
   return gdpy != NULL;
 
 #else /* not HAVE_GTK_MULTIDISPLAY */
@@ -140,40 +141,30 @@ xg_display_close (Display *dpy)
 #ifdef HAVE_GTK_MULTIDISPLAY
   GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpy);
 
-  /* If this is the default display, we must change it before calling
-     dispose, otherwise it will crash on some Gtk+ versions.  */
+  /* If this is the default display, try to change it before closing.
+     If there is no other display to use, gdpy_def is set to NULL, and
+     the next call to xg_display_open resets the default display.  */
   if (gdk_display_get_default () == gdpy)
     {
       struct x_display_info *dpyinfo;
-      Display *new_dpy = 0;
-      GdkDisplay *gdpy_new;
+      GdkDisplay *gdpy_new = NULL;
 
       /* Find another display.  */
       for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
         if (dpyinfo->display != dpy)
           {
-            new_dpy = dpyinfo->display;
+           gdpy_new = gdk_x11_lookup_xdisplay (dpyinfo->display);
+           gdk_display_manager_set_default_display (gdk_display_manager_get (),
+                                                    gdpy_new);
             break;
           }
-
-      if (new_dpy)
-        gdpy_new = gdk_x11_lookup_xdisplay (new_dpy);
-      else
-        {
-          if (!gdpy_def)
-            gdpy_def = gdk_display_open (gdk_display_get_name (gdpy));
-          gdpy_new = gdpy_def;
-        }
-
-      gdk_display_manager_set_default_display (gdk_display_manager_get (),
-                                               gdpy_new);
+      gdpy_def = gdpy_new;
     }
 
-  /* GTK 2.2-2.8 has a bug that makes gdk_display_close crash (bug
-     http://bugzilla.gnome.org/show_bug.cgi?id=85715).  This way
-     we can continue running, but there will be memory leaks.  */
-
 #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 10
+  /* GTK 2.2-2.8 has a bug that makes gdk_display_close crash (bug
+     http://bugzilla.gnome.org/show_bug.cgi?id=85715).  This way we
+     can continue running, but there will be memory leaks.  */
   g_object_run_dispose (G_OBJECT (gdpy));
 #else
   /* This seems to be fixed in GTK 2.10. */
@@ -934,97 +925,95 @@ x_wm_set_size_hint (f, flags, user_position)
      long flags;
      int user_position;
 {
-  if (FRAME_GTK_OUTER_WIDGET (f))
-  {
-    /* Must use GTK routines here, otherwise GTK resets the size hints
-       to its own defaults.  */
-    GdkGeometry size_hints;
-    gint hint_flags = 0;
-    int base_width, base_height;
-    int min_rows = 0, min_cols = 0;
-    int win_gravity = f->win_gravity;
-
-    if (flags)
-      {
-        memset (&size_hints, 0, sizeof (size_hints));
-        f->output_data.x->size_hints = size_hints;
-        f->output_data.x->hint_flags = hint_flags;
-      }
-     else
-       flags = f->size_hint_flags;
-
-    size_hints = f->output_data.x->size_hints;
-    hint_flags = f->output_data.x->hint_flags;
-
-    hint_flags |= GDK_HINT_RESIZE_INC | GDK_HINT_MIN_SIZE;
-    size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
-    size_hints.height_inc = FRAME_LINE_HEIGHT (f);
-
-    hint_flags |= GDK_HINT_BASE_SIZE;
-    base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
-    base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0)
-      + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
-
-    check_frame_size (f, &min_rows, &min_cols);
-
-    size_hints.base_width = base_width;
-    size_hints.base_height = base_height;
-    size_hints.min_width  = base_width + min_cols * size_hints.width_inc;
-    size_hints.min_height = base_height + min_rows * size_hints.height_inc;
-
-
-    /* These currently have a one to one mapping with the X values, but I
-       don't think we should rely on that.  */
-    hint_flags |= GDK_HINT_WIN_GRAVITY;
-    size_hints.win_gravity = 0;
-    if (win_gravity == NorthWestGravity)
-      size_hints.win_gravity = GDK_GRAVITY_NORTH_WEST;
-    else if (win_gravity == NorthGravity)
-      size_hints.win_gravity = GDK_GRAVITY_NORTH;
-    else if (win_gravity == NorthEastGravity)
-      size_hints.win_gravity = GDK_GRAVITY_NORTH_EAST;
-    else if (win_gravity == WestGravity)
-      size_hints.win_gravity = GDK_GRAVITY_WEST;
-    else if (win_gravity == CenterGravity)
-      size_hints.win_gravity = GDK_GRAVITY_CENTER;
-    else if (win_gravity == EastGravity)
-      size_hints.win_gravity = GDK_GRAVITY_EAST;
-    else if (win_gravity == SouthWestGravity)
-      size_hints.win_gravity = GDK_GRAVITY_SOUTH_WEST;
-    else if (win_gravity == SouthGravity)
-      size_hints.win_gravity = GDK_GRAVITY_SOUTH;
-    else if (win_gravity == SouthEastGravity)
-      size_hints.win_gravity = GDK_GRAVITY_SOUTH_EAST;
-    else if (win_gravity == StaticGravity)
-      size_hints.win_gravity = GDK_GRAVITY_STATIC;
-
-    if (flags & PPosition) hint_flags |= GDK_HINT_POS;
-    if (flags & USPosition) hint_flags |= GDK_HINT_USER_POS;
-    if (flags & USSize) hint_flags |= GDK_HINT_USER_SIZE;
-
-    if (user_position)
-      {
-        hint_flags &= ~GDK_HINT_POS;
-        hint_flags |= GDK_HINT_USER_POS;
-      }
+  /* Don't set size hints during initialization; that apparently leads
+     to a race condition.  See the thread at
+     http://lists.gnu.org/archive/html/emacs-devel/2008-10/msg00033.html  */
+  if (NILP (Vafter_init_time) || !FRAME_GTK_OUTER_WIDGET (f))
+    return;
 
-    if (hint_flags != f->output_data.x->hint_flags
-        || memcmp (&size_hints,
-                   &f->output_data.x->size_hints,
-                   sizeof (size_hints)) != 0)
-      {
-        BLOCK_INPUT;
+  /* Must use GTK routines here, otherwise GTK resets the size hints
+     to its own defaults.  */
+  GdkGeometry size_hints;
+  gint hint_flags = 0;
+  int base_width, base_height;
+  int min_rows = 0, min_cols = 0;
+  int win_gravity = f->win_gravity;
 
-        gtk_window_set_geometry_hints (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
-                                       NULL,
-                                       &size_hints,
-                                       hint_flags);
+  if (flags)
+    {
+      memset (&size_hints, 0, sizeof (size_hints));
+      f->output_data.x->size_hints = size_hints;
+      f->output_data.x->hint_flags = hint_flags;
+    }
+  else
+    flags = f->size_hint_flags;
 
-        f->output_data.x->size_hints = size_hints;
-        f->output_data.x->hint_flags = hint_flags;
-        UNBLOCK_INPUT;
-      }
-  }
+  size_hints = f->output_data.x->size_hints;
+  hint_flags = f->output_data.x->hint_flags;
+
+  hint_flags |= GDK_HINT_RESIZE_INC | GDK_HINT_MIN_SIZE;
+  size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
+  size_hints.height_inc = FRAME_LINE_HEIGHT (f);
+
+  hint_flags |= GDK_HINT_BASE_SIZE;
+  base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
+  base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0)
+    + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
+
+  check_frame_size (f, &min_rows, &min_cols);
+
+  size_hints.base_width = base_width;
+  size_hints.base_height = base_height;
+  size_hints.min_width  = base_width + min_cols * size_hints.width_inc;
+  size_hints.min_height = base_height + min_rows * size_hints.height_inc;
+
+  /* These currently have a one to one mapping with the X values, but I
+     don't think we should rely on that.  */
+  hint_flags |= GDK_HINT_WIN_GRAVITY;
+  size_hints.win_gravity = 0;
+  if (win_gravity == NorthWestGravity)
+    size_hints.win_gravity = GDK_GRAVITY_NORTH_WEST;
+  else if (win_gravity == NorthGravity)
+    size_hints.win_gravity = GDK_GRAVITY_NORTH;
+  else if (win_gravity == NorthEastGravity)
+    size_hints.win_gravity = GDK_GRAVITY_NORTH_EAST;
+  else if (win_gravity == WestGravity)
+    size_hints.win_gravity = GDK_GRAVITY_WEST;
+  else if (win_gravity == CenterGravity)
+    size_hints.win_gravity = GDK_GRAVITY_CENTER;
+  else if (win_gravity == EastGravity)
+    size_hints.win_gravity = GDK_GRAVITY_EAST;
+  else if (win_gravity == SouthWestGravity)
+    size_hints.win_gravity = GDK_GRAVITY_SOUTH_WEST;
+  else if (win_gravity == SouthGravity)
+    size_hints.win_gravity = GDK_GRAVITY_SOUTH;
+  else if (win_gravity == SouthEastGravity)
+    size_hints.win_gravity = GDK_GRAVITY_SOUTH_EAST;
+  else if (win_gravity == StaticGravity)
+    size_hints.win_gravity = GDK_GRAVITY_STATIC;
+
+  if (flags & PPosition) hint_flags |= GDK_HINT_POS;
+  if (flags & USPosition) hint_flags |= GDK_HINT_USER_POS;
+  if (flags & USSize) hint_flags |= GDK_HINT_USER_SIZE;
+
+  if (user_position)
+    {
+      hint_flags &= ~GDK_HINT_POS;
+      hint_flags |= GDK_HINT_USER_POS;
+    }
+
+  if (hint_flags != f->output_data.x->hint_flags
+      || memcmp (&size_hints,
+                &f->output_data.x->size_hints,
+                sizeof (size_hints)) != 0)
+    {
+      BLOCK_INPUT;
+      gtk_window_set_geometry_hints (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+                                    NULL, &size_hints, hint_flags);
+      f->output_data.x->size_hints = size_hints;
+      f->output_data.x->hint_flags = hint_flags;
+      UNBLOCK_INPUT;
+    }
 }
 
 /* Change background color of a frame.
@@ -3873,7 +3862,7 @@ update_frame_tool_bar (f)
       int icon_size = 0;
       struct image *img = NULL;
       Lisp_Object image;
-      Lisp_Object stock;
+      Lisp_Object stock = Qnil;
       GtkStockItem stock_item;
       char *stock_name = NULL;
       char *icon_name = NULL;