Prefer intptr_t/uintptr_t for integers the same widths as pointers.
[bpt/emacs.git] / src / gtkutil.c
index e6141de..ff33a3f 100644 (file)
@@ -1,6 +1,6 @@
 /* Functions for creating and updating GTK widgets.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
-     Free Software Foundation, Inc.
+
+Copyright (C) 2003-2011  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -40,15 +40,16 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <X11/Xft/Xft.h>
 #endif
 
+#ifdef HAVE_GTK3
+#include <gtk/gtkx.h>
+#endif
+
 #define FRAME_TOTAL_PIXEL_HEIGHT(f) \
   (FRAME_PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f))
 
 #define FRAME_TOTAL_PIXEL_WIDTH(f) \
   (FRAME_PIXEL_WIDTH (f) + FRAME_TOOLBAR_WIDTH (f))
 
-/* Avoid "differ in sign" warnings */
-#define SSDATA(x)  ((char *) SDATA (x))
-
 #ifndef HAVE_GTK_WIDGET_SET_HAS_WINDOW
 #define gtk_widget_set_has_window(w, b) \
   (gtk_fixed_set_has_window (GTK_FIXED (w), b))
@@ -72,8 +73,28 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #define remove_submenu(w) gtk_menu_item_remove_submenu ((w))
 #endif
 
+#ifndef HAVE_GTK3
+#ifdef USE_GTK_TOOLTIP
+#define gdk_window_get_screen(w) gdk_drawable_get_screen (w)
+#endif
+#define gdk_window_get_geometry(w, a, b, c, d) \
+  gdk_window_get_geometry (w, a, b, c, d, 0)
+#define gdk_x11_window_lookup_for_display(d, w) \
+  gdk_xid_table_lookup_for_display (d, w)
+#ifndef GDK_KEY_g
+#define GDK_KEY_g GDK_g
+#endif
+#endif
+
 #define XG_BIN_CHILD(x) gtk_bin_get_child (GTK_BIN (x))
 
+/* Get the current value of the range, truncated to an integer.  */
+static int
+int_gtk_range_get_value (GtkRange *range)
+{
+  return gtk_range_get_value (range);
+}
+
 \f
 /***********************************************************************
                       Display handling functions
@@ -91,7 +112,7 @@ static GdkDisplay *gdpy_def;
 static void
 xg_set_screen (GtkWidget *w, FRAME_PTR f)
 {
-  if (FRAME_X_DISPLAY (f) != GDK_DISPLAY ())
+  if (FRAME_X_DISPLAY (f) != DEFAULT_GDK_DISPLAY ())
     {
       GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f));
       GdkScreen *gscreen = gdk_display_get_default_screen (gdpy);
@@ -232,29 +253,55 @@ xg_create_default_cursor (Display *dpy)
   return gdk_cursor_new_for_display (gdpy, GDK_LEFT_PTR);
 }
 
+static GdkPixbuf *
+xg_get_pixbuf_from_pixmap (FRAME_PTR f, Pixmap pix)
+{
+  int iunused;
+  GdkPixbuf *tmp_buf;
+  Window wunused;
+  unsigned int width, height, uunused;
+  XImage *xim;
+
+  XGetGeometry (FRAME_X_DISPLAY (f), pix, &wunused, &iunused, &iunused,
+                &width, &height, &uunused, &uunused);
+
+  xim = XGetImage (FRAME_X_DISPLAY (f), pix, 0, 0, width, height,
+                   ~0, XYPixmap);
+  if (!xim) return 0;
+
+  tmp_buf = gdk_pixbuf_new_from_data ((guchar *) xim->data,
+                                      GDK_COLORSPACE_RGB,
+                                      FALSE,
+                                      xim->bitmap_unit,
+                                      (int) width,
+                                      (int) height,
+                                      xim->bytes_per_line,
+                                      NULL,
+                                      NULL);
+  XDestroyImage (xim);
+  return tmp_buf;
+}
+
 /* Apply GMASK to GPIX and return a GdkPixbuf with an alpha channel.  */
 
 static GdkPixbuf *
