static void
show_helper_text_title (CalibArea *area)
{
  ClutterTransition *transition;

  gfloat height = clutter_actor_get_height (area->helper_text_title);
  clutter_actor_set_y (area->helper_text_title,
                       - clutter_actor_get_height (area->helper_text_title));
  clutter_actor_show (area->helper_text_title);

  transition = clutter_property_transition_new ("y");
  clutter_timeline_set_progress_mode (CLUTTER_TIMELINE (transition),
                                      CLUTTER_EASE_OUT);
  clutter_timeline_set_duration (CLUTTER_TIMELINE (transition),
                                 HELP_TEXT_ANIMATION_DURATION);
  clutter_transition_set_animatable (transition,
                                     CLUTTER_ANIMATABLE (area->helper_text_title));
  clutter_transition_set_from (transition, G_TYPE_FLOAT, -height);
  clutter_transition_set_to (transition, G_TYPE_FLOAT, 0.0);

  g_signal_connect (CLUTTER_TIMELINE (transition),
                    "completed",
                    G_CALLBACK (on_helper_text_title_shown),
                    area);

  clutter_timeline_start (CLUTTER_TIMELINE (transition));

  g_clear_object (&area->helper_msg_timeline);
  area->helper_msg_timeline = transition;
}
Пример #2
0
static void
clutter_timeline_set_property (GObject      *object,
			       guint         prop_id,
			       const GValue *value,
			       GParamSpec   *pspec)
{
  ClutterTimeline        *timeline;
  ClutterTimelinePrivate *priv;

  timeline = CLUTTER_TIMELINE(object);
  priv = timeline->priv;

  switch (prop_id)
    {
    case PROP_LOOP:
      priv->loop = g_value_get_boolean (value);
      break;

    case PROP_DELAY:
      priv->delay = g_value_get_uint (value);
      break;

    case PROP_DURATION:
      clutter_timeline_set_duration (timeline, g_value_get_uint (value));
      break;

    case PROP_DIRECTION:
      clutter_timeline_set_direction (timeline, g_value_get_enum (value));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}
Пример #3
0
static ClutterTransition *
create_fade_out_transition()
{
    auto transition  = clutter_property_transition_new("opacity");
    clutter_transition_set_from(transition, G_TYPE_UINT, 255);
    clutter_transition_set_to(transition, G_TYPE_UINT, 0);
    clutter_timeline_set_duration(CLUTTER_TIMELINE(transition), FADE_DURATION);
    clutter_timeline_set_repeat_count(CLUTTER_TIMELINE(transition), 0);
    clutter_timeline_set_progress_mode(CLUTTER_TIMELINE(transition), CLUTTER_EASE_IN_OUT_CUBIC);
    return transition;
}
Пример #4
0
/**
 * mx_adjustment_interpolate:
 * @adjustment: A #MxAdjustment
 * @value: A #gdouble
 * @duration: duration in milliseconds
 * @mode: A #ClutterAnimationMode
 *
 * Interpolate #MxAdjustment:value to the new value specified by @value, using
 * the mode and duration given.
 */
void
mx_adjustment_interpolate (MxAdjustment *adjustment,
                           gdouble       value,
                           guint         duration,
                           gulong        mode)
{
  MxAdjustmentPrivate *priv = adjustment->priv;

  g_return_if_fail (isfinite (value));

  if (duration <= 1)
    {
      stop_interpolation (adjustment);
      mx_adjustment_set_value (adjustment, value);
      return;
    }

  priv->old_position = priv->value;
  priv->new_position = value;

  if (!priv->interpolation)
    {
      priv->interpolation = clutter_timeline_new (duration);

      g_signal_connect (priv->interpolation,
                        "new-frame",
                        G_CALLBACK (interpolation_new_frame_cb),
                        adjustment);
      g_signal_connect (priv->interpolation,
                        "completed",
                        G_CALLBACK (interpolation_completed_cb),
                        adjustment);
    }
  else
    {
      /* Extend the animation if it gets interrupted, otherwise frequent calls
       * to this function will end up with no advancements until the calls
       * finish (as the animation never gets a chance to start).
       */
      clutter_timeline_set_direction (priv->interpolation,
                                      CLUTTER_TIMELINE_FORWARD);
      clutter_timeline_rewind (priv->interpolation);
      clutter_timeline_set_duration (priv->interpolation, duration);
    }

  if (priv->interpolate_alpha)
    g_object_unref (priv->interpolate_alpha);

  priv->interpolate_alpha = clutter_alpha_new_full (priv->interpolation,
                                                    mode);

  clutter_timeline_start (priv->interpolation);
}
static ClutterTransition *
get_error_message_transition (CalibArea *area)
{
  ClutterTransition *transition;

  clutter_actor_show (area->error_text);
  transition = clutter_property_transition_new ("opacity");
  clutter_timeline_set_progress_mode (CLUTTER_TIMELINE (transition),
                                      CLUTTER_EASE_OUT);
  clutter_timeline_set_duration (CLUTTER_TIMELINE (transition),
                                 ERROR_MESSAGE_ANIMATION_DURATION);
  clutter_transition_set_animatable (transition,
                                     CLUTTER_ANIMATABLE (area->error_text));
  clutter_transition_set_from (transition, G_TYPE_UINT, 0);
  clutter_transition_set_to (transition, G_TYPE_UINT, 255);

  return transition;
}
Пример #6
0
static ClutterAlpha *
layout_manager_real_begin_animation (ClutterLayoutManager *manager,
                                     guint                 duration,
                                     gulong                mode)
{
    ClutterTimeline *timeline;
    ClutterAlpha *alpha;

    alpha = g_object_get_qdata (G_OBJECT (manager), quark_layout_alpha);
    if (alpha != NULL)
    {
        clutter_alpha_set_mode (alpha, mode);

        timeline = clutter_alpha_get_timeline (alpha);
        clutter_timeline_set_duration (timeline, duration);
        clutter_timeline_rewind (timeline);

        return alpha;
    };

    timeline = clutter_timeline_new (duration);

    alpha = clutter_alpha_new_full (timeline, mode);

    /* let the alpha take ownership of the timeline */
    g_object_unref (timeline);

    g_signal_connect_swapped (timeline, "completed",
                              G_CALLBACK (clutter_layout_manager_end_animation),
                              manager);
    g_signal_connect_swapped (timeline, "new-frame",
                              G_CALLBACK (clutter_layout_manager_layout_changed),
                              manager);

    g_object_set_qdata_full (G_OBJECT (manager),
                             quark_layout_alpha, alpha,
                             (GDestroyNotify) g_object_unref);

    clutter_timeline_start (timeline);

    return alpha;
}
Пример #7
0
void
tweet_animation_set_duration (TweetAnimation *animation,
                              gint           msecs)
{
  TweetAnimationPrivate *priv;

  g_return_if_fail (TWEET_IS_ANIMATION (animation));

  priv = animation->priv;

  if (priv->duration != msecs)
    {
      priv->duration = msecs;

      if (priv->timeline)
        clutter_timeline_set_duration (priv->timeline, msecs);

      g_object_notify (G_OBJECT (animation), "duration");
    }
}
Пример #8
0
static void
interpolation_completed_cb (ClutterTimeline *timeline,
                            MxAdjustment    *adjustment)
{
  MxAdjustmentPrivate *priv = adjustment->priv;

  if (priv->elastic && priv->clamp_value)
    {
      if (clutter_timeline_get_direction (priv->interpolation) ==
            CLUTTER_TIMELINE_FORWARD)
        {
          clutter_timeline_set_direction (priv->interpolation,
                                          CLUTTER_TIMELINE_BACKWARD);
          clutter_timeline_set_duration (priv->interpolation, 250);
          clutter_timeline_rewind (priv->interpolation);

          if (priv->new_position < priv->lower)
            {
              priv->old_position = priv->lower;
              clutter_timeline_start (priv->interpolation);
            }
          else if (priv->new_position > (priv->upper - priv->page_size))
            {
              priv->old_position = priv->upper - priv->page_size;
              clutter_timeline_start (priv->interpolation);
            }
        }
      else
        {
          stop_interpolation (adjustment);
          mx_adjustment_set_value (adjustment, priv->old_position);
        }
    }
  else
    {
      stop_interpolation (adjustment);
      mx_adjustment_set_value (adjustment, priv->new_position);
    }

  g_signal_emit (adjustment, signals[INTERPOLATION_COMPLETED], 0);
}
G_MODULE_EXPORT int
test_keyframe_transition_main (int argc, char *argv[])
{
  ClutterActor *stage;
  int i;

  if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
    return EXIT_FAILURE;

  stage = clutter_stage_new ();
  clutter_stage_set_title (CLUTTER_STAGE (stage), "Keyframe Transitions");
  g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);

  for (i = 0; i < 3; i++)
    {
      ClutterTransition *transition, *group;
      ClutterActor *rect;
      float cur_x, cur_y;
      float new_x, new_y;
      gchar *name;

      cur_x = PADDING;
      cur_y = PADDING + ((SIZE + PADDING) * i);

      new_x = clutter_actor_get_width (stage) - PADDING - SIZE;
      new_y = g_random_double_range (PADDING, clutter_actor_get_height (stage) - PADDING - SIZE);

      name = g_strdup_printf ("rect%02d", i);

      rect = clutter_actor_new ();

      clutter_actor_set_name (rect, name);
      clutter_actor_set_background_color (rect, &colors[i]);
      clutter_actor_set_size (rect, SIZE, SIZE);
      clutter_actor_set_position (rect, PADDING, cur_y);
      clutter_actor_add_child (stage, rect);

      group = clutter_transition_group_new ();
      clutter_timeline_set_duration (CLUTTER_TIMELINE (group), 2000);
      clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (group), 1);
      clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (group), TRUE);

      transition = clutter_keyframe_transition_new ("x");
      clutter_transition_set_from (transition, G_TYPE_FLOAT, cur_x);
      clutter_transition_set_to (transition, G_TYPE_FLOAT, new_x);

      clutter_keyframe_transition_set (CLUTTER_KEYFRAME_TRANSITION (transition),
                                       G_TYPE_FLOAT, 1,
                                       0.5, new_x / 2.0f, CLUTTER_EASE_OUT_EXPO);
      clutter_transition_group_add_transition (CLUTTER_TRANSITION_GROUP (group), transition);
      g_object_unref (transition);

      transition = clutter_keyframe_transition_new ("y");
      clutter_transition_set_from (transition, G_TYPE_FLOAT, cur_y);
      clutter_transition_set_to (transition, G_TYPE_FLOAT, cur_y);

      clutter_keyframe_transition_set (CLUTTER_KEYFRAME_TRANSITION (transition),
                                       G_TYPE_FLOAT, 1,
                                       0.5, new_y, CLUTTER_EASE_OUT_EXPO);
      clutter_transition_group_add_transition (CLUTTER_TRANSITION_GROUP (group), transition);
      g_object_unref (transition);

      clutter_actor_add_transition (rect, "rectAnimation", group);

      g_signal_connect (rect, "transition-stopped",
                        G_CALLBACK (on_transition_stopped),
                        NULL);
      g_object_unref (group);

      g_free (name);
    }

  clutter_actor_show (stage);

  clutter_main ();

  return EXIT_SUCCESS;
}
Пример #10
0
void
st_theme_node_transition_update (StThemeNodeTransition *transition,
                                 StThemeNode           *new_node)
{
  StThemeNodeTransitionPrivate *priv = transition->priv;
  StThemeNode *old_node;
  ClutterTimelineDirection direction;

  g_return_if_fail (ST_IS_THEME_NODE_TRANSITION (transition));
  g_return_if_fail (ST_IS_THEME_NODE (new_node));

  direction = clutter_timeline_get_direction (priv->timeline);
  old_node = (direction == CLUTTER_TIMELINE_FORWARD) ? priv->old_theme_node
                                                     : priv->new_theme_node;

  /* If the update is the reversal of the current transition,
   * we reverse the timeline.
   * Otherwise, we should initiate a new transition from the
   * current state to the new one; this is hard to do if the
   * transition is in an intermediate state, so we just cancel
   * the ongoing transition in that case.
   * Note that reversing a timeline before any time elapsed
   * results in the timeline's time position being set to the
   * full duration - this is not what we want, so we cancel the
   * transition as well in that case.
   */
  if (st_theme_node_equal (new_node, old_node))
    {
      if (clutter_timeline_get_elapsed_time (priv->timeline) > 0)
        {
          if (direction == CLUTTER_TIMELINE_FORWARD)
            clutter_timeline_set_direction (priv->timeline,
                                            CLUTTER_TIMELINE_BACKWARD);
          else
            clutter_timeline_set_direction (priv->timeline,
                                            CLUTTER_TIMELINE_FORWARD);
        }
      else
        {
          clutter_timeline_stop (priv->timeline);
          g_signal_emit (transition, signals[COMPLETED], 0);
        }
    }
  else
    {
      if (clutter_timeline_get_elapsed_time (priv->timeline) > 0)
        {
          clutter_timeline_stop (priv->timeline);
          g_signal_emit (transition, signals[COMPLETED], 0);
        }
      else
        {
          guint new_duration = st_theme_node_get_transition_duration (new_node);

          clutter_timeline_set_duration (priv->timeline, new_duration);

          /* If the change doesn't affect painting, we don't need to redraw,
           * but we still need to replace the node so that we properly share
           * caching with the painting that happens after the transition finishes.
           */
          if (!st_theme_node_paint_equal (priv->new_theme_node, new_node))
              priv->needs_setup = TRUE;

          g_object_unref (priv->new_theme_node);
          priv->new_theme_node = g_object_ref (new_node);
        }
    }
}
Пример #11
0
static void
mex_column_expand_children (MexColumn    *column,
                            ClutterActor *start_at)
{
  MexColumnPrivate *priv = column->priv;
  guint offset, increment;
  GList *c;
  gchar **markers;
  gint i;
  gboolean start;

  if (priv->n_items < 1)
    return;

  /* Open/close boxes as appropriate */
  offset = 0;
  increment = 150;

  clutter_timeline_set_duration (priv->expand_timeline,
                                 priv->n_items * increment);

  clutter_timeline_set_delay (priv->expand_timeline, 350);

  /* remove the previous markers */
  markers = clutter_timeline_list_markers (priv->expand_timeline, -1, NULL);
  if (markers)
    {
      for (i = 0; markers[i]; i++)
        {
          clutter_timeline_remove_marker (priv->expand_timeline,
                                          markers[i]);
        }
    }
  g_strfreev (markers);

  /* start is TRUE if start_at is NULL, otherwise it is set to TRUE when the
   * start_at item is found */
  start = (start_at == NULL);

  for (c = priv->children; c; c = g_list_next (c))
    {
      gchar signal_name[32+16];
      ClutterActor *child = c->data;

      if (!MEX_IS_CONTENT_BOX (child))
        continue;

      mex_content_box_set_important (MEX_CONTENT_BOX (child), TRUE);
      mex_column_expand_child (child);

      /* continue until the start item has been found */
      if (child == start_at)
        start = TRUE;

      if (!start)
        continue;

      /* Note, 'marker-reached::' is 16 characters long */
      g_snprintf (signal_name, G_N_ELEMENTS (signal_name),
                  "marker-reached::%p", child);

      /* stagger opening */
      clutter_timeline_add_marker_at_time (priv->expand_timeline,
                                           signal_name + 16, offset);
      g_signal_connect_swapped (priv->expand_timeline, signal_name,
                                G_CALLBACK (mex_column_expand_child),
                                child);

      offset += increment;

    }

    clutter_timeline_start (priv->expand_timeline);
}
Пример #12
0
int
main (int argc, char *argv[])
{
  ClutterActor *stage, *actor;
  ClutterContent *canvas;
  ClutterTransition *transition;

  /* initialize Clutter */
  if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
    return EXIT_FAILURE;

  /* create a stage */
  stage = clutter_stage_new ();
  clutter_stage_set_title (CLUTTER_STAGE (stage), "Rectangle with rounded corners");
  clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black);
  clutter_actor_set_size (stage, 500, 500);
  clutter_actor_show (stage);

  /* our 2D canvas, courtesy of Cairo */
  canvas = clutter_canvas_new ();
  clutter_canvas_set_size (CLUTTER_CANVAS (canvas), 300, 300);

  /* the actor that will display the contents of the canvas */
  actor = clutter_actor_new ();
  clutter_actor_set_content (actor, canvas);
  clutter_actor_set_content_gravity (actor, CLUTTER_CONTENT_GRAVITY_CENTER);
  clutter_actor_set_content_scaling_filters (actor,
                                             CLUTTER_SCALING_FILTER_TRILINEAR,
                                             CLUTTER_SCALING_FILTER_LINEAR);
  clutter_actor_set_pivot_point (actor, 0.5f, 0.5f);
  clutter_actor_add_constraint (actor, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5));
  clutter_actor_set_request_mode (actor, CLUTTER_REQUEST_CONTENT_SIZE);
  clutter_actor_add_child (stage, actor);

  /* the actor now owns the canvas */
  g_object_unref (canvas);

  /* create the continuous animation of the actor spinning around its center */
  transition = clutter_property_transition_new ("rotation-angle-y");
  clutter_transition_set_from (transition, G_TYPE_DOUBLE, 0.0);
  clutter_transition_set_to (transition, G_TYPE_DOUBLE, 360.0);
  clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 2000);
  clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), -1);
  clutter_actor_add_transition (actor, "rotateActor", transition);

  /* the actor now owns the transition */
  g_object_unref (transition);

  /* quit on destroy */
  g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);

  /* connect our drawing code */
  g_signal_connect (canvas, "draw", G_CALLBACK (draw_content), NULL);

  /* invalidate the canvas, so that we can draw before the main loop starts */
  clutter_content_invalidate (canvas);

  clutter_main ();

  return EXIT_SUCCESS;
}
static void
set_up_stage (CalibArea *calib_area, ClutterActor *stage)
{
  ClutterPoint anchor;
  ClutterColor color;
  ClutterContent *success_content;
  gfloat height;
  gchar *markup;

  calib_area->stage = stage;
  calib_area->action_layer = clutter_actor_new ();
  calib_area->clock = cc_clock_actor_new ();
  calib_area->target = cc_target_actor_new ();
  calib_area->text_title_holder = clutter_actor_new ();
  calib_area->helper_text_title = clutter_text_new ();
  calib_area->text_body_holder = clutter_actor_new ();
  calib_area->helper_text_body = clutter_text_new ();
  calib_area->error_text = clutter_text_new ();
  calib_area->success_image = clutter_actor_new ();

  clutter_stage_set_use_alpha (CLUTTER_STAGE (stage), TRUE);

  clutter_actor_hide (calib_area->target);

  /* bind the action layer's geometry to the stage's */
  clutter_actor_add_constraint (calib_area->action_layer,
                                clutter_bind_constraint_new (stage,
                                                             CLUTTER_BIND_SIZE,
                                                             0));
  clutter_actor_add_child (stage, calib_area->action_layer);

  g_signal_connect (stage,
                    "allocation-changed",
                    G_CALLBACK (on_allocation_changed),
                    calib_area);

  clutter_color_from_string (&color, "#000");
  color.alpha = WINDOW_OPACITY * 255;
  clutter_actor_set_background_color (stage, &color);

  clutter_actor_add_child (calib_area->action_layer, calib_area->clock);
  clutter_actor_add_constraint (calib_area->clock,
                                clutter_align_constraint_new (stage,
                                                              CLUTTER_ALIGN_BOTH,
                                                              0.5));

  clutter_actor_add_child (calib_area->action_layer, calib_area->target);

  /* set the helper text */
  anchor.x =  0;
  g_object_set (calib_area->text_title_holder, "pivot-point", &anchor, NULL);

  clutter_actor_add_child (calib_area->action_layer,
                           calib_area->text_title_holder);
  clutter_actor_add_child (calib_area->text_title_holder,
                           calib_area->helper_text_title);
  height = clutter_actor_get_height (calib_area->clock);
  clutter_actor_add_constraint (calib_area->text_title_holder,
                                clutter_bind_constraint_new (calib_area->clock,
                                                             CLUTTER_BIND_Y,
                                                             height * 1.5));
  clutter_actor_add_constraint (calib_area->text_title_holder,
                                clutter_align_constraint_new (stage,
                                                              CLUTTER_ALIGN_X_AXIS,
                                                              .5));

  clutter_text_set_line_alignment (CLUTTER_TEXT (calib_area->helper_text_title),
                                   PANGO_ALIGN_CENTER);

  color.red = COLOR_GRAY;
  color.green = COLOR_GRAY;
  color.blue = COLOR_GRAY;
  color.alpha = 255;

  markup = g_strdup_printf ("<big><b>%s</b></big>",
                            _(HELP_TEXT_TITLE));
  clutter_text_set_markup (CLUTTER_TEXT (calib_area->helper_text_title), markup);
  clutter_text_set_color (CLUTTER_TEXT (calib_area->helper_text_title), &color);
  g_free (markup);

  g_object_set (calib_area->text_body_holder, "pivot-point", &anchor, NULL);

  clutter_actor_add_child (calib_area->action_layer,
                           calib_area->text_body_holder);
  clutter_actor_add_child (calib_area->text_body_holder,
                           calib_area->helper_text_body);
  height = clutter_actor_get_height (calib_area->helper_text_title);
  clutter_actor_add_constraint (calib_area->text_body_holder,
                                clutter_bind_constraint_new (calib_area->text_title_holder,
                                                             CLUTTER_BIND_Y,
                                                             height * 1.2));
  clutter_actor_add_constraint (calib_area->text_body_holder,
                                clutter_align_constraint_new (stage,
                                                              CLUTTER_ALIGN_X_AXIS,
                                                              .5));

  clutter_text_set_line_alignment (CLUTTER_TEXT (calib_area->helper_text_body),
                                   PANGO_ALIGN_CENTER);
  markup = g_strdup_printf ("<span foreground=\"white\"><big>%s</big></span>",
                            _(HELP_TEXT_MAIN));
  clutter_text_set_markup (CLUTTER_TEXT (calib_area->helper_text_body), markup);
  g_free (markup);

  /* set the error text */
  g_object_set (calib_area->error_text, "pivot-point", &anchor, NULL);

  clutter_actor_add_child (calib_area->action_layer, calib_area->error_text);
  height = clutter_actor_get_height (calib_area->helper_text_body);
  clutter_actor_add_constraint (calib_area->error_text,
                                clutter_bind_constraint_new (calib_area->text_title_holder,
                                                             CLUTTER_BIND_Y,
                                                             height * 3));
  clutter_actor_add_constraint (calib_area->error_text,
                                clutter_align_constraint_new (stage,
                                                              CLUTTER_ALIGN_X_AXIS,
                                                              .5));

  clutter_text_set_line_alignment (CLUTTER_TEXT (calib_area->error_text),
                                   PANGO_ALIGN_CENTER);
  markup = g_strdup_printf ("<span foreground=\"white\"><big>"
                            "<b>%s</b></big></span>",
                            ERROR_MESSAGE);
  clutter_text_set_markup (CLUTTER_TEXT (calib_area->error_text), markup);
  g_free (markup);

  clutter_actor_hide (calib_area->error_text);

  /* configure success image */
  success_content = clutter_image_new ();
  clutter_actor_set_content (calib_area->success_image,
                             success_content);
  g_object_unref (success_content);
  clutter_actor_add_child (stage, calib_area->success_image);
  clutter_actor_add_constraint (calib_area->success_image,
                                clutter_align_constraint_new (stage,
                                                              CLUTTER_ALIGN_BOTH,
                                                              .5));

  /* animate clock */
  calib_area->clock_timeline = clutter_property_transition_new ("angle");
  clutter_timeline_set_progress_mode (CLUTTER_TIMELINE (calib_area->clock_timeline),
                                      CLUTTER_LINEAR);
  clutter_timeline_set_duration (CLUTTER_TIMELINE (calib_area->clock_timeline),
                                 MAX_TIME);
  clutter_transition_set_animatable (calib_area->clock_timeline,
                                     CLUTTER_ANIMATABLE (calib_area->clock));
  clutter_transition_set_from (calib_area->clock_timeline, G_TYPE_FLOAT, .0);
  clutter_transition_set_to (calib_area->clock_timeline, G_TYPE_FLOAT, 360.0);
  clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (calib_area->clock_timeline),
                                     -1);
  clutter_timeline_start (CLUTTER_TIMELINE (calib_area->clock_timeline));
  g_signal_connect (CLUTTER_TIMELINE (calib_area->clock_timeline),
                    "completed",
                    G_CALLBACK (on_timeout),
                    calib_area);

  g_signal_connect (stage,
                    "button-press-event",
                    G_CALLBACK (on_button_press_event),
                    calib_area);
  g_signal_connect (stage,
                    "key-release-event",
                    G_CALLBACK (on_key_release_event),
                    calib_area);
}