Index: gtk/gtkentry.c
===================================================================
--- gtk/gtkentry.c	(revision 17906)
+++ gtk/gtkentry.c	(working copy)
@@ -91,6 +91,9 @@
   GtkShadowType shadow_type;
 
   GtkAdjustment *cursor_hadjustment;
+
+  gboolean hinting;
+  char *hint;
 };
 
 typedef struct _GtkEntryPasswordHint GtkEntryPasswordHint;
@@ -133,7 +136,8 @@
   PROP_TEXT,
   PROP_XALIGN,
   PROP_TRUNCATE_MULTILINE,
-  PROP_SHADOW_TYPE
+  PROP_SHADOW_TYPE,
+  PROP_HINT,
 };
 
 static guint signals[LAST_SIGNAL] = { 0 };
@@ -624,6 +628,21 @@
                                                       GTK_SHADOW_IN,
                                                       GTK_PARAM_READWRITE));
 
+  /**
+   * GtkEntry::hint:
+   *
+   * A message to display in the entry when it is unfocused and has no other content.
+   *
+   * Since: 2.12
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_HINT,
+                                   g_param_spec_string ("hint",
+							P_("Hint"),
+							P_("The hint to display when the entry is unfocused and empty"),
+							"",
+							GTK_PARAM_READWRITE));
+
   signals[POPULATE_POPUP] =
     g_signal_new (I_("populate_popup"),
 		  G_OBJECT_CLASS_TYPE (gobject_class),
@@ -1016,6 +1035,10 @@
       priv->shadow_type = g_value_get_enum (value);
       break;
 
+    case PROP_HINT:
+      gtk_entry_set_hint (entry, g_value_get_string (value));
+      break;
+
     case PROP_SCROLL_OFFSET:
     case PROP_CURSOR_POSITION:
     default:
@@ -1080,6 +1103,9 @@
     case PROP_SHADOW_TYPE:
       g_value_set_enum (value, priv->shadow_type);
       break;
+    case PROP_HINT:
+      g_value_set_string (value, gtk_entry_get_hint (entry));
+      break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1110,6 +1136,9 @@
   priv->shadow_type = GTK_SHADOW_IN;
   priv->xalign = 0.0;
 
+  priv->hinting = FALSE;
+  priv->hint = NULL;
+
   gtk_drag_dest_set (GTK_WIDGET (entry),
                      GTK_DEST_DEFAULT_HIGHLIGHT,
                      NULL, 0,
@@ -2089,6 +2118,36 @@
   return GTK_WIDGET_CLASS (gtk_entry_parent_class)->key_release_event (widget, event);
 }
 
+static void
+update_hint (GtkEntry *entry)
+{
+  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
+  GdkColor *colour;
+
+  if (priv->hint == NULL)
+    return;
+  
+  if (GTK_WIDGET_HAS_FOCUS (entry)) {
+    if (priv->hinting) {
+      gtk_editable_delete_text (GTK_EDITABLE (entry), 0, -1);
+      gtk_widget_modify_text (GTK_WIDGET (entry), GTK_STATE_NORMAL, NULL);
+    }
+    priv->hinting = FALSE;
+  } else {
+    if (entry->text == NULL || entry->text[0] == '\0') {
+      entry->text = g_strdup (priv->hint);
+      entry->n_bytes = entry->text_length = strlen (entry->text);
+      gtk_entry_recompute (entry);
+
+      colour = &gtk_widget_get_style (GTK_WIDGET (entry))->text[GTK_STATE_INSENSITIVE];
+      gtk_widget_modify_text (GTK_WIDGET (entry), GTK_STATE_NORMAL, colour);
+      priv->hinting = TRUE;
+    } else {
+      priv->hinting = FALSE;
+    }
+  }
+}
+
 static gint
 gtk_entry_focus_in (GtkWidget     *widget,
 		    GdkEventFocus *event)
@@ -2097,6 +2156,8 @@
   
   gtk_widget_queue_draw (widget);
   
+  update_hint (entry);
+
   if (entry->editable)
     {
       entry->need_im_reset = TRUE;
@@ -2122,6 +2183,8 @@
   
   gtk_widget_queue_draw (widget);
 
+  update_hint (entry);
+
   if (entry->editable)
     {
       entry->need_im_reset = TRUE;
@@ -2278,6 +2341,8 @@
   GtkEntry *entry = GTK_ENTRY (editable);
   gint start_index, end_index;
   
+  /* TODO: handle hinted */
+  
   if (end_pos < 0)
     end_pos = entry->text_length;
 
@@ -4332,6 +4397,8 @@
   g_object_thaw_notify (G_OBJECT (entry));
   end_change (entry);
 
+  update_hint (entry);
+
   if (completion && completion->priv->changed_id > 0)
     g_signal_handler_unblock (entry, completion->priv->changed_id);
 }
@@ -4497,9 +4564,16 @@
 G_CONST_RETURN gchar*
 gtk_entry_get_text (GtkEntry *entry)
 {
+  GtkEntryPrivate *priv;
+
   g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
 
-  return entry->text;
+  priv = GTK_ENTRY_GET_PRIVATE (entry);
+
+  if (priv->hinting)
+    return "";
+  else
+    return entry->text;
 }
 
 void       