-xg_get_pixbuf_from_pix_and_mask (GdkPixmap *gpix,
-                                 GdkPixmap *gmask,
-                                 GdkColormap *cmap)
+xg_get_pixbuf_from_pix_and_mask (FRAME_PTR f,
+                                 Pixmap pix,
+                                 Pixmap mask)
 {
   int width, height;
   GdkPixbuf *icon_buf, *tmp_buf;
 
-  gdk_drawable_get_size (gpix, &width, &height);
-  tmp_buf = gdk_pixbuf_get_from_drawable (NULL, gpix, cmap,
-                                          0, 0, 0, 0, width, height);
+  tmp_buf = xg_get_pixbuf_from_pixmap (f, pix);
   icon_buf = gdk_pixbuf_add_alpha (tmp_buf, FALSE, 0, 0, 0);
   g_object_unref (G_OBJECT (tmp_buf));
 
-  if (gmask)
+  width = gdk_pixbuf_get_width (icon_buf);
+  height = gdk_pixbuf_get_height (icon_buf);
+
+  if (mask)
     {
-      GdkPixbuf *mask_buf = gdk_pixbuf_get_from_drawable (NULL,
-                                                          gmask,
-                                                          NULL,
-                                                          0, 0, 0, 0,
-                                                          width, height);
+      GdkPixbuf *mask_buf = xg_get_pixbuf_from_pixmap (f, mask);
       guchar *pixels = gdk_pixbuf_get_pixels (icon_buf);
       guchar *mask_pixels = gdk_pixbuf_get_pixels (mask_buf);
       int rowstride = gdk_pixbuf_get_rowstride (icon_buf);
@@ -319,10 +366,6 @@ xg_get_image_for_pixmap (FRAME_PTR f,
                          GtkWidget *widget,
                          GtkImage *old_widget)
 {
-  GdkPixmap *gpix;
-  GdkPixmap *gmask;
-  GdkDisplay *gdpy;
-  GdkColormap *cmap;
   GdkPixbuf *icon_buf;
 
   /* If we have a file, let GTK do all the image handling.
@@ -350,10 +393,6 @@ xg_get_image_for_pixmap (FRAME_PTR f,
      on a monochrome display, and sometimes bad on all displays with
      certain themes.  */
 
-  gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f));
-  gpix = gdk_pixmap_foreign_new_for_display (gdpy, img->pixmap);
-  gmask = img->mask ? gdk_pixmap_foreign_new_for_display (gdpy, img->mask) : 0;
-
   /* This is a workaround to make icons look good on pseudo color
      displays.  Apparently GTK expects the images to have an alpha
      channel.  If they don't, insensitive and activated icons will
@@ -363,18 +402,17 @@ xg_get_image_for_pixmap (FRAME_PTR f,
      not associated with the img->pixmap.  The img->pixmap may be removed
      by clearing the image cache and then the tool bar redraw fails, since
      Gtk+ assumes the pixmap is always there.  */
-  cmap = gtk_widget_get_colormap (widget);
-  icon_buf = xg_get_pixbuf_from_pix_and_mask (gpix, gmask, cmap);
+  icon_buf = xg_get_pixbuf_from_pix_and_mask (f, img->pixmap, img->mask);
 
-  if (! old_widget)
-    old_widget = GTK_IMAGE (gtk_image_new_from_pixbuf (icon_buf));
-  else
-    gtk_image_set_from_pixbuf (old_widget, icon_buf);
-
-  g_object_unref (G_OBJECT (icon_buf));
+  if (icon_buf)
+    {
+      if (! old_widget)
+        old_widget = GTK_IMAGE (gtk_image_new_from_pixbuf (icon_buf));
+      else
+        gtk_image_set_from_pixbuf (old_widget, icon_buf);
 
-  g_object_unref (G_OBJECT (gpix));
-  if (gmask) g_object_unref (G_OBJECT (gmask));
+      g_object_unref (G_OBJECT (icon_buf));
+    }
 
   return GTK_WIDGET (old_widget);
 }
@@ -458,22 +496,22 @@ get_utf8_string (const char *str)
       gsize bytes_written;
       unsigned char *p = (unsigned char *)str;
       char *cp, *up;
-      GError *error = NULL;
+      GError *err = NULL;
 
       while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read,
-                                       &bytes_written, &error))
-             && error->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE)
+                                       &bytes_written, &err))
+             && err->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE)
         {
           ++nr_bad;
           p += bytes_written+1;
-          g_error_free (error);
-          error = NULL;
+          g_error_free (err);
+          err = NULL;
         }
 
-      if (error)
+      if (err)
         {
-          g_error_free (error);
-          error = NULL;
+          g_error_free (err);
+          err = NULL;
         }
       if (cp) g_free (cp);
 
@@ -481,16 +519,16 @@ get_utf8_string (const char *str)
       p = (unsigned char *)str;
 
       while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read,
-                                       &bytes_written, &error))
-             && error->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE)
+                                       &bytes_written, &err))
+             && err->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE)
         {
           strncpy (up, (char *)p, bytes_written);
           sprintf (up + bytes_written, "\\%03o", p[bytes_written]);
           up[bytes_written+4] = '\0';
           up += bytes_written+4;
           p += bytes_written+1;
-          g_error_free (error);
-          error = NULL;
+          g_error_free (err);
+          err = NULL;
         }
 
       if (cp)
@@ -498,10 +536,10 @@ get_utf8_string (const char *str)
           strcat (utf8_str, cp);
           g_free (cp);
         }
-      if (error)
+      if (err)
         {
-          g_error_free (error);
-          error = NULL;
+          g_error_free (err);
+          err = NULL;
         }
     }
   return utf8_str;
