Index: gtkentry.c
===================================================================
--- gtkentry.c	(revision 22335)
+++ gtkentry.c	(working copy)
@@ -1198,6 +1198,20 @@ gtk_entry_class_init (GtkEntryClass *cla
                                                                  P_("Whether activatable icons should prelight when hovered"),
                                                                  TRUE,
                                                                  GTK_PARAM_READABLE));
+
+  /**
+   * GtkEntry::progress-border:
+   *
+   * The border around the progress bar in the entry.
+   *
+   * Since: 2.16
+   */
+  gtk_widget_class_install_style_property (widget_class,
+					   g_param_spec_boxed ("progress-border",
+                                                               P_("Progress Border"),
+                                                               P_("Border around the progress bar"),
+                                                               GTK_TYPE_BORDER,
+                                                               GTK_PARAM_READABLE));
   
   /**
    * GtkEntry::populate-popup:
@@ -3150,49 +3164,109 @@ gtk_entry_draw_frame (GtkWidget    *widg
 }
 
 static void
-gtk_entry_draw_progress (GtkWidget      *widget,
-                         GdkEventExpose *event)
+gtk_entry_get_progress_border (GtkWidget *widget,
+                               GtkBorder *progress_border)
+{
+  GtkBorder *tmp_border;
+
+  gtk_widget_style_get (widget, "progress-border", &tmp_border, NULL);
+  if (tmp_border)
+    {
+      *progress_border = *tmp_border;
+      gtk_border_free (tmp_border);
+    }
+  else
+    {
+      progress_border->left = widget->style->xthickness;
+      progress_border->right = widget->style->xthickness;
+      progress_border->top = widget->style->ythickness;
+      progress_border->bottom = widget->style->ythickness;
+    }
+}
+
+static void
+get_progress_area (GtkWidget *widget,
+                  gint       *x,
+                  gint       *y,
+                  gint       *width,
+                  gint       *height)
 {
   GtkEntryPrivate *private = GTK_ENTRY_GET_PRIVATE (widget);
   GtkEntry *entry = GTK_ENTRY (widget);
+  GtkBorder progress_border;
+
+  gtk_entry_get_progress_border (widget, &progress_border);
+
+  *x = progress_border.left;
+  *y = progress_border.top;
+
+  gdk_drawable_get_size (widget->window, width, height);
+
+  *width -= progress_border.left + progress_border.right;
+  *height -= progress_border.top + progress_border.bottom;
+
+  if (GTK_WIDGET_HAS_FOCUS (widget) && !private->interior_focus)
+    {
+      *x += private->focus_width;
+      *y += private->focus_width;
+      *width -= 2 * private->focus_width;
+      *height -= 2 * private->focus_width;
+    }
 
   if (private->progress_pulse_mode)
     {
       gdouble value = private->progress_pulse_current;
-      gint    area_width, area_height;
 
-      gdk_drawable_get_size (entry->text_area, &area_width, &area_height);
-
-      gtk_paint_box (widget->style, entry->text_area,
-                     GTK_STATE_SELECTED, GTK_SHADOW_OUT,
-                     &event->area, widget, "entry-progress",
-                     value * area_width, 0,
-                     private->progress_pulse_fraction * area_width, area_height);
+      *x += (gint) lrint (value * (*width));
+      *width = (gint) lrint (private->progress_pulse_fraction * (*width));
     }
   else if (private->progress_fraction > 0)
     {
       gdouble value = private->progress_fraction;
-      gint    area_width, area_height;
-
-      gdk_drawable_get_size (entry->text_area, &area_width, &area_height);
 
       if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
         {
-          gtk_paint_box (widget->style, entry->text_area,
-                         GTK_STATE_SELECTED, GTK_SHADOW_OUT,
-                         &event->area, widget, "entry-progress",
-                         area_width - value * area_width, 0,
-                         value * area_width, area_height);
+          *x += (gint) lrint (*width - value * (*width));
+          *width = (gint) lrint (value * (*width));
         }
       else
         {
-          gtk_paint_box (widget->style, entry->text_area,
-                         GTK_STATE_SELECTED, GTK_SHADOW_OUT,
-                         &event->area, widget, "entry-progress",
-                         0, 0,
-                         value * area_width, area_height);
+          *width = (gint) lrint (value * (*width));
         }
     }
+  else
+    {
+      *width = 0;
+      *height = 0;
+    }
+}
+
+static void
+gtk_entry_draw_progress (GtkWidget      *widget,
+                         GdkEventExpose *event)
+{
+  gint x, y, width, height;
+
+  get_progress_area (widget, &x, &y, &width, &height);
+
+  if ((width <= 0) || (height <= 0))
+    return;
+
+  if (event->window != widget->window)
+    {
+      gint pos_x, pos_y;
+
+      gdk_window_get_position (event->window, &pos_x, &pos_y);
+
+      x -= pos_x;
+      y -= pos_y;
+    }
+
+  gtk_paint_box (widget->style, event->window,
+                 GTK_STATE_SELECTED, GTK_SHADOW_OUT,
+                 &event->area, widget, "entry-progress",
+                 x, y,
+                 width, height);
 }
 
 static gint
@@ -3214,6 +3288,8 @@ gtk_entry_expose (GtkWidget      *widget
   if (widget->window == event->window)
     {
       gtk_entry_draw_frame (widget, &event->area);
+
+      gtk_entry_draw_progress (widget, event);
     }
   else if (entry->text_area == event->window)
     {
@@ -3251,12 +3327,12 @@ gtk_entry_expose (GtkWidget      *widget
               gint width, height;
 
               gdk_drawable_get_size (icon_info->window, &width, &height);
-
               gtk_paint_flat_box (widget->style, icon_info->window,
                                   GTK_WIDGET_STATE (widget), GTK_SHADOW_NONE,
                                   NULL, widget, "entry_bg",
                                   0, 0, width, height);
 
+              gtk_entry_draw_progress (widget, event);
               draw_icon (widget, i);
 
               break;
@@ -5357,72 +5433,108 @@ get_layout_position (GtkEntry *entry,
 }
 
 static void
-gtk_entry_draw_text (GtkEntry *entry)
+draw_text_with_color (GtkEntry *entry, cairo_t *cr, GdkColor *default_color)
 {
+  PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
   GtkWidget *widget;
-  
-  if (!entry->visible && entry->invisible_char == 0)
-    return;
-  
-  if (GTK_WIDGET_DRAWABLE (entry))
-    {
-      PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
-      cairo_t *cr;
-      gint x, y;
-      gint start_pos, end_pos;
-      
-      widget = GTK_WIDGET (entry);
-      
-      get_layout_position (entry, &x, &y);
+  gint x, y;
+  gint start_pos, end_pos;
 
-      cr = gdk_cairo_create (entry->text_area);
+  widget = GTK_WIDGET (entry);
 
-      cairo_move_to (cr, x, y);
-      gdk_cairo_set_source_color (cr, &widget->style->text [widget->state]);
-      pango_cairo_show_layout (cr, layout);
+  cairo_save (cr);
 
-      if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos))
-	{
-	  gint *ranges;
-	  gint n_ranges, i;
-          PangoRectangle logical_rect;
-	  GdkColor *selection_color, *text_color;
-          GtkBorder inner_border;
+  get_layout_position (entry, &x, &y);
 
-	  pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
-	  gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges);
+  cairo_move_to (cr, x, y);
+  gdk_cairo_set_source_color (cr, default_color);
+  pango_cairo_show_layout (cr, layout);
 
-	  if (GTK_WIDGET_HAS_FOCUS (entry))
-	    {
-	      selection_color = &widget->style->base [GTK_STATE_SELECTED];
-	      text_color = &widget->style->text [GTK_STATE_SELECTED];
-	    }
-	  else
-	    {
-	      selection_color = &widget->style->base [GTK_STATE_ACTIVE];
-	      text_color = &widget->style->text [GTK_STATE_ACTIVE];
-	    }
+  if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos))
+    {
+      gint *ranges;
+      gint n_ranges, i;
+      PangoRectangle logical_rect;
+      GdkColor *selection_color, *text_color;
+      GtkBorder inner_border;
+
+      pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
+      gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges);
 
-          _gtk_entry_effective_inner_border (entry, &inner_border);
+      if (GTK_WIDGET_HAS_FOCUS (entry))
+        {
+          selection_color = &widget->style->base [GTK_STATE_SELECTED];
+          text_color = &widget->style->text [GTK_STATE_SELECTED];
+        }
+      else
+        {
+          selection_color = &widget->style->base [GTK_STATE_ACTIVE];
+	  text_color = &widget->style->text [GTK_STATE_ACTIVE];
+        }
 
-	  for (i = 0; i < n_ranges; ++i)
-	    cairo_rectangle (cr,
-			     inner_border.left - entry->scroll_offset + ranges[2 * i],
-			     y,
-			     ranges[2 * i + 1],
-			     logical_rect.height);
+      _gtk_entry_effective_inner_border (entry, &inner_border);
 
-	  cairo_clip (cr);
-	  
-	  gdk_cairo_set_source_color (cr, selection_color);
-	  cairo_paint (cr);
+      for (i = 0; i < n_ranges; ++i)
+        cairo_rectangle (cr,
+        	         inner_border.left - entry->scroll_offset + ranges[2 * i],
+			 y,
+			 ranges[2 * i + 1],
+			 logical_rect.height);
 
-	  cairo_move_to (cr, x, y);
-	  gdk_cairo_set_source_color (cr, text_color);
-	  pango_cairo_show_layout (cr, layout);
+      cairo_clip (cr);
 	  
-	  g_free (ranges);
-	}
+      gdk_cairo_set_source_color (cr, selection_color);
+      cairo_paint (cr);
+
+      cairo_move_to (cr, x, y);
+      gdk_cairo_set_source_color (cr, text_color);
+      pango_cairo_show_layout (cr, layout);
+  
+      g_free (ranges);
+    }
+  cairo_restore (cr);
+}
+
+static void
+gtk_entry_draw_text (GtkEntry *entry)
+{
+  GtkWidget *widget = GTK_WIDGET (entry);
+  cairo_t *cr;
+
+  if (!entry->visible && entry->invisible_char == 0)
+    return;
+  
+  if (GTK_WIDGET_DRAWABLE (entry))
+    {
+      gint pos_x, pos_y;
+      gint x, y, width, height;
+
+      cr = gdk_cairo_create (entry->text_area);
+
+      gdk_drawable_get_size (entry->text_area, &width, &height);
+
+      cairo_rectangle (cr, 0, 0, width, height);
+      cairo_clip (cr);
+      cairo_save (cr);
+
+      cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+      cairo_rectangle (cr, 0, 0, width, height);
+
+      get_progress_area (widget, &x, &y, &width, &height);
+      gdk_window_get_position (entry->text_area, &pos_x, &pos_y);
+      x -= pos_x;
+      y -= pos_y;
+
+      cairo_rectangle (cr, x, y, width, height);
+      cairo_clip (cr);
+      cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
+      
+      draw_text_with_color (entry, cr, &widget->style->text[widget->state]);
+      cairo_restore (cr);
+
+      cairo_rectangle (cr, x, y, width, height);
+      cairo_clip (cr);
+      draw_text_with_color (entry, cr, &widget->style->fg[GTK_STATE_SELECTED]);
 
       cairo_destroy (cr);
     }
@@ -9434,6 +9546,8 @@ gtk_entry_set_progress_fraction (GtkEntr
 {
   GtkEntryPrivate *private;
   gdouble          old_fraction;
+  gint x, y, width, height;
+  gint old_x, old_y, old_width, old_height;
 
   g_return_if_fail (GTK_IS_ENTRY (entry));
 
@@ -9444,14 +9558,18 @@ gtk_entry_set_progress_fraction (GtkEntr
   else
     old_fraction = private->progress_fraction;
 
+  get_progress_area (GTK_WIDGET(entry), &old_x, &old_y, &old_width, &old_height);
+
   fraction = CLAMP (fraction, 0.0, 1.0);
 
   private->progress_fraction = fraction;
   private->progress_pulse_mode = FALSE;
   private->progress_pulse_current = 0.0;
 
-  if (fabs (fraction - old_fraction) > 0.0001)
-    gtk_entry_queue_draw (entry);
+  get_progress_area (GTK_WIDGET(entry), &x, &y, &width, &height);
+
+  if ((x != old_x) || (y != old_y) || (width != old_width) || (height != old_height))
+    gtk_widget_queue_draw (GTK_WIDGET (entry));
 
   if (fraction != old_fraction)
     g_object_notify (G_OBJECT (entry), "progress-fraction");
@@ -9506,7 +9624,7 @@ gtk_entry_set_progress_pulse_step (GtkEn
     {
       private->progress_pulse_fraction = fraction;
 
-      gtk_entry_queue_draw (entry);
+      gtk_widget_queue_draw (GTK_WIDGET (entry));
 
       g_object_notify (G_OBJECT (entry), "progress-pulse-step");
     }
@@ -9587,7 +9705,7 @@ gtk_entry_progress_pulse (GtkEntry *entr
       private->progress_pulse_current = 0.0;
     }
 
-  gtk_entry_queue_draw (entry);
+  gtk_widget_queue_draw (GTK_WIDGET (entry));
 }
 
 /* Caps Lock warning for password entries */
