diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index ebe87fe..54bea4b 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -377,6 +377,7 @@ gtk_private_h_sources =		\
 	gtkplugprivate.h	\
 	gtkprintoperation-private.h\
 	gtkprintutils.h		\
+	gtkrangeprivate.h       \
 	gtkrbtree.h		\
 	gtkrecentchooserdefault.h \
 	gtkrecentchooserprivate.h \
diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c
index 430764a..8fa6677 100644
--- a/gtk/gtkrange.c
+++ b/gtk/gtkrange.c
@@ -3972,3 +3972,32 @@ _gtk_range_get_stop_positions (GtkRange  *range,
 
   return range->layout->n_marks;
 }
+
+void
+_gtk_range_get_internal_geometry (GtkRange     *range,
+                                  GdkRectangle *trough,
+                                  GdkRectangle *slider,
+                                  GdkRectangle *stepper_a,
+                                  GdkRectangle *stepper_b,
+                                  GdkRectangle *stepper_c,
+                                  GdkRectangle *stepper_d)
+{
+  if (trough)
+    *trough = range->layout->trough;
+
+  if (slider)
+    *slider = range->layout->slider;
+
+  if (stepper_a)
+    *stepper_a = range->layout->stepper_a;
+
+  if (stepper_b)
+    *stepper_b = range->layout->stepper_b;
+
+  if (stepper_c)
+    *stepper_c = range->layout->stepper_c;
+
+  if (stepper_c)
+    *stepper_c = range->layout->stepper_d;
+}
+
diff --git a/gtk/gtkrangeprivate.h b/gtk/gtkrangeprivate.h
new file mode 100644
index 0000000..4c58b6a
--- /dev/null
+++ b/gtk/gtkrangeprivate.h
@@ -0,0 +1,13 @@
+#ifndef __GTK_RANGE_PRIVATE_H__
+#define __GTK_RANGE_PRIVATE_H__
+#include <gtk.h>
+
+void
+_gtk_range_get_internal_geometry (GtkRange     *range,
+                                  GdkRectangle *trough,
+                                  GdkRectangle *slider,
+                                  GdkRectangle *stepper_a,
+                                  GdkRectangle *stepper_b,
+                                  GdkRectangle *stepper_c,
+                                  GdkRectangle *stepper_d);
+#endif
diff --git a/gtk/gtkscrollbar.c b/gtk/gtkscrollbar.c
index 34ef5b6..939f81d 100644
--- a/gtk/gtkscrollbar.c
+++ b/gtk/gtkscrollbar.c
@@ -1,6 +1,7 @@
 /* GTK - The GIMP Toolkit
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
  * Copyright (C) 2001 Red Hat, Inc.
+ * Copyright (C) 2010 Alberto Ruiz <aruiz@gnome.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -30,18 +31,42 @@
 #include "gtkscrollbar.h"
 #include "gtkintl.h"
 #include "gtkprivate.h"
+#include "gtkrangeprivate.h"
+#include "gtkorientable.h"
 
-static void gtk_scrollbar_style_set (GtkWidget *widget,
-                                     GtkStyle  *previous);
+typedef struct _GtkScrollbarPrivate
+{
+  GList    *marks;
+  gboolean  grab_on_slider;
+} GtkScrollbarPrivate;
+
+#define GTK_SCROLLBAR_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_SCROLLBAR, GtkScrollbarPrivate))
 
+static void     gtk_scrollbar_style_set      (GtkWidget      *widget,
+                                              GtkStyle       *previous);
+static void     gtk_scrollbar_finalize       (GObject        *object);
+static gboolean gtk_scrollbar_expose         (GtkWidget      *widget,
+                                              GdkEventExpose *event);
+static gint     gtk_scrollbar_button_press   (GtkWidget      *widget,
+                                              GdkEventButton *event);
+static gint     gtk_scrollbar_button_release (GtkWidget      *widget,
+                                              GdkEventButton *event);
+       void     gtk_scrollbar_clear_marks    (GtkScrollbar   *scrollbar);
+ 
 G_DEFINE_TYPE (GtkScrollbar, gtk_scrollbar, GTK_TYPE_RANGE)
 
 static void
 gtk_scrollbar_class_init (GtkScrollbarClass *class)
 {
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+  GObjectClass   *gobject_class = G_OBJECT_CLASS (class);
 
+  widget_class->expose_event = gtk_scrollbar_expose;
   widget_class->style_set = gtk_scrollbar_style_set;
+  widget_class->button_press_event = gtk_scrollbar_button_press;
+  widget_class->button_release_event = gtk_scrollbar_button_release;
+  gobject_class->finalize = gtk_scrollbar_finalize;
+
 
   GTK_RANGE_CLASS (class)->stepper_detail = "Xscrollbar";
 
@@ -88,11 +113,186 @@ gtk_scrollbar_class_init (GtkScrollbarClass *class)
                                                                  P_("Display a second forward arrow button on the opposite end of the scrollbar"),
                                                                  FALSE,
                                                                  GTK_PARAM_READABLE));
+                                                                 
+                                                                 
+  g_type_class_add_private (gobject_class, sizeof (GtkScrollbarPrivate));
+}
+
+static void
+paint_slider (GtkWidget      *widget,
+              GdkRectangle   *area,
+              GdkRectangle   *slider,
+              GtkOrientation  orientation)
+{
+  GdkRectangle real_area, real_slider;
+  gint state, x, y;
+  gboolean touchscreen, hover, shadow_type;
+  GtkScrollbarPrivate *priv = GTK_SCROLLBAR_GET_PRIVATE (GTK_SCROLLBAR (widget));
+  
+  real_slider = *slider;
+  real_slider.x += widget->allocation.x;
+  real_slider.y += widget->allocation.y;
+  
+  if (!gdk_rectangle_intersect (&real_slider, area, &real_area))
+    return;
+
+  gtk_widget_get_pointer (widget, &x, &y);
+  hover = FALSE;
+
+  g_object_get (gtk_widget_get_settings (widget),
+                "gtk-touchscreen-mode", &touchscreen,
+                NULL);  
+  
+  if (x >= slider->x && x <= (slider->x + slider->width) &&
+      y >= slider->y && y <= (slider->y + slider->height))
+    hover = TRUE;
+  
+  if (!gtk_widget_is_sensitive (widget))
+    state = GTK_STATE_INSENSITIVE;
+  else if (!touchscreen && (hover || priv->grab_on_slider))
+    state = GTK_STATE_PRELIGHT;
+  else
+    state = GTK_STATE_NORMAL;
+
+  shadow_type = GTK_SHADOW_OUT;
+
+  if (priv->grab_on_slider)
+  {
+    gboolean activate_slider;
+
+    gtk_widget_style_get (widget, "activate-slider", &activate_slider, NULL);
+
+    if (activate_slider)
+    {
+      state = GTK_STATE_ACTIVE;
+      shadow_type = GTK_SHADOW_IN;
+    }
+  }
+    
+  gtk_paint_slider (widget->style,
+                    widget->window,
+                    state,
+                    shadow_type,
+                    &real_area,
+                    widget,
+                    "slider",
+                    real_slider.x,
+                    real_slider.y,
+                    real_slider.width,
+                    real_slider.height,
+                    orientation);                      
+}
+
+static gboolean
+gtk_scrollbar_expose (GtkWidget *widget, GdkEventExpose *event)
+{
+  GList *marks, *next;
+  GtkScrollbar  *scrollbar;
+  GdkRectangle   slider, trough, mark_rect;
+  gint           orientation, state;
+  gchar         *detail;
+
+  scrollbar = (GtkScrollbar*)widget;
+  marks = GTK_SCROLLBAR_GET_PRIVATE (scrollbar)->marks;
+  orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget));
+  
+  GTK_WIDGET_CLASS (gtk_scrollbar_parent_class)->expose_event (widget, event);
+
+  _gtk_range_get_internal_geometry (GTK_RANGE(widget), &trough, &slider,
+                                    NULL, NULL, NULL, NULL);
+
+  if (!gtk_widget_is_sensitive (widget))
+    state = GTK_STATE_INSENSITIVE;
+  else
+    state = GTK_STATE_SELECTED;
+  next = marks;
+  while (next)
+  {
+    GdkRectangle real_mark, real_area;
+    gdouble *mark =  (gdouble*)next->data;
+
+    if (orientation == GTK_ORIENTATION_VERTICAL)
+    {
+      mark_rect.x = slider.x;
+      mark_rect.y = trough.y + (trough.height - widget->style->ythickness) * *mark;
+      mark_rect.width = slider.width;
+      mark_rect.height = widget->style->ythickness;
+      detail = "scrollbar-vmarker";
+    }
+    else
+    {
+      mark_rect.x = trough.x + (trough.width - widget->style->xthickness) * *mark;
+      mark_rect.y = slider.y;
+      mark_rect.width = widget->style->xthickness;
+      mark_rect.height = slider.height;
+      detail = "scrollbar-hmarker";
+    }
+    
+    real_mark = mark_rect;
+    real_mark.x += widget->allocation.x;
+    real_mark.y += widget->allocation.y;
+    
+    if (gdk_rectangle_intersect (&event->area, &real_mark, &real_area))
+      gtk_paint_flat_box (widget->style,
+                          widget->window,
+                          state,
+                          GTK_SHADOW_NONE,
+                          &real_area,
+                          widget,
+                          detail,
+                          real_mark.x,
+                          real_mark.y,
+                          real_mark.width,
+                          real_mark.height);
+
+    next = next->next;
+  }
+    
+  paint_slider (widget, &event->area, &slider, orientation);
+  
+  return FALSE;
+}
+
+static gint
+gtk_scrollbar_button_press (GtkWidget *widget, GdkEventButton *event)
+{
+  gint                 x, y;
+  GtkScrollbarPrivate *priv;
+  GdkRectangle         slider;
+  
+  GTK_WIDGET_CLASS (gtk_scrollbar_parent_class)->button_press_event (widget, event);
+  
+  priv = GTK_SCROLLBAR_GET_PRIVATE (GTK_SCROLLBAR (widget));
+  gtk_widget_get_pointer (widget, &x, &y);
+  _gtk_range_get_internal_geometry (GTK_RANGE(widget), NULL, &slider, NULL,
+                                    NULL, NULL, NULL);
+  
+  if (x >= slider.x && x <= (slider.x + slider.width) &&
+      y >= slider.y && y <= (slider.y + slider.height))
+    priv->grab_on_slider = TRUE;
+  
+  return FALSE;
+}
+
+static gint
+gtk_scrollbar_button_release (GtkWidget *widget, GdkEventButton *event)
+{
+  GtkScrollbarPrivate *priv;
+
+  GTK_WIDGET_CLASS (gtk_scrollbar_parent_class)->button_release_event (widget, event);
+  
+  priv = GTK_SCROLLBAR_GET_PRIVATE (GTK_SCROLLBAR (widget));
+  
+  priv->grab_on_slider = FALSE;
+  return FALSE;
 }
 
 static void
 gtk_scrollbar_init (GtkScrollbar *scrollbar)
 {
+  GtkScrollbarPrivate *priv = GTK_SCROLLBAR_GET_PRIVATE (scrollbar);
+  priv->marks = NULL;
+  priv->grab_on_slider = FALSE;
 }
 
 static void
@@ -147,3 +347,71 @@ gtk_scrollbar_new (GtkOrientation  orientation,
                        "adjustment",  adjustment,
                        NULL);
 }
+
+/**
+ * gtk_scrollbar_add_mark
+ * @scrollbar: a #GtkScrollbar
+ * @mark: a double with a value from 0.0 to 1.0 which represents a relative position along the trough
+ * 
+ * Sets a mark in the trough of the scrollbar to hint the location of a certain
+ * element in the area tha is being scrolled. This is useful for search or any
+ * other content matching in a text buffer.
+ * See gtk_scrollbar_clear_marks() for mark removal.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_scrollbar_add_mark (GtkScrollbar *scrollbar, gdouble mark)
+{
+  GtkScrollbarPrivate *priv;
+  gdouble *stored_mark;
+  GList *next;
+  
+  g_return_if_fail (mark >= 0.0 && mark <= 1.0);
+
+  priv = GTK_SCROLLBAR_GET_PRIVATE (scrollbar);
+
+  next = priv->marks;
+  while (next)
+  {
+    gdouble *stored_mark = next->data;
+    g_return_if_fail (*stored_mark != mark);
+    next = next->next;
+  }
+  
+  stored_mark = (gdouble*)g_memdup (&mark, sizeof (gdouble));
+  priv->marks = g_list_append (priv->marks, (gpointer)stored_mark);
+}
+
+/**
+ * gtk_scrollbar_clear_marks
+ * @scrollbar: a #GtkScrollbar
+ * 
+ * Removes any marks that have been added with gtk_scrollbar_add_mark().
+ *
+ * Since: 3.0
+ **/
+void
+gtk_scrollbar_clear_marks (GtkScrollbar *scrollbar)
+{
+  GList *marks, *next;
+  marks = GTK_SCROLLBAR_GET_PRIVATE (scrollbar)->marks;
+  next = marks;
+  
+  while (next)
+  {
+    g_free (next->data);
+    next = next->next;
+  }
+  
+  g_list_free (marks);
+  GTK_SCROLLBAR_GET_PRIVATE (scrollbar)->marks = NULL;
+}
+
+static void
+gtk_scrollbar_finalize (GObject *object)
+{
+  gtk_scrollbar_clear_marks (GTK_SCROLLBAR (object));
+  G_OBJECT_CLASS (gtk_scrollbar_parent_class)->finalize (object);
+}
+
diff --git a/gtk/gtkscrollbar.h b/gtk/gtkscrollbar.h
index 992bb0d..c203b62 100644
--- a/gtk/gtkscrollbar.h
+++ b/gtk/gtkscrollbar.h
@@ -65,10 +65,12 @@ struct _GtkScrollbarClass
 };
 
 
