diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
index 3c7aa25..bc3c61b 100644
--- a/gtk/gtkentry.c
+++ b/gtk/gtkentry.c
@@ -133,6 +133,9 @@ struct _GtkEntryPrivate
   gdouble progress_pulse_fraction;
   gdouble progress_pulse_current;
 
+  gchar *placeholder_text;
+  PangoLayout *placeholder_layout;
+
   EntryIconInfo *icons[MAX_ICONS];
   gint icon_margin;
   gint start_x;
@@ -220,7 +223,8 @@ enum {
   PROP_TOOLTIP_MARKUP_PRIMARY,
   PROP_TOOLTIP_MARKUP_SECONDARY,
   PROP_IM_MODULE,
-  PROP_EDITING_CANCELED
+  PROP_EDITING_CANCELED,
+  PROP_PLACEHOLDER_TEXT
 };
 
 static guint signals[LAST_SIGNAL] = { 0 };
@@ -426,6 +430,7 @@ static void         gtk_entry_queue_draw               (GtkEntry       *entry);
 static void         gtk_entry_recompute                (GtkEntry       *entry);
 static gint         gtk_entry_find_position            (GtkEntry       *entry,
 							gint            x);
+static PangoLayout *gtk_entry_create_placeholder_layout(GtkEntry *entry);
 static void         gtk_entry_get_cursor_locations     (GtkEntry       *entry,
 							CursorType      type,
 							gint           *strong_x,
@@ -893,6 +898,21 @@ gtk_entry_class_init (GtkEntryClass *class)
                                                         GTK_PARAM_READWRITE));
 
   /**
+  * GtkEntry:placeholder-text:
+  *
+  * Text to be displayed in the #GtkEntry when it is empty.
+  *
+  * Since: 3.0
+  */
+ g_object_class_install_property (gobject_class,
+                                  PROP_PLACEHOLDER_TEXT,
+                                  g_param_spec_string ("placeholder-text",
+                                                       P_("Placeholder text"),
+                                                       P_("Text to be displayed when the entry is empty"),
+                                                       "",
+                                                       G_PARAM_READWRITE));
+
+   /**
    * GtkEntry:primary-icon-pixbuf:
    *
    * A pixbuf to use as the primary icon for the entry.
@@ -1913,6 +1933,10 @@ gtk_entry_set_property (GObject         *object,
       gtk_entry_set_progress_pulse_step (entry, g_value_get_double (value));
       break;
 
+    case PROP_PLACEHOLDER_TEXT:
+      gtk_entry_set_placeholder_text (entry, g_value_get_string (value));
+      break;
+
     case PROP_PIXBUF_PRIMARY:
       gtk_entry_set_icon_from_pixbuf (entry,
                                       GTK_ENTRY_ICON_PRIMARY,
@@ -2131,6 +2155,10 @@ gtk_entry_get_property (GObject         *object,
       g_value_set_double (value, priv->progress_pulse_fraction);
       break;
 
+    case PROP_PLACEHOLDER_TEXT:
+      g_value_set_string (value, gtk_entry_get_placeholder_text (entry));
+      break;
+
     case PROP_PIXBUF_PRIMARY:
       g_value_set_object (value,
                           gtk_entry_get_icon_pixbuf (entry,
@@ -2313,6 +2341,8 @@ gtk_entry_init (GtkEntry *entry)
   priv->caps_lock_warning_shown = FALSE;
   priv->progress_fraction = 0.0;
   priv->progress_pulse_fraction = 0.1;
+  priv->placeholder_text = NULL;
+  priv->placeholder_layout = NULL;
 
   gtk_drag_dest_set (GTK_WIDGET (entry),
                      GTK_DEST_DEFAULT_HIGHLIGHT,
@@ -2520,6 +2550,15 @@ gtk_entry_finalize (GObject *object)
 
   g_free (priv->im_module);
 
+  if (priv->placeholder_text)
+    {
+      g_free (priv->placeholder_text);
+      priv->placeholder_text = NULL;
+
+      g_object_unref (priv->placeholder_layout);
+      priv->placeholder_layout = NULL;
+    }
+
   G_OBJECT_CLASS (gtk_entry_parent_class)->finalize (object);
 }
 
@@ -4466,6 +4505,12 @@ gtk_entry_style_set (GtkWidget *widget,
 
   gtk_entry_recompute (entry);
 
+  if (priv->placeholder_text)
+    {
+      g_object_unref (priv->placeholder_layout);
+      priv->placeholder_layout = gtk_entry_create_placeholder_layout (entry);
+    }
+
   if (previous_style && gtk_widget_get_realized (widget))
     {
       gdk_window_set_background (widget->window, &widget->style->base[gtk_widget_get_state (widget)]);
@@ -4550,6 +4595,53 @@ gtk_entry_remove_password_hint (gpointer data)
   return FALSE;
 }
 
+static PangoLayout *
+gtk_entry_create_placeholder_layout (GtkEntry *entry)
+{
+  GtkWidget *widget = GTK_WIDGET (entry);
+  PangoLayout *layout = gtk_widget_create_pango_layout (widget, NULL);
+  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
+  PangoDirection pango_dir;
+
+  pango_layout_set_single_paragraph_mode (layout, TRUE);
+
+  pango_dir = pango_find_base_dir (priv->placeholder_text,
+                                   strlen (priv->placeholder_text));
+
+  if (pango_dir == PANGO_DIRECTION_NEUTRAL)
+    {
+      if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+        pango_dir = PANGO_DIRECTION_RTL;
+      else
+        pango_dir = PANGO_DIRECTION_LTR;
+    }
+
+  pango_context_set_base_dir (gtk_widget_get_pango_context (widget),
+                              pango_dir);
+
+  pango_layout_set_alignment (layout, pango_dir);
+
+  pango_layout_set_text (layout, priv->placeholder_text,
+                         strlen (priv->placeholder_text));
+
+  PangoAttrList *list;
+  PangoAttribute *attr;
+
+  list = pango_attr_list_new ();
+  attr = pango_attr_foreground_new (widget->style->text_aa [widget->state].red,
+                                    widget->style->text_aa [widget->state].green,
+                                    widget->style->text_aa [widget->state].blue);
+  attr->start_index = 0;
+  attr->end_index = G_MAXINT;
+  pango_attr_list_insert (list, attr);
+
+  pango_layout_set_attributes (layout, list);
+
+  pango_attr_list_unref (list);
+
+  return layout;
+}
+
 /* Default signal handlers
  */
 static void
