static void
gesture_end (ClutterGestureAction *action,
             ClutterActor         *actor)
{
  ClutterSwipeActionPrivate *priv = CLUTTER_SWIPE_ACTION (action)->priv;
  gfloat press_x, press_y;
  gfloat release_x, release_y;
  ClutterSwipeDirection direction = 0;
  gboolean can_emit_swipe;

  clutter_gesture_action_get_press_coords (action,
                                           0,
                                           &press_x, &press_y);

  clutter_gesture_action_get_release_coords (action,
                                             0,
                                             &release_x, &release_y);

  if (release_x - press_x > priv->threshold)
    direction |= CLUTTER_SWIPE_DIRECTION_RIGHT;
  else if (press_x - release_x > priv->threshold)
    direction |= CLUTTER_SWIPE_DIRECTION_LEFT;

  if (release_y - press_y > priv->threshold)
    direction |= CLUTTER_SWIPE_DIRECTION_DOWN;
  else if (press_y - release_y > priv->threshold)
    direction |= CLUTTER_SWIPE_DIRECTION_UP;

  /* XXX:2.0 remove */
  g_signal_emit (action, swipe_signals[SWIPE], 0, actor, direction,
                 &can_emit_swipe);
  if (can_emit_swipe)
    g_signal_emit (action, swipe_signals[SWEPT], 0, actor, direction);
}
Example #2
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);
    }
}