diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c
index 28e5e57..c744f5d 100644
--- a/gtk/gtkrange.c
+++ b/gtk/gtkrange.c
@@ -37,6 +37,7 @@
 #include "gtkrange.h"
 #include "gtkscale.h"
 #include "gtkscrollbar.h"
+#include "gtkwindow.h"
 #include "gtkprivate.h"
 #include "gtkintl.h"
 
@@ -1572,12 +1573,123 @@ gtk_range_size_request (GtkWidget      *widget,
   requisition->height = range_rect.height + border.top + border.bottom;
 }
 
+static GtkWidget *
+find_toplevel_window (GtkWidget *widget)
+{
+  if (GTK_IS_WINDOW (widget))
+    {
+      return widget;
+    }
+  else if (gtk_widget_get_parent (widget))
+    {
+      return find_toplevel_window (gtk_widget_get_parent (widget));
+    }
+  else
+    {
+      return NULL;
+    }
+}
+
+static gint
+get_fixup_for_window_grip (GtkWidget *widget)
+{
+  GtkWidget *window;
+  GtkRange *range = GTK_RANGE (widget);
+
+  window = find_toplevel_window (widget);
+  if (window == NULL)
+    {
+      return 0;
+    }
+
+  if (!gtk_window_resize_grip_is_visible (GTK_WINDOW (window)))
+    {
+      return 0;
+    }
+
+  if (gtk_window_get_has_resize_grip (GTK_WINDOW (window)))
+    {
+      GtkRangePrivate *priv;
+      GdkRectangle grip_rect;
+      GdkRectangle orig_rect;
+      GdkRectangle translated_rect;
+      gint x = 0;
+      gint y = 0;
+
+      priv = range->priv;
+
+      gtk_range_calc_layout (range, priv->adjustment->value);
+
+      /* Get the area of the window's corner grip */
+      gtk_window_get_corner_grip_area (GTK_WINDOW (window),
+                                       &grip_rect);
+
+      /* Get the area of the stepper that might be blocked by the grip */
+      if (gtk_widget_get_direction (window) == GTK_TEXT_DIR_LTR)
+        {
+          orig_rect = priv->stepper_d;
+        }
+      else
+        {
+          orig_rect = priv->stepper_a;
+        }
+
+      /* Translate the stepper's area into window coords */
+      if (gtk_widget_translate_coordinates (widget,
+                                            window,
+                                            orig_rect.x,
+                                            orig_rect.y,
+                                            &x,
+                                            &y))
+        {
+          translated_rect.x = x;
+          translated_rect.y = y;
+          translated_rect.width = orig_rect.width;
+          translated_rect.height = orig_rect.height;
+
+          /* If the stepper button intersects the window resize grip.. */
+          if (gdk_rectangle_intersect (&grip_rect, &translated_rect, NULL))
+            {
+              gint grip_height;
+              gint grip_width;
+
+              /* Return the height of the grip */
+              gtk_widget_style_get (window,
+                                    "resize-grip-height", &grip_height,
+                                    "resize-grip-width",  &grip_width,
+                                    NULL);
+
+              if (gtk_orientable_get_orientation (GTK_ORIENTABLE (range)) == GTK_ORIENTATION_HORIZONTAL)
+                return grip_width;
+              else
+                return grip_height;
+            }
+        }
+    }
+
+  return 0;
+}
+
 static void
 gtk_range_size_allocate (GtkWidget     *widget,
                          GtkAllocation *allocation)
 {
   GtkRange *range = GTK_RANGE (widget);
   GtkRangePrivate *priv = range->priv;
+  gint fixup;
+
+  gtk_widget_set_allocation (widget, allocation);
+
+  fixup = get_fixup_for_window_grip (widget);
+
+  if (gtk_orientable_get_orientation (GTK_ORIENTABLE (range)) == GTK_ORIENTATION_VERTICAL)
+    {
+      allocation->height -= fixup;
+    }
+  else
+    {
+      allocation->width -= fixup;
+    }
 
   gtk_widget_set_allocation (widget, allocation);
 
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 756266e..5cdd592 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -105,6 +105,9 @@ struct _GtkWindowPrivate
 
   gdouble  opacity;
 
+  gboolean   has_resize_grip;
+  GdkWindow *grip_window;
+
   gchar   *startup_id;
   gchar   *title;
   gchar   *wmclass_class;
@@ -201,7 +204,8 @@ enum {
   PROP_GRAVITY,
   PROP_TRANSIENT_FOR,
   PROP_OPACITY,
-  
+  PROP_HAS_RESIZE_GRIP,
+
   /* Readonly properties */
   PROP_IS_ACTIVE,
   PROP_HAS_TOPLEVEL_FOCUS,
@@ -309,6 +313,8 @@ static gint gtk_window_key_press_event    (GtkWidget         *widget,
 					   GdkEventKey       *event);
 static gint gtk_window_key_release_event  (GtkWidget         *widget,
 					   GdkEventKey       *event);
+static gint gtk_window_button_press_event (GtkWidget         *widget,
+                                           GdkEventButton    *event);
 static gint gtk_window_enter_notify_event (GtkWidget         *widget,
 					   GdkEventCrossing  *event);
 static gint gtk_window_leave_notify_event (GtkWidget         *widget,
@@ -383,6 +389,7 @@ static GList   *icon_list_from_theme                  (GtkWidget    *widget,
 						       const gchar  *name);
 static void     gtk_window_realize_icon               (GtkWindow    *window);
 static void     gtk_window_unrealize_icon             (GtkWindow    *window);
+static void     resize_grip_create_window             (GtkWindow    *window);
 
 static void        gtk_window_notify_keys_changed (GtkWindow   *window);
 static GtkKeyHash *gtk_window_get_key_hash        (GtkWindow   *window);
@@ -390,6 +397,9 @@ static void        gtk_window_free_key_hash       (GtkWindow   *window);
 static void	   gtk_window_on_composited_changed (GdkScreen *screen,
 						     GtkWindow *window);
 
+static gboolean    gtk_window_state_event           (GtkWidget           *widget,
+                                                     GdkEventWindowState *event);
+
 static GSList      *toplevel_list = NULL;
 static guint        window_signals[LAST_SIGNAL] = { 0 };
 static GList       *default_icon_list = NULL;
@@ -554,10 +564,12 @@ gtk_window_class_init (GtkWindowClass *klass)
   widget_class->enter_notify_event = gtk_window_enter_notify_event;
   widget_class->leave_notify_event = gtk_window_leave_notify_event;
   widget_class->focus_in_event = gtk_window_focus_in_event;
+  widget_class->button_press_event = gtk_window_button_press_event;
   widget_class->focus_out_event = gtk_window_focus_out_event;
   widget_class->client_event = gtk_window_client_event;
   widget_class->focus = gtk_window_focus;
   widget_class->expose_event = gtk_window_expose;
+  widget_class->window_state_event = gtk_window_state_event;
 
   container_class->check_resize = gtk_window_check_resize;
 
@@ -597,6 +609,7 @@ gtk_window_class_init (GtkWindowClass *klass)
 							NULL,
 							GTK_PARAM_READWRITE));
 
+
   /**
    * GtkWindow:startup-id:
    *
@@ -815,6 +828,21 @@ gtk_window_class_init (GtkWindowClass *klass)
 							 TRUE,
 							 GTK_PARAM_READWRITE));
 
+  /**
+   * GtkWindow:has-resize-grip
+   *
+   * Whether the window should have a corner resize grip.
+   *
+   * Since: 2.20
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_HAS_RESIZE_GRIP,
+                                   g_param_spec_boolean ("has-resize-grip",
+                                                         P_("Resize grip"),
+                                                         P_("Specifies whether the window should have a resize grip"),
+                                                         TRUE,
+                                                         GTK_PARAM_READWRITE));
+
 
   /**
    * GtkWindow:gravity:
@@ -868,6 +896,23 @@ gtk_window_class_init (GtkWindowClass *klass)
 							1.0,
 							GTK_PARAM_READWRITE));
 
+  /* Style properties.
+   */
+  gtk_widget_class_install_style_property (widget_class,
+                                           g_param_spec_int ("resize-grip-width",
+                                                             P_("Width of resize grip"),
+                                                             P_("Width of resize grip"),
+                                                             0, G_MAXINT, 16, GTK_PARAM_READWRITE));
+
+  gtk_widget_class_install_style_property (widget_class,
+                                           g_param_spec_int ("resize-grip-height",
+                                                             P_("Height of resize grip"),
+                                                             P_("Height of resize grip"),
+                                                             0, G_MAXINT, 16, GTK_PARAM_READWRITE));
+
+
+  /* Signals
+   */
   window_signals[SET_FOCUS] =
     g_signal_new (I_("set-focus"),
                   G_TYPE_FROM_CLASS (gobject_class),
@@ -1023,6 +1068,7 @@ gtk_window_init (GtkWindow *window)
   priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
   priv->opacity = 1.0;
   priv->startup_id = NULL;
+  priv->has_resize_grip = TRUE;
   priv->mnemonics_visible = TRUE;
 
   colormap = _gtk_widget_peek_colormap ();
@@ -1039,6 +1085,8 @@ gtk_window_init (GtkWindow *window)
 		    G_CALLBACK (gtk_window_on_composited_changed), window);
 }
 
