Exemple #1
0
static gboolean
on_pan (ClutterPanAction *action,
        ClutterActor     *scroll,
        gboolean          is_interpolated,
        gpointer         *user_data)
{
  gfloat delta_x, delta_y;
  const ClutterEvent *event = NULL;

  if (is_interpolated)
    clutter_pan_action_get_interpolated_delta (action, &delta_x, &delta_y);
  else
    {
      clutter_gesture_action_get_motion_delta (CLUTTER_GESTURE_ACTION (action), 0, &delta_x, &delta_y);
      event = clutter_gesture_action_get_last_event (CLUTTER_GESTURE_ACTION (action), 0);
    }

  g_print ("[%s] panning dx:%.2f dy:%.2f\n",
           event == NULL ? "INTERPOLATED" :
           event->type == CLUTTER_MOTION ? "MOTION" :
           event->type == CLUTTER_TOUCH_UPDATE ? "TOUCH UPDATE" :
           "?",
           delta_x, delta_y);

  return TRUE;
}
static void
clutter_gesture_action_set_property (GObject      *gobject,
                                     guint         prop_id,
                                     const GValue *value,
                                     GParamSpec   *pspec)
{
  ClutterGestureAction *self = CLUTTER_GESTURE_ACTION (gobject);

  switch (prop_id)
    {
    case PROP_N_TOUCH_POINTS:
      clutter_gesture_action_set_n_touch_points (self, g_value_get_int (value));
      break;

    case PROP_THRESHOLD_TRIGGER_EDGE:
      clutter_gesture_action_set_threshold_trigger_edge (self, g_value_get_enum (value));
      break;

    case PROP_THRESHOLD_TRIGGER_DISTANCE_X:
      clutter_gesture_action_set_threshold_trigger_distance (self, g_value_get_float (value), self->priv->distance_y);
      break;

    case PROP_THRESHOLD_TRIGGER_DISTANCE_Y:
      clutter_gesture_action_set_threshold_trigger_distance (self, self->priv->distance_x, g_value_get_float (value));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
      break;
    }
}
Exemple #3
0
/**
 * clutter_pan_action_get_motion_coords:
 * @self: A #ClutterPanAction
 * @point: the touch point index, with 0 being the first touch
 *   point received by the action
 * @motion_x: (out) (allow-none): return location for the X coordinate
 * @motion_y: (out) (allow-none): return location for the Y coordinate
 *
 * Retrieves the coordinates, in stage space, dependent on the current state
 * of the #ClutterPanAction. If it is inactive, both fields will be
 * set to 0. If it is panning by user action, the values will be equivalent
 * to those returned by clutter_gesture_action_get_motion_coords().
 * If it is interpolating with some form of kinetic scrolling, the values
 * will be equivalent to those returned by
 * clutter_pan_action_get_interpolated_coords(). This is a convenience
 * method designed to be used in replacement "pan" signal handlers.
 */
void
clutter_pan_action_get_motion_coords (ClutterPanAction *self,
                                      guint             point,
                                      gfloat           *motion_x,
                                      gfloat           *motion_y)
{
  ClutterPanActionPrivate *priv;

  g_return_if_fail (CLUTTER_IS_PAN_ACTION (self));

  priv = self->priv;

  switch (priv->state)
    {
    case PAN_STATE_INACTIVE:
      if (motion_x)
        *motion_x = 0;

      if (motion_y)
        *motion_y = 0;
      break;
    case PAN_STATE_PANNING:
      clutter_gesture_action_get_motion_coords (CLUTTER_GESTURE_ACTION (self),
                                                point, motion_x, motion_y);
      break;
    case PAN_STATE_INTERPOLATING:
      clutter_pan_action_get_interpolated_coords (self, motion_x, motion_y);
      break;
    default:
      g_assert_not_reached ();
    }
}
Exemple #4
0
/**
 * clutter_pan_action_get_motion_delta:
 * @self: A #ClutterPanAction
 * @point: the touch point index, with 0 being the first touch
 *   point received by the action
 * @delta_x: (out) (allow-none): return location for the X delta
 * @delta_y: (out) (allow-none): return location for the Y delta
 *
 * Retrieves the delta, in stage space, dependent on the current state
 * of the #ClutterPanAction. If it is inactive, both fields will be
 * set to 0. If it is panning by user action, the values will be equivalent
 * to those returned by clutter_gesture_action_get_motion_delta().
 * If it is interpolating with some form of kinetic scrolling, the values
 * will be equivalent to those returned by
 * clutter_pan_action_get_interpolated_delta(). This is a convenience
 * method designed to be used in replacement "pan" signal handlers.
 */