@@ -517,28 +555,43 @@ xg_check_special_colors (struct frame *f,
                          XColor *color)
 {
   int success_p = 0;
-  if (FRAME_GTK_WIDGET (f))
-    {
-      if (strcmp ("gtk_selection_bg_color", color_name) == 0)
-        {
-          GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f));
-          color->red = gsty->bg[GTK_STATE_SELECTED].red;
-          color->green = gsty->bg[GTK_STATE_SELECTED].green;
-          color->blue = gsty->bg[GTK_STATE_SELECTED].blue;
-          color->pixel = gsty->bg[GTK_STATE_SELECTED].pixel;
-          success_p = 1;
-        }
-      else if (strcmp ("gtk_selection_fg_color", color_name) == 0)
-        {
-          GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f));
-          color->red = gsty->fg[GTK_STATE_SELECTED].red;
-          color->green = gsty->fg[GTK_STATE_SELECTED].green;
-          color->blue = gsty->fg[GTK_STATE_SELECTED].blue;
-          color->pixel = gsty->fg[GTK_STATE_SELECTED].pixel;
-          success_p = 1;
-        }
-    }
+  int get_bg = strcmp ("gtk_selection_bg_color", color_name) == 0;
+  int get_fg = !get_bg && strcmp ("gtk_selection_fg_color", color_name) == 0;
+
+  if (! FRAME_GTK_WIDGET (f) || ! (get_bg || get_fg))
+    return success_p;
+
+  BLOCK_INPUT;
+  {
+#ifdef HAVE_GTK3
+    GtkStyleContext *gsty
+      = gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f));
+    GdkRGBA col;
+    char buf[64];
+    int state = GTK_STATE_FLAG_SELECTED|GTK_STATE_FLAG_FOCUSED;
+    if (get_fg)
+      gtk_style_context_get_color (gsty, state, &col);
+    else
+      gtk_style_context_get_background_color (gsty, state, &col);
 
+    sprintf (buf, "rgbi:%lf/%lf/%lf", col.red, col.green, col.blue);
+    success_p = XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+                             buf, color);
+#else
+    GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f));
+    GdkColor *grgb = get_bg
+      ? &gsty->bg[GTK_STATE_SELECTED]
+      : &gsty->fg[GTK_STATE_SELECTED];
+
+    color->red = grgb->red;
+    color->green = grgb->green;
+    color->blue = grgb->blue;
+    color->pixel = grgb->pixel;
+    success_p = 1;
+#endif
+
+  }
+  UNBLOCK_INPUT;
   return success_p;
 }
 
@@ -632,7 +685,7 @@ xg_prepare_tooltip (FRAME_PTR f,
   encoded_string = ENCODE_UTF_8 (string);
   widget = GTK_WIDGET (x->ttip_lbl);
   gwin = gtk_widget_get_window (GTK_WIDGET (x->ttip_window));
-  screen = gdk_drawable_get_screen (gwin);
+  screen = gdk_window_get_screen (gwin);
   settings = gtk_settings_get_for_screen (screen);
   g_object_get (settings, "gtk-enable-tooltips", &tt_enabled, NULL);
   if (tt_enabled)
@@ -652,8 +705,8 @@ xg_prepare_tooltip (FRAME_PTR f,
      hierarchy-changed.  */
   gtk_tooltip_set_custom (x->ttip_widget, widget);
 
-  gtk_tooltip_set_text (x->ttip_widget, SDATA (encoded_string));
-  gtk_widget_size_request (GTK_WIDGET (x->ttip_window), &req);
+  gtk_tooltip_set_text (x->ttip_widget, SSDATA (encoded_string));
+  gtk_widget_get_preferred_size (GTK_WIDGET (x->ttip_window), NULL, &req);
   if (width) *width = req.width;
   if (height) *height = req.height;
 
@@ -699,7 +752,7 @@ xg_hide_tooltip (FRAME_PTR f)
       if (g_object_get_data (G_OBJECT (win), "restore-tt"))
         {
           GdkWindow *gwin = gtk_widget_get_window (GTK_WIDGET (win));
-          GdkScreen *screen = gdk_drawable_get_screen (gwin);
+          GdkScreen *screen = gdk_window_get_screen (gwin);
           GtkSettings *settings = gtk_settings_get_for_screen (screen);
           g_object_set (settings, "gtk-enable-tooltips", TRUE, NULL);
         }
@@ -800,7 +853,7 @@ xg_frame_resized (FRAME_PTR f, int pixelwidth, int pixelheight)
       if (FRAME_GTK_WIDGET (f) && gtk_widget_get_mapped (FRAME_GTK_WIDGET (f)))
           gdk_window_get_geometry (gtk_widget_get_window (FRAME_GTK_WIDGET (f)),
                                    0, 0,
-                                   &pixelwidth, &pixelheight, 0);
+                                   &pixelwidth, &pixelheight);
       else return;
     }
 
@@ -913,8 +966,8 @@ xg_win_to_widget (Display *dpy, Window wdesc)
 
   BLOCK_INPUT;
 
-  gdkwin = gdk_xid_table_lookup_for_display (gdk_x11_lookup_xdisplay (dpy),
-                                             wdesc);
+  gdkwin = gdk_x11_window_lookup_for_display (gdk_x11_lookup_xdisplay (dpy),
+                                              wdesc);
   if (gdkwin)
     {
       GdkEvent event;
@@ -926,14 +979,29 @@ xg_win_to_widget (Display *dpy, Window wdesc)
   return gwdesc;
 }
 