+
+
 static void
 gtk_window_set_property (GObject      *object,
 			 guint         prop_id,
@@ -1047,7 +1095,7 @@ gtk_window_set_property (GObject      *object,
 {
   GtkWindow  *window = GTK_WINDOW (object);
   GtkWindowPrivate *priv = window->priv;
-  
+
   switch (prop_id)
     {
     case PROP_TYPE:
@@ -1061,7 +1109,7 @@ gtk_window_set_property (GObject      *object,
       break;
     case PROP_STARTUP_ID:
       gtk_window_set_startup_id (window, g_value_get_string (value));
-      break; 
+      break;
     case PROP_RESIZABLE:
       priv->resizable = g_value_get_boolean (value);
       gtk_widget_queue_resize (GTK_WIDGET (window));
@@ -1134,6 +1182,8 @@ gtk_window_set_property (GObject      *object,
     case PROP_OPACITY:
       gtk_window_set_opacity (window, g_value_get_double (value));
       break;
+    case PROP_HAS_RESIZE_GRIP:
+      gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
     case PROP_MNEMONICS_VISIBLE:
       gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
       break;
@@ -1243,6 +1293,8 @@ gtk_window_get_property (GObject      *object,
     case PROP_OPACITY:
       g_value_set_double (value, gtk_window_get_opacity (window));
       break;
+    case PROP_HAS_RESIZE_GRIP:
+      g_value_set_boolean (value, priv->has_resize_grip);
     case PROP_MNEMONICS_VISIBLE:
       g_value_set_boolean (value, priv->mnemonics_visible);
       break;
@@ -4715,6 +4767,9 @@ gtk_window_map (GtkWidget *widget)
   if (priv->frame)
     gdk_window_show (priv->frame);
 
+  if (priv->grip_window)
+    gdk_window_show (priv->grip_window);
+
   if (!disable_startup_notification)
     {
       /* Do we have a custom startup-notification id? */
@@ -4766,7 +4821,7 @@ gtk_window_unmap (GtkWidget *widget)
 {
   GtkWindow *window = GTK_WINDOW (widget);
   GtkWindowPrivate *priv = window->priv;
-  GtkWindowGeometryInfo *info;    
+  GtkWindowGeometryInfo *info;
   GdkWindow *gdk_window;
   GdkWindowState state;
 
@@ -4778,6 +4833,9 @@ gtk_window_unmap (GtkWidget *widget)
   else
     gdk_window_withdraw (gdk_window);
 
+  if (priv->grip_window)
+    gdk_window_hide (priv->grip_window);
+
   priv->configure_request_count = 0;
   priv->configure_notify_received = FALSE;
 
@@ -4943,6 +5001,9 @@ gtk_window_realize (GtkWidget *widget)
   if (priv->frame)
     gtk_style_set_background (style, priv->frame, GTK_STATE_NORMAL);
 
+  if (priv->has_resize_grip)
+    resize_grip_create_window (window);
+
   /* This is a bad hack to set the window background. */
   gtk_window_paint (widget, NULL);
   
@@ -5068,6 +5129,17 @@ gtk_window_size_allocate (GtkWidget     *widget,
 			 allocation->width + priv->frame_left + priv->frame_right,
 			 allocation->height + priv->frame_top + priv->frame_bottom);
     }
+
+  if (priv->grip_window != NULL)
+    {
+      GdkRectangle rect;
+
+      gtk_window_get_corner_grip_area (window, &rect);
+
+      gdk_window_move_resize (priv->grip_window,
+                              rect.x, rect.y,
+                              rect.width, rect.height);
+    }
 }
 
 static gint
@@ -5188,11 +5260,248 @@ gtk_window_configure_event (GtkWidget         *widget,
   allocation.height = event->height;
   gtk_widget_set_allocation (widget, &allocation);
 
+  gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
+
   _gtk_container_queue_resize (GTK_CONTAINER (widget));
   
   return TRUE;
 }
 
+static gboolean
+gtk_window_state_event (GtkWidget           *widget,
+                        GdkEventWindowState *event)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
+
+  if (priv->grip_window != NULL &&
+      ((event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) ||
+       (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN)))
+    {
+      if (event->new_window_state == GDK_WINDOW_STATE_MAXIMIZED ||
+          event->new_window_state == GDK_WINDOW_STATE_FULLSCREEN)
+        {
+          gdk_window_hide (priv->grip_window);
+        }
+      else
+        {
+          gdk_window_show (priv->grip_window);
+        }
+    }
+
+  return FALSE;
+}
+
+static void
+set_grip_cursor (GtkWindow *window)
+{
+  GtkWindowPrivate *priv = window->priv;
+
+  if (priv->has_resize_grip && priv->grip_window != NULL)
+    {
+      GtkWidget *widget = GTK_WIDGET (window);
+      GdkDisplay *display = gtk_widget_get_display (widget);
+      GdkCursorType cursor_type;
+      GdkCursor *cursor;
+
+      if (gtk_widget_is_sensitive (widget))
+        {
+          if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
+            cursor_type = GDK_BOTTOM_RIGHT_CORNER;
+          else
+            cursor_type = GDK_BOTTOM_LEFT_CORNER;
+
+          cursor = gdk_cursor_new_for_display (display, cursor_type);
+          gdk_window_set_cursor (priv->grip_window, cursor);
+          gdk_cursor_unref (cursor);
+        }
+      else
+        gdk_window_set_cursor (priv->grip_window, NULL);
+    }
+}
+
+static void
+resize_grip_create_window (GtkWindow *window)
+{
+  GtkWidget *widget;
+  GtkWindowPrivate *priv;
+  GdkWindowAttr attributes;
+  gint attributes_mask;
+  GdkRectangle rect;
+
+  priv = window->priv;
+  widget = GTK_WIDGET (window);
+
+  g_return_if_fail (gtk_widget_get_realized (widget));
+  g_return_if_fail (priv->grip_window == NULL);
+
+  gtk_window_get_corner_grip_area (window, &rect);
+
+  attributes.x = rect.x;
+  attributes.y = rect.y;
+  attributes.width = rect.width;
+  attributes.height = rect.height;
+  attributes.window_type = GDK_WINDOW_CHILD;
+  attributes.wclass = GDK_INPUT_ONLY;
+  attributes.event_mask = gtk_widget_get_events (widget) | GDK_BUTTON_PRESS_MASK;
+
+  attributes_mask = GDK_WA_X | GDK_WA_Y;
+
+  priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
+                                      &attributes,
+                                      attributes_mask);
+
+  gdk_window_set_user_data (priv->grip_window, widget);
+
+  gdk_window_raise (priv->grip_window);
+
+  set_grip_cursor (window);
+}
+
+static void
+resize_grip_destroy_window (GtkWindow *window)
+{
+  GtkWindowPrivate *priv = window->priv;
+
+  gdk_window_set_user_data (priv->grip_window, NULL);
+  gdk_window_destroy (priv->grip_window);
+  priv->grip_window = NULL;
+}
+
+/**
+ * gtk_window_set_has_resize_grip:
+ * @window: a #GtkWindow
+ * @setting: %TRUE to enable a corner resize grip
+ *
+ * Sets whether the window will have a corner resize grip.
+ * This is %TRUE by default.
+ *
+ * Since: 3.0
+ */
+void
+gtk_window_set_has_resize_grip (GtkWindow *window,
+                                gboolean   value)
+{
+  GtkWidget *widget;
+  GtkWindowPrivate *priv;
+
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  widget = GTK_WIDGET (window);
+  priv = window->priv;
+
+  value = value != FALSE;
+
+  if (value != priv->has_resize_grip)
+    {
+      priv->has_resize_grip = value;
+
+      if (gtk_widget_get_realized (widget))
+        {
+          if (priv->has_resize_grip && priv->grip_window == NULL)
+            {
+              resize_grip_create_window (window);
+
+              if (gtk_widget_get_mapped (widget))
+                {
+                  gdk_window_show (priv->grip_window);
+                }
+            }
+          else if (!priv->has_resize_grip && priv->grip_window != NULL)
+            {
+              resize_grip_destroy_window (window);
+            }
+        }
+
+      gtk_widget_queue_draw (widget);
+
+      g_object_notify (G_OBJECT (priv), "has-resize-grip");
+    }
+}
+
+/**
+ * gtk_window_get_has_resize_grip:
+ * @window: a #GtkWindow
+ *
+ * Returns whether the window has a corner resize grip.
+ *
+ * Returns: %TRUE if the window has a corner resize grip.
+ *
+ * Since: 3.0
+ */
+gboolean
+gtk_window_get_has_resize_grip (GtkWindow *window)
+{
+  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+  return window->priv->has_resize_grip;
+}
+
+/**
+ * gtk_window_resize_grip_is_visible:
+ * @window: a #GtkWindow
+ *
+ * Determines whether a resize grip is visible for the
+ * specified window.
+ *
+ * Returns: %TRUE if a resize grip exists and is visible.
+ *
+ * Since: 3.0
+ */
+gboolean
+gtk_window_resize_grip_is_visible (GtkWindow *window)
+{
+  GdkWindowState state;
+
+  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+  if (!gtk_widget_get_realized (GTK_WIDGET (window)))
+    return FALSE;
+
+  state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)));
+
+  if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
+    {
+      return FALSE;
+    }
+
+  return window->priv->has_resize_grip;
+}
+
+
+void
+gtk_window_get_corner_grip_area (GtkWindow *window,
+                                 GdkRectangle *rect)
+{
+  GtkWidget *widget = GTK_WIDGET (window);
+  GtkAllocation allocation;
+  GtkStyle *style;
+  gint grip_width;
+  gint grip_height;
+
+  gtk_widget_get_allocation (widget, &allocation);
+  style = gtk_widget_get_style (widget);
+
+  gtk_widget_style_get (widget,
+                        "resize-grip-width", &grip_width,
+                        "resize-grip-height", &grip_height,
+                        NULL);
+
+  if (grip_width > allocation.width)
+    grip_width = allocation.width;
+
+  if (grip_height > allocation.height)
+    grip_height = allocation.height;
+
+  rect->width = grip_width;
+  rect->height = grip_height;
+  rect->y = allocation.y + allocation.height - grip_height;
+
+  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
+    rect->x = allocation.x + allocation.width - grip_width;
+  else
+    rect->x = allocation.x + style->xthickness;
+}
+
 /* the accel_key and accel_mods fields of the key have to be setup
  * upon calling this function. it'll then return whether that key
  * is at all used as accelerator, and if so will OR in the
@@ -5331,6 +5640,25 @@ gtk_window_key_release_event (GtkWidget   *widget,
   return handled;
 }
 
+static gint
+gtk_window_button_press_event (GtkWidget *widget,
+                               GdkEventButton *event)
+{
+  GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
+
+  if (event->window == priv->grip_window)
+    {
+      gtk_window_begin_resize_drag (GTK_WINDOW (widget),
+                                    GDK_WINDOW_EDGE_SOUTH_EAST,
+                                    event->button,
+                                    event->x_root,
+                                    event->y_root,
+                                    event->time);
+    }
+
+  return FALSE;
+}
+
 static void
 gtk_window_real_activate_default (GtkWindow *window)
 {
@@ -6834,18 +7162,51 @@ gtk_window_compute_hints (GtkWindow   *window,
   new_geometry->win_gravity = priv->gravity;
 }
 
+static GdkWindowEdge
+get_grip_edge (GtkWidget *widget)
+{
+  return gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
+}
+
 /***********************
  * Redrawing functions *
  ***********************/
 
 static void
-gtk_window_paint (GtkWidget     *widget,
+gtk_window_paint (GtkWidget    *widget,
 		  GdkRectangle *area)
 {
+  GtkWindow *window = GTK_WINDOW (widget);
+  GtkWindowPrivate *priv = window->priv;
+
   gtk_paint_flat_box (gtk_widget_get_style (widget),
                       gtk_widget_get_window (widget),
                       GTK_STATE_NORMAL,
 		      GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1);
+
+  if (gtk_window_resize_grip_is_visible (window))
+    {
+      GdkWindowEdge edge;
+      GdkRectangle rect;
+      GtkAllocation allocation;
+
+      gtk_widget_get_allocation (widget, &allocation);
+
+      edge = get_grip_edge (widget);
+
+      gtk_window_get_corner_grip_area (window, &rect);
+
+      gtk_paint_resize_grip (gtk_widget_get_style (widget),
+                             gtk_widget_get_window (widget),
+                             gtk_widget_get_state (widget),
+                             area,
+                             widget,
+                             "statusbar",
+                             edge,
+                             rect.x, rect.y,
+                             rect.width,
+                             rect.height);
+    }
 }
 
 static gint
diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h
index 805c9a6..9ca5677 100644
--- a/gtk/gtkwindow.h
+++ b/gtk/gtkwindow.h
@@ -337,6 +337,14 @@ GList *          gtk_window_group_list_windows  (GtkWindowGroup     *window_grou
 GtkWidget *      gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group,
                                                            GdkDevice      *device);
 
+/* Window grips
+ */
+void     gtk_window_set_has_resize_grip    (GtkWindow    *window,
+                                            gboolean      value);
+gboolean gtk_window_get_has_resize_grip    (GtkWindow    *window);
+gboolean gtk_window_resize_grip_is_visible (GtkWindow    *window);
+void     gtk_window_get_corner_grip_area   (GtkWindow    *window,
+                                            GdkRectangle *rect);
 
 /* --- internal functions --- */
 void            _gtk_window_internal_set_focus (GtkWindow *window,
