--- /dev/null	2008-11-30 10:52:27.712047315 -0500
+++ gtk/gtkiconentry.h	2008-11-11 09:13:39.000000000 -0500
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2004-2006 Christian Hammond.
+ * Copyright (C) 2008 Cody Russell  <bratsche@gnome.org>
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA  02111-1307, USA.
+ */
+
+#ifndef __GTK_ICON_ENTRY_H__
+#define __GTK_ICON_ENTRY_H__
+
+
+#include <gtk/gtkentry.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtkselection.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_ICON_ENTRY (gtk_icon_entry_get_type())
+#define GTK_ICON_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_ICON_ENTRY, GtkIconEntry))
+#define GTK_ICON_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_ICON_ENTRY, GtkIconEntryClass))
+#define GTK_IS_ICON_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_ICON_ENTRY))
+#define GTK_IS_ICON_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_ICON_ENTRY))
+#define GTK_ICON_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ICON_ENTRY, GtkIconEntryClass))
+
+typedef enum
+{
+  GTK_ICON_ENTRY_PRIMARY,
+  GTK_ICON_ENTRY_SECONDARY
+} GtkIconEntryPosition;
+
+typedef struct _GtkIconEntry      GtkIconEntry;
+typedef struct _GtkIconEntryClass GtkIconEntryClass;
+
+struct _GtkIconEntry
+{
+  GtkEntry parent_object;
+};
+
+struct _GtkIconEntryClass
+{
+  GtkEntryClass parent_class;
+
+  /* Signals */
+  void (*icon_pressed)  (GtkIconEntry         *entry,
+                         GtkIconEntryPosition  icon_pos,
+                         GdkEventButton       *event);
+  void (*icon_released) (GtkIconEntry         *entry,
+                         GtkIconEntryPosition  icon_pos,
+                         GdkEventButton       *event);
+
+  void (*gtk_reserved1) (void);
+  void (*gtk_reserved2) (void);
+  void (*gtk_reserved3) (void);
+  void (*gtk_reserved4) (void);
+};
+
+GType        gtk_icon_entry_get_type                (void) G_GNUC_CONST;
+
+GtkWidget*   gtk_icon_entry_new                     (void);
+
+void         gtk_icon_entry_set_icon_from_pixbuf    (GtkIconEntry         *entry,
+                                                     GtkIconEntryPosition  icon_pos,
+                                                     GdkPixbuf            *pixbuf);
+void         gtk_icon_entry_set_icon_from_stock     (GtkIconEntry         *entry,
+                                                     GtkIconEntryPosition  icon_pos,
+                                                     const gchar          *stock_id);
+void         gtk_icon_entry_set_icon_from_icon_name (GtkIconEntry         *entry,
+                                                     GtkIconEntryPosition  icon_pos,
+                                                     const gchar          *icon_name);
+void         gtk_icon_entry_set_icon_from_gicon     (GtkIconEntry         *entry,
+                                                     GtkIconEntryPosition  icon_pos,
+                                                     GIcon                *icon);
+GtkImageType gtk_icon_entry_get_storage_type        (GtkIconEntry         *entry,
+                                                     GtkIconEntryPosition  icon_pos);
+GdkPixbuf*   gtk_icon_entry_get_pixbuf              (GtkIconEntry         *entry,
+                                                     GtkIconEntryPosition  icon_pos);
+const gchar* gtk_icon_entry_get_stock               (GtkIconEntry         *entry,
+                                                     GtkIconEntryPosition  icon_pos);
+const gchar* gtk_icon_entry_get_icon_name           (GtkIconEntry         *entry,
+                                                     GtkIconEntryPosition  icon_pos);
+GIcon*       gtk_icon_entry_get_gicon               (GtkIconEntry         *entry,
+                                                     GtkIconEntryPosition  icon_pos);
+void         gtk_icon_entry_set_icon_activatable    (GtkIconEntry         *entry,
+                                                     GtkIconEntryPosition  icon_pos,
+                                                     gboolean              activatable);
+gboolean     gtk_icon_entry_get_icon_activatable    (GtkIconEntry         *entry,
+                                                     GtkIconEntryPosition  icon_pos);
+void         gtk_icon_entry_set_icon_sensitive      (GtkIconEntry         *entry,
+                                                     GtkIconEntryPosition  icon_pos,
+                                                     gboolean              sensitive);
+gboolean     gtk_icon_entry_get_icon_sensitive      (GtkIconEntry         *entry,
+                                                     GtkIconEntryPosition  icon_pos);
+gint         gtk_icon_entry_get_icon_at_pos         (GtkIconEntry         *entry,
+                                                     gint                  x,
+                                                     gint                  y);
+void         gtk_icon_entry_set_icon_tooltip_text   (GtkIconEntry         *entry,
+                                                     GtkIconEntryPosition  icon_pos,
+                                                     const gchar          *tooltip);
+void         gtk_icon_entry_set_icon_tooltip_markup (GtkIconEntry         *entry,
+                                                     GtkIconEntryPosition  icon_pos,
+                                                     const gchar          *tooltip);
+void         gtk_icon_entry_set_icon_drag_source    (GtkIconEntry         *entry,
+                                                     GtkIconEntryPosition  icon_pos,
+                                                     GtkTargetList        *target_list,
+                                                     GdkDragAction         actions);
+gint         gtk_icon_entry_get_current_icon_drag_source (GtkIconEntry    *entry);
+  
+
+G_END_DECLS
+
+#endif /* __GTK_ICON_ENTRY_H__ */
--- /dev/null	2008-11-30 10:52:27.712047315 -0500
+++ gtk/gtkiconentry.c	2008-11-14 00:28:27.000000000 -0500
@@ -0,0 +1,2422 @@
+/*
+ * Copyright (C) 2004-2006 Christian Hammond.
+ * Copyright (C) 2008 Cody Russell  <bratsche@gnome.org>
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA  02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "gtkprivate.h"
+#include "gtkdnd.h"
+#include "gtkentryprivate.h"
+#include "gtkintl.h"
+#include "gtkiconentry.h"
+#include "gtkiconfactory.h"
+#include "gtkicontheme.h"
+#include "gtkimage.h"
+#include "gtkmarshalers.h"
+#include "gtkselection.h"
+#include "gtkstock.h"
+#include "gtktooltip.h"
+
+#define MAX_ICONS 2
+
+#define IS_VALID_ICON_ENTRY_POSITION(pos) \
+        ((pos) == GTK_ICON_ENTRY_PRIMARY || \
+        (pos) == GTK_ICON_ENTRY_SECONDARY)
+
+#define GTK_ICON_ENTRY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_ICON_ENTRY, GtkIconEntryPrivate))
+
+typedef struct
+{
+  GdkWindow *window;
+  gchar *tooltip;
+  guint insensitive    : 1;
+  guint nonactivatable : 1;
+  guint prelight       : 1;
+  guint in_drag        : 1;
+  guint pressed        : 1;
+
+  GtkImageType storage_type;
+  GdkPixbuf *pixbuf;
+  gchar *stock_id;
+  gchar *icon_name;
+  GIcon *gicon;
+
+  GtkTargetList *target_list;
+  GdkDragAction actions;
+} EntryIconInfo;
+
+typedef struct _GtkIconEntryPrivate
+{
+  EntryIconInfo icons[MAX_ICONS];
+  gint icon_margin;
+  gint start_x;
+  gint start_y;
+} GtkIconEntryPrivate;
+
+enum
+{
+  ICON_PRESSED,
+  ICON_RELEASED,
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_PIXBUF_PRIMARY,
+  PROP_PIXBUF_SECONDARY,
+  PROP_STOCK_PRIMARY,
+  PROP_STOCK_SECONDARY,
+  PROP_ICON_NAME_PRIMARY,
+  PROP_ICON_NAME_SECONDARY,
+  PROP_GICON_PRIMARY,
+  PROP_GICON_SECONDARY,
+  PROP_STORAGE_TYPE_PRIMARY,
+  PROP_STORAGE_TYPE_SECONDARY,
+  PROP_ACTIVATABLE_PRIMARY,
+  PROP_ACTIVATABLE_SECONDARY,
+  PROP_SENSITIVE_PRIMARY,
+  PROP_SENSITIVE_SECONDARY
+};
+
+static void gtk_icon_entry_class_init        (GtkIconEntryClass    *klass);
+static void gtk_icon_entry_editable_init     (GtkEditableClass     *iface);
+static void gtk_icon_entry_init              (GtkIconEntry         *entry);
+static void gtk_icon_entry_dispose           (GObject              *obj);
+static void gtk_icon_entry_map               (GtkWidget            *widget);
+static void gtk_icon_entry_unmap             (GtkWidget            *widget);
+static void gtk_icon_entry_realize           (GtkWidget            *widget);
+static void gtk_icon_entry_unrealize         (GtkWidget            *widget);
+static void gtk_icon_entry_size_request      (GtkWidget            *widget,
+                                              GtkRequisition       *requisition);
+static void gtk_icon_entry_size_allocate     (GtkWidget            *widget,
+                                              GtkAllocation        *allocation);
+static gint gtk_icon_entry_expose            (GtkWidget            *widget,
+                                              GdkEventExpose       *event);
+static gint gtk_icon_entry_enter_notify      (GtkWidget            *widget,
+                                              GdkEventCrossing     *event);
+static gint gtk_icon_entry_leave_notify      (GtkWidget            *widget,
+                                              GdkEventCrossing     *event);
+static gint gtk_icon_entry_button_press      (GtkWidget            *widget,
+                                              GdkEventButton       *event);
+static gint gtk_icon_entry_button_release    (GtkWidget            *widget,
+                                              GdkEventButton       *event);
+static gint gtk_icon_entry_motion_notify     (GtkWidget            *widget,
+                                              GdkEventMotion       *event);
+static void gtk_icon_entry_set_property      (GObject              *object,
+                                              guint                 prop_id,
+                                              const GValue         *value,
+                                              GParamSpec           *pspec);
+static void gtk_icon_entry_get_property      (GObject              *object,
+                                              guint                 prop_id,
+                                              GValue               *value,
+                                              GParamSpec           *pspec);
+static void gtk_icon_entry_style_set         (GtkWidget            *widget,
+                                              GtkStyle             *prev_style);
+static void icon_theme_changed               (GtkIconEntry         *entry);
+static void gtk_icon_entry_ensure_pixbuf     (GtkIconEntry         *entry,
+                                              GtkIconEntryPosition  icon_pos);
+static gboolean gtk_icon_entry_query_tooltip (GtkWidget            *widget,
+                                              gint                  x,
+                                              gint                  y,
+                                              gboolean              keyboard_tip,
+                                              GtkTooltip           *tooltip);
+
+static void gtk_icon_entry_icon_pressed      (GtkIconEntry         *entry,
+                                              GtkIconEntryPosition  icon_pos,
+                                              GdkEventButton       *event);
+static void gtk_icon_entry_icon_released     (GtkIconEntry         *entry,
+                                              GtkIconEntryPosition  icon_pos,
+                                              GdkEventButton       *event);
+
+static void gtk_icon_entry_drag_begin        (GtkWidget            *widget,
+                                              GdkDragContext       *context);
+static void gtk_icon_entry_drag_end          (GtkWidget            *widget,
+                                              GdkDragContext       *context);
+
+static void gtk_icon_entry_drag_data_get     (GtkWidget            *widget,
+                                              GdkDragContext       *context,
+                                              GtkSelectionData     *selection_data,
+                                              guint                 info,
+                                              guint                 time);
+static void gtk_icon_entry_drag_data_delete  (GtkWidget            *widget,
+                                              GdkDragContext       *context);
+
+
+static guint signals[LAST_SIGNAL] = {0};
+
+G_DEFINE_TYPE_EXTENDED (GtkIconEntry, gtk_icon_entry, GTK_TYPE_ENTRY,
+                        0,
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
+                                               gtk_icon_entry_editable_init));
+
+static void
+gtk_icon_entry_class_init (GtkIconEntryClass *klass)
+{
+  GObjectClass *gobject_class;
+  GtkObjectClass *object_class;
+  GtkWidgetClass *widget_class;
+  GtkEntryClass *entry_class;
+
+  gobject_class = G_OBJECT_CLASS(klass);
+  object_class  = GTK_OBJECT_CLASS(klass);
+  widget_class  = GTK_WIDGET_CLASS(klass);
+  entry_class   = GTK_ENTRY_CLASS(klass);
+
+  gobject_class->dispose = gtk_icon_entry_dispose;
+  gobject_class->set_property = gtk_icon_entry_set_property;
+  gobject_class->get_property = gtk_icon_entry_get_property;
+
+  widget_class->map = gtk_icon_entry_map;
+  widget_class->unmap = gtk_icon_entry_unmap;
+  widget_class->realize = gtk_icon_entry_realize;
+  widget_class->unrealize = gtk_icon_entry_unrealize;
+  widget_class->size_request = gtk_icon_entry_size_request;
+  widget_class->size_allocate = gtk_icon_entry_size_allocate;
+  widget_class->expose_event = gtk_icon_entry_expose;
+  widget_class->enter_notify_event = gtk_icon_entry_enter_notify;
+  widget_class->leave_notify_event = gtk_icon_entry_leave_notify;
+  widget_class->motion_notify_event = gtk_icon_entry_motion_notify;
+  widget_class->button_press_event = gtk_icon_entry_button_press;
+  widget_class->button_release_event = gtk_icon_entry_button_release;
+  widget_class->style_set = gtk_icon_entry_style_set;
+  widget_class->query_tooltip = gtk_icon_entry_query_tooltip;
+  widget_class->drag_begin = gtk_icon_entry_drag_begin;
+  widget_class->drag_end = gtk_icon_entry_drag_end;
+  widget_class->drag_data_get = gtk_icon_entry_drag_data_get;
+  widget_class->drag_data_delete = gtk_icon_entry_drag_data_delete;
+
+  klass->icon_pressed = gtk_icon_entry_icon_pressed;
+  klass->icon_released = gtk_icon_entry_icon_released;
+
+  /**
+   * GtkIconEntry::icon-pressed:
+   * @entry: The entry on which the signal is emitted
+   * @icon_pos: The position of the clicked icon
+   * @buttomotione mouse button clicked
+   *
+   * The ::icon-pressed signal is emitted when an icon is clicked.
+   *
+   * Since: 2.16
+   */
+  signals[ICON_PRESSED] =
+    g_signal_new ("icon-pressed",
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                  G_STRUCT_OFFSET (GtkIconEntryClass, icon_pressed),
+                  NULL, NULL,
+                  _gtk_marshal_VOID__INT_BOXED,
+                  G_TYPE_NONE, 2,
+                  G_TYPE_INT,
+                  GDK_TYPE_EVENT);
+
+  /**
+   * GtkIconEntry::icon-released:
+   * @entry: The entry on which the signal is emitted
+   * @icon_pos: The position of the clicked icon
+   * @button: The mouse button clicked
+   *
+   * The ::icon-released signal is emitted on the button release from a
+   * mouse click.
+   *
+   * Since: 2.16
+   */
+  signals[ICON_RELEASED] =
+    g_signal_new ("icon-released",
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                  G_STRUCT_OFFSET (GtkIconEntryClass, icon_released),
+                  NULL, NULL,
+                  _gtk_marshal_VOID__INT_BOXED,
+                  G_TYPE_NONE, 2,
+                  G_TYPE_INT,
+                  GDK_TYPE_EVENT);
+
+  /**
+   * GtkIconEntry:pixbuf-primary:
+   *
+   * A pixbuf to use as the primary icon for the entry.
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_PIXBUF_PRIMARY,
+                                   g_param_spec_object ("pixbuf-primary",
+                                                        P_("Primary pixbuf"),
+                                                        P_("Primary pixbuf for the entry"),
+                                                        GDK_TYPE_PIXBUF,
+                                                        GTK_PARAM_READWRITE));
+
+  /**
+   * GtkIconEntry:pixbuf-secondary:
+   *
+   * An pixbuf to use as the secondary icon for the entry.
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_PIXBUF_SECONDARY,
+                                   g_param_spec_object ("pixbuf-secondary",
+                                                        P_("Secondary pixbuf"),
+                                                        P_("Secondary pixbuf for the entry"),
+                                                        GDK_TYPE_PIXBUF,
+                                                        GTK_PARAM_READWRITE));
+
+  /**
+   * GtkIconEntry:stock-primary:
+   *
+   * The stock id to use for the primary icon for the entry.
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_STOCK_PRIMARY,
+                                   g_param_spec_string ("stock-primary",
+                                                        P_("Primary stock ID"),
+                                                        P_("Stock ID for primary icon"),
+                                                        NULL,
+                                                        GTK_PARAM_WRITABLE));
+
+  /**
+   * GtkIconEntry:stock-secondary:
+   *
+   * The stock id to use for the secondary icon for the entry.
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_STOCK_SECONDARY,
+                                   g_param_spec_string ("stock-secondary",
+                                                        P_("Secondary stock ID"),
+                                                        P_("Stock ID for secondary icon"),
+                                                        NULL,
+                                                        GTK_PARAM_WRITABLE));
+
+  /**
+   * GtkIconEntry:icon-name-primary:
+   *
+   * The icon name to use for the primary icon for the entry.
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_ICON_NAME_PRIMARY,
+                                   g_param_spec_string ("icon-name-primary",
+                                                        P_("Primary icon name"),
+                                                        P_("Icon name for primary icon"),
+                                                        NULL,
+                                                        GTK_PARAM_WRITABLE));
+
+  /**
+   * GtkIconEntry:icon-name-secondary:
+   *
+   * The icon name to use for the secondary icon for the entry.
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_ICON_NAME_SECONDARY,
+                                   g_param_spec_string ("icon-name-secondary",
+                                                        P_("Secondary icon name"),
+                                                        P_("Icon name for secondary icon"),
+                                                        NULL,
+                                                        GTK_PARAM_WRITABLE));
+
+  /**
+   * GtkIconEntry:gicon-primary:
+   *
+   * The #GIcon to use for the primary icon for the entry.
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_GICON_PRIMARY,
+                                   g_param_spec_object ("gicon-primary",
+                                                        P_("Primary GIcon"),
+                                                        P_("GIcon for primary icon"),
+                                                        G_TYPE_ICON,
+                                                        GTK_PARAM_READWRITE));
+
+  /**
+   * GtkIconEntry:gicon-secondary:
+   *
+   * The #GIcon to use for the secondary icon for the entry.
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_GICON_SECONDARY,
+                                   g_param_spec_object ("gicon-secondary",
+                                                        P_("Secondary GIcon"),
+                                                        P_("GIcon for secondary icon"),
+                                                        G_TYPE_ICON,
+                                                        GTK_PARAM_READWRITE));
+
+  /**
+   * GtkIconEntry:storage-type-primary:
+   *
+   * The representation which is used for the primary icon of the entry.
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_STORAGE_TYPE_PRIMARY,
+                                   g_param_spec_enum ("storage-type-primary",
+                                                      P_("Primary storage type"),
+                                                      P_("The representation being used for primary icon"),
+                                                      GTK_TYPE_IMAGE_TYPE,
+                                                      GTK_IMAGE_EMPTY,
+                                                      GTK_PARAM_READABLE));
+
+  /**
+   * GtkIconEntry:storage-type-secondary:
+   *
+   * The representation which is used for the secondary icon of the entry.
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_STORAGE_TYPE_SECONDARY,
+                                   g_param_spec_enum ("storage-type-secondary",
+                                                      P_("Secondary storage type"),
+                                                      P_("The representation being used for secondary icon"),
+                                                      GTK_TYPE_IMAGE_TYPE,
+                                                      GTK_IMAGE_EMPTY,
+                                                      GTK_PARAM_READABLE));
+
+  /**
+   * GtkIconEntry:activatable-primary:
+   *
+   * Wether the primary icon is activatable.
+   *
+   * GTK+ emits the #GtkIconEntry::icon-pressed and
+   * #GtkIconEntry::icon-released signals only on
+   * sensitive, activatable icons.
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_ACTIVATABLE_PRIMARY,
+                                   g_param_spec_boolean ("activatable-primary",
+                                                         P_("Primary icon activatable"),
+                                                         P_("Whether the primary icon is activatable"),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
+
+  /**
+   * GtkIconEntry:activatable-secondary:
+   *
+   * Wether the secondary icon is activatable.
+   *
+   * GTK+ emits the #GtkIconEntry::icon-pressed and
+   * #GtkIconEntry::icon-released signals only on
+   * sensitive, activatable icons.
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_ACTIVATABLE_SECONDARY,
+                                   g_param_spec_boolean ("activatable-secondary",
+                                                         P_("Secondary icon activatable"),
+                                                         P_("Whether the secondary icon is activatable"),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
+
+  /**
+   * GtkIconEntry:sensitive-primary:
+   *
+   * Wether the primary icon is sensitive.
+   *
+   * An insensitive icon will appear grayed out, it will not emit
+   * #GtkIconEntry::icon-pressed signal and not change the cursor.
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_SENSITIVE_PRIMARY,
+                                   g_param_spec_boolean ("sensitive-primary",
+                                                         P_("Primary icon sensitvitiy"),
+                                                         P_("Whether the primary icon is sensitive"),
+                                                         TRUE,
+                                                         GTK_PARAM_READWRITE));
+
+  /**
+   * GtkIconEntry:sensitive-secondary:
+   *
+   * Wether the secondary icon is sensitive.
+   *
+   * An insensitive icon will appear grayed out, it will not emit
+   * #GtkIconEntry::icon-pressed signal and not change the cursor.
+   *
+   * Since: 2.16
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_SENSITIVE_SECONDARY,
+                                   g_param_spec_boolean ("sensitive-secondary",
+                                                         P_("Secondary icon sensitivity"),
+                                                         P_("Whether the secondary icon is sensitive"),
+                                                         TRUE,
+                                                         GTK_PARAM_READWRITE));
+
+  /**
+   * GtkIconEntry:prelight:
+   *
+   * The prelight style property determines whether activatable
+   * icons prelight on mouseover.
+   *
+   * Since: 2.16
+   */
+  gtk_widget_class_install_style_property (widget_class,
+                                           g_param_spec_boolean ("prelight",
+                                                                 P_("Prelight"),
+                                                                 P_("Whether activatable icons should prelight when hovered"),
+                                                                 TRUE,
+                                                                 GTK_PARAM_READABLE));
+
+  g_type_class_add_private (klass, sizeof (GtkIconEntryPrivate));
+}
+
+static void
+gtk_icon_entry_editable_init (GtkEditableClass *iface)
+{
+};
+
+static void
+gtk_icon_entry_init (GtkIconEntry *entry)
+{
+}
+
+static void
+gtk_icon_entry_dispose (GObject *obj)
+{
+  GtkIconEntry *entry;
+
+  entry = GTK_ICON_ENTRY (obj);
+
+  gtk_icon_entry_set_icon_from_pixbuf (entry, GTK_ICON_ENTRY_PRIMARY, NULL);
+  gtk_icon_entry_set_icon_tooltip_markup (entry, GTK_ICON_ENTRY_PRIMARY, NULL);
+  gtk_icon_entry_set_icon_from_pixbuf (entry, GTK_ICON_ENTRY_SECONDARY, NULL);
+  gtk_icon_entry_set_icon_tooltip_markup (entry, GTK_ICON_ENTRY_SECONDARY, NULL);
+
+  G_OBJECT_CLASS (gtk_icon_entry_parent_class)->dispose (obj);
+}
+
+static void
+update_cursors (GtkWidget *widget)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (widget);
+  EntryIconInfo *icon_info;
+  GdkDisplay *display;
+  GdkCursor *cursor;
+  gint i;
+
+  for (i = 0; i < MAX_ICONS; i++)
+    {
+      icon_info = &priv->icons[i];
+      if (icon_info->pixbuf != NULL)
+        gdk_window_show (icon_info->window);
+
+      if (icon_info->insensitive || 
+          (icon_info->nonactivatable && icon_info->target_list == NULL))
+        {
+          display = gtk_widget_get_display (widget);
+          cursor = gdk_cursor_new_for_display (display, GDK_XTERM);
+          gdk_window_set_cursor (icon_info->window, cursor);
+          gdk_cursor_unref (cursor);
+        }
+      else
+        gdk_window_set_cursor (icon_info->window, NULL);
+    }
+}
+
+static void
+gtk_icon_entry_map (GtkWidget *widget)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (widget);
+  gint i;
+
+  if (GTK_WIDGET_REALIZED (widget) && !GTK_WIDGET_MAPPED (widget))
+    {
+      GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->map (widget);
+
+      for (i = 0; i < MAX_ICONS; i++)
+        {
+          if (priv->icons[i].pixbuf != NULL)
+            gdk_window_show (priv->icons[i].window);
+        }
+
+      update_cursors (widget);
+    }
+}
+
+static void
+gtk_icon_entry_unmap (GtkWidget *widget)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (widget);
+  gint i;
+
+  if (GTK_WIDGET_MAPPED (widget))
+    {
+      for (i = 0; i < MAX_ICONS; i++)
+        if (priv->icons[i].pixbuf != NULL)
+          gdk_window_hide (priv->icons[i].window);
+
+      GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->unmap (widget);
+    }
+}
+
+static void
+gtk_icon_entry_set_property (GObject      *object,
+                             guint         prop_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+  GtkIconEntry *entry = GTK_ICON_ENTRY (object);
+
+  switch (prop_id)
+    {
+    case PROP_PIXBUF_PRIMARY:
+      gtk_icon_entry_set_icon_from_pixbuf (entry,
+                                           GTK_ICON_ENTRY_PRIMARY,
+                                           g_value_get_object (value));
+      break;
+
+    case PROP_PIXBUF_SECONDARY:
+      gtk_icon_entry_set_icon_from_pixbuf (entry,
+                                           GTK_ICON_ENTRY_SECONDARY,
+                                           g_value_get_object (value));
+      break;
+
+    case PROP_STOCK_PRIMARY:
+      gtk_icon_entry_set_icon_from_stock (entry,
+                                          GTK_ICON_ENTRY_PRIMARY,
+                                          g_value_get_string (value));
+      break;
+
+    case PROP_STOCK_SECONDARY:
+      gtk_icon_entry_set_icon_from_stock (entry,
+                                          GTK_ICON_ENTRY_SECONDARY,
+                                          g_value_get_string (value));
+      break;
+
+    case PROP_ICON_NAME_PRIMARY:
+      gtk_icon_entry_set_icon_from_icon_name (entry,
+                                              GTK_ICON_ENTRY_PRIMARY,
+                                              g_value_get_string (value));
+      break;
+
+    case PROP_ICON_NAME_SECONDARY:
+      gtk_icon_entry_set_icon_from_icon_name (entry,
+                                              GTK_ICON_ENTRY_SECONDARY,
+                                              g_value_get_string (value));
+      break;
+
+    case PROP_GICON_PRIMARY:
+      gtk_icon_entry_set_icon_from_gicon (entry,
+                                          GTK_ICON_ENTRY_PRIMARY,
+                                          g_value_get_object (value));
+      break;
+
+    case PROP_GICON_SECONDARY:
+      gtk_icon_entry_set_icon_from_gicon (entry,
+                                          GTK_ICON_ENTRY_SECONDARY,
+                                          g_value_get_object (value));
+      break;
+
+    case PROP_ACTIVATABLE_PRIMARY:
+      gtk_icon_entry_set_icon_activatable (entry,
+                                           GTK_ICON_ENTRY_PRIMARY,
+                                           g_value_get_boolean (value));
+      break;
+
+    case PROP_ACTIVATABLE_SECONDARY:
+      gtk_icon_entry_set_icon_activatable (entry,
+                                           GTK_ICON_ENTRY_SECONDARY,
+                                           g_value_get_boolean (value));
+      break;
+
+    case PROP_SENSITIVE_PRIMARY:
+      gtk_icon_entry_set_icon_sensitive (entry,
+                                         GTK_ICON_ENTRY_PRIMARY,
+                                         g_value_get_boolean (value));
+      break;
+
+    case PROP_SENSITIVE_SECONDARY:
+      gtk_icon_entry_set_icon_sensitive (entry,
+                                         GTK_ICON_ENTRY_SECONDARY,
+                                         g_value_get_boolean (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_icon_entry_get_property (GObject      *object,
+                             guint         prop_id,
+                             GValue       *value,
+                             GParamSpec   *pspec)
+{
+  GtkIconEntry *entry = GTK_ICON_ENTRY (object);
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+
+  switch (prop_id)
+    {
+    case PROP_PIXBUF_PRIMARY:
+      g_value_set_object (value,
+                          gtk_icon_entry_get_pixbuf (entry,
+                                                     GTK_ICON_ENTRY_PRIMARY));
+      break;
+
+    case PROP_PIXBUF_SECONDARY:
+      g_value_set_object (value,
+                          gtk_icon_entry_get_pixbuf (entry,
+                                                     GTK_ICON_ENTRY_SECONDARY));
+      break;
+
+    case PROP_STOCK_PRIMARY:
+      g_value_set_string (value,
+                          gtk_icon_entry_get_stock (entry,
+                                                    GTK_ICON_ENTRY_PRIMARY));
+      break;
+
+    case PROP_STOCK_SECONDARY:
+      g_value_set_string (value,
+                          gtk_icon_entry_get_stock (entry,
+                                                    GTK_ICON_ENTRY_SECONDARY));
+      break;
+
+    case PROP_ICON_NAME_PRIMARY:
+      g_value_set_string (value,
+                          gtk_icon_entry_get_icon_name (entry,
+                                                        GTK_ICON_ENTRY_PRIMARY));
+      break;
+
+    case PROP_ICON_NAME_SECONDARY:
+      g_value_set_string (value,
+                          gtk_icon_entry_get_icon_name (entry,
+                                                        GTK_ICON_ENTRY_SECONDARY));
+      break;
+
+    case PROP_GICON_PRIMARY:
+      g_value_set_object (value,
+                          gtk_icon_entry_get_gicon (entry,
+                                                    GTK_ICON_ENTRY_PRIMARY));
+      break;
+
+    case PROP_GICON_SECONDARY:
+      g_value_set_object (value,
+                          gtk_icon_entry_get_gicon (entry,
+                                                    GTK_ICON_ENTRY_SECONDARY));
+
+    case PROP_STORAGE_TYPE_PRIMARY:
+      g_value_set_enum (value,
+                        priv->icons[GTK_ICON_ENTRY_PRIMARY].storage_type);
+      break;
+
+    case PROP_STORAGE_TYPE_SECONDARY:
+      g_value_set_enum (value,
+                        priv->icons[GTK_ICON_ENTRY_SECONDARY].storage_type);
+      break;
+
+    case PROP_ACTIVATABLE_PRIMARY:
+      g_value_set_boolean (value,
+                           gtk_icon_entry_get_icon_activatable (entry, GTK_ICON_ENTRY_PRIMARY));
+      break;
+
+    case PROP_ACTIVATABLE_SECONDARY:
+      g_value_set_boolean (value,
+                           gtk_icon_entry_get_icon_activatable (entry, GTK_ICON_ENTRY_SECONDARY));
+      break;
+
+    case PROP_SENSITIVE_PRIMARY:
+      g_value_set_boolean (value,
+                           gtk_icon_entry_get_icon_sensitive (entry, GTK_ICON_ENTRY_PRIMARY));
+      break;
+
+    case PROP_SENSITIVE_SECONDARY:
+      g_value_set_boolean (value,
+                           gtk_icon_entry_get_icon_sensitive (entry, GTK_ICON_ENTRY_SECONDARY));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static gint
+get_icon_width (GtkIconEntry         *entry,
+                GtkIconEntryPosition  icon_pos)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  EntryIconInfo *icon_info = &priv->icons[icon_pos];
+  GdkScreen *screen;
+  GtkSettings *settings;
+  gint menu_icon_width;
+
+  if (icon_info->pixbuf == NULL)
+    return 0;
+
+  screen = gtk_widget_get_screen (GTK_WIDGET (entry));
+  settings = gtk_settings_get_for_screen (screen);
+
+  gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU,
+                                     &menu_icon_width, NULL);
+
+  return MAX (gdk_pixbuf_get_width (icon_info->pixbuf), menu_icon_width);
+}
+
+static void
+get_borders (GtkIconEntry *entry,
+             gint         *xborder,
+             gint         *yborder)
+{
+  GtkWidget *widget = GTK_WIDGET (entry);
+  gint focus_width;
+  gboolean interior_focus;
+
+  gtk_widget_style_get (widget,
+                        "interior-focus", &interior_focus,
+                        "focus-line-width", &focus_width,
+                        NULL);
+
+  if (gtk_entry_get_has_frame (GTK_ENTRY (entry)))
+    {
+      *xborder = widget->style->xthickness;
+      *yborder = widget->style->ythickness;
+    }
+  else
+    {
+      *xborder = 0;
+      *yborder = 0;
+    }
+
+  if (!interior_focus)
+    {
+      *xborder += focus_width;
+      *yborder += focus_width;
+    }
+}
+
+static void
+get_text_area_size (GtkIconEntry  *entry,
+                    GtkAllocation *alloc)
+{
+  GTK_ENTRY_GET_CLASS (entry)->get_text_area_size (entry, 
+                                                   &alloc->x, 
+                                                   &alloc->y, 
+                                                   &alloc->width, 
+                                                   &alloc->height);
+}
+
+static void
+icon_margin_changed (GtkIconEntry *entry)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  GtkBorder border;
+
+  _gtk_entry_effective_inner_border (GTK_ENTRY (entry), &border);
+
+  priv->icon_margin = border.left;
+}
+
+static void
+get_icon_allocation (GtkIconEntry         *entry,
+                     gboolean              left,
+                     GtkAllocation        *widget_alloc,
+                     GtkAllocation        *text_area_alloc,
+                     GtkAllocation        *allocation,
+                     GtkIconEntryPosition *icon_pos)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  gboolean rtl;
+
+  rtl = (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL);
+
+  if (left)
+    *icon_pos = (rtl ? GTK_ICON_ENTRY_SECONDARY : GTK_ICON_ENTRY_PRIMARY);
+  else
+    *icon_pos = (rtl ? GTK_ICON_ENTRY_PRIMARY : GTK_ICON_ENTRY_SECONDARY);
+
+  allocation->y = text_area_alloc->y;
+  allocation->width = get_icon_width (entry, *icon_pos);
+  allocation->height = text_area_alloc->height;
+
+  if (allocation->width > 0)
+    allocation->width += 2 * priv->icon_margin;
+
+  if (left)
+    allocation->x = text_area_alloc->x;
+  else
+    allocation->x = text_area_alloc->x + text_area_alloc->width - allocation->width;
+}
+
+static void
+gtk_icon_entry_realize (GtkWidget *widget)
+{
+  GtkIconEntry *entry = GTK_ICON_ENTRY (widget);
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  EntryIconInfo *icon_info;
+  GdkWindowAttr attributes;
+  gint attributes_mask;
+  gint i;
+
+  GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->realize (widget);
+
+  attributes.x = 0;
+  attributes.y = 0;
+  attributes.width = 1;
+  attributes.height = 1;
+  attributes.window_type = GDK_WINDOW_CHILD;
+  attributes.wclass = GDK_INPUT_OUTPUT;
+  attributes.visual = gtk_widget_get_visual (widget);
+  attributes.colormap = gtk_widget_get_colormap (widget);
+  attributes.event_mask = gtk_widget_get_events (widget);
+  attributes.event_mask |=
+    (GDK_EXPOSURE_MASK |
+     GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+                            GDK_BUTTON1_MOTION_MASK |
+                            GDK_BUTTON3_MOTION_MASK |
+                            GDK_POINTER_MOTION_HINT_MASK |
+                            GDK_POINTER_MOTION_MASK |
+     GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
+
+  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+  for (i = 0; i < MAX_ICONS; i++)
+    {
+      icon_info = &priv->icons[i];
+      icon_info->window = gdk_window_new (widget->window, &attributes,
+                                          attributes_mask);
+      gdk_window_set_user_data (icon_info->window, widget);
+      gdk_window_set_background (icon_info->window,
+                                 &widget->style->base[GTK_WIDGET_STATE (widget)]);
+    }
+
+  gtk_widget_queue_resize (widget);
+}
+
+static void
+gtk_icon_entry_unrealize (GtkWidget *widget)
+{
+  GtkIconEntry *entry = GTK_ICON_ENTRY (widget);
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  EntryIconInfo *icon_info;
+  gint i;
+
+  GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->unrealize (widget);
+
+  for (i = 0; i < MAX_ICONS; i++)
+    {
+      icon_info = &priv->icons[i];
+      gdk_window_destroy (icon_info->window);
+      icon_info->window = NULL;
+    }
+}
+
+static void
+gtk_icon_entry_size_request (GtkWidget      *widget,
+                             GtkRequisition *requisition)
+{
+  GtkIconEntry *entry = GTK_ICON_ENTRY (widget);
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  gint icon_widths = 0;
+  gint icon_width;
+  gint i;
+
+  for (i = 0; i < MAX_ICONS; i++)
+    {
+      icon_width = get_icon_width (entry, i);
+
+      if (icon_width > 0)
+        icon_widths += icon_width + 2 * priv->icon_margin;
+    }
+
+  GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->size_request (widget, requisition);
+
+  if (icon_widths > requisition->width)
+    requisition->width += icon_widths;
+}
+
+static void
+place_windows (GtkIconEntry  *entry,
+               GtkAllocation *widget_alloc)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  GtkIconEntryPosition left_icon_pos;
+  GtkIconEntryPosition right_icon_pos;
+  GtkAllocation left_icon_alloc;
+  GtkAllocation right_icon_alloc;
+  GtkAllocation text_area_alloc;
+
+  get_text_area_size (entry, &text_area_alloc);
+  get_icon_allocation (entry, TRUE, widget_alloc, &text_area_alloc,
+                       &left_icon_alloc, &left_icon_pos);
+  get_icon_allocation (entry, FALSE, widget_alloc, &text_area_alloc,
+                       &right_icon_alloc, &right_icon_pos);
+
+  if (left_icon_alloc.width > 0)
+    {
+      text_area_alloc.x = left_icon_alloc.x + left_icon_alloc.width;
+      text_area_alloc.width -= left_icon_alloc.width;
+    }
+
+  if (right_icon_alloc.width > 0)
+    text_area_alloc.width -= right_icon_alloc.width;
+
+  gdk_window_move_resize (priv->icons[left_icon_pos].window,
+                          left_icon_alloc.x, left_icon_alloc.y,
+                          left_icon_alloc.width, left_icon_alloc.height);
+
+  gdk_window_move_resize (priv->icons[right_icon_pos].window,
+                          right_icon_alloc.x, right_icon_alloc.y,
+                          right_icon_alloc.width, right_icon_alloc.height);
+
+  gdk_window_move_resize (GTK_ENTRY (entry)->text_area,
+                          text_area_alloc.x, text_area_alloc.y,
+                          text_area_alloc.width, text_area_alloc.height);
+
+  _gtk_entry_adjust_scroll (GTK_ENTRY (entry));
+}
+
+static void
+gtk_icon_entry_size_allocate (GtkWidget     *widget,
+                              GtkAllocation *allocation)
+{
+  widget->allocation = *allocation;
+
+  GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->size_allocate (widget, allocation);
+
+  if (GTK_WIDGET_REALIZED (widget))
+    place_windows (GTK_ICON_ENTRY (widget), allocation);
+}
+
+static GdkPixbuf *
+get_pixbuf_from_icon (GtkIconEntry         *entry,
+                      GtkIconEntryPosition  icon_pos)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  EntryIconInfo *icon_info = &priv->icons[icon_pos];
+
+  g_object_ref (icon_info->pixbuf);
+
+  return icon_info->pixbuf;
+}
+
+/* Kudos to the gnome-panel guys. */
+static void
+colorshift_pixbuf (GdkPixbuf *dest,
+                   GdkPixbuf *src,
+                   gint       shift)
+{
+  gint i, j;
+  gint width, height, has_alpha, src_rowstride, dest_rowstride;
+  guchar *target_pixels;
+  guchar *original_pixels;
+  guchar *pix_src;
+  guchar *pix_dest;
+  int val;
+  guchar r, g, b;
+
+  has_alpha       = gdk_pixbuf_get_has_alpha (src);
+  width           = gdk_pixbuf_get_width (src);
+  height          = gdk_pixbuf_get_height (src);
+  src_rowstride   = gdk_pixbuf_get_rowstride (src);
+  dest_rowstride  = gdk_pixbuf_get_rowstride (dest);
+  original_pixels = gdk_pixbuf_get_pixels (src);
+  target_pixels   = gdk_pixbuf_get_pixels (dest);
+
+  for (i = 0; i < height; i++)
+    {
+      pix_dest = target_pixels   + i * dest_rowstride;
+      pix_src  = original_pixels + i * src_rowstride;
+
+      for (j = 0; j < width; j++)
+        {
+          r = *(pix_src++);
+          g = *(pix_src++);
+          b = *(pix_src++);
+
+          val = r + shift;
+          *(pix_dest++) = CLAMP (val, 0, 255);
+
+          val = g + shift;
+          *(pix_dest++) = CLAMP (val, 0, 255);
+
+          val = b + shift;
+          *(pix_dest++) = CLAMP (val, 0, 255);
+
+          if (has_alpha)
+            *(pix_dest++) = *(pix_src++);
+        }
+    }
+}
+
+static gboolean
+should_prelight (GtkIconEntry         *entry,
+                 GtkIconEntryPosition  icon_pos)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  EntryIconInfo *icon_info = &priv->icons[icon_pos];
+  gboolean prelight;
+
+  if (icon_info->nonactivatable && icon_info->target_list == NULL)
+    return FALSE;
+
+  gtk_widget_style_get (GTK_WIDGET (entry),
+                        "prelight", &prelight,
+                        NULL);
+
+  return prelight;
+}
+
+static void
+draw_icon (GtkWidget            *widget,
+           GtkIconEntryPosition  icon_pos)
+{
+  GtkIconEntry *entry = GTK_ICON_ENTRY (widget);
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  EntryIconInfo *icon_info = &priv->icons[icon_pos];
+  GdkPixbuf *pixbuf;
+  gint x, y, width, height;
+
+  gtk_icon_entry_ensure_pixbuf (entry, icon_pos);
+
+  if (icon_info->pixbuf == NULL)
+    return;
+
+  gdk_drawable_get_size (icon_info->window, &width, &height);
+
+  /* size_allocate hasn't been called yet. These are the default values.
+   */
+  if (width == 1 || height == 1)
+    return;
+
+  pixbuf = icon_info->pixbuf;
+  g_object_ref (pixbuf);
+
+  if (gdk_pixbuf_get_height (pixbuf) > height)
+    {
+      GdkPixbuf *temp_pixbuf;
+      gint scale;
+
+      scale = height - 2 * priv->icon_margin;
+      temp_pixbuf = gdk_pixbuf_scale_simple (pixbuf, scale, scale,
+                                             GDK_INTERP_BILINEAR);
+      g_object_unref (pixbuf);
+      pixbuf = temp_pixbuf;
+    }
+
+  x = (width  - gdk_pixbuf_get_width (pixbuf)) / 2;
+  y = (height - gdk_pixbuf_get_height (pixbuf)) / 2;
+
+  if (icon_info->insensitive)
+    {
+      GdkPixbuf *temp_pixbuf;
+
+      temp_pixbuf = gdk_pixbuf_copy (pixbuf);
+      gdk_pixbuf_saturate_and_pixelate (pixbuf,
+                                        temp_pixbuf,
+                                        0.8f,
+                                        TRUE);
+      g_object_unref (pixbuf);
+      pixbuf = temp_pixbuf;
+    }
+  else if (icon_info->prelight)
+    {
+      GdkPixbuf *temp_pixbuf;
+
+      temp_pixbuf = gdk_pixbuf_copy (pixbuf);
+      colorshift_pixbuf (temp_pixbuf, pixbuf, 30);
+      g_object_unref (pixbuf);
+      pixbuf = temp_pixbuf;
+    }
+
+  gdk_draw_pixbuf (icon_info->window, widget->style->black_gc, pixbuf,
+                   0, 0, x, y, -1, -1,
+                   GDK_RGB_DITHER_NORMAL, 0, 0);
+
+  g_object_unref (pixbuf);
+}
+
+static gint
+gtk_icon_entry_expose (GtkWidget      *widget,
+                       GdkEventExpose *event)
+{
+  GtkIconEntry *entry = GTK_ICON_ENTRY (widget);
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+
+  if (GTK_WIDGET_DRAWABLE (widget))
+    {
+      gboolean found = FALSE;
+      gint i;
+
+      for (i = 0; i < MAX_ICONS && !found; i++)
+        {
+          EntryIconInfo *icon_info = &priv->icons[i];
+
+          if (event->window == icon_info->window)
+            {
+              gint width;
+              GtkAllocation text_area_alloc;
+
+              get_text_area_size (entry, &text_area_alloc);
+              gdk_drawable_get_size (icon_info->window, &width, NULL);
+
+              gtk_paint_flat_box (widget->style, icon_info->window,
+                                  GTK_WIDGET_STATE (widget), GTK_SHADOW_NONE,
+                                  NULL, widget, "entry_bg",
+                                  0, 0, width, text_area_alloc.height);
+
+              draw_icon (widget, i);
+
+              found = TRUE;
+            }
+        }
+
+      if (!found)
+        GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->expose_event (widget, event);
+    }
+
+  return FALSE;
+}
+
+static gint
+gtk_icon_entry_enter_notify (GtkWidget        *widget,
+                             GdkEventCrossing *event)
+{
+  GtkIconEntry *entry = GTK_ICON_ENTRY (widget);
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  gint i;
+
+  g_print ("icon entry enter notify\n");
+
+  for (i = 0; i < MAX_ICONS; i++)
+    {
+      EntryIconInfo *icon_info = &priv->icons[i];
+
+      if (event->window == icon_info->window)
+        {
+          if (should_prelight (entry, i))
+            {
+              icon_info->prelight = TRUE;
+              gtk_widget_queue_draw (widget);
+              break;
+            }
+        }
+    }
+
+  return FALSE;
+}
+
+static gint
+gtk_icon_entry_leave_notify (GtkWidget        *widget,
+                             GdkEventCrossing *event)
+{
+  GtkIconEntry *entry = GTK_ICON_ENTRY (widget);
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  gint i;
+
+  g_print ("icon entry leave notify\n");
+
+  for (i = 0; i < MAX_ICONS; i++)
+    {
+      EntryIconInfo *icon_info = &priv->icons[i];
+
+      if (event->window == icon_info->window)
+        {
+          if (should_prelight (entry, i))
+            {
+              icon_info->prelight = FALSE;
+              gtk_widget_queue_draw (widget);
+              break;
+            }
+        }
+    }
+
+  return FALSE;
+}
+
+static gint
+gtk_icon_entry_button_press (GtkWidget      *widget,
+                             GdkEventButton *event)
+{
+  GtkIconEntry *entry = GTK_ICON_ENTRY (widget);
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  gint i;
+
+  g_print ("icon entry button press\n");
+
+  for (i = 0; i < MAX_ICONS; i++)
+    {
+      EntryIconInfo *icon_info = &priv->icons[i];
+
+      if (icon_info->insensitive)
+        continue;
+
+      if (event->window == icon_info->window)
+        {
+          if (should_prelight (entry, i))
+            {
+              icon_info->prelight = FALSE;
+              gtk_widget_queue_draw (widget);
+            }
+
+          g_signal_emit (entry, signals[ICON_PRESSED], 0, i, event);
+
+          return TRUE;
+        }
+    }
+
+  if (GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->button_press_event)
+    return GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->button_press_event (widget, event);
+
+  return FALSE;
+}
+
+static gint
+gtk_icon_entry_button_release (GtkWidget      *widget,
+                               GdkEventButton *event)
+{
+  GtkIconEntry *entry = GTK_ICON_ENTRY (widget);
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  gint i;
+
+  g_print ("icon entry button release\n");
+
+  for (i = 0; i < MAX_ICONS; i++)
+    {
+      EntryIconInfo *icon_info = &priv->icons[i];
+      GdkWindow *icon_window = icon_info->window;
+
+      if (icon_info->insensitive)
+        continue;
+
+      if (event->window == icon_window)
+        {
+          gint width, height;
+
+          gdk_drawable_get_size (icon_window, &width, &height);
+
+          if (should_prelight (entry, i) &&
+              event->x >= 0 && event->y >= 0 &&
+              event->x <= width && event->y <= height)
+            {
+              icon_info->prelight = TRUE;
+              gtk_widget_queue_draw (widget);
+            }
+
+          g_signal_emit (entry, signals[ICON_RELEASED], 0, i, event);
+
+          return TRUE;
+        }
+    }
+
+  if (GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->button_release_event)
+    return GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->button_release_event (widget, event);
+
+  return FALSE;
+}
+
+static void
+gtk_icon_entry_style_set (GtkWidget *widget,
+                          GtkStyle  *prev_style)
+{
+  GtkIconEntry *icon_entry = GTK_ICON_ENTRY (widget);
+
+  if (GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->style_set)
+    GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->style_set (widget, prev_style);
+
+  icon_theme_changed (icon_entry);
+  icon_margin_changed (icon_entry);
+}
+
+static void
+icon_theme_changed (GtkIconEntry *entry)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  gint i;
+
+  for (i = 0; i < MAX_ICONS; i++)
+    {
+      EntryIconInfo *icon_info = &priv->icons[i];
+
+      if (icon_info->storage_type == GTK_IMAGE_ICON_NAME)
+        gtk_icon_entry_set_icon_from_icon_name (entry, i, icon_info->icon_name);
+      else if (icon_info->storage_type == GTK_IMAGE_STOCK)
+        gtk_icon_entry_set_icon_from_stock (entry, i, icon_info->stock_id);
+      else if (icon_info->storage_type == GTK_IMAGE_GICON)
+        gtk_icon_entry_set_icon_from_gicon (entry, i, icon_info->gicon);
+    }
+
+  gtk_widget_queue_draw (GTK_WIDGET (entry));
+}
+
+/**
+ * gtk_icon_entry_new:
+ *
+ * Creates a new GtkIconEntry widget.
+ *
+ * Returns a new #GtkIconEntry.
+ */
+GtkWidget *
+gtk_icon_entry_new (void)
+{
+  return GTK_WIDGET (g_object_new (GTK_TYPE_ICON_ENTRY, NULL));
+}
+
+static void
+gtk_icon_entry_clear (GtkIconEntry         *entry,
+                      GtkIconEntryPosition  icon_pos)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  EntryIconInfo *icon_info = &priv->icons[icon_pos];
+
+  if (icon_info->storage_type == GTK_IMAGE_EMPTY)
+    return;
+
+  g_object_freeze_notify (G_OBJECT (entry));
+
+  /* Explicitly check, as the pointer may become invalidated
+   * during destruction.
+   */
+  if (GDK_IS_WINDOW (icon_info->window))
+    gdk_window_hide (icon_info->window);
+
+  if (icon_info->pixbuf)
+    {
+      g_object_unref (icon_info->pixbuf);
+      icon_info->pixbuf = NULL;
+    }
+
+  switch (icon_info->storage_type)
+    {
+    case GTK_IMAGE_PIXBUF:
+      g_object_notify (G_OBJECT (entry),
+                       icon_pos == GTK_ICON_ENTRY_PRIMARY ? "pixbuf-primary" : "pixbuf-secondary");
+      break;
+
+    case GTK_IMAGE_STOCK:
+      g_free (icon_info->stock_id);
+      icon_info->stock_id = NULL;
+      g_object_notify (G_OBJECT (entry),
+                       icon_pos == GTK_ICON_ENTRY_PRIMARY ? "stock-primary" : "stock-secondary");
+      break;
+
+    case GTK_IMAGE_ICON_NAME:
+      g_free (icon_info->icon_name);
+      icon_info->icon_name = NULL;
+      g_object_notify (G_OBJECT (entry),
+                       icon_pos == GTK_ICON_ENTRY_PRIMARY ? "icon-name-primary" : "icon-name-secondary");
+      break;
+
+    case GTK_IMAGE_GICON:
+      if (icon_info->gicon)
+        {
+          g_object_unref (icon_info->gicon);
+          icon_info->gicon = NULL;
+        }
+      g_object_notify (G_OBJECT (entry),
+                       icon_pos == GTK_ICON_ENTRY_PRIMARY ? "gicon-primary" : "gicon-secondary");
+      break;
+
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  icon_info->storage_type = GTK_IMAGE_EMPTY;
+  g_object_notify (G_OBJECT (entry),
+                   icon_pos == GTK_ICON_ENTRY_PRIMARY ? "storage-type-primary" : "storage-type-secondary");
+
+  g_object_thaw_notify (G_OBJECT (entry));
+}
+
+static void
+gtk_icon_entry_ensure_pixbuf (GtkIconEntry         *entry,
+                              GtkIconEntryPosition  icon_pos)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  EntryIconInfo *icon_info = &priv->icons[icon_pos];
+  GdkScreen *screen;
+  GtkIconTheme *icon_theme;
+  GtkSettings *settings;
+  gint width, height;
+  GtkIconInfo *info;
+
+  if (icon_info->pixbuf)
+    return;
+
+  switch (icon_info->storage_type)
+    {
+    case GTK_IMAGE_EMPTY:
+    case GTK_IMAGE_PIXBUF:
+      break;
+    case GTK_IMAGE_STOCK:
+      icon_info->pixbuf = gtk_widget_render_icon (GTK_WIDGET (entry),
+                                                  icon_info->stock_id,
+                                                  GTK_ICON_SIZE_MENU,
+                                                  NULL);
+      break;
+    case GTK_IMAGE_ICON_NAME:
+      screen = gtk_widget_get_screen (GTK_WIDGET (entry));
+      if (screen)
+        {
+          icon_theme = gtk_icon_theme_get_for_screen (screen);
+          settings = gtk_settings_get_for_screen (screen);
+
+          gtk_icon_size_lookup_for_settings (settings,
+                                             GTK_ICON_SIZE_MENU,
+                                             &width, &height);
+
+          icon_info->pixbuf = gtk_icon_theme_load_icon (icon_theme,
+                                                        icon_info->icon_name,
+                                                        MIN (width, height),
+                                                        0, NULL);
+
+          if (icon_info->pixbuf == NULL)
+            icon_info->pixbuf = gtk_widget_render_icon (GTK_WIDGET (entry),
+                                                        GTK_STOCK_MISSING_IMAGE,
+                                                        GTK_ICON_SIZE_MENU,
+                                                        NULL);
+        }
+      break;
+    case GTK_IMAGE_GICON:
+      screen = gtk_widget_get_screen (GTK_WIDGET (entry));
+      if (screen)
+        {
+          icon_theme = gtk_icon_theme_get_for_screen (screen);
+          settings = gtk_settings_get_for_screen (screen);
+
+          gtk_icon_size_lookup_for_settings (settings,
+                                             GTK_ICON_SIZE_MENU,
+                                             &width, &height);
+
+          info = gtk_icon_theme_lookup_by_gicon (icon_theme,
+                                                 icon_info->gicon,
+                                                 MIN (width, height), 0);
+
+          icon_info->pixbuf = gtk_icon_info_load_icon (info, NULL);
+          if (icon_info->pixbuf == NULL)
+            icon_info->pixbuf = gtk_widget_render_icon (GTK_WIDGET (entry),
+                                                        GTK_STOCK_MISSING_IMAGE,
+                                                        GTK_ICON_SIZE_MENU,
+                                                        NULL);
+        }
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  if (GDK_IS_WINDOW (icon_info->window))
+    gdk_window_show (icon_info->window);
+
+  gtk_widget_queue_resize (GTK_WIDGET (entry));
+}
+
+/**
+ * gtk_icon_entry_set_icon_from_pixbuf:
+ * @entry: a #GtkIconEntry
+ * @position: Icon position
+ * @pixbuf: A #GdkPixbuf, or %NULL
+ *
+ * Sets the icon shown in the specified position using a pixbuf.
+ *
+ * If @pixbuf is %NULL, no icon will be shown in the specified position.
+ */
+void
+gtk_icon_entry_set_icon_from_pixbuf (GtkIconEntry         *entry,
+                                     GtkIconEntryPosition  icon_pos,
+                                     GdkPixbuf            *pixbuf)
+{
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+
+  g_return_if_fail (GTK_IS_ICON_ENTRY (entry));
+  g_return_if_fail (IS_VALID_ICON_ENTRY_POSITION (icon_pos));
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  icon_info = &priv->icons[icon_pos];
+
+  g_object_freeze_notify (G_OBJECT (entry));
+
+  if (pixbuf)
+    g_object_ref (pixbuf);
+
+  gtk_icon_entry_clear (entry, icon_pos);
+
+  if (pixbuf)
+    {
+      icon_info->storage_type = GTK_IMAGE_PIXBUF;
+      icon_info->pixbuf = pixbuf;
+
+      if (icon_pos == GTK_ICON_ENTRY_PRIMARY)
+        {
+          g_object_notify (G_OBJECT (entry), "pixbuf-primary");
+          g_object_notify (G_OBJECT (entry), "storage-type-primary");
+        }
+      else
+        {
+          g_object_notify (G_OBJECT (entry), "pixbuf-secondary");
+          g_object_notify (G_OBJECT (entry), "storage-type-secondary");
+        }
+    }
+
+  gtk_icon_entry_ensure_pixbuf (entry, icon_pos);
+  
+  g_object_thaw_notify (G_OBJECT (entry));
+}
+
+/**
+ * gtk_icon_entry_set_icon_from_stock:
+ * @entry: A #GtkIconEntry
+ * @position: Icon position
+ * @stock_id: The name of the stock item, or %NULL
+ *
+ * Sets the icon shown in the entry at the specified position from
+ * a stock image.
+ *
+ * If @stock_id is %NULL, no icon will be shown in the specified position.
+ */
+void
+gtk_icon_entry_set_icon_from_stock (GtkIconEntry         *entry,
+                                    GtkIconEntryPosition  icon_pos,
+                                    const gchar          *stock_id)
+{
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+  gchar *new_id;
+
+  g_return_if_fail (GTK_IS_ICON_ENTRY (entry));
+  g_return_if_fail (IS_VALID_ICON_ENTRY_POSITION (icon_pos));
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  icon_info = &priv->icons[icon_pos];
+
+  g_object_freeze_notify (G_OBJECT (entry));
+
+  gtk_widget_ensure_style (GTK_WIDGET (entry));
+
+  /* need to dup before clearing */
+  new_id = g_strdup (stock_id);
+
+  gtk_icon_entry_clear (entry, icon_pos);
+
+  if (new_id != NULL)
+    {
+      icon_info->storage_type = GTK_IMAGE_STOCK;
+      icon_info->stock_id = new_id;
+
+      if (icon_pos == GTK_ICON_ENTRY_PRIMARY)
+        {
+          g_object_notify (G_OBJECT (entry), "stock-primary");
+          g_object_notify (G_OBJECT (entry), "storage-type-primary");
+        }
+      else
+        {
+          g_object_notify (G_OBJECT (entry), "stock-secondary");
+          g_object_notify (G_OBJECT (entry), "storage-type-secondary");
+        }
+    }
+
+  gtk_icon_entry_ensure_pixbuf (entry, icon_pos);
+
+  g_object_thaw_notify (G_OBJECT (entry));
+}
+
+/**
+ * gtk_icon_entry_set_icon_from_icon_name:
+ * @entry: A #GtkIconEntry
+ * @icon_pos: The position at which to set the icon
+ * @icon_name: An icon name, or %NULL
+ *
+ * Sets the icon shown in the entry at the specified position
+ * from the current icon theme.
+ *
+ * If the icon name isn't known, a "broken image" icon will be displayed
+ * instead.
+ *
+ * If @icon_name is %NULL, no icon will be shown in the specified position.
+ */
+void
+gtk_icon_entry_set_icon_from_icon_name (GtkIconEntry         *entry,
+                                        GtkIconEntryPosition  icon_pos,
+                                        const gchar          *icon_name)
+{
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+  gchar *new_name;
+
+  g_return_if_fail (GTK_IS_ICON_ENTRY (entry));
+  g_return_if_fail (IS_VALID_ICON_ENTRY_POSITION (icon_pos));
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  icon_info = &priv->icons[icon_pos];
+
+  g_object_freeze_notify (G_OBJECT (entry));
+
+  gtk_widget_ensure_style (GTK_WIDGET (entry));
+
+  /* need to dup before clearing */
+  new_name = g_strdup (icon_name);
+
+  gtk_icon_entry_clear (entry, icon_pos);
+
+  if (new_name != NULL)
+    {
+      icon_info->storage_type = GTK_IMAGE_ICON_NAME;
+      icon_info->icon_name = new_name;
+
+      if (icon_pos == GTK_ICON_ENTRY_PRIMARY)
+        {
+          g_object_notify (G_OBJECT (entry), "icon-name-primary");
+          g_object_notify (G_OBJECT (entry), "storage-type-primary");
+        }
+      else
+        {
+          g_object_notify (G_OBJECT (entry), "icon-name-secondary");
+          g_object_notify (G_OBJECT (entry), "storage-type-secondary");
+        }
+    }
+
+  gtk_icon_entry_ensure_pixbuf (entry, icon_pos);
+
+  g_object_thaw_notify (G_OBJECT (entry));
+}
+
+/**
+ * gtk_icon_entry_set_icon_from_gicon:
+ * @entry: A #GtkIconEntry
+ * @icon_pos: The position at which to set the icon
+ * @icon: The icon to set, or %NULL
+ *
+ * Sets the icon shown in the entry at the specified position
+ * from the current icon theme.
+ * If the icon isn't known, a "broken image" icon will be displayed
+ * instead.
+ *
+ * If @icon is %NULL, no icon will be shown in the specified position.
+ */
+void
+gtk_icon_entry_set_icon_from_gicon (GtkIconEntry         *entry,
+                                    GtkIconEntryPosition  icon_pos,
+                                    GIcon                *icon)
+{
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+
+  g_return_if_fail (GTK_IS_ICON_ENTRY (entry));
+  g_return_if_fail (IS_VALID_ICON_ENTRY_POSITION (icon_pos));
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  icon_info = &priv->icons[icon_pos];
+
+  g_object_freeze_notify (G_OBJECT (entry));
+
+  /* need to ref before clearing */
+  if (icon)
+    g_object_ref (icon);
+
+  gtk_icon_entry_clear (entry, icon_pos);
+
+  if (icon)
+    {
+      icon_info->storage_type = GTK_IMAGE_GICON;
+      icon_info->gicon = icon;
+
+      if (icon_pos == GTK_ICON_ENTRY_PRIMARY)
+        {
+          g_object_notify (G_OBJECT (entry), "gicon-primary");
+          g_object_notify (G_OBJECT (entry), "storage-type-primary");
+        }
+      else
+        {
+          g_object_notify (G_OBJECT (entry), "gicon-secondary");
+          g_object_notify (G_OBJECT (entry), "storage-type-secondary");
+        }
+    }
+
+  gtk_icon_entry_ensure_pixbuf (entry, icon_pos);
+
+  g_object_thaw_notify (G_OBJECT (entry));
+}
+
+/**
+ * gtk_icon_entry_set_icon_activatable:
+ * @entry: A #GtkIconEntry
+ * @position: Icon position
+ * @activatable: %TRUE if the icon should be activatable
+ *
+ * Sets whether the icon is activatable.
+ */
+void
+gtk_icon_entry_set_icon_activatable (GtkIconEntry         *entry,
+                                     GtkIconEntryPosition  icon_pos,
+                                     gboolean              activatable)
+{
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+
+  g_return_if_fail (GTK_IS_ICON_ENTRY (entry));
+  g_return_if_fail (IS_VALID_ICON_ENTRY_POSITION (icon_pos));
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  icon_info = &priv->icons[icon_pos];
+
+  activatable = activatable != FALSE;
+
+  if (icon_info->nonactivatable != !activatable)
+    {
+      icon_info->nonactivatable = !activatable;
+
+      if (GTK_WIDGET_REALIZED (GTK_WIDGET (entry)))
+        update_cursors (GTK_WIDGET (entry));
+
+      g_object_notify (G_OBJECT (entry),
+                       icon_pos == GTK_ICON_ENTRY_PRIMARY ? "activatable-primary" : "activatable-secondary");
+    }
+}
+
+/**
+ * gtk_icon_entry_get_icon_activtable:
+ * @entry: a #GtkIconEntry
+ * @icon_pos: Icon position
+ *
+ * Returns whether the icon is activatable.
+ *
+ * Returns: %TRUE if the icon is activatable.
+ */
+gboolean
+gtk_icon_entry_get_icon_activatable (GtkIconEntry         *entry,
+                                     GtkIconEntryPosition  icon_pos)
+{
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+
+  g_return_val_if_fail (GTK_IS_ICON_ENTRY (entry), FALSE);
+  g_return_val_if_fail (IS_VALID_ICON_ENTRY_POSITION (icon_pos), FALSE);
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  icon_info = &priv->icons[icon_pos];
+
+  return !icon_info->nonactivatable;
+}
+
+
+/**
+ * gtk_icon_entry_get_pixbuf:
+ * @entry: A #GtkIconEntry
+ * @position: Icon position
+ *
+ * Retrieves the image used for the icon.
+ *
+ * Unlike the other methods of setting and getting icon data, this
+ * method will work regardless of whether the icon was set using a
+ * #GdkPixbuf, a #GIcon, a stock item, or an icon name.
+ *
+ * Returns: A #GdkPixbuf, or %NULL if no icon is set for this position.
+ */
+GdkPixbuf *
+gtk_icon_entry_get_pixbuf (GtkIconEntry         *entry,
+                           GtkIconEntryPosition  icon_pos)
+{
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+
+  g_return_val_if_fail (GTK_IS_ICON_ENTRY (entry), NULL);
+  g_return_val_if_fail (IS_VALID_ICON_ENTRY_POSITION (icon_pos), NULL);
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  icon_info = &priv->icons[icon_pos];
+
+  gtk_icon_entry_ensure_pixbuf (entry, icon_pos);
+
+  return icon_info->pixbuf;
+}
+
+/**
+ * gtk_icon_entry_get_gicon:
+ * @entry: A #GtkIconEntry
+ * @position: Icon position
+ *
+ * Retrieves the #GIcon used for the icon, or %NULL if there is
+ * no icon or if the icon was set by some other method (e.g., by
+ * stock, pixbuf, or icon name).
+ *
+ * Returns: A #GIcon, or %NULL if no icon is set or if the icon
+ *          is not a #GIcon
+ */
+GIcon *
+gtk_icon_entry_get_gicon (GtkIconEntry         *entry,
+                          GtkIconEntryPosition  icon_pos)
+{
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+
+  g_return_val_if_fail (GTK_IS_ICON_ENTRY (entry), NULL);
+  g_return_val_if_fail (IS_VALID_ICON_ENTRY_POSITION (icon_pos), NULL);
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  icon_info = &priv->icons[icon_pos];
+
+  return icon_info->storage_type == GTK_IMAGE_GICON ? icon_info->gicon : NULL;
+}
+
+/**
+ * gtk_icon_entry_get_stock:
+ * @entry: A #GtkIconEntry
+ * @position: Icon position
+ *
+ * Retrieves the stock id used for the icon, or %NULL if there is
+ * no icon or if the icon was set by some other method (e.g., by
+ * pixbuf, icon name or gicon).
+ *
+ * Returns: A stock id, or %NULL if no icon is set or if the icon
+ *          wasn't set from a stock id
+ */
+const gchar *
+gtk_icon_entry_get_stock (GtkIconEntry         *entry,
+                          GtkIconEntryPosition  icon_pos)
+{
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+
+  g_return_val_if_fail (GTK_IS_ICON_ENTRY (entry), NULL);
+  g_return_val_if_fail (IS_VALID_ICON_ENTRY_POSITION (icon_pos), NULL);
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  icon_info = &priv->icons[icon_pos];
+
+  return icon_info->storage_type == GTK_IMAGE_STOCK ? icon_info->stock_id : NULL;
+}
+
+/**
+ * gtk_icon_entry_get_icon_name:
+ * @entry: A #GtkIconEntry
+ * @position: Icon position
+ *
+ * Retrieves the icon name used for the icon, or %NULL if there is
+ * no icon or if the icon was set by some other method (e.g., by
+ * pixbuf, stock or gicon).
+ *
+ * Returns: An icon name, or %NULL if no icon is set or if the icon
+ *          wasn't set from an icon name
+ */
+const gchar *
+gtk_icon_entry_get_icon_name (GtkIconEntry         *entry,
+                              GtkIconEntryPosition  icon_pos)
+{
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+
+  g_return_val_if_fail (GTK_IS_ICON_ENTRY (entry), NULL);
+  g_return_val_if_fail (IS_VALID_ICON_ENTRY_POSITION (icon_pos), NULL);
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  icon_info = &priv->icons[icon_pos];
+
+  return icon_info->storage_type == GTK_IMAGE_ICON_NAME ? icon_info->icon_name : NULL;
+}
+
+/**
+ * gtk_icon_entry_set_icon_sensitive:
+ * @entry: A #GtkIconEntry
+ * @position: Icon position
+ * @sensitive: Specifies whether the icon should appear
+ *             sensitive or insensitive
+ *
+ * Sets the sensitivity for the specified icon.
+ */
+void
+gtk_icon_entry_set_icon_sensitive (GtkIconEntry         *entry,
+                                   GtkIconEntryPosition  icon_pos,
+                                   gboolean              sensitive)
+{
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+
+  g_return_if_fail (GTK_IS_ICON_ENTRY (entry));
+  g_return_if_fail (IS_VALID_ICON_ENTRY_POSITION (icon_pos));
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  icon_info = &priv->icons[icon_pos];
+
+  if (icon_info->insensitive != !sensitive)
+    {
+      icon_info->insensitive = !sensitive;
+
+      if (GTK_WIDGET_REALIZED (GTK_WIDGET (entry)))
+        update_cursors (GTK_WIDGET (entry));
+
+      g_object_notify (G_OBJECT (entry),
+                        icon_pos == GTK_ICON_ENTRY_PRIMARY ? "sensitive-primary" : "sensitive-secondary");
+    }
+}
+
+/**
+ * gtk_icon_entry_get_icon_sensitive:
+ * @entry: a #GtkIconEntry
+ * @icon_pos: Icon position
+ *
+ * Returns whether the icon appears sensitive or insensitive.
+ *
+ * Returns: %TRUE if the icon is sensitive.
+ */
+gboolean
+gtk_icon_entry_get_icon_sensitive (GtkIconEntry         *entry,
+                                   GtkIconEntryPosition  icon_pos)
+{
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+
+  g_return_val_if_fail (GTK_IS_ICON_ENTRY (entry), TRUE);
+  g_return_val_if_fail (IS_VALID_ICON_ENTRY_POSITION (icon_pos), TRUE);
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  icon_info = &priv->icons[icon_pos];
+
+  return !icon_info->insensitive;
+}
+
+GtkImageType
+gtk_icon_entry_get_storage_type (GtkIconEntry         *entry,
+                                 GtkIconEntryPosition  icon_pos)
+{
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+
+  g_return_val_if_fail (GTK_IS_ICON_ENTRY (entry), TRUE);
+  g_return_val_if_fail (IS_VALID_ICON_ENTRY_POSITION (icon_pos), TRUE);
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  icon_info = &priv->icons[icon_pos];
+
+  return icon_info->storage_type;
+}
+
+/**
+ * gtk_icon_entry_get_icon_at_pos:
+ * @entry: a #GtkIconEntry
+ * @x: the x coordinate of the position to find
+ * @y: the y coordinate of the position to find
+ *
+ * Finds the icon at the given position and return its index.
+ * If @x, @y doesn't lie inside an icon, -1 is returned.
+ * This function is intended for use in a #GtkWidget::query-tooltip
+ * signal handler.
+ *
+ * Returns: the index of the icon at the given position, or -1
+ */
+gint
+gtk_icon_entry_get_icon_at_pos (GtkIconEntry *entry,
+                                gint          x,
+                                gint          y)
+{
+  GtkIconEntryPrivate *priv;
+  GtkIconEntryPosition left_icon_pos;
+  GtkIconEntryPosition right_icon_pos;
+  GtkAllocation left_icon_alloc;
+  GtkAllocation right_icon_alloc;
+  GtkAllocation text_area_alloc;
+  GtkAllocation *widget_alloc;
+
+  g_return_val_if_fail (GTK_IS_ICON_ENTRY (entry), -1);
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+
+  widget_alloc = &GTK_WIDGET (entry)->allocation;
+
+  get_text_area_size (entry, &text_area_alloc);
+  get_icon_allocation (entry, TRUE, widget_alloc, &text_area_alloc,
+                       &left_icon_alloc, &left_icon_pos);
+  get_icon_allocation (entry, FALSE, widget_alloc, &text_area_alloc,
+                       &right_icon_alloc, &right_icon_pos);
+
+  if (left_icon_alloc.width > 0)
+    text_area_alloc.x = left_icon_alloc.x + left_icon_alloc.width + priv->icon_margin;
+
+  if (right_icon_alloc.width > 0)
+    text_area_alloc.width -= right_icon_alloc.width + priv->icon_margin;
+
+  text_area_alloc.width -= text_area_alloc.x;
+
+  if (left_icon_alloc.x <= x &&
+      left_icon_alloc.y <= y &&
+      x < left_icon_alloc.x + left_icon_alloc.width &&
+      y < left_icon_alloc.y + left_icon_alloc.height)
+    return left_icon_pos;
+
+  if (right_icon_alloc.x <= x &&
+      right_icon_alloc.y <= y &&
+      x < right_icon_alloc.x + right_icon_alloc.width &&
+      y < right_icon_alloc.y + right_icon_alloc.height)
+    return right_icon_pos;
+
+  return -1;
+}
+
+/**
+ * gtk_icon_entry_set_icon_tooltip_text:
+ * @entry: a #GtkIconEntry
+ * @icon_pos: the icon position
+ * @tooltip: the contents of the tooltip for the icon, or %NULL
+ *
+ * Sets @tooltip as the contents of the tooltip for the icon
+ * at the specified position.
+ *
+ * Use %NULL for @tooltip to remove an existing tooltip.
+ *
+ * See also gtk_widget_set_tooltip_text().
+ */
+void
+gtk_icon_entry_set_icon_tooltip_text (GtkIconEntry         *entry,
+                                      GtkIconEntryPosition  icon_pos,
+                                      const gchar          *tooltip)
+{
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+
+  g_return_if_fail (GTK_IS_ICON_ENTRY (entry));
+  g_return_if_fail (IS_VALID_ICON_ENTRY_POSITION (icon_pos));
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  icon_info = &priv->icons[icon_pos];
+
+  g_free (icon_info->tooltip);
+  icon_info->tooltip = tooltip ? g_markup_escape_text (tooltip, -1) : NULL;
+
+  gtk_widget_set_has_tooltip (GTK_WIDGET (entry), icon_info->tooltip != NULL);
+}
+
+/**
+ * gtk_icon_entry_set_icon_tooltip_markup:
+ * @entry: a #GtkIconEntry
+ * @icon_pos: the icon position
+ * @tooltip: the contents of the tooltip for the icon, or %NULL
+ *
+ * Sets @tooltip as the contents of the tooltip for the icon at
+ * the specified position. @tooltip is assumed to be marked up with
+ * the <link linkend="PangoMarkupFormat">Pango text markup language</link>.
+ *
+ * Use %NULL for @tooltip to remove an existing tooltip.
+ *
+ * See also gtk_widget_set_tooltip_markup().
+ */
+void
+gtk_icon_entry_set_icon_tooltip_markup (GtkIconEntry         *entry,
+                                        GtkIconEntryPosition  icon_pos,
+                                        const gchar          *tooltip)
+{
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+
+  g_return_if_fail (GTK_IS_ICON_ENTRY (entry));
+  g_return_if_fail (IS_VALID_ICON_ENTRY_POSITION (icon_pos));
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  icon_info = &priv->icons[icon_pos];
+
+  g_free (icon_info->tooltip);
+  icon_info->tooltip = g_strdup (tooltip);
+
+  gtk_widget_set_has_tooltip (GTK_WIDGET (entry), icon_info->tooltip != NULL);
+}
+
+static gboolean
+gtk_icon_entry_query_tooltip (GtkWidget  *widget,
+                              gint        x,
+                              gint        y,
+                              gboolean    keyboard_tip,
+                              GtkTooltip *tooltip)
+{
+  GtkIconEntry *entry;
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+  gint icon_pos;
+
+  entry = GTK_ICON_ENTRY (widget);
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+
+  if (!keyboard_tip)
+    {
+      icon_pos = gtk_icon_entry_get_icon_at_pos (entry, x, y);
+      if (icon_pos != -1)
+        {
+          icon_info = &priv->icons[icon_pos];
+          if (icon_info->tooltip && !icon_info->insensitive)
+            {
+              gtk_tooltip_set_markup (tooltip, icon_info->tooltip);
+              return TRUE;
+            }
+
+          return FALSE;
+        }
+    }
+
+  return GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->query_tooltip (widget,
+                                                                        x, y,
+                                                                        keyboard_tip,
+                                                                        tooltip);
+}
+
+static void
+gtk_icon_entry_icon_pressed (GtkIconEntry         *entry,
+                             GtkIconEntryPosition  icon_pos,
+                             GdkEventButton       *event)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  EntryIconInfo *icon_info = &priv->icons[icon_pos];
+
+  if (icon_info->insensitive)
+    return;
+
+  if (icon_info->target_list == NULL)
+    return;
+
+  if (event->button != 1)
+    return;
+
+  priv->start_x = event->x;
+  priv->start_y = event->y;
+
+  icon_info->pressed = TRUE;
+}
+
+static void
+gtk_icon_entry_icon_released (GtkIconEntry         *entry,
+                              GtkIconEntryPosition  icon_pos,
+                              GdkEventButton       *event)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  EntryIconInfo *icon_info = &priv->icons[icon_pos];
+  
+  icon_info->pressed = FALSE;
+}
+
+static gint
+gtk_icon_entry_motion_notify (GtkWidget      *widget,
+                              GdkEventMotion *event)
+{
+  GtkIconEntry *entry = GTK_ICON_ENTRY (widget);
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  EntryIconInfo *icon_info;
+  GdkDragContext *context;
+  gint i;
+
+  for (i = 0; i < MAX_ICONS; i++)
+    {
+      icon_info = &priv->icons[i];
+
+      if (icon_info->insensitive)
+        continue;
+
+      if (event->window == icon_info->window)
+        {
+          if (icon_info->pressed &&
+              icon_info->target_list != NULL &&
+              gtk_drag_check_threshold (widget,
+                                        priv->start_x,
+                                        priv->start_y,
+                                        event->x,
+                                        event->y))
+            {
+              icon_info->in_drag = TRUE;
+              icon_info->pressed = FALSE;
+              context = gtk_drag_begin (widget, 
+                                        icon_info->target_list,
+                                        icon_info->actions,
+                                        1,
+                                        (GdkEvent*)event);
+            }
+
+          return TRUE;
+        }
+    }
+
+  if (GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->motion_notify_event)
+    return GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->motion_notify_event (widget, event);
+
+  return FALSE;
+}
+
+/**
+ * gtk_icon_entry_set_icon_drag_source:
+ * @entry: a #GtkIconEntry
+ * @icon_pos: icon position
+ * @target_list: the targets (data formats) in which the data can be provided
+ * @actions: a bitmask of the allowed drag actions
+ *
+ * Sets up the icon at the given position so that GTK+ will start a drag
+ * operation when the user clicks and drags the icon.
+ *
+ * To handle the drag operation, you need to connect to the usual
+ * #GtkWidget::drag-data-get (or possibly #GtkWidget::drag-data-delete) 
+ * signal, and use gtk_icon_entry_get_current_icon_drag_source() in
+ * your signal handler to find out if the drag was started from
+ * an icon.
+ */
+void 
+gtk_icon_entry_set_icon_drag_source (GtkIconEntry         *entry,
+                                     GtkIconEntryPosition  icon_pos,
+                                     GtkTargetList        *target_list,
+                                     GdkDragAction         actions)
+{
+  GtkIconEntryPrivate *priv;
+  EntryIconInfo *icon_info;
+
+  g_return_if_fail (GTK_IS_ICON_ENTRY (entry));
+  g_return_if_fail (IS_VALID_ICON_ENTRY_POSITION (icon_pos));
+
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+  icon_info = &priv->icons[icon_pos];
+  
+  if (icon_info->target_list)
+    gtk_target_list_unref (icon_info->target_list);
+  icon_info->target_list = target_list;
+  if (icon_info->target_list)
+    gtk_target_list_ref (icon_info->target_list);
+
+  icon_info->actions = actions;
+}
+
+/**
+ * gtk_icon_entry_get_current_icon_drag_source:
+ * @entry: a #GtkIconEntry
+ *
+ * Returns the index of the icon which is the source of the current
+ * DND operation, or -1.
+ *
+ * This function is meant to be used in a #GtkWidget::drag-data-get 
+ * callback.
+ *
+ * Returns: index of the icon which is the source of the current
+ *          DND operation, or -1.
+ */
+gint
+gtk_icon_entry_get_current_icon_drag_source (GtkIconEntry *entry)
+{
+  GtkIconEntryPrivate *priv;
+  gint i;
+
+  g_return_val_if_fail (GTK_IS_ICON_ENTRY (entry), -1);
+  
+  priv = GTK_ICON_ENTRY_GET_PRIVATE (entry);
+
+  for (i = 0; i < MAX_ICONS; i++)
+    if (priv->icons[i].in_drag)
+      return i;
+
+  return -1;
+}
+
+static void
+gtk_icon_entry_drag_begin (GtkWidget      *widget,
+                           GdkDragContext *context)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (widget);
+  EntryIconInfo *icon_info;
+  gint i;
+
+  for (i = 0; i < MAX_ICONS; i++)
+    {
+      icon_info = &priv->icons[i];
+      if (icon_info->in_drag) 
+        {
+          switch (icon_info->storage_type)
+            {
+            case GTK_IMAGE_STOCK:
+              gtk_drag_set_icon_stock (context, icon_info->stock_id, -2, -2);
+              break;
+
+            case GTK_IMAGE_ICON_NAME:
+              gtk_drag_set_icon_name (context, icon_info->icon_name, -2, -2);
+              break;
+
+            /* FIXME: No GIcon support for dnd icons */
+            case GTK_IMAGE_GICON:
+            case GTK_IMAGE_PIXBUF:
+              gtk_drag_set_icon_pixbuf (context, icon_info->pixbuf, -2, -2);
+              break;
+            default:
+              g_assert_not_reached ();
+            }
+        }
+    }
+}
+
+static void
+gtk_icon_entry_drag_end (GtkWidget      *widget,
+                         GdkDragContext *context)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (widget);
+  gint i;
+
+  for (i = 0; i < MAX_ICONS; i++)
+    priv->icons[i].in_drag = 0;
+}
+
+static void
+gtk_icon_entry_drag_data_get (GtkWidget        *widget,
+                              GdkDragContext   *context,
+                              GtkSelectionData *selection_data,
+                              guint             info,
+                              guint             time)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (widget);
+  gint i;
+
+  /* Only call the GtkEntry drag-data-get class handler if there
+   * is no icon drag going on. 
+   */ 
+  for (i = 0; i < MAX_ICONS; i++)
+    if (priv->icons[i].in_drag)
+      return;
+
+  if (GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->drag_data_get)
+    GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->drag_data_get (widget,
+                                                                   context,
+                                                                   selection_data,
+                                                                   info,
+                                                                   time);
+}
+
+static void
+gtk_icon_entry_drag_data_delete (GtkWidget      *widget,
+                                 GdkDragContext *context)
+{
+  GtkIconEntryPrivate *priv = GTK_ICON_ENTRY_GET_PRIVATE (widget);
+  gint i;
+
+  /* Only call the GtkEntry drag-data-delete class handler if there
+   * is no icon drag going on. 
+   */ 
+  for (i = 0; i < MAX_ICONS; i++)
+    if (priv->icons[i].in_drag)
+      return;
+
+  if (GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->drag_data_delete)
+    GTK_WIDGET_CLASS (gtk_icon_entry_parent_class)->drag_data_delete (widget,
+                                                                      context);
+}
