diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 756266e..730e04f 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,11 @@ 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     get_grip_rect                         (GtkWindow    *window,
+                                                       GdkRectangle *rect);
+static void     gtk_window_set_has_resize_grip        (GtkWindow    *window,
+                                                       gboolean      value);
+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);
@@ -554,6 +565,7 @@ 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;
@@ -815,6 +827,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:
@@ -1023,6 +1050,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 ();
@@ -1047,7 +1075,7 @@ gtk_window_set_property (GObject      *object,
 {
   GtkWindow  *window = GTK_WINDOW (object);
   GtkWindowPrivate *priv = window->priv;
-  
+
   switch (prop_id)
     {
     case PROP_TYPE:
@@ -1061,7 +1089,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 +1162,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 +1273,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 +4747,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 +4801,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 +4813,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 +4981,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 +5109,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;
+
+      get_grip_rect (window, &rect);
+
+      gdk_window_move_resize (priv->grip_window,
+                              rect.x, rect.y,
+                              rect.width, rect.height);
+    }
 }
 
 static gint
@@ -5188,11 +5240,158 @@ 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 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
+get_grip_rect (GtkWindow    *window,
+                               GdkRectangle *rect)
+{
+  GtkWidget *widget;
+  GtkAllocation allocation;
+  GtkStyle *style;
+  gint w, h;
+
+  widget = GTK_WIDGET (window);
+  gtk_widget_get_allocation (widget, &allocation);
+  style = gtk_widget_get_style (widget);
+
+  /* These are in effect the max/default size of the grip. */
+  w = 18;
+  h = 18;
+
+  if (w > allocation.width)
+    w = allocation.width;
+
+  if (h > allocation.height - style->ythickness)
+    h = allocation.height - style->ythickness;
+
+  rect->width = w;
+  rect->height = h;
+  rect->y = allocation.y + allocation.height - h;
+
+  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
+    rect->x = allocation.x + allocation.width - w;
+  else
+    rect->x = allocation.x + style->xthickness;
+}
+
+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);
+
+  get_grip_rect (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;
+}
+
+static void
+gtk_window_set_has_resize_grip (GtkWindow *window,
+                                gboolean   value)
+{
+  GtkWidget *widget = GTK_WIDGET (window);
+  GtkWindowPrivate *priv = window->priv;
+
+  value = value != FALSE;
+
+  if (value != priv->has_resize_grip)
+    {
+      priv->has_resize_grip = value;
+      //gtk_widget_queue_resize (statusbar->label);  // XXX
+      gtk_widget_queue_draw (widget);
+
+      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);
+            }
+        }
+
+      g_object_notify (G_OBJECT (priv), "has-resize-grip");
+    }
+}
+
 /* 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 +5530,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 +7052,54 @@ 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)
 {
+  GtkWindowPrivate *priv = GTK_WINDOW (widget)->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 (priv->has_resize_grip)
+    {
+      GdkWindowEdge edge;
+      GdkRectangle rect;
+      GtkAllocation allocation;
+
+      gtk_widget_get_allocation (widget, &allocation);
+
+      edge = get_grip_edge (widget);
+
+      get_grip_rect (GTK_WINDOW (widget), &rect);
+
+      rect.x = allocation.width - 18;
+      rect.y = allocation.height - 18;
+
+      gtk_paint_resize_grip (gtk_widget_get_style (widget),
+                             //priv->grip_window,
+                             gtk_widget_get_window (widget),
+                             gtk_widget_get_state (widget),
+                             area,
+                             widget,
+                             "statusbar",
+                             edge,
+                             rect.x, rect.y,
+                             rect.width,
+                             rect.height);
+    }
 }
 
 static gint