gfloat
clutter_pan_action_get_motion_delta (ClutterPanAction *self,
                                     guint             point,
                                     gfloat           *delta_x,
                                     gfloat           *delta_y)
{
  ClutterPanActionPrivate *priv;

  g_return_val_if_fail (CLUTTER_IS_PAN_ACTION (self), 0.0f);

  priv = self->priv;

  switch (priv->state)
    {
    case PAN_STATE_INACTIVE:
      if (delta_x)
        *delta_x = 0;

      if (delta_y)
        *delta_y = 0;

      return 0;
    case PAN_STATE_PANNING:
      return clutter_gesture_action_get_motion_delta (CLUTTER_GESTURE_ACTION (self),
                                                      point, delta_x, delta_y);
    case PAN_STATE_INTERPOLATING:
      return clutter_pan_action_get_interpolated_delta (self, delta_x, delta_y);
    default:
      g_assert_not_reached ();
    }
}
static void
clutter_gesture_action_finalize (GObject *gobject)
{
  ClutterGestureActionPrivate *priv = CLUTTER_GESTURE_ACTION (gobject)->priv;

  g_array_unref (priv->points);

  G_OBJECT_CLASS (clutter_gesture_action_parent_class)->finalize (gobject);
}
Exemple #6
0
static void
gesture_end (ClutterGestureAction *gesture,
             ClutterActor         *actor)
{
  ClutterPanAction *self = CLUTTER_PAN_ACTION (gesture);
  ClutterPanActionPrivate *priv = self->priv;
  gfloat velocity, velocity_x, velocity_y;
  gfloat delta_x, delta_y;
  gfloat tau;
  gint duration;

  clutter_gesture_action_get_release_coords (CLUTTER_GESTURE_ACTION (self), 0, &priv->release_x, &priv->release_y);

  if (!priv->should_interpolate)
    {
      priv->state = PAN_STATE_INACTIVE;
      return;
    }

  priv->state = PAN_STATE_INTERPOLATING;

  clutter_gesture_action_get_motion_delta (gesture, 0, &delta_x, &delta_y);
  velocity = clutter_gesture_action_get_velocity (gesture, 0, &velocity_x, &velocity_y);

  /* Exponential timing constant v(t) = v(0) * exp(-t/tau)
   * tau = 1000ms / (frame_per_second * - ln(decay_per_frame))
   * with frame_per_second = 60 and decay_per_frame = 0.95, tau ~= 325ms
   * see http://ariya.ofilabs.com/2011/10/flick-list-with-its-momentum-scrolling-and-deceleration.html */
  tau = 1000.0f / (reference_fps * - logf (priv->deceleration_rate));

  /* See where the decreasing velocity reaches $min_velocity px/ms
   * v(t) = v(0) * exp(-t/tau) = min_velocity
   * t = - tau * ln( min_velocity / |v(0)|) */
  duration = - tau * logf (min_velocity / (ABS (velocity) * priv->acceleration_factor));

  /* Target point: x(t) = v(0) * tau * [1 - exp(-t/tau)] */
  priv->target_x = velocity_x * priv->acceleration_factor * tau * (1 - exp ((float)-duration / tau));
  priv->target_y = velocity_y * priv->acceleration_factor * tau * (1 - exp ((float)-duration / tau));

  if (ABS (velocity) * priv->acceleration_factor > min_velocity && duration > FLOAT_EPSILON)
    {
      priv->interpolated_x = priv->interpolated_y = 0.0f;
      priv->deceleration_timeline = clutter_timeline_new (duration);
      clutter_timeline_set_progress_mode (priv->deceleration_timeline, CLUTTER_EASE_OUT_EXPO);

      g_signal_connect (priv->deceleration_timeline, "new_frame",
                        G_CALLBACK (on_deceleration_new_frame), self);
      g_signal_connect (priv->deceleration_timeline, "stopped",
                        G_CALLBACK (on_deceleration_stopped), self);
      clutter_timeline_start (priv->deceleration_timeline);
    }
  else
    {
      emit_pan_stopped (self, actor);
    }
}
Exemple #7
0
static void
clutter_zoom_action_init (ClutterZoomAction *self)
{
  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, CLUTTER_TYPE_ZOOM_ACTION,
                                            ClutterZoomActionPrivate);

  self->priv->zoom_axis = CLUTTER_ZOOM_BOTH;

  clutter_gesture_action_set_n_touch_points (CLUTTER_GESTURE_ACTION (self), 2);
}
static void
clutter_gesture_action_get_property (GObject    *gobject,
                                     guint       prop_id,
                                     GValue     *value,
                                     GParamSpec *pspec)
{
  ClutterGestureAction *self = CLUTTER_GESTURE_ACTION (gobject);

  switch (prop_id)
    {
    case PROP_N_TOUCH_POINTS:
      g_value_set_int (value, self->priv->requested_nb_points);
      break;

    case PROP_THRESHOLD_TRIGGER_EDGE:
      g_value_set_enum (value, self->priv->edge);
      break;

    case PROP_THRESHOLD_TRIGGER_DISTANCE_X:
      if (self->priv->distance_x > 0.0)
        g_value_set_float (value, self->priv->distance_x);
      else
        g_value_set_float (value, gesture_get_default_threshold ());
      break;

    case PROP_THRESHOLD_TRIGGER_DISTANCE_Y:
      if (self->priv->distance_y > 0.0)
        g_value_set_float (value, self->priv->distance_y);
      else
        g_value_set_float (value, gesture_get_default_threshold ());
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
      break;
    }
}
static void
clutter_gesture_action_set_actor (ClutterActorMeta *meta,
                                  ClutterActor     *actor)
{
  ClutterGestureActionPrivate *priv = CLUTTER_GESTURE_ACTION (meta)->priv;
  ClutterActorMetaClass *meta_class =
    CLUTTER_ACTOR_META_CLASS (clutter_gesture_action_parent_class);

  if (priv->actor_capture_id != 0)
    {
      ClutterActor *old_actor = clutter_actor_meta_get_actor (meta);

      if (old_actor != NULL)
        g_signal_handler_disconnect (old_actor, priv->actor_capture_id);

      priv->actor_capture_id = 0;
    }

  if (priv->stage_capture_id != 0)
    {
      if (priv->stage != NULL)
        g_signal_handler_disconnect (priv->stage, priv->stage_capture_id);

      priv->stage_capture_id = 0;
      priv->stage = NULL;
    }

  if (actor != NULL)
    {
      priv->actor_capture_id =
        g_signal_connect (actor, "captured-event",
                          G_CALLBACK (actor_captured_event_cb),
                          meta);
    }

  meta_class->set_actor (meta, actor);
}
static void
clutter_tap_action_init (ClutterTapAction *self)
{
  _clutter_gesture_action_set_threshold_trigger_edge (CLUTTER_GESTURE_ACTION (self),
                                                      CLUTTER_GESTURE_TRIGGER_EDGE_BEFORE);
}