-/* Fill in the GdkColor C so that it represents PIXEL.
-   W is the widget that color will be used for.  Used to find colormap.  */
+/* Set the background of widget W to PIXEL.  */
 
 static void
-xg_pix_to_gcolor (GtkWidget *w, long unsigned int pixel, GdkColor *c)
+xg_set_widget_bg (FRAME_PTR f, GtkWidget *w, long unsigned int pixel)
 {
+#ifdef HAVE_GTK3
+  GdkRGBA bg;
+  XColor xbg;
+  xbg.pixel = pixel;
+  if (XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &xbg))
+    {
+      bg.red = (double)xbg.red/65536.0;
+      bg.green = (double)xbg.green/65536.0;
+      bg.blue = (double)xbg.blue/65536.0;
+      bg.alpha = 1.0;
+      gtk_widget_override_background_color (w, GTK_STATE_FLAG_NORMAL, &bg);
+    }
+#else
+  GdkColor bg;
   GdkColormap *map = gtk_widget_get_colormap (w);
-  gdk_colormap_query_color (map, pixel, c);
+  gdk_colormap_query_color (map, pixel, &bg);
+  gtk_widget_modify_bg (FRAME_GTK_WIDGET (f), GTK_STATE_NORMAL, &bg);
+#endif
 }
 
 /* Callback called when the gtk theme changes.
@@ -956,6 +1024,28 @@ style_changed_cb (GObject *go,
   kbd_buffer_store_event (&event);
 }
 
+/* Called when a delete-event occurs on WIDGET.  */
+
+static gboolean
+delete_cb (GtkWidget *widget,
+           GdkEvent  *event,
+           gpointer user_data)
+{
+#ifdef HAVE_GTK3
+  /* The event doesn't arrive in the normal event loop.  Send event
+     here.  */
+  FRAME_PTR f = (FRAME_PTR) user_data;
+  struct input_event ie;
+
+  EVENT_INIT (ie);
+  ie.kind = DELETE_WINDOW_EVENT;
+  XSETFRAME (ie.frame_or_window, f);
+  kbd_buffer_store_event (&ie);
+#endif
+
+  return TRUE;
+}
+
 /* Create and set up the GTK widgets for frame F.
    Return 0 if creation failed, non-zero otherwise.  */
 
@@ -965,7 +1055,6 @@ xg_create_frame_widgets (FRAME_PTR f)
   GtkWidget *wtop;
   GtkWidget *wvbox, *whbox;
   GtkWidget *wfixed;
-  GdkColor bg;
   GtkRcStyle *style;
   char *title = 0;
 
@@ -1032,7 +1121,7 @@ xg_create_frame_widgets (FRAME_PTR f)
   /* Add callback to do nothing on WM_DELETE_WINDOW.  The default in
      GTK is to destroy the widget.  We want Emacs to do that instead.  */
   g_signal_connect (G_OBJECT (wtop), "delete-event",
-                    G_CALLBACK (gtk_true), 0);
+                    G_CALLBACK (delete_cb), f);
 
   /* Convert our geometry parameters into a geometry string
      and specify it.
@@ -1060,9 +1149,9 @@ xg_create_frame_widgets (FRAME_PTR f)
 
   /* Since GTK clears its window by filling with the background color,
      we must keep X and GTK background in sync.  */
-  xg_pix_to_gcolor (wfixed, FRAME_BACKGROUND_PIXEL (f), &bg);
-  gtk_widget_modify_bg (wfixed, GTK_STATE_NORMAL, &bg);
+  xg_set_widget_bg (f, wfixed, FRAME_BACKGROUND_PIXEL (f));
 
+#ifndef HAVE_GTK3
   /* Also, do not let any background pixmap to be set, this looks very
      bad as Emacs overwrites the background pixmap with its own idea
      of background color.  */
@@ -1071,6 +1160,9 @@ xg_create_frame_widgets (FRAME_PTR f)
   /* Must use g_strdup because gtk_widget_modify_style does g_free.  */
   style->bg_pixmap_name[GTK_STATE_NORMAL] = g_strdup ("<none>");
   gtk_widget_modify_style (wfixed, style);
+#else
+  gtk_widget_set_can_focus (wfixed, TRUE);
+#endif
 
 #ifdef USE_GTK_TOOLTIP
   /* Steal a tool tip window we can move ourselves.  */