@@ -5472,6 +5564,19 @@ gtk_entry_ensure_layout (GtkEntry *entry,
   return entry->cached_layout;
 }
 
+static inline gboolean
+show_placeholder (GtkEntry *entry)
+{
+  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
+
+  if (!gtk_widget_has_focus (GTK_WIDGET (entry))
+      && gtk_entry_buffer_get_bytes (get_buffer (entry)) == 0
+      && priv->placeholder_text)
+    return TRUE;
+
+  return FALSE;
+}
+
 static void
 get_layout_position (GtkEntry *entry,
                      gint     *x,
@@ -5483,8 +5588,12 @@ get_layout_position (GtkEntry *entry,
   GtkBorder inner_border;
   gint y_pos;
   PangoLayoutLine *line;
+  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
   
-  layout = gtk_entry_ensure_layout (entry, TRUE);
+  if (show_placeholder (entry))
+    layout = priv->placeholder_layout;
+  else
+    layout = gtk_entry_ensure_layout (entry, TRUE);
 
   gtk_entry_get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
   _gtk_entry_effective_inner_border (entry, &inner_border);
@@ -5518,13 +5627,19 @@ get_layout_position (GtkEntry *entry,
 static void
 draw_text_with_color (GtkEntry *entry, cairo_t *cr, GdkColor *default_color)
 {
-  PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
+  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
+  PangoLayout *layout;
   GtkWidget *widget;
   gint x, y;
   gint start_pos, end_pos;
 
   widget = GTK_WIDGET (entry);
 
+  if (show_placeholder (entry))
+    layout = priv->placeholder_layout;
+  else
+    layout = gtk_entry_ensure_layout (entry, TRUE);
+
   cairo_save (cr);
 
   get_layout_position (entry, &x, &y);
@@ -9974,6 +10089,75 @@ gtk_entry_progress_pulse (GtkEntry *entry)
   gtk_widget_queue_draw (GTK_WIDGET (entry));
 }
 
+/**
+ * gtk_entry_set_placeholder_text:
+ * @entry: a #GtkEntry
+ * @placeholder_text: a string to be displayed when @entry is empty
+ * and unfocused or %NULL to remove current placeholder text.
+ *
+ * Sets a text string to be displayed when @entry is empty and unfocused.
+ * This can be provided to give a visual hint of the expected contents
+ * of the #GtkEntry.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_entry_set_placeholder_text (GtkEntry    *entry,
+                                const gchar *placeholder_text)
+{
+  GtkEntryPrivate *priv;
+
+  g_return_if_fail (GTK_IS_ENTRY (entry));
+
+  priv = GTK_ENTRY_GET_PRIVATE (entry);
+
+  if (priv->placeholder_text)
+    {
+      g_free (priv->placeholder_text);
+      g_object_unref (priv->placeholder_layout);
+    }
+
+  if (placeholder_text)
+    {
+      priv->placeholder_text = g_strdup (placeholder_text);
+      priv->placeholder_layout = gtk_entry_create_placeholder_layout (entry);
+    }
+  else
+    {
+      priv->placeholder_text = NULL;
+      priv->placeholder_layout = NULL;
+    }
+
+  if (show_placeholder (entry))
+    {
+      gtk_widget_queue_draw (GTK_WIDGET (entry));
+    }
+
+  g_object_notify (G_OBJECT (entry), "placeholder-text");
+}
+
+/**
+ * gtk_entry_get_placeholder_text:
+ * @entry: a #GtkEntry
+ *
+ * Gets the text to be displayed if @entry is empty and unfocused.
+ *
+ * Returns: a string or %NULL if no placeholder text is set
+ *
+ * Since: 3.0
+ **/
+const gchar *
+gtk_entry_get_placeholder_text (GtkEntry *entry)
+{
+  GtkEntryPrivate *priv;
+
+  g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
+
+  priv = GTK_ENTRY_GET_PRIVATE (entry);
+
+  return priv->placeholder_text;
+}
+
 /* Caps Lock warning for password entries */
 
 static void
diff --git a/gtk/gtkentry.h b/gtk/gtkentry.h
index 9bf5f85..85010f8 100644
--- a/gtk/gtkentry.h
+++ b/gtk/gtkentry.h
@@ -250,6 +250,11 @@ gdouble        gtk_entry_get_progress_pulse_step (GtkEntry     *entry);
 
 void           gtk_entry_progress_pulse          (GtkEntry     *entry);
 
+const gchar *  gtk_entry_get_placeholder_text    (GtkEntry *entry);
+
+void           gtk_entry_set_placeholder_text    (GtkEntry    *entry,
+						  const gchar *placeholder_text);
+
 /* Setting and managing icons
  */
 void           gtk_entry_set_icon_from_pixbuf            (GtkEntry             *entry,
