diff --git a/gtk/gtkpaned.c b/gtk/gtkpaned.c
index 64b0429..682599c 100644
--- a/gtk/gtkpaned.c
+++ b/gtk/gtkpaned.c
@@ -42,6 +42,8 @@ enum {
   PROP_ORIENTATION,
   PROP_POSITION,
   PROP_POSITION_SET,
+  PROP_RATIO,
+  PROP_RATIO_SET,
   PROP_MIN_POSITION,
   PROP_MAX_POSITION
 };
@@ -150,6 +152,8 @@ struct _GtkPanedPrivate
   GtkWidget      *saved_focus;
   GtkPaned       *first_paned;
   guint32         grab_time;
+  gdouble         ratio;
+  gboolean        ratio_set;
 };
 
 
@@ -330,6 +334,41 @@ gtk_paned_class_init (GtkPanedClass *class)
 								    GTK_PARAM_READWRITE));
 
   /**
+   * GtkPaned:ratio:
+   *
+   * The "ratio" property determines the relative position of the divider
+   * based on the actual size of the widget. Allowed values are percentages
+   * from 0.0 to 1.0.
+   *
+   * Since: 2.18
+   */
+    g_object_class_install_property (object_class,
+                                     PROP_RATIO,
+                                     g_param_spec_double ("ratio",
+                                     P_("Ratio"),
+                                     P_("Ratio of panel separator in percent (0.0 to 1.0)"),
+                                     0,
+                                     1.0,
+                                     0,
+                                     GTK_PARAM_READWRITE));
+
+  /**
+  * GtkPaned:ratio-set:
+   *
+   * TRUE if the divider position should be computed relative to the allocated
+   * size of the widget, based on the value of "ratio".
+   *
+   * Since: 2.18
+   */
+    g_object_class_install_property (object_class,
+                                     PROP_RATIO_SET,
+                                     g_param_spec_boolean ("ratio-set",
+                                     P_("Ratio Set"),
+                                     P_("TRUE if the Ratio property should be used"),
+                                     FALSE,
+                                     GTK_PARAM_READWRITE));
+
+  /**
    * GtkPaned::cycle-child-focus:
    * @widget: the object that received the signal
    * @reversed: whether cycling backward or forward
@@ -569,6 +608,8 @@ gtk_paned_init (GtkPaned *paned)
   paned->priv = G_TYPE_INSTANCE_GET_PRIVATE (paned, GTK_TYPE_PANED, GtkPanedPrivate);
 
   paned->priv->orientation = GTK_ORIENTATION_HORIZONTAL;
+  paned->priv->ratio = 0.0;
+  paned->priv->ratio_set = FALSE;
   paned->cursor_type = GDK_SB_H_DOUBLE_ARROW;
 
   paned->child1 = NULL;
@@ -625,6 +666,13 @@ gtk_paned_set_property (GObject        *object,
       paned->position_set = g_value_get_boolean (value);
       gtk_widget_queue_resize_no_redraw (GTK_WIDGET (paned));
       break;
+    case PROP_RATIO:
+      gtk_paned_set_ratio (paned, g_value_get_double (value));
+      break;
+    case PROP_RATIO_SET:
+      paned->priv->ratio_set = g_value_get_boolean (value);
+      gtk_widget_queue_resize (GTK_WIDGET (paned));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -650,6 +698,12 @@ gtk_paned_get_property (GObject        *object,
     case PROP_POSITION_SET:
       g_value_set_boolean (value, paned->position_set);
       break;
+    case PROP_RATIO:
+      g_value_set_double (value, paned->priv->ratio);
+      break;
+    case PROP_RATIO_SET:
+      g_value_set_boolean (value, paned->priv->ratio_set);
+      break;
     case PROP_MIN_POSITION:
       g_value_set_int (value, paned->min_position);
       break;
@@ -1243,10 +1297,17 @@ gtk_paned_grab_broken (GtkWidget          *widget,
 		       GdkEventGrabBroken *event)
 {
   GtkPaned *paned = GTK_PANED (widget);
+  GObject *object = G_OBJECT (object);
 
   paned->in_drag = FALSE;
   paned->drag_pos = -1;
   paned->position_set = TRUE;
+  paned->priv->ratio_set = FALSE;
+
+  g_object_freeze_notify (object);
+  g_object_notify (object, "position-set");
+  g_object_notify (object, "ratio-set");
+  g_object_thaw_notify (object);
 
   return TRUE;
 }
@@ -1254,9 +1315,18 @@ gtk_paned_grab_broken (GtkWidget          *widget,
 static void
 stop_drag (GtkPaned *paned)
 {
+  GObject *object = G_OBJECT (object);
+
   paned->in_drag = FALSE;
   paned->drag_pos = -1;
   paned->position_set = TRUE;
+  paned->priv->ratio_set = FALSE;
+
+  g_object_freeze_notify (object);
+  g_object_notify (object, "position-set");
+  g_object_notify (object, "ratio-set");
+  g_object_thaw_notify (object);
+
   gdk_display_pointer_ungrab (gtk_widget_get_display (GTK_WIDGET (paned)),
 			      paned->priv->grab_time);
 }
@@ -1479,6 +1549,31 @@ gtk_paned_get_position (GtkPaned  *paned)
   return paned->child1_size;
 }
 
+void
+_gtk_paned_update_divider (GtkPaned *paned)
+{
+  GObject *object;
+
+  object = G_OBJECT (paned);
+
+  g_object_freeze_notify (object);
+  g_object_notify (object, "position");
+  g_object_notify (object, "position-set");
+  g_object_notify (object, "ratio");
+  g_object_notify (object, "ratio-set");
+  g_object_thaw_notify (object);
+
+  gtk_widget_queue_resize (GTK_WIDGET (paned));
+
+#ifdef G_OS_WIN32
+  /* Hacky work-around for bug #144269 */
+  if (paned->child2 != NULL)
+    {
+      gtk_widget_queue_draw (paned->child2);
+    }
+#endif
+}
+
 /**
  * gtk_paned_set_position:
  * @paned: a #GtkPaned widget
@@ -1486,17 +1581,18 @@ gtk_paned_get_position (GtkPaned  *paned)
  *            is unset.
  * 
  * Sets the position of the divider between the two panes.
+ *
+ * Note that the position cannot exceed the available space, so if @panel
+ * is too small, the resulting position differs from the value set.
  **/
 void
 gtk_paned_set_position (GtkPaned *paned,
 			gint      position)
 {
   GObject *object;
-  
+
   g_return_if_fail (GTK_IS_PANED (paned));
 
-  object = G_OBJECT (paned);
-  
   if (position >= 0)
     {
       /* We don't clamp here - the assumption is that
@@ -1514,20 +1610,57 @@ gtk_paned_set_position (GtkPaned *paned,
       paned->position_set = FALSE;
     }
 
-  g_object_freeze_notify (object);
-  g_object_notify (object, "position");
-  g_object_notify (object, "position-set");
-  g_object_thaw_notify (object);
+  paned->priv->ratio_set = FALSE;
+  _gtk_paned_update_divider (paned);
+}
 
-  gtk_widget_queue_resize_no_redraw (GTK_WIDGET (paned));
+/**
+ * gtk_paned_get_ratio:
+ * @paned: a #GtkPaned widget
+ *
+ * Obtains the ratio that determines the relative position of the divider
+ * between the two panes.
+ *
+ * Since: 2.18
+ *
+ * Return value: ratio in percent
+ **/
+gdouble
+gtk_paned_get_ratio (GtkPaned *paned)
+{
+  g_return_val_if_fail (GTK_IS_PANED (paned), 0.0);
 
-#ifdef G_OS_WIN32
-  /* Hacky work-around for bug #144269 */
-  if (paned->child2 != NULL)
-    {
-      gtk_widget_queue_draw (paned->child2);
-    }
-#endif
+  return paned->priv->ratio;
+}
+
+/**
+ * gtk_paned_set_ratio:
+ * @paned: a #GtkPaned widget
+ * @ratio: relative position of the divider
+ *
+ * Sets the relative position of the divider between the two panes, i.e. the
+ * relative size of the first child. Whenever the size of @paned changes, the
+ * divider is repositioned and the value of "position" is updated accordingly.
+ *
+ * The value should be between 0.0 and 1.0, inclusive.
+ *
+ * Note that any manual adjustment of "position" through code or user
+ * interaction will override the effects of "ratio".
+ *
+ * Since: 2.18
+ **/
+void
+gtk_paned_set_ratio (GtkPaned *paned,
+                     gdouble   ratio)
+{
+  g_return_if_fail (GTK_IS_PANED (paned));
+  g_return_if_fail (ratio >= 0.0 && ratio <= 1.0);
+
+  paned->position_set = FALSE;
+  paned->priv->ratio_set = TRUE;
+  paned->priv->ratio = ratio;
+
+  _gtk_paned_update_divider (paned);
 }
 
 /**
@@ -1587,6 +1720,10 @@ gtk_paned_calc_position (GtkPaned *paned,
   gint old_min_position;
   gint old_max_position;
 
+  if (paned->priv->ratio_set)
+      paned->child1_size = GTK_WIDGET (paned)->allocation.width
+                           * paned->priv->ratio;
+
   old_position = paned->child1_size;
   old_min_position = paned->min_position;
   old_max_position = paned->max_position;
@@ -1598,7 +1735,7 @@ gtk_paned_calc_position (GtkPaned *paned,
     paned->max_position = MAX (1, paned->max_position - child2_req);
   paned->max_position = MAX (paned->min_position, paned->max_position);
 
-  if (!paned->position_set)
+  if (!paned->position_set && !paned->priv->ratio_set)
     {
       if (paned->child1_resize && !paned->child2_resize)
 	paned->child1_size = MAX (0, allocation - child2_req);
diff --git a/gtk/gtkpaned.h b/gtk/gtkpaned.h
index 178d6cf..759acf6 100644
--- a/gtk/gtkpaned.h
+++ b/gtk/gtkpaned.h
@@ -124,6 +124,10 @@ gint        gtk_paned_get_position (GtkPaned       *paned);
 void        gtk_paned_set_position (GtkPaned       *paned,
                                     gint            position);
 
+gdouble     gtk_paned_get_ratio    (GtkPaned       *paned);
+void        gtk_paned_set_ratio    (GtkPaned       *paned,
+                                    gdouble         ratio);
+
 GtkWidget * gtk_paned_get_child1   (GtkPaned       *paned);
 GtkWidget * gtk_paned_get_child2   (GtkPaned       *paned);
 