@@ -1107,7 +1199,9 @@ xg_free_frame_widgets (FRAME_PTR f)
 {
   if (FRAME_GTK_OUTER_WIDGET (f))
     {
+#ifdef USE_GTK_TOOLTIP
       struct x_output *x = f->output_data.x;
+#endif
       gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
       FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */
       FRAME_GTK_OUTER_WIDGET (f) = 0;
@@ -1227,11 +1321,8 @@ xg_set_background_color (FRAME_PTR f, long unsigned int bg)
 {
   if (FRAME_GTK_WIDGET (f))
     {
-      GdkColor gdk_bg;
-
       BLOCK_INPUT;
-      xg_pix_to_gcolor (FRAME_GTK_WIDGET (f), bg, &gdk_bg);
-      gtk_widget_modify_bg (FRAME_GTK_WIDGET (f), GTK_STATE_NORMAL, &gdk_bg);
+      xg_set_widget_bg (f, FRAME_GTK_WIDGET (f), FRAME_BACKGROUND_PIXEL (f));
       UNBLOCK_INPUT;
     }
 }
@@ -1243,11 +1334,10 @@ xg_set_background_color (FRAME_PTR f, long unsigned int bg)
 void
 xg_set_frame_icon (FRAME_PTR f, Pixmap icon_pixmap, Pixmap icon_mask)
 {
-    GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f));
-    GdkPixmap *gpix = gdk_pixmap_foreign_new_for_display (gdpy, icon_pixmap);
-    GdkPixmap *gmask = gdk_pixmap_foreign_new_for_display (gdpy, icon_mask);
-    GdkPixbuf *gp = xg_get_pixbuf_from_pix_and_mask (gpix, gmask, NULL);
-
+  GdkPixbuf *gp = xg_get_pixbuf_from_pix_and_mask (f,
+                                                   icon_pixmap,
+                                                   icon_mask);
+  if (gp)
     gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), gp);
 }
 