-GType       gtk_scrollbar_get_type (void) G_GNUC_CONST;
-GtkWidget * gtk_scrollbar_new      (GtkOrientation  orientation,
-                                    GtkAdjustment  *adjustment);
-
+GType       gtk_scrollbar_get_type    (void) G_GNUC_CONST;
+GtkWidget * gtk_scrollbar_new         (GtkOrientation  orientation,
+                                       GtkAdjustment  *adjustment);
+void        gtk_scrollbar_add_mark    (GtkScrollbar   *scrollbar,
+                                       gdouble         mark);
+void        gtk_scrollbar_clear_marks (GtkScrollbar  *scrollbar);
 G_END_DECLS
 
 #endif /* __GTK_SCROLLBAR_H__ */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 91cd10d..bbe0e62 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -90,7 +90,8 @@ noinst_PROGRAMS =  $(TEST_PROGS)	\
 	testgrouping			\
 	testtooltips			\
 	testexpander			\
-	testvolumebutton
+	testvolumebutton                \
+        testscrollbar
 
 if USE_X11
 noinst_PROGRAMS += testapplication
@@ -174,6 +175,7 @@ testtooltips_DEPENDENCIES = $(TEST_DEPS)
 testvolumebutton_DEPENDENCIES = $(TEST_DEPS)
 testwindows_DEPENDENCIES = $(TEST_DEPS)
 testexpander_DEPENDENCIES = $(TEST_DEPS)
