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