@@ -1329,8 +1419,6 @@ create_dialog (widget_value *wv,
   GtkDialog *wd = GTK_DIALOG (wdialog);
   GtkBox *cur_box = GTK_BOX (gtk_dialog_get_action_area (wd));
   widget_value *item;
-  GtkWidget *wvbox;
-  GtkWidget *whbox_up;
   GtkWidget *whbox_down;
 
   /* If the number of buttons is greater than 4, make two rows of buttons
@@ -1346,8 +1434,8 @@ create_dialog (widget_value *wv,
 
   if (make_two_rows)
     {
-      wvbox = gtk_vbox_new (TRUE, button_spacing);
-      whbox_up = gtk_hbox_new (FALSE, 0);
+      GtkWidget *wvbox = gtk_vbox_new (TRUE, button_spacing);
+      GtkWidget *whbox_up = gtk_hbox_new (FALSE, 0);
       whbox_down = gtk_hbox_new (FALSE, 0);
 
       gtk_box_pack_start (cur_box, wvbox, FALSE, FALSE, 0);
@@ -1384,7 +1472,7 @@ create_dialog (widget_value *wv,
           /* Try to make dialog look better.  Must realize first so
              the widget can calculate the size it needs.  */
           gtk_widget_realize (w);
-          gtk_widget_size_request (w, &req);
+          gtk_widget_get_preferred_size (w, NULL, &req);
           gtk_box_set_spacing (wvbox, req.height);
          if (item->value && strlen (item->value) > 0)
             button_spacing = 2*req.width/strlen (item->value);
@@ -1469,7 +1557,7 @@ static gboolean
 xg_maybe_add_timer (gpointer data)
 {
   struct xg_dialog_data *dd = (struct xg_dialog_data *) data;
-  EMACS_TIME next_time = timer_check (1);
+  EMACS_TIME next_time = timer_check ();
   long secs = EMACS_SECS (next_time);
   long usecs = EMACS_USECS (next_time);
 
@@ -1536,7 +1624,6 @@ int
 xg_uses_old_file_dialog (void)
 {
 #ifdef HAVE_GTK_FILE_SELECTION_NEW
-  extern int x_gtk_use_old_file_dialog;
   return x_gtk_use_old_file_dialog;
 #else
   return 0;
@@ -1577,8 +1664,6 @@ xg_toggle_visibility_cb (GtkWidget *widget, gpointer data)
 static void
 xg_toggle_notify_cb (GObject *gobject, GParamSpec *arg1, gpointer user_data)
 {
-  extern int x_gtk_show_hidden_files;
-
   if (strcmp (arg1->name, "show-hidden") == 0)
     {
       GtkWidget *wtoggle = GTK_WIDGET (user_data);
@@ -1619,16 +1704,13 @@ xg_get_file_with_chooser (FRAME_PTR f,
                          int mustmatch_p, int only_dir_p,
                          xg_get_file_func *func)
 {
-  char message[1024];
+  char msgbuf[1024];
 
-  GtkWidget *filewin, *wtoggle, *wbox, *wmessage;
+  GtkWidget *filewin, *wtoggle, *wbox, *wmessage IF_LINT (= NULL);
   GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
   GtkFileChooserAction action = (mustmatch_p ?
                                  GTK_FILE_CHOOSER_ACTION_OPEN :
                                  GTK_FILE_CHOOSER_ACTION_SAVE);
-  extern int x_gtk_show_hidden_files;
-  extern int x_gtk_file_dialog_help_text;
-
 
   if (only_dir_p)
     action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
@@ -1658,16 +1740,16 @@ xg_get_file_with_chooser (FRAME_PTR f,
 
   if (x_gtk_file_dialog_help_text)
     {
-      message[0] = '\0';
+      msgbuf[0] = '\0';
       /* Gtk+ 2.10 has the file name text entry box integrated in the dialog.
          Show the C-l help text only for versions < 2.10.  */
       if (gtk_check_version (2, 10, 0) && action != GTK_FILE_CHOOSER_ACTION_SAVE)
-        strcat (message, "\nType C-l to display a file name text entry box.\n");
-      strcat (message, "\nIf you don't like this file selector, use the "
+        strcat (msgbuf, "\nType C-l to display a file name text entry box.\n");
+      strcat (msgbuf, "\nIf you don't like this file selector, use the "
               "corresponding\nkey binding or customize "
               "use-file-dialog to turn it off.");
 
-      wmessage = gtk_label_new (message);
+      wmessage = gtk_label_new (msgbuf);
       gtk_widget_show (wmessage);
     }
 
@@ -3037,7 +3119,7 @@ menubar_map_cb (GtkWidget *w, gpointer user_data)
 {
   GtkRequisition req;
   FRAME_PTR f = (FRAME_PTR) user_data;
-  gtk_widget_size_request (w, &req);
+  gtk_widget_get_preferred_size (w, NULL, &req);
   if (FRAME_MENUBAR_HEIGHT (f) != req.height)
     {
       FRAME_MENUBAR_HEIGHT (f) = req.height;
@@ -3068,7 +3150,7 @@ xg_update_frame_menubar (FRAME_PTR f)
 
   g_signal_connect (x->menubar_widget, "map", G_CALLBACK (menubar_map_cb), f);
   gtk_widget_show_all (x->menubar_widget);
-  gtk_widget_size_request (x->menubar_widget, &req);
+  gtk_widget_get_preferred_size (x->menubar_widget, NULL, &req);
 
   /* If menu bar doesn't know its height yet, cheat a little so the frame
      doesn't jump so much when resized later in menubar_map_cb.  */
@@ -3129,7 +3211,7 @@ xg_event_is_for_menubar (FRAME_PTR f, XEvent *event)
     return 0;
 
   gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f));
-  gw = gdk_xid_table_lookup_for_display (gdpy, event->xbutton.window);
+  gw = gdk_x11_window_lookup_for_display (gdpy, event->xbutton.window);
   if (! gw) return 0;
   gevent.any.window = gw;
   gwdesc = gtk_get_event_widget (&gevent);
@@ -3272,7 +3354,7 @@ xg_get_scroll_id_for_window (Display *dpy, Window wid)
 static void
 xg_gtk_scroll_destroy (GtkWidget *widget, gpointer data)
 {
-  int id = (int) (EMACS_INT) data; /* The EMACS_INT cast avoids a warning. */
+  int id = (EMACS_INTPTR) data;
   xg_remove_widget_from_map (id);
 }
 
@@ -3293,8 +3375,12 @@ xg_create_scroll_bar (FRAME_PTR f,
 {
   GtkWidget *wscroll;
   GtkWidget *webox;
+  EMACS_INTPTR scroll_id;
+#ifdef HAVE_GTK3
+  GtkAdjustment *vadj;
+#else
   GtkObject *vadj;
-  int scroll_id;
+#endif
 
   /* Page, step increment values are not so important here, they
      will be corrected in x_set_toolkit_scroll_bar_thumb. */
@@ -3304,16 +3390,17 @@ xg_create_scroll_bar (FRAME_PTR f,
   wscroll = gtk_vscrollbar_new (GTK_ADJUSTMENT (vadj));
   webox = gtk_event_box_new ();
   gtk_widget_set_name (wscroll, scroll_bar_name);
+#ifndef HAVE_GTK3
   gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS);
+#endif
   g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f);
 
   scroll_id = xg_store_widget_in_map (wscroll);
 
-  /* The EMACS_INT cast avoids a warning. */
   g_signal_connect (G_OBJECT (wscroll),
                     "destroy",
                     G_CALLBACK (xg_gtk_scroll_destroy),
-                    (gpointer) (EMACS_INT) scroll_id);
+                    (gpointer) scroll_id);
   g_signal_connect (G_OBJECT (wscroll),
                     "change-value",
                     scroll_callback,
@@ -3441,6 +3528,7 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
       gdouble shown;
       gdouble top;
       int size, value;
+      int old_size;
       int new_step;
       int changed = 0;
 
@@ -3473,17 +3561,21 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
       /* Assume all lines are of equal size.  */
       new_step = size / max (1, FRAME_LINES (f));
 
-      if ((int) gtk_adjustment_get_page_size (adj) != size
-          || (int) gtk_adjustment_get_step_increment (adj) != new_step)
-        {
-          gtk_adjustment_set_page_size (adj, size);
-          gtk_adjustment_set_step_increment (adj, new_step);
-          /* Assume a page increment is about 95% of the page size  */
-          gtk_adjustment_set_page_increment (adj,(int) (0.95*size));
-          changed = 1;
-        }
+      old_size = gtk_adjustment_get_page_size (adj);
+      if (old_size != size)
+       {
+         int old_step = gtk_adjustment_get_step_increment (adj);
+         if (old_step != new_step)
+           {
+             gtk_adjustment_set_page_size (adj, size);
+             gtk_adjustment_set_step_increment (adj, new_step);
+             /* Assume a page increment is about 95% of the page size  */
+             gtk_adjustment_set_page_increment (adj,(int) (0.95*size));
+             changed = 1;
+           }
+       }
 
-      if (changed || (int) gtk_range_get_value (GTK_RANGE (wscroll)) != value)
+      if (changed || int_gtk_range_get_value (GTK_RANGE (wscroll)) != value)
       {
         BLOCK_INPUT;
 
@@ -3491,7 +3583,7 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar,
            ignore_gtk_scrollbar to make the callback do nothing  */
         xg_ignore_gtk_scrollbar = 1;
 
-        if ((int) gtk_range_get_value (GTK_RANGE (wscroll)) != value)
+        if (int_gtk_range_get_value (GTK_RANGE (wscroll)) != value)
           gtk_range_set_value (GTK_RANGE (wscroll), (gdouble)value);
         else if (changed)
           gtk_adjustment_changed (adj);
@@ -3570,8 +3662,8 @@ xg_tool_bar_button_cb (GtkWidget *widget,
                        GdkEventButton *event,
                        gpointer user_data)
 {
-  /* Casts to avoid warnings when gpointer is 64 bits and int is 32 bits */
-  gpointer ptr = (gpointer) (EMACS_INT) event->state;
+  EMACS_INTPTR state = event->state;
+  gpointer ptr = (gpointer) state;
   g_object_set_data (G_OBJECT (widget), XG_TOOL_BAR_LAST_MODIFIER, ptr);
   return FALSE;
 }
@@ -3585,10 +3677,9 @@ xg_tool_bar_button_cb (GtkWidget *widget,
 static void
 xg_tool_bar_callback (GtkWidget *w, gpointer client_data)
 {
-  /* The EMACS_INT cast avoids a warning. */
-  int idx = (int) (EMACS_INT) client_data;
-  int mod = (int) (EMACS_INT) g_object_get_data (G_OBJECT (w),
-                                                 XG_TOOL_BAR_LAST_MODIFIER);
+  EMACS_INTPTR idx = (EMACS_INTPTR) client_data;
+  gpointer gmod = g_object_get_data (G_OBJECT (w), XG_TOOL_BAR_LAST_MODIFIER);
+  EMACS_INTPTR mod = (EMACS_INTPTR) gmod;
 
   FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (w), XG_FRAME_DATA);
   Lisp_Object key, frame;
@@ -3686,7 +3777,7 @@ xg_tool_bar_menu_proxy (GtkToolItem *toolitem, gpointer user_data)
   GtkLabel *wlbl = GTK_LABEL (xg_get_tool_bar_widgets (vb, &c1));
   GtkImage *wimage = GTK_IMAGE (c1);
   GtkWidget *wmenuitem = gtk_image_menu_item_new_with_label
-    (gtk_label_get_text (wlbl));
+    (wlbl ? gtk_label_get_text (wlbl) : "");
   GtkWidget *wmenuimage;
 
 
@@ -3794,7 +3885,6 @@ xg_tool_bar_detach_callback (GtkHandleBox *wbox,
                              gpointer client_data)
 {
   FRAME_PTR f = (FRAME_PTR) client_data;
-  extern int x_gtk_whole_detached_tool_bar;
 
   g_object_set (G_OBJECT (w), "show-arrow", !x_gtk_whole_detached_tool_bar,
                NULL);
@@ -3803,8 +3893,8 @@ xg_tool_bar_detach_callback (GtkHandleBox *wbox,
     {
       GtkRequisition req, req2;
       FRAME_X_OUTPUT (f)->toolbar_detached = 1;
-      gtk_widget_size_request (GTK_WIDGET (wbox), &req);
-      gtk_widget_size_request (w, &req2);
+      gtk_widget_get_preferred_size (GTK_WIDGET (wbox), NULL, &req);
+      gtk_widget_get_preferred_size (w, NULL, &req2);
       req.width -= req2.width;
       req.height -= req2.height;
       if (FRAME_TOOLBAR_TOP_HEIGHT (f) != 0)
@@ -3838,8 +3928,8 @@ xg_tool_bar_attach_callback (GtkHandleBox *wbox,
     {
       GtkRequisition req, req2;
       FRAME_X_OUTPUT (f)->toolbar_detached = 0;
-      gtk_widget_size_request (GTK_WIDGET (wbox), &req);
-      gtk_widget_size_request (w, &req2);
+      gtk_widget_get_preferred_size (GTK_WIDGET (wbox), NULL, &req);
+      gtk_widget_get_preferred_size (w, NULL, &req2);
       req.width += req2.width;
       req.height += req2.height;
       if (FRAME_TOOLBAR_TOP_HEIGHT (f) != 0)
@@ -3868,8 +3958,7 @@ xg_tool_bar_help_callback (GtkWidget *w,
                            GdkEventCrossing *event,
                            gpointer client_data)
 {
-  /* The EMACS_INT cast avoids a warning. */
-  int idx = (int) (EMACS_INT) client_data;
+  EMACS_INTPTR idx = (EMACS_INTPTR) client_data;
   FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (w), XG_FRAME_DATA);
   Lisp_Object help, frame;
 
@@ -3904,6 +3993,7 @@ xg_tool_bar_help_callback (GtkWidget *w,
 
    Returns FALSE to tell GTK to keep processing this event.  */
 
+#ifndef HAVE_GTK3
 static gboolean
 xg_tool_bar_item_expose_callback (GtkWidget *w,
                                   GdkEventExpose *event,
@@ -3912,7 +4002,6 @@ xg_tool_bar_item_expose_callback (GtkWidget *w,
   gint width, height;
 
   gdk_drawable_get_size (event->window, &width, &height);
-
   event->area.x -= width > event->area.width ? width-event->area.width : 0;
   event->area.y -= height > event->area.height ? height-event->area.height : 0;
 
@@ -3924,6 +4013,7 @@ xg_tool_bar_item_expose_callback (GtkWidget *w,
 
   return FALSE;
 }
+#endif
 
 #ifdef HAVE_GTK_ORIENTABLE_SET_ORIENTATION
 #define toolbar_set_orientation(w, o) \
@@ -4062,24 +4152,27 @@ xg_make_tool_item (FRAME_PTR f,
 
   if (wimage)
     {
-      /* The EMACS_INT cast avoids a warning. */
+      EMACS_INTPTR ii = i;
+      gpointer gi = (gpointer) ii;
+
       g_signal_connect (G_OBJECT (ti), "create-menu-proxy",
                         G_CALLBACK (xg_tool_bar_menu_proxy),
-                        (gpointer) (EMACS_INT) i);
+                        gi);
 
       g_signal_connect (G_OBJECT (wb), "clicked",
                         G_CALLBACK (xg_tool_bar_callback),
-                        (gpointer) (EMACS_INT) i);
+                        gi);
 
       g_object_set_data (G_OBJECT (weventbox), XG_FRAME_DATA, (gpointer)f);
 
+#ifndef HAVE_GTK3
       /* Catch expose events to overcome an annoying redraw bug, see
          comment for xg_tool_bar_item_expose_callback.  */
       g_signal_connect (G_OBJECT (ti),
                         "expose-event",
                         G_CALLBACK (xg_tool_bar_item_expose_callback),
                         0);
-
+#endif
       gtk_tool_item_set_homogeneous (ti, FALSE);
 
       /* Callback to save modifyer mask (Shift/Control, etc).  GTK makes
@@ -4099,11 +4192,11 @@ xg_make_tool_item (FRAME_PTR f,
       g_signal_connect (G_OBJECT (weventbox),
                         "enter-notify-event",
                         G_CALLBACK (xg_tool_bar_help_callback),
-                        (gpointer) (EMACS_INT) i);
+                        gi);
       g_signal_connect (G_OBJECT (weventbox),
                         "leave-notify-event",
                         G_CALLBACK (xg_tool_bar_help_callback),
-                        (gpointer) (EMACS_INT) i);
+                        gi);
     }
 
   if (wbutton) *wbutton = wb;
@@ -4138,9 +4231,9 @@ xg_tool_item_stale_p (GtkWidget *wbutton, const char *stock_name,
     }
   else
     {
-      Pixmap old_img
-       = (Pixmap) g_object_get_data (G_OBJECT (wimage),
-                                     XG_TOOL_BAR_IMAGE_DATA);
+      gpointer gold_img = g_object_get_data (G_OBJECT (wimage),
+                                           XG_TOOL_BAR_IMAGE_DATA);
+      Pixmap old_img = (Pixmap) gold_img;
       if (old_img != img->pixmap)
        return 1;
     }
@@ -4163,7 +4256,7 @@ xg_update_tool_bar_sizes (FRAME_PTR f)
   GtkRequisition req;
   int nl = 0, nr = 0, nt = 0, nb = 0;
 
-  gtk_widget_size_request (GTK_WIDGET (x->handlebox_widget), &req);
+  gtk_widget_get_preferred_size (GTK_WIDGET (x->handlebox_widget), NULL, &req);
   if (x->toolbar_in_hbox)
     {
       int pos;
@@ -4213,7 +4306,6 @@ update_frame_tool_bar (FRAME_PTR f)
   GtkToolItem *ti;
   GtkTextDirection dir;
   int pack_tool_bar = x->handlebox_widget == NULL;
-
   Lisp_Object style;
   int text_image, horiz;
 
@@ -4561,17 +4653,14 @@ xg_initialize (void)
   /* Make dialogs close on C-g.  Since file dialog inherits from
      dialog, this works for them also.  */
   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_DIALOG));
-  gtk_binding_entry_add_signal (binding_set, GDK_g, GDK_CONTROL_MASK,
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_g, GDK_CONTROL_MASK,
                                 "close", 0);
 
   /* Make menus close on C-g.  */
   binding_set = gtk_binding_set_by_class (g_type_class_ref
                                           (GTK_TYPE_MENU_SHELL));
-  gtk_binding_entry_add_signal (binding_set, GDK_g, GDK_CONTROL_MASK,
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_g, GDK_CONTROL_MASK,
                                 "cancel", 0);
 }
 
 #endif /* USE_GTK */
-
-/* arch-tag: fe7104da-bc1e-4aba-9bd1-f349c528f7e3
-   (do not change this comment) */