Attachments are patches and demo file for finger scroll to nbtk
Hope it is helpful for some guys.
 
diff -Nur nbtk-0.11.1/nbtk/Makefile.am nbtk-0.11.1-xx/nbtk/Makefile.am
--- nbtk-0.11.1/nbtk/Makefile.am	2009-06-11 23:49:11.000000000 +0800
+++ nbtk-0.11.1-xx/nbtk/Makefile.am	2009-06-26 17:35:16.000000000 +0800
@@ -38,6 +38,7 @@
 	$(top_srcdir)/nbtk/nbtk-types.h 		\
 	$(top_srcdir)/nbtk/nbtk-viewport.h		\
 	$(top_srcdir)/nbtk/nbtk-widget.h		\
+	$(top_srcdir)/nbtk/nbtk-finger-scroll.h  \
 	$(NULL)
 
 source_h_priv = \
@@ -160,6 +161,7 @@
 	nbtk-tooltip.c 			\
 	nbtk-viewport.c 		\
 	nbtk-widget.c			\
+	nbtk-finger-scroll.c		\
 	nbtk.h 				\
 	$(NULL)
 
diff -Nur nbtk-0.11.1/nbtk/nbtk-finger-scroll.c nbtk-0.11.1-xx/nbtk/nbtk-finger-scroll.c
--- nbtk-0.11.1/nbtk/nbtk-finger-scroll.c	1970-01-01 08:00:00.000000000 +0800
+++ nbtk-0.11.1-xx/nbtk/nbtk-finger-scroll.c	2009-06-26 17:35:10.000000000 +0800
@@ -0,0 +1,791 @@
+/* nbtk-finger-scroll.c: Finger scrolling container actor
+ *
+ * Copyright (C) 2008 OpenedHand
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Written by: Chris Lord <[email protected]>
+ */
+
+#include "nbtk-finger-scroll.h"
+#include "nbtk-enum-types.h"
+#include "nbtk-marshal.h"
+#include "nbtk-scroll-bar.h"
+#include "nbtk-scrollable.h"
+#include "nbtk-scroll-view.h"
+#include <clutter/clutter.h>
+#include <math.h>
+
+G_DEFINE_TYPE (NbtkFingerScroll, nbtk_finger_scroll, NBTK_TYPE_SCROLL_VIEW)
+
+#define FINGER_SCROLL_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+                                  NBTK_TYPE_FINGER_SCROLL, \
+                                  NbtkFingerScrollPrivate))
+
+typedef struct {
+  /* Units to store the origin of a click when scrolling */
+  gfloat x;
+  gfloat y;
+  GTimeVal    time;
+} NbtkFingerScrollMotion;
+
+typedef struct _NbtkFingerScrollPrivate
+{
+  /* Scroll mode */
+  NbtkFingerScrollMode mode;
+  
+  GArray                *motion_buffer;
+  guint                  last_motion;
+  
+  /* Variables for storing acceleration information for kinetic mode */
+  ClutterTimeline       *deceleration_timeline;
+  gfloat        dx;
+  gfloat          dy;
+  CoglFixed           decel_rate;
+  
+  /* Variables to fade in/out scroll-bars */
+  ClutterAnimation *template;
+  ClutterTimeline       *hscroll_timeline;
+  ClutterTimeline       *vscroll_timeline;
+} 
+;
+
+enum {
+  PROP_MODE = 1,
+  PROP_DECEL_RATE,
+  PROP_BUFFER,
+};
+
+static void
+nbtk_finger_scroll_get_property (GObject *object, guint property_id,
+                                 GValue *value, GParamSpec *pspec)
+{
+  NbtkFingerScrollPrivate *priv = NBTK_FINGER_SCROLL (object)->priv;
+  
+  switch (property_id)
+    {
+    case PROP_MODE :
+      g_value_set_enum (value, priv->mode);
+      break;
+    case PROP_DECEL_RATE :
+      g_value_set_double (value, COGL_FIXED_TO_FLOAT (priv->decel_rate));
+      break;
+    case PROP_BUFFER :
+      g_value_set_uint (value, priv->motion_buffer->len);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+nbtk_finger_scroll_set_property (GObject *object, guint property_id,
+                                 const GValue *value, GParamSpec *pspec)
+{
+  NbtkFingerScrollPrivate *priv = NBTK_FINGER_SCROLL (object)->priv;
+  
+  switch (property_id)
+    {
+    case PROP_MODE :
+      priv->mode = g_value_get_enum (value);
+      g_object_notify (object, "mode");
+      break;
+    case PROP_DECEL_RATE :
+      priv->decel_rate = COGL_FIXED_FROM_FLOAT (g_value_get_double (value));
+//	printf("decel is %f \n",priv->decel_rate);
+      g_object_notify (object, "decel-rate");
+      break;
+    case PROP_BUFFER :
+      g_array_set_size (priv->motion_buffer, g_value_get_uint (value));
+      g_object_notify (object, "motion-buffer");
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+nbtk_finger_scroll_dispose (GObject *object)
+{
+  NbtkFingerScrollPrivate *priv = NBTK_FINGER_SCROLL (object)->priv;
+
+  if (priv->deceleration_timeline)
+    {
+      clutter_timeline_stop (priv->deceleration_timeline);
+      g_object_unref (priv->deceleration_timeline);
+      priv->deceleration_timeline = NULL;
+    }
+  
+  if (priv->hscroll_timeline)
+    {
+      clutter_timeline_stop (priv->hscroll_timeline);
+      g_object_unref (priv->hscroll_timeline);
+      priv->hscroll_timeline = NULL;
+    }
+  
+  if (priv->vscroll_timeline)
+    {
+      clutter_timeline_stop (priv->vscroll_timeline);
+      g_object_unref (priv->vscroll_timeline);
+      priv->vscroll_timeline = NULL;
+    }
+  
+  if (priv->template)
+    {
+      g_object_unref (priv->template);
+      priv->template = NULL;
+    }
+
+  G_OBJECT_CLASS (nbtk_finger_scroll_parent_class)->dispose (object);
+}
+
+static void
+nbtk_finger_scroll_finalize (GObject *object)
+{
+  NbtkFingerScrollPrivate *priv = NBTK_FINGER_SCROLL (object)->priv;
+
+  g_array_free (priv->motion_buffer, TRUE);
+  
+  G_OBJECT_CLASS (nbtk_finger_scroll_parent_class)->finalize (object);
+}
+
+
+static void
+nbtk_finger_scroll_class_init (NbtkFingerScrollClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (NbtkFingerScrollPrivate));
+
+  object_class->get_property = nbtk_finger_scroll_get_property;
+  object_class->set_property = nbtk_finger_scroll_set_property;
+  object_class->dispose = nbtk_finger_scroll_dispose;
+  object_class->finalize = nbtk_finger_scroll_finalize;
+
+  g_object_class_install_property (object_class,
+                                   PROP_MODE,
+                                   g_param_spec_enum ("mode",
+                                                      "NbtkFingerScrollMode",
+                                                      "Scrolling mode",
+                                                      NBTK_TYPE_FINGER_SCROLL_MODE,
+                                                      NBTK_FINGER_SCROLL_MODE_PUSH,
+                                                      G_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class,
+                                   PROP_DECEL_RATE,
+                                   g_param_spec_double ("decel-rate",
+                                                        "Deceleration rate",
+                                                        "Rate at which the view "
+                                                        "will decelerate in "
+                                                        "kinetic mode.",
+                                                        COGL_FIXED_TO_FLOAT (COGL_FIXED_1 + 0x80000000),
+                                                        COGL_FIXED_TO_FLOAT (0x7fffffff),
+                                                        1.1,
+                                                        G_PARAM_READWRITE));
+
+printf("max %f min %f\n",COGL_FIXED_TO_FLOAT (COGL_FIXED_1 + 0x80000000), COGL_FIXED_TO_FLOAT (0x7fffffff));
+  g_object_class_install_property (object_class,
+                                   PROP_BUFFER,
+                                   g_param_spec_uint ("motion-buffer",
+                                                      "Motion buffer",
+                                                      "Amount of motion "
+                                                      "events to buffer",
+                                                      1, G_MAXUINT, 3,
+                                                      G_PARAM_READWRITE));
+}
+
+static gboolean
+motion_event_cb (ClutterActor *actor,
+                 ClutterMotionEvent *event,
+                 NbtkFingerScroll *scroll)
+{
+  gfloat  x, y;
+  
+  NbtkFingerScrollPrivate *priv = scroll->priv;
+
+  if (clutter_actor_transform_stage_point (actor,
+                                           event->x,
+                                           event->y,
+                                           &x, &y))
+    {
+      NbtkFingerScrollMotion *motion;
+      ClutterActor *child =
+        nbtk_bin_get_child (NBTK_SCROLL_VIEW(scroll));
+      
+      if (child)
+        {
+          gfloat dx, dy;
+          NbtkAdjustment *hadjust, *vadjust;
+          
+          nbtk_scrollable_get_adjustments (NBTK_SCROLLABLE (child),
+                                           &hadjust,
+                                           &vadjust);
+
+          motion = &g_array_index (priv->motion_buffer,
+                                   NbtkFingerScrollMotion, priv->last_motion);
+          dx = (motion->x - x) +
+               (nbtk_adjustment_get_value (hadjust));
+          dy = (motion->y - y) +
+               (nbtk_adjustment_get_value (vadjust));
+          
+          nbtk_adjustment_set_value (hadjust, dx);
+          nbtk_adjustment_set_value (vadjust, dy);
+        }
+      
+      priv->last_motion ++;
+      if (priv->last_motion == priv->motion_buffer->len)
+        {
+          priv->motion_buffer = g_array_remove_index (priv->motion_buffer, 0);
+          g_array_set_size (priv->motion_buffer, priv->last_motion);
+          priv->last_motion --;
+        }
+      
+      motion = &g_array_index (priv->motion_buffer,
+                               NbtkFingerScrollMotion, priv->last_motion);
+      motion->x = x;
+      motion->y = y;
+      g_get_current_time (&motion->time);
+    }
+
+  return TRUE;
+}
+
+static void
+hfade_complete_cb (ClutterActor *scrollbar, NbtkFingerScroll *scroll)
+{
+  scroll->priv->hscroll_timeline = NULL;
+}
+
+static void
+vfade_complete_cb (ClutterActor *scrollbar, NbtkFingerScroll *scroll)
+{
+  scroll->priv->vscroll_timeline = NULL;
+}
+
+static void
+clamp_adjustments (NbtkFingerScroll *scroll)
+{
+  ClutterActor *child = nbtk_bin_get_child (NBTK_SCROLL_VIEW (scroll));
+  
+  if (child)
+    {
+      guint fps, n_frames;
+      NbtkAdjustment *hadj, *vadj;
+      gboolean snap;
+      
+      nbtk_scrollable_get_adjustments (NBTK_SCROLLABLE (child),
+                                       &hadj, &vadj);
+      
+      /* FIXME: Hard-coded value here */
+      fps = clutter_get_default_frame_rate ();
+      n_frames = fps / 6;
+      
+      snap = TRUE;
+      if (nbtk_adjustment_get_elastic (hadj))
+        snap = !nbtk_adjustment_clamp (hadj, TRUE, (n_frames/fps)*1000);
+      
+      /* Snap to the nearest step increment on hadjustment */
+      if (snap)
+        {
+          gdouble d, value, lower, step_increment;
+          
+          nbtk_adjustment_get_values (hadj, &value, &lower, NULL,
+                                      &step_increment, NULL, NULL);
+          d = (rint ((value - lower) / step_increment) *
+              step_increment) + lower;
+          nbtk_adjustment_set_value (hadj, d);
+        }
+      
+      snap = TRUE;
+      if (nbtk_adjustment_get_elastic (vadj))
+        snap = !nbtk_adjustment_clamp (vadj, TRUE, (n_frames/fps)*1000);
+
+      /* Snap to the nearest step increment on vadjustment */
+      if (snap)
+        {
+          gdouble d, value, lower, step_increment;
+          
+          nbtk_adjustment_get_values (vadj, &value, &lower, NULL,
+                                      &step_increment, NULL, NULL);
+          d = (rint ((value - lower) / step_increment) *
+              step_increment) + lower;
+          nbtk_adjustment_set_value (vadj, d);
+        }
+    }
+}
+
+static void
+deceleration_completed_cb (ClutterTimeline *timeline,
+                           NbtkFingerScroll *scroll)
+{
+  clamp_adjustments (scroll);
+  g_object_unref (timeline);
+  scroll->priv->deceleration_timeline = NULL;
+}
+static int n_frame;
+static void
+deceleration_new_frame_cb (ClutterTimeline *timeline,
+                           gint frame_num,
+                           NbtkFingerScroll *scroll)
+{
+printf(" deceleration  sss\n");
+
+  NbtkFingerScrollPrivate *priv = scroll->priv;
+  ClutterActor *child = nbtk_bin_get_child (NBTK_SCROLL_VIEW(scroll));
+  
+  if (child)
+    {
+      CoglFixed value, lower, upper, page_size;
+      NbtkAdjustment *hadjust, *vadjust;
+      gint i;
+      gboolean stop = FALSE;
+      
+      nbtk_scrollable_get_adjustments (NBTK_SCROLLABLE (child),
+                                       &hadjust,
+                                       &vadjust);
+static int  dr ;
+dr = clutter_timeline_get_duration(timeline);
+
+      printf("   %d frame since last new signal emit \n",clutter_timeline_get_delta (timeline));
+      for (i = 0; i < clutter_timeline_get_delta (timeline) * n_frame / dr ; i++)
+	  {
+			printf("will set adjustments orig %f move  %f  \n",   nbtk_adjustment_get_value (hadjust),priv->dx);
+
+			  nbtk_adjustment_set_value (hadjust,
+							  priv->dx +
+							  nbtk_adjustment_get_value (hadjust));
+			  nbtk_adjustment_set_value (vadjust,
+							  priv->dy +
+							  nbtk_adjustment_get_value (vadjust));
+		//	  priv->dx = CLUTTER_UNITS_DIV (priv->dx, COGL_FIXED_TO_UNIT(priv->decel_rate));
+	//		  priv->dx = CLUTTER_UNITS_FROM_FIXED(COGL_FIXED_DIV(CLUTTER_UNITS_TO_FIXED(priv->dx), priv->decel_rate));
+				priv->dx = priv->dx/COGL_FIXED_TO_FLOAT(priv->decel_rate);
+
+			  priv->dy = priv->dy/COGL_FIXED_TO_FLOAT(priv->decel_rate);
+	  }
+      
+      /* Check if we've hit the upper or lower bounds and stop the timeline */
+      nbtk_adjustment_get_values (hadjust, &value, &lower, &upper,
+                                   NULL, NULL, &page_size);
+      if (((priv->dx > 0) && (value < upper - page_size)) ||
+          ((priv->dx < 0) && (value > lower)))
+       {printf("contiue move\n"); stop = FALSE;}
+      
+      if (stop)
+        {
+          nbtk_adjustment_get_values(vadjust, &value, &lower, &upper,
+                                       NULL, NULL, &page_size);
+          if (((priv->dy > 0) && (value < upper - page_size)) ||
+              ((priv->dy < 0) && (value > lower)))
+            stop = FALSE;
+        }
+      printf("cccccccccc\n");
+      if (stop)
+        { printf("stop\n");
+          clutter_timeline_stop (timeline);
+          deceleration_completed_cb (timeline, scroll);
+        }
+    }
+}
+
+static gboolean
+button_release_event_cb (ClutterActor *actor,
+                         ClutterButtonEvent *event,
+                         NbtkFingerScroll *scroll)
+{
+  NbtkFingerScrollPrivate *priv = scroll->priv;
+  ClutterActor *child = nbtk_bin_get_child (NBTK_SCROLL_VIEW(scroll));
+  gboolean decelerating = FALSE;
+
+  if (event->button != 1)
+    return FALSE;
+  
+  g_signal_handlers_disconnect_by_func (actor,
+                                        motion_event_cb,
+                                        scroll);
+  g_signal_handlers_disconnect_by_func (actor,
+                                        button_release_event_cb,
+                                        scroll);
+  
+  clutter_ungrab_pointer ();
+
+  if ((priv->mode == NBTK_FINGER_SCROLL_MODE_KINETIC) && (child))
+    { 
+      gfloat x, y;
+      
+      if (clutter_actor_transform_stage_point (actor,
+                                               event->x,
+                                               event->y,
+                                               &x, &y))
+        {
+
+          gfloat frac, x_origin, y_origin;
+          GTimeVal release_time, motion_time;
+          NbtkAdjustment *hadjust, *vadjust;
+          glong time_diff;
+          gint i;
+          
+          /* Get time delta */
+          g_get_current_time (&release_time);
+          
+          /* Get average position/time of last x mouse events */
+          priv->last_motion ++;
+          x_origin = y_origin = 0;
+          motion_time = (GTimeVal){ 0, 0 };
+          for (i = 0; i < priv->last_motion; i++)
+            {
+              NbtkFingerScrollMotion *motion =
+                &g_array_index (priv->motion_buffer, NbtkFingerScrollMotion, i);
+              
+              /* FIXME: This doesn't guard against overflows - Should
+               *        either fix that, or calculate the correct maximum
+               *        value for the buffer size
+               */
+              x_origin += motion->x;
+              y_origin += motion->y;
+              motion_time.tv_sec += motion->time.tv_sec;
+              motion_time.tv_usec += motion->time.tv_usec;
+            }
+          x_origin = 
+            x_origin/priv->last_motion;
+          y_origin = 
+            y_origin/
+                           priv->last_motion;
+          motion_time.tv_sec /= priv->last_motion;
+          motion_time.tv_usec /= priv->last_motion;
+          
+          if (motion_time.tv_sec == release_time.tv_sec)
+            time_diff = release_time.tv_usec - motion_time.tv_usec;
+          else
+            time_diff = release_time.tv_usec +
+                        (G_USEC_PER_SEC - motion_time.tv_usec);
+          
+          /* Work out the fraction of 1/60th of a second that has elapsed */
+          frac =  (time_diff/1000.0)/ (1000.0/60.0);
+          printf("time_diff is %d\n",time_diff);
+          /* See how many units to move in 1/60th of a second */
+          priv->dx = 
+                     (x_origin - x)/frac;
+          priv->dy =
+                     (y_origin - y)/frac;
+		        
+printf("every 1/60 second to move %f \n", priv->dx);
+          /* Get adjustments to do step-increment snapping */
+          nbtk_scrollable_get_adjustments (NBTK_SCROLLABLE (child),
+                                           &hadjust,
+                                           &vadjust);
+
+          if (ABS(priv->dx) > 1 ||
+              ABS(priv->dy) > 1)
+            {
+              gdouble value, lower, step_increment, d, a, x, y, n;
+              
+              /* TODO: Convert this all to fixed point? */
+              
+              /* We want n, where x / y^n < z,
+               * x = Distance to move per frame
+               * y = Deceleration rate
+               * z = maximum distance from target
+               *
+               * Rearrange to n = log (x / z) / log (y)
+               * To simplify, z = 1, so n = log (x) / log (y)
+               *
+               * As z = 1, this will cause stops to be slightly abrupt - 
+               * add a constant 15 frames to compensate.
+               */
+          //    x = COGL_FIXED_TO_FLOAT (MAX(ABS(priv->dx), ABS(priv->dy)));
+            //  y = COGL_FIXED_TO_FLOAT (priv->decel_rate);
+				x=MAX(ABS(priv->dx), ABS(priv->dy))     ; 
+			    y=COGL_FIXED_TO_FLOAT(priv->decel_rate);
+			printf("decel rate is %f\n", COGL_FIXED_TO_FLOAT(priv->decel_rate));
+        n = logf (x) / logf (y) + 15.0;
+
+              /* Now we have n, adjust dx/dy so that we finish on a step
+               * boundary.
+               *
+               * Distance moved, using the above variable names:
+               *
+               * d = x + x/y + x/y^2 + ... + x/y^n
+               *
+               * Using geometric series,
+               *
+               * d = (1 - 1/y^(n+1))/(1 - 1/y)*x
+               * 
+               * Let a = (1 - 1/y^(n+1))/(1 - 1/y),
+               *
+               * d = a * x
+               *
+               * Find d and find its nearest page boundary, then solve for x
+               *
+               * x = d / a
+               */
+              
+              /* Get adjustments, work out y^n */
+              a = (1.0 - 1.0 / pow (y, n + 1)) / (1.0 - 1.0 / y);
+
+              /* Solving for dx */
+              d = a * (priv->dx);
+              nbtk_adjustment_get_values (hadjust, &value, &lower, NULL,
+                                          &step_increment, NULL, NULL);
+              d = ((rint (((value + d) - lower) / step_increment) *
+                    step_increment) + lower) - value;
+              priv->dx =  (d / a);
+
+              /* Solving for dy */
+              d = a * (priv->dy);
+              nbtk_adjustment_get_values (vadjust, &value, &lower, NULL,
+                                          &step_increment, NULL, NULL);
+              d = ((rint (((value + d) - lower) / step_increment) *
+                    step_increment) + lower) - value;
+              priv->dy =  (d / a);
+		n_frame = n ;              
+           priv->deceleration_timeline = clutter_timeline_new ( (int)((n*1000))/60 );
+
+				printf(" deceleration_timeline!!!!!!!!!!!!!!!!!%d msecod %d\n",(gint)n, (int)((n*1000))/60);
+	//	        priv->deceleration_timeline = clutter_timeline_new (50, 60);
+   }
+          else
+            {
+              gdouble value, lower, step_increment, d, a, y;
+              
+              /* Start a short effects timeline to snap to the nearest step 
+               * boundary (see equations above)
+               */
+              y = COGL_FIXED_TO_FLOAT (priv->decel_rate);
+              a = (1.0 - 1.0 / pow (y, 4 + 1)) / (1.0 - 1.0 / y);
+              
+              nbtk_adjustment_get_values (hadjust, &value, &lower, NULL,
+                                          &step_increment, NULL, NULL);
+              d = ((rint ((value - lower) / step_increment) *
+                    step_increment) + lower) - value;
+              priv->dx =  (d / a);
+              
+              nbtk_adjustment_get_values (vadjust, &value, &lower, NULL,
+                                          &step_increment, NULL, NULL);
+              d = ((rint ((value - lower) / step_increment) *
+                    step_increment) + lower) - value;
+              priv->dy =  (d / a);
+              
+              priv->deceleration_timeline = clutter_timeline_new (4000/60);
+          }
+
+          g_signal_connect (priv->deceleration_timeline, "new_frame",
+                            G_CALLBACK (deceleration_new_frame_cb), scroll);
+          g_signal_connect (priv->deceleration_timeline, "completed",
+                            G_CALLBACK (deceleration_completed_cb), scroll);
+          clutter_timeline_start (priv->deceleration_timeline);
+          decelerating = TRUE;
+        }
+    }
+
+  /* Reset motion event buffer */
+  priv->last_motion = 0;
+  
+  if (!decelerating)
+    {
+      clamp_adjustments (scroll);
+    }
+  
+  /* Pass through events to children.
+   * FIXME: this probably breaks click-count.
+   */
+  clutter_event_put ((ClutterEvent *)event);
+  
+  return TRUE;
+}
+
+static gboolean
+after_event_cb (NbtkFingerScroll *scroll)
+{
+  /* Check the pointer grab - if something else has grabbed it - for example,
+   * a scroll-bar or some such, don't do our funky stuff.
+   */
+  if (clutter_get_pointer_grab () != CLUTTER_ACTOR (scroll))
+    {
+      g_signal_handlers_disconnect_by_func (scroll,
+                                            motion_event_cb,
+                                            scroll);
+      g_signal_handlers_disconnect_by_func (scroll,
+                                            button_release_event_cb,
+                                            scroll);
+    }
+  
+  return FALSE;
+}
+
+static gboolean
+captured_event_cb (ClutterActor     *actor,
+                   ClutterEvent     *event,
+                   NbtkFingerScroll *scroll)
+{
+  NbtkFingerScrollPrivate *priv = scroll->priv;
+  
+  if (event->type == CLUTTER_BUTTON_PRESS)
+    {
+      NbtkFingerScrollMotion *motion;
+      ClutterButtonEvent *bevent = (ClutterButtonEvent *)event;
+      
+      /* Reset motion buffer */
+      priv->last_motion = 0;
+      motion = &g_array_index (priv->motion_buffer, NbtkFingerScrollMotion, 0);
+      
+      if ((bevent->button == 1) &&
+          (clutter_actor_transform_stage_point (actor,
+                                           (bevent->x),
+                                           (bevent->y),
+                                           &motion->x, &motion->y)))
+        {
+          g_get_current_time (&motion->time);
+          
+          if (priv->deceleration_timeline)
+            {
+              clutter_timeline_stop (priv->deceleration_timeline);
+              g_object_unref (priv->deceleration_timeline);
+              priv->deceleration_timeline = NULL;
+            }
+          
+          /* Fade in scroll-bars */
+          
+          clutter_grab_pointer (actor);
+          
+          /* Add a high priority idle to check the grab after the event
+           * emission is finished.
+           */
+          g_idle_add_full (G_PRIORITY_HIGH_IDLE,
+                           (GSourceFunc)after_event_cb,
+                           scroll,
+                           NULL);
+          
+          g_signal_connect (actor,
+                            "motion-event",
+                            G_CALLBACK (motion_event_cb),
+                            scroll);
+          g_signal_connect (actor,
+                            "button-release-event",
+                            G_CALLBACK (button_release_event_cb),
+                            scroll);
+        }
+    }
+  
+  return FALSE;
+}
+
+static void
+hscroll_notify_reactive_cb (ClutterActor     *bar,
+                            GParamSpec       *pspec,
+                            NbtkFingerScroll *scroll)
+{
+  NbtkFingerScrollPrivate *priv;
+  
+  priv = scroll->priv;
+  if (CLUTTER_ACTOR_IS_REACTIVE (bar))
+    {
+      if (priv->hscroll_timeline)
+        {
+          clutter_timeline_stop (priv->hscroll_timeline);
+          g_object_unref (priv->hscroll_timeline);
+          priv->hscroll_timeline = NULL;
+        }
+      clutter_actor_set_opacity (bar, 0xFF);
+    }
+}
+
+static void
+vscroll_notify_reactive_cb (ClutterActor     *bar,
+                            GParamSpec       *pspec,
+                            NbtkFingerScroll *scroll)
+{
+  NbtkFingerScrollPrivate *priv;
+  
+  priv = scroll->priv;
+  if (CLUTTER_ACTOR_IS_REACTIVE (bar))
+    {
+      if (priv->vscroll_timeline)
+        {
+          clutter_timeline_stop (priv->vscroll_timeline);
+          g_object_unref (priv->vscroll_timeline);
+          priv->vscroll_timeline = NULL;
+        }
+      clutter_actor_set_opacity (bar, 0xFF);
+    }
+}
+
+static void
+nbtk_finger_scroll_init (NbtkFingerScroll *self)
+{
+  ClutterActor *scrollbar;
+  NbtkFingerScrollPrivate *priv = self->priv = FINGER_SCROLL_PRIVATE (self);
+  
+  priv->motion_buffer = g_array_sized_new (FALSE, TRUE,
+                                           sizeof (NbtkFingerScrollMotion), 3);
+  g_array_set_size (priv->motion_buffer, 3);
+  priv->decel_rate = COGL_FIXED_FROM_FLOAT (1.1f);
+  
+  clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
+  g_signal_connect (CLUTTER_ACTOR (self),
+                    "captured-event",
+                    G_CALLBACK (captured_event_cb),
+                    self);
+  
+  /* Make the scroll-bars unreactive and set their opacity - we'll fade them 
+   * in/out when we scroll.
+   * Also, hook onto notify::reactive and don't fade in/out when the bars are 
+   * set reactive (which you might want to do if you want finger-scrolling 
+   * *and* a scroll bar.
+   */
+  scrollbar = nbtk_scroll_view_get_hscroll_bar (NBTK_SCROLL_VIEW (self));
+  clutter_actor_set_reactive (scrollbar, FALSE);
+  clutter_actor_set_opacity (scrollbar, 0x00);
+  g_signal_connect (scrollbar, "notify::reactive",
+                    G_CALLBACK (hscroll_notify_reactive_cb), self);
+
+  scrollbar = nbtk_scroll_view_get_vscroll_bar (NBTK_SCROLL_VIEW (self));
+  clutter_actor_set_reactive (scrollbar, FALSE);
+  clutter_actor_set_opacity (scrollbar, 0x00);
+  g_signal_connect (scrollbar, "notify::reactive",
+                    G_CALLBACK (vscroll_notify_reactive_cb), self);
+  
+//  priv->template = clutter_effect_template_new_for_duration (250,
+  //                                              CLUTTER_LINEAR);
+
+	priv->template =  clutter_animation_new();
+	clutter_animation_set_mode(priv->template,atoi("sex"));
+	//clutter_animation_set_duration(priv->template, 1250);
+}
+
+ClutterActor *
+nbtk_finger_scroll_new (NbtkFingerScrollMode mode)
+{
+  return CLUTTER_ACTOR (g_object_new (NBTK_TYPE_FINGER_SCROLL,
+                                      "mode", mode, NULL));
+}
+
+void
+nbtk_finger_scroll_stop (NbtkFingerScroll *scroll)
+{
+  NbtkFingerScrollPrivate *priv;
+  
+  g_return_if_fail (NBTK_IS_FINGER_SCROLL (scroll));
+  
+  priv = scroll->priv;
+
+  if (priv->deceleration_timeline)
+    {
+      clutter_timeline_stop (priv->deceleration_timeline);
+      g_object_unref (priv->deceleration_timeline);
+      priv->deceleration_timeline = NULL;
+    }
+}
diff -Nur nbtk-0.11.1/nbtk/nbtk-finger-scroll.h nbtk-0.11.1-xx/nbtk/nbtk-finger-scroll.h
--- nbtk-0.11.1/nbtk/nbtk-finger-scroll.h	1970-01-01 08:00:00.000000000 +0800
+++ nbtk-0.11.1-xx/nbtk/nbtk-finger-scroll.h	2009-06-26 17:35:10.000000000 +0800
@@ -0,0 +1,75 @@
+/* nbtk-finger-scroll.h: Finger scrolling container actor
+ *
+ * Copyright (C) 2008 OpenedHand
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Written by: Chris Lord <[email protected]>
+ */
+
+#ifndef __NBTK_FINGER_SCROLL_H__
+#define __NBTK_FINGER_SCROLL_H__
+
+#include <glib-object.h>
+#include <nbtk/nbtk-scroll-view.h>
+
+G_BEGIN_DECLS
+
+#define NBTK_TYPE_FINGER_SCROLL            (nbtk_finger_scroll_get_type())
+#define NBTK_FINGER_SCROLL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_FINGER_SCROLL, NbtkFingerScroll))
+#define NBTK_IS_FINGER_SCROLL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_FINGER_SCROLL))
+#define NBTK_FINGER_SCROLL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_FINGER_SCROLL, NbtkFingerScrollClass))
+#define NBTK_IS_FINGER_SCROLL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_FINGER_SCROLL))
+#define NBTK_FINGER_SCROLL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_FINGER_SCROLL, NbtkFingerScrollClass))
+
+/**
+ * NbtkFingerScrollMode:
+ * @NBTK_FINGER_SCROLL_MODE_PUSH: Non-kinetic scrolling
+ * @NBTK_FINGER_SCROLL_MODE_KINETIC: Kinetic scrolling
+ *
+ * Type of scrolling.
+ */
+typedef enum {
+  NBTK_FINGER_SCROLL_MODE_PUSH,
+  NBTK_FINGER_SCROLL_MODE_KINETIC
+} NbtkFingerScrollMode;
+
+typedef struct _NbtkFingerScroll          NbtkFingerScroll;
+typedef struct _NbtkFingerScrollPrivate   NbtkFingerScrollPrivate;
+typedef struct _NbtkFingerScrollClass     NbtkFingerScrollClass;
+
+struct _NbtkFingerScroll
+{
+  /*< private >*/
+  NbtkScrollView parent_instance;
+  
+  NbtkFingerScrollPrivate *priv;
+};
+
+struct _NbtkFingerScrollClass
+{
+  NbtkScrollViewClass parent_class;
+};
+
+GType nbtk_finger_scroll_get_type (void) G_GNUC_CONST;
+
+ClutterActor *nbtk_finger_scroll_new  (NbtkFingerScrollMode mode);
+
+void          nbtk_finger_scroll_stop (NbtkFingerScroll *scroll);
+
+G_END_DECLS
+
+#endif /* __NBTK_FINGER_SCROLL_H__ */
#include <clutter/clutter.h>
#include <nbtk/nbtk.h>
#include<stdlib.h>
#define RECT_W 300
#define RECT_H 300
#define RECT_N 200
#define RECT_GAP 40

static void
viewport_x_origin_notify_cb (NbtkViewport *viewport,
                             GParamSpec *args1,
                             ClutterActor *group)
{
  GList *children, *c;
  gint origin_x, width;
  
  nbtk_viewport_get_origin (viewport, &origin_x, NULL, NULL);

  width = clutter_actor_get_width (
            clutter_actor_get_parent (CLUTTER_ACTOR (viewport)));
  
  children = clutter_container_get_children (CLUTTER_CONTAINER (group));
  for (c = children; c; c = c->next)
    {
      gint x;
      gdouble pos;
      ClutterActor *actor;
      
      actor = (ClutterActor *)c->data;
      
      /* Get actor position with respect to viewport origin */
      x = clutter_actor_get_x (actor) - origin_x;

      pos = (((gdouble)x / (gdouble)(width-RECT_W)) - 0.5) * 2.0;
      
      /* Apply a function that transforms the actor depending on its 
       * viewport position.
       */
//	printf("%f  pos \n",pos);
//		if(pos==0) exit(0);
      pos = CLAMP(pos * 4.25, -0.5, 0.5);
//	printf("%f  pos \n",pos);
      clutter_actor_set_rotation (actor, CLUTTER_Y_AXIS, -pos * 120.0,
                                  RECT_W/2, 0, RECT_H/2);


      clutter_actor_set_depth (actor, -ABS(pos) * RECT_W);
    }
  g_list_free (children);
}

static void
add_rects (ClutterActor *stage, ClutterActor *group)
{
  gint i;
  
  ClutterColor colour = { 0x72, 0x9f, 0xcf, 0xff };

  for (i = 0; i < RECT_N; i++)
    {
      ClutterActor *rect = clutter_rectangle_new_with_color (&colour);
      
      clutter_container_add_actor (CLUTTER_CONTAINER (group), rect);

      clutter_actor_set_size (rect, RECT_W, RECT_H);
      clutter_actor_set_position (rect, i * RECT_GAP,
                                  CLUTTER_STAGE_HEIGHT ()/2 - RECT_H/2);
		clutter_actor_set_reactive(rect , TRUE);
		g_signal_connect(G_OBJECT(rect), "button-press-event",G_CALLBACK(exit),NULL);

      colour.red = g_random_int_range (0, 255);
      colour.green = g_random_int_range (0, 255);
    }
}

int
main (int argc, char **argv)
{
  gdouble lower, upper;
  NbtkAdjustment *hadjust;
  ClutterActor *stage, *finger_scroll, *viewport, *group;
  ClutterColor stage_color = { 0x34, 0x39, 0x39, 0xff };

  clutter_init (&argc, &argv);

  stage = clutter_stage_get_default ();

  clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
  clutter_actor_set_size (stage, 800, 600);
  
  viewport = nbtk_viewport_new ();
  clutter_actor_set_clip (viewport, 0, 0, 800, 600);
//  group = nbtk_depth_group_new ();
	group = clutter_group_new();
  add_rects (stage, group);
  clutter_container_add_actor (CLUTTER_CONTAINER (viewport), group);
  g_signal_connect (viewport, "notify::x-origin",
                    G_CALLBACK (viewport_x_origin_notify_cb), group);

  g_object_set (G_OBJECT (viewport), "sync-adjustments", FALSE, NULL);
  nbtk_scrollable_get_adjustments (NBTK_SCROLLABLE (viewport), &hadjust, NULL);
  nbtk_adjustment_get_values (hadjust, NULL, &lower, &upper, NULL, NULL, NULL);
  lower -= RECT_W - RECT_GAP;
  upper += RECT_W - RECT_GAP;
  g_object_set (hadjust, "lower", lower, "upper", upper,
                "step-increment", (gdouble)RECT_GAP, "elastic", TRUE, NULL);
  
 // finger_scroll = nbtk_finger_scroll_new (NBTK_FINGER_SCROLL_MODE_KINETIC);
    finger_scroll = nbtk_finger_scroll_new (1); 
 g_object_set (finger_scroll, "decel-rate", 1.1, NULL);
  
  clutter_container_add_actor (CLUTTER_CONTAINER (finger_scroll), viewport);
  clutter_container_add_actor (CLUTTER_CONTAINER (stage), finger_scroll);

  clutter_actor_set_position (finger_scroll, 0, 0);
  clutter_actor_set_size (finger_scroll, 800, 600);

  clutter_actor_show_all (stage);
  clutter_actor_show_all (viewport);
  clutter_actor_show_all (group);
  clutter_actor_show (finger_scroll);
  
  g_object_notify (G_OBJECT (viewport), "x-origin");

cogl_set_depth_test_enabled (TRUE);
  clutter_main ();

  return 0;
}

_______________________________________________
Moblin dev Mailing List
[email protected]

To manage or unsubscribe from this mailing list visit:
https://lists.moblin.org/mailman/listinfo/dev or your user account on 
http://moblin.org once logged in.

For more information on the Moblin Developer Mailing lists visit:
http://moblin.org/community/mailing-lists

Reply via email to