+testscrollbar_DEPENDENCIES = $(TEST_DEPS)
 
 flicker_LDADD = $(LDADDS)
 simple_LDADD = $(LDADDS)
@@ -243,6 +245,7 @@ testtooltips_LDADD = $(LDADDS)
 testvolumebutton_LDADD = $(LDADDS)
 testwindows_LDADD = $(LDADDS)
 testexpander_LDADD = $(LDADDS)
+testscrollbar_LDADD = $(LDADDS)
 
 testentrycompletion_SOURCES = 	\
 	prop-editor.c		\
@@ -353,6 +356,9 @@ testwindows_SOURCES = 	\
 
 testexpander_SOURCES = testexpander.c
 
+testscrollbar_SOURCES =         \
+	testscrollbar.c
+
 EXTRA_DIST += 			\
 	prop-editor.h		\
 	testgtk.1 		\
diff --git a/tests/testscrollbar.c b/tests/testscrollbar.c
new file mode 100644
index 0000000..334e767
--- /dev/null
+++ b/tests/testscrollbar.c
@@ -0,0 +1,54 @@
+/*
+ * testscrollbar.c
+ */
+
+#include <gtk/gtk.h>
+#include <glib-object.h>
+
+gint
+main (gint argc, gchar** argv)
+{
+	GtkAdjustment *adj;
+	GtkWidget     *win, *hbox, *vbox;
+	GtkWidget     *vs1, *vs2, *hs1, *hs2;
+	gboolean       activate_slider;
+	
+	gtk_init (NULL, NULL);
+
+	win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+	gtk_window_set_title (GTK_WINDOW(win), "testscrollbar");
+	gtk_widget_set_size_request (win, 400, 400);
+	
+	g_signal_connect (win, "destroy", G_CALLBACK(gtk_main_quit), NULL);
+
+	adj = GTK_ADJUSTMENT (gtk_adjustment_new (0.1, 0.0, 100.0, 0.01, 0.1, 10.0));
+
+	hbox = gtk_hbox_new (TRUE, 5);
+	vbox = gtk_vbox_new (TRUE, 5);
+
+	vs1  = gtk_vscrollbar_new (adj);
+	vs2  = gtk_vscrollbar_new (adj);
+	hs1  = gtk_hscrollbar_new (adj);
+	hs2  = gtk_hscrollbar_new (adj);
+
+	gtk_container_add (GTK_CONTAINER (win), hbox);
+	gtk_container_add (GTK_CONTAINER (hbox), vs1);
+	gtk_container_add (GTK_CONTAINER (hbox), vs2);
+
+	gtk_container_add (GTK_CONTAINER (hbox), vbox);
+	gtk_container_add (GTK_CONTAINER (vbox), hs1);
+	gtk_container_add (GTK_CONTAINER (vbox), hs2);
+
+	gtk_scrollbar_add_mark (GTK_SCROLLBAR (vs1), 0.0);
+	gtk_scrollbar_add_mark (GTK_SCROLLBAR (vs2), 0.3);
+	gtk_scrollbar_add_mark (GTK_SCROLLBAR (hs1), 0.8);
+	gtk_scrollbar_add_mark (GTK_SCROLLBAR (hs2), 1.0);
+
+	gtk_widget_set_sensitive (vs2, FALSE);
+	gtk_widget_set_sensitive (hs2, FALSE);
+
+	gtk_widget_show_all (win);
+
+	gtk_main ();
+	return 0;
+}