@@ -6163,5 +6237,38 @@
   return priv->cursor_hadjustment;
 }
 
+void
+gtk_entry_set_hint (GtkEntry *entry, const char *hint)
+{
+  GtkEntryPrivate *priv;
+  
+  g_return_if_fail (GTK_IS_ENTRY (entry));
+  
+  priv = GTK_ENTRY_GET_PRIVATE (entry);
+  
+  if (priv->hint) {
+    g_free (priv->hint);
+    priv->hint = NULL;
+  }
+  
+  if (hint) {
+    priv->hint = g_strdup (hint);
+  }
+
+  update_hint (entry);
+}
+
+const char *
+gtk_entry_get_hint (GtkEntry *entry)
+{
+  GtkEntryPrivate *priv;
+    
+  g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
+
+  priv = GTK_ENTRY_GET_PRIVATE (entry);
+
+  return priv->hint;
+}
+
 #define __GTK_ENTRY_C__
 #include "gtkaliasdef.c"
Index: gtk/gtkentry.h
===================================================================
--- gtk/gtkentry.h	(revision 17906)
+++ gtk/gtkentry.h	(working copy)
@@ -197,6 +197,9 @@
                                                  GtkAdjustment *adjustment);
 GtkAdjustment* gtk_entry_get_cursor_hadjustment (GtkEntry      *entry);
 
+void        gtk_entry_set_hint (GtkEntry *entry, const char *hint);
+const char* gtk_entry_get_hint (GtkEntry *entry);
+
 /* Deprecated compatibility functions
  */
 
Index: tests/testentryhint.c
===================================================================
--- tests/testentryhint.c	(revision 0)
+++ tests/testentryhint.c	(revision 0)
@@ -0,0 +1,43 @@
+#include <gtk/gtk.h>
+
+static void
+changed (GtkEntry *entry, GtkLabel *label)
+{
+  gtk_label_set_text (label, gtk_entry_get_text (entry));
+}
+
+int
+main (int argc, char **argv)
+{
+  GtkWidget *window, *box, *entry, *hinted, *label_entry, *label_hinted;
+
+  gtk_init (&argc, &argv);
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_container_set_border_width (GTK_CONTAINER (window), 12);
+
+  box = gtk_vbox_new (TRUE, 12);
+
+  entry = gtk_entry_new ();
+  
+  hinted = gtk_entry_new ();
+  gtk_entry_set_hint (GTK_ENTRY (hinted), "Type in me!");
+
+  label_entry = gtk_label_new (NULL);
+  g_signal_connect (entry, "changed", G_CALLBACK (changed), label_entry);
+
+  label_hinted = gtk_label_new (NULL);
+  g_signal_connect (hinted, "changed", G_CALLBACK (changed), label_hinted);
+
+  gtk_box_pack_start_defaults (GTK_BOX (box), entry);
+  gtk_box_pack_start_defaults (GTK_BOX (box), hinted);
+  gtk_box_pack_start_defaults (GTK_BOX (box), label_entry);
+  gtk_box_pack_start_defaults (GTK_BOX (box), label_hinted);
+  gtk_container_add (GTK_CONTAINER (window), box);
+
+  gtk_widget_show_all (window);
+  
+  gtk_main ();
+
+  return 0;
+}
Index: tests/Makefile.am
===================================================================
--- tests/Makefile.am	(revision 17906)
+++ tests/Makefile.am	(working copy)
@@ -42,6 +42,7 @@
 	testdnd				\
 	testellipsise			\
 	testentrycompletion 		\
+	testentryhint			\
 	testfilechooser			\
 	testfilechooserbutton		\
 	testgtk				\
@@ -105,6 +106,7 @@
 testdnd_DEPENDENCIES = $(TEST_DEPS)
 testellipsise_DEPENDENCIES = $(TEST_DEPS)
 testentrycompletion_DEPENDENCIES = $(TEST_DEPS)
+testentryhint_DEPENDENCIES = $(TEST_DEPS)
 testfilechooser_DEPENDENCIES = $(TEST_DEPS)
 testfilechooserbutton_DEPENDENCIES = $(TEST_DEPS)
 testgtk_DEPENDENCIES = $(TEST_DEPS)
@@ -158,6 +160,7 @@
 testdnd_LDADD = $(LDADDS)
 testellipsise_LDADD = $(LDADDS)
 testentrycompletion_LDADD = $(LDADDS)
+testentryhint_LDADD = $(LDADDS)
 testfilechooser_LDADD = $(LDADDS)
 testfilechooserbutton_LDADD = $(LDADDS)
 testgtk_LDADD = $(LDADDS)
@@ -212,6 +215,9 @@
 	prop-editor.c		\
 	testentrycompletion.c
 
+testentryhint_SOURCES = 	\
+	testentryhint.c
+
 testfilechooser_SOURCES = 	\
 	prop-editor.c		\
 	testfilechooser.c 	
