[gnome-control-center/wip/carlosg/calibrator-gtk: 31/32] wacom: Port calibrator UI to GTK+



commit 0a86f275505e49cdf3e48c379811106c4abae9e4
Author: Carlos Garnacho <carlosg gnome org>
Date:   Tue Oct 9 18:28:08 2018 +0200

    wacom: Port calibrator UI to GTK+
    
    Same dog, different collar. The UI has been ported 1:1 to GTK+, using
    GtkBuilder, CSS and event controllers fairly reduced the amount of code
    needed for this.
    
    It also allows us to stop initializing clutter-gtk across the several
    executables.

 meson.build                                        |   5 -
 panels/wacom/calibrator/calibrator-gui.c           | 546 ++++-----------------
 panels/wacom/calibrator/calibrator.css             |  47 ++
 panels/wacom/calibrator/calibrator.ui              | 243 +++++++++
 panels/wacom/calibrator/cc-clock-actor.c           | 192 --------
 panels/wacom/calibrator/cc-clock.c                 | 299 +++++++++++
 .../calibrator/{cc-clock-actor.h => cc-clock.h}    |  27 +-
 panels/wacom/calibrator/cc-target-actor.c          | 226 ---------
 panels/wacom/calibrator/cc-target-actor.h          |  39 --
 panels/wacom/calibrator/main.c                     |  10 +-
 panels/wacom/calibrator/meson.build                |   5 +-
 panels/wacom/calibrator/target.svg                 |  93 ++++
 panels/wacom/meson.build                           |  21 +-
 panels/wacom/test-wacom.c                          |   7 +-
 panels/wacom/wacom.gresource.xml                   |   3 +
 shell/cc-application.c                             |  12 -
 16 files changed, 811 insertions(+), 964 deletions(-)
---
diff --git a/meson.build b/meson.build
index 49816d185..e9e5f7c70 100644
--- a/meson.build
+++ b/meson.build
@@ -198,15 +198,10 @@ if host_is_linux_not_s390
   # gnome-bluetooth
   gnome_bluetooth_dep = dependency('gnome-bluetooth-1.0', version: '>= 3.18.2')
 
-  # Wacom
-  assert(clutter_gtk_dep.found(), 'clutter-gtk library is required for wacom support, but is not available.')
-
   libwacom_dep = dependency('libwacom', version: '>= 0.7')
 
   wacom_deps = [
-    clutter_gtk_dep,
     libwacom_dep,
-    dependency('clutter-1.0', version: '>= 1.11.3'),
   ]
   config_h.set('HAVE_WACOM_3D_STYLUS', libwacom_dep.version().version_compare('>= 0.27'),
                description: 'Define to 1 if libwacom provides definition for 3D styli')
diff --git a/panels/wacom/calibrator/calibrator-gui.c b/panels/wacom/calibrator/calibrator-gui.c
index 81a52cc56..661fc519d 100644
--- a/panels/wacom/calibrator/calibrator-gui.c
+++ b/panels/wacom/calibrator/calibrator-gui.c
@@ -14,8 +14,8 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
- * Author: Joaquim Rocha <jrocha redhat com>
- *         (based on previous work by Tias Guns and Soren Hauberg)
+ * Author: Carlos Garnacho <carlosg gnome org>
+ *         (based on previous work by Joaquim Rocha, Tias Guns and Soren Hauberg)
  */
 
 #include "config.h"
@@ -26,14 +26,10 @@
 #include <glib/gi18n.h>
 #include <gdk/gdkx.h>
 #include <gtk/gtk.h>
-#include <cairo.h>
-#include <clutter-gtk/clutter-gtk.h>
-#include <clutter/clutter.h>
 
 #include "calibrator.h"
 #include "calibrator-gui.h"
-#include "cc-clock-actor.h"
-#include "cc-target-actor.h"
+#include "cc-clock.h"
 
 struct CalibArea
 {
@@ -46,54 +42,23 @@ struct CalibArea
   double X[4], Y[4];
   int display_width, display_height;
 
-  GtkWidget         *window;
-  ClutterActor      *stage;
-  ClutterActor      *action_layer;
-  ClutterActor      *clock;
-  ClutterActor      *target;
-  ClutterActor      *success_image;
-  ClutterActor      *text_title_holder;
-  ClutterActor      *helper_text_title;
-  ClutterActor      *text_body_holder;
-  ClutterActor      *helper_text_body;
-  ClutterActor      *error_text;
-  ClutterTransition *clock_timeline;
-  ClutterTransition *error_msg_timeline;
-  ClutterTransition *helper_msg_timeline;
-  GdkPixbuf         *icon_success;
+  GtkWidget  *window;
+  GtkBuilder *builder;
+  GtkWidget  *error_revealer;
+  GtkWidget  *clock;
 
   FinishCallback callback;
   gpointer       user_data;
 };
 
-#define TARGET_SHOW_ANIMATION_DURATION 500
-#define TARGET_HIDE_ANIMATION_DURATION 200
-
-#define COLOR_GRAY 127
-
-/* Window parameters */
-#define WINDOW_OPACITY          0.9
-
 /* Timeout parameters */
 #define MAX_TIME                15000 /* 15000 = 15 sec */
 #define END_TIME                750   /*  750 = 0.75 sec */
 
-/* Text printed on screen */
-#define HELP_TEXT_TITLE            N_("Screen Calibration")
-#define HELP_TEXT_MAIN             N_("Please tap the target markers as they " \
-                                      "appear on screen to calibrate the tablet.")
-#define HELP_TEXT_ANIMATION_DURATION 300
-
-#define ERROR_MESSAGE                    N_("Mis-click detected, restarting…")
-#define ERROR_MESSAGE_ANIMATION_DURATION 500
-
-#define ICON_SUCCESS    "emblem-ok-symbolic"
-#define ICON_SIZE       300
-
 static void
-set_display_size(CalibArea *calib_area,
-                 int        width,
-                 int        height)
+set_display_size (CalibArea *calib_area,
+                  int        width,
+                  int        height)
 {
   int delta_x;
   int delta_y;
@@ -118,48 +83,12 @@ set_display_size(CalibArea *calib_area,
   calib_area->Y[LR] = calib_area->display_height - delta_y - 1;
 
   /* reset calibration if already started */
-  reset(&calib_area->calibrator);
-}
-
-static void
-resize_display(CalibArea *calib_area)
-{
-  gfloat width, height;
-
-  clutter_actor_get_size (calib_area->stage, &width, &height);
-  if (calib_area->display_width != width ||
-      calib_area->display_height != height)
-    {
-      gint i = calib_area->calibrator.num_clicks;
-      set_display_size(calib_area, width, height);
-      cc_target_actor_move_center (CC_TARGET_ACTOR (calib_area->target),
-                                   calib_area->X[i],
-                                   calib_area->Y[i]);
-    }
-}
-
-static void
-on_allocation_changed (ClutterActor          *actor,
-                       ClutterActorBox       *box,
-                       ClutterAllocationFlags flags,
-                       CalibArea             *area)
-{
-  if (!gtk_widget_is_visible (area->window))
-    return;
-
-  resize_display (area);
+  reset (&calib_area->calibrator);
 }
 
 static void
 calib_area_notify_finish (CalibArea *area)
 {
-  clutter_timeline_stop (CLUTTER_TIMELINE (area->clock_timeline));
-
-  if (area->error_msg_timeline)
-    clutter_timeline_stop (CLUTTER_TIMELINE (area->error_msg_timeline));
-  if (area->helper_msg_timeline)
-    clutter_timeline_stop (CLUTTER_TIMELINE (area->helper_msg_timeline));
-
   gtk_widget_hide (area->window);
 
   (*area->callback) (area, area->user_data);
@@ -184,64 +113,18 @@ calib_area_finish_idle_cb (CalibArea *area)
 static void
 set_success (CalibArea *area)
 {
-  ClutterImage *image;
-  GdkPixbuf *icon = area->icon_success;
+  GtkWidget *stack;
 
-  if (icon == NULL)
-    return;
-
-  image = CLUTTER_IMAGE (clutter_actor_get_content (area->success_image));
-  clutter_image_set_data (image,
-                          gdk_pixbuf_get_pixels (icon),
-                          gdk_pixbuf_get_has_alpha (icon)
-                          ? COGL_PIXEL_FORMAT_RGBA_8888
-                          : COGL_PIXEL_FORMAT_RGB_888,
-                          gdk_pixbuf_get_width (icon),
-                          gdk_pixbuf_get_height (icon),
-                          gdk_pixbuf_get_rowstride (icon),
-                          NULL);
-  clutter_actor_set_size (area->success_image,
-                          gdk_pixbuf_get_width (icon),
-                          gdk_pixbuf_get_height (icon));
-
-  clutter_actor_show (area->success_image);
-  clutter_actor_hide (area->action_layer);
+  stack = GTK_WIDGET (gtk_builder_get_object (area->builder, "stack"));
+  gtk_stack_set_visible_child_name (GTK_STACK (stack), "page1");
 }
 
 static void
 set_calibration_status (CalibArea *area)
 {
-  GtkIconTheme *icon_theme;
-  GtkIconInfo  *icon_info;
-  GdkRGBA       white;
-
-  icon_theme = gtk_icon_theme_get_default ();
-  icon_info = gtk_icon_theme_lookup_icon (icon_theme,
-                                          ICON_SUCCESS,
-                                          ICON_SIZE,
-                                          GTK_ICON_LOOKUP_USE_BUILTIN);
-  if (icon_info == NULL)
-    {
-      g_warning ("Failed to find icon \"%s\"", ICON_SUCCESS);
-      goto out;
-    }
-
-  gdk_rgba_parse (&white, "White");
-  area->icon_success = gtk_icon_info_load_symbolic (icon_info,
-                                                    &white,
-                                                    NULL,
-                                                    NULL,
-                                                    NULL,
-                                                    NULL,
-                                                    NULL);
-  g_object_unref (icon_info);
-
-  if (!area->icon_success)
-    g_warning ("Failed to load icon \"%s\"", ICON_SUCCESS);
-
- out:
   area->success = finish (&area->calibrator, &area->axis, &area->swap);
-  if (area->success && area->icon_success)
+
+  if (area->success)
     {
       set_success (area);
       g_timeout_add (END_TIME,
@@ -254,119 +137,82 @@ set_calibration_status (CalibArea *area)
     }
 }
 
-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;
-}
-
 static void
 show_error_message (CalibArea *area)
 {
-  ClutterTransition *transition;
-  clutter_actor_show (area->error_text);
-  transition = get_error_message_transition (area);
-  clutter_timeline_start (CLUTTER_TIMELINE (transition));
-
-  g_clear_object (&area->error_msg_timeline);
-  area->error_msg_timeline = transition;
+  gtk_revealer_set_reveal_child (GTK_REVEALER (area->error_revealer), TRUE);
 }
 
 static void
-on_error_message_transparent (ClutterTimeline *timeline,
-                              CalibArea       *area)
+hide_error_message (CalibArea *area)
 {
-  clutter_actor_hide (area->error_text);
+  gtk_revealer_set_reveal_child (GTK_REVEALER (area->error_revealer), FALSE);
 }
 
 static void
-hide_error_message (CalibArea *area)
+set_active_target (CalibArea *area,
+                   int        n_target)
 {
-  ClutterTransition *transition;
-  transition = get_error_message_transition (area);
-  clutter_transition_set_from (transition, G_TYPE_UINT, 255);
-  clutter_transition_set_to (transition, G_TYPE_UINT, 0);
-  g_signal_connect (CLUTTER_TIMELINE (transition),
-                    "completed",
-                    G_CALLBACK (on_error_message_transparent),
-                    area);
-  clutter_timeline_start (CLUTTER_TIMELINE (transition));
-
-  g_clear_object (&area->error_msg_timeline);
-  area->error_msg_timeline = transition;
+  GtkWidget *targets[] = {
+    GTK_WIDGET (gtk_builder_get_object (area->builder, "target1")),
+    GTK_WIDGET (gtk_builder_get_object (area->builder, "target2")),
+    GTK_WIDGET (gtk_builder_get_object (area->builder, "target3")),
+    GTK_WIDGET (gtk_builder_get_object (area->builder, "target4")),
+  };
+  int i;
+
+  for (i = 0; i < G_N_ELEMENTS (targets); i++)
+    gtk_widget_set_sensitive (targets[i], i == n_target);
 }
 
-static gboolean
-on_button_press_event (GtkWidget      *widget,
-                       GdkEventButton *event,
-                       CalibArea      *area)
+static void
+on_gesture_press (GtkGestureMultiPress *gesture,
+                  guint                 n_press,
+                  gdouble               x,
+                  gdouble               y,
+                  CalibArea            *area)
 {
   gint num_clicks;
   gboolean success;
   GdkDevice *source;
+  GdkEvent *event;
 
   if (area->success)
-    return FALSE;
-
-  if (event->type != GDK_BUTTON_PRESS ||
-      event->button != GDK_BUTTON_PRIMARY)
-    return FALSE;
+    return;
 
+  event = gtk_get_current_event ();
   source = gdk_event_get_source_device ((GdkEvent *) event);
+  gdk_event_free (event);
 
   /* Check matching device if a device was provided */
   if (area->device && area->device != source)
     {
       g_debug ("Ignoring input from device %s",
               gdk_device_get_name (source));
-      return FALSE;
+      return;
     }
 
   /* Handle click */
-  clutter_timeline_stop (CLUTTER_TIMELINE (area->clock_timeline));
-  clutter_timeline_start (CLUTTER_TIMELINE (area->clock_timeline));
+  /* FIXME: reset clock */
   success = add_click(&area->calibrator,
-                      (int) event->x,
-                      (int) event->y);
+                      (int) x,
+                      (int) y);
 
   num_clicks = area->calibrator.num_clicks;
 
   if (!success && num_clicks == 0)
     show_error_message (area);
   else
-    {
-      gboolean visible;
-      g_object_get (area->error_text, "visible", &visible, NULL);
-
-      if (visible)
-        hide_error_message (area);
-    }
+    hide_error_message (area);
 
   /* Are we done yet? */
   if (num_clicks >= 4)
     {
       set_calibration_status (area);
-      return FALSE;
+      return;
     }
 
-  cc_target_actor_move_center (CC_TARGET_ACTOR (area->target),
-                               area->X[num_clicks],
-                               area->Y[num_clicks]);
-
-  return FALSE;
+  set_active_target (area, num_clicks);
 }
 
 static gboolean
@@ -397,72 +243,19 @@ on_focus_out_event (GtkWidget *widget,
 }
 
 static void
-on_timeout (ClutterTimeline *timeline,
-            CalibArea       *area)
+on_clock_finished (CcClock   *clock,
+                   CalibArea *area)
 {
   set_calibration_status (area);
 }
 
 static void
-show_helper_text_body (CalibArea *area)
+on_title_revealed (CalibArea *area)
 {
-  ClutterTransition *transition;
-  gfloat height;
-
-  height = clutter_actor_get_height (area->helper_text_body);
-  clutter_actor_show (area->helper_text_body);
-
-  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_body));
-  clutter_transition_set_from (transition, G_TYPE_FLOAT, -height);
-  clutter_transition_set_to (transition, G_TYPE_FLOAT, 0.0);
-  clutter_timeline_start (CLUTTER_TIMELINE (transition));
-
-  g_clear_object (&area->helper_msg_timeline);
-  area->helper_msg_timeline = transition;
-}
+  GtkWidget *revealer;
 
-static void
-on_helper_text_title_shown (ClutterTimeline *timelines,
-                            CalibArea       *area)
-{
-  show_helper_text_body (area);
-}
-
-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;
+  revealer = GTK_WIDGET (gtk_builder_get_object (area->builder, "subtitle_revealer"));
+  gtk_revealer_set_reveal_child (GTK_REVEALER (revealer), TRUE);
 }
 
 static gboolean
@@ -470,191 +263,28 @@ on_fullscreen (GtkWindow           *window,
                GdkEventWindowState *event,
                CalibArea           *area)
 {
-  ClutterRect rect;
+  GtkWidget *revealer;
 
   if ((event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) == 0)
     return FALSE;
 
-  /* Protect against window state multiple changes*/
-  if (clutter_actor_is_visible (area->action_layer))
-    return FALSE;
-
-  clutter_actor_show (area->action_layer);
-  clutter_actor_show (area->clock);
-
-  rect.origin.x = 0;
-  rect.origin.y = 0;
-  clutter_actor_get_size (area->helper_text_title,
-                          &rect.size.width,
-                          &rect.size.height);
-  g_object_set (area->text_title_holder, "clip-rect", &rect, NULL);
+  revealer = GTK_WIDGET (gtk_builder_get_object (area->builder, "title_revealer"));
+  g_signal_connect_swapped (revealer, "notify::child-revealed",
+                            G_CALLBACK (on_title_revealed),
+                            area);
+  gtk_revealer_set_reveal_child (GTK_REVEALER (revealer), TRUE);
 
-  clutter_actor_get_size (area->helper_text_body,
-                          &rect.size.width,
-                          &rect.size.height);
-  g_object_set (area->text_body_holder, "clip-rect", &rect, NULL);
-  clutter_actor_set_y (area->helper_text_body,
-                       - clutter_actor_get_height (area->helper_text_body));
+  set_active_target (area, 0);
 
-  show_helper_text_title (area);
   return FALSE;
 }
 
 static void
-set_up_stage (CalibArea *calib_area, ClutterActor *stage)
+on_size_allocate (GtkWidget     *widget,
+                  GtkAllocation *allocation,
+                  CalibArea     *area)
 {
-  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);
+  set_display_size (area, allocation->width, allocation->height);
 }
 
 /**
@@ -680,11 +310,13 @@ calib_area_new (GdkScreen      *screen,
   GdkWindow *window;
   GdkCursor *cursor;
 #endif /* FAKE_AREA */
-  GtkWidget *clutter_embed;
-  ClutterActor *stage;
+  GtkCssProvider *provider;
+  GtkGesture *press;
 
   g_return_val_if_fail (callback, NULL);
 
+  g_type_ensure (CC_TYPE_CLOCK);
+
   calib_area = g_new0 (CalibArea, 1);
   calib_area->callback = callback;
   calib_area->user_data = user_data;
@@ -692,7 +324,20 @@ calib_area_new (GdkScreen      *screen,
   calib_area->calibrator.threshold_doubleclick = threshold_doubleclick;
   calib_area->calibrator.threshold_misclick = threshold_misclick;
 
-  calib_area->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  calib_area->builder = gtk_builder_new_from_resource 
("/org/gnome/control-center/wacom/calibrator/calibrator.ui");
+  calib_area->window = GTK_WIDGET (gtk_builder_get_object (calib_area->builder, "window"));
+  calib_area->error_revealer = GTK_WIDGET (gtk_builder_get_object (calib_area->builder, "error_revealer"));
+  calib_area->clock = GTK_WIDGET (gtk_builder_get_object (calib_area->builder, "clock"));
+
+  provider = gtk_css_provider_new ();
+  gtk_css_provider_load_from_resource (provider, 
"/org/gnome/control-center/wacom/calibrator/calibrator.css");
+  gtk_style_context_add_provider_for_screen (gtk_widget_get_screen (calib_area->window),
+                                             GTK_STYLE_PROVIDER (provider),
+                                             GTK_STYLE_PROVIDER_PRIORITY_USER);
+
+  cc_clock_set_duration (CC_CLOCK (calib_area->clock), MAX_TIME);
+  g_signal_connect (calib_area->clock, "finished",
+                    G_CALLBACK (on_clock_finished), calib_area);
 
 #ifndef FAKE_AREA
   /* No cursor */
@@ -706,13 +351,6 @@ calib_area_new (GdkScreen      *screen,
   gtk_window_set_keep_above (GTK_WINDOW (calib_area->window), TRUE);
 #endif /* FAKE_AREA */
 
-  /* Set up the embedded stage */
-  clutter_embed = gtk_clutter_embed_new ();
-  gtk_container_add (GTK_CONTAINER (calib_area->window),
-                     clutter_embed);
-
-  stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (clutter_embed));
-
   /* Move to correct screen */
   if (screen == NULL)
     screen = gdk_screen_get_default ();
@@ -721,8 +359,6 @@ calib_area_new (GdkScreen      *screen,
 
   calib_area->calibrator.geometry = rect;
 
-  set_up_stage (calib_area, stage);
-
   g_signal_connect (calib_area->window,
                     "key-release-event",
                     G_CALLBACK (on_key_release_event),
@@ -740,18 +376,22 @@ calib_area_new (GdkScreen      *screen,
                     G_CALLBACK (on_fullscreen),
                     calib_area);
   g_signal_connect (calib_area->window,
-                    "button-press-event",
-                    G_CALLBACK (on_button_press_event),
+                    "size-allocate",
+                    G_CALLBACK (on_size_allocate),
                     calib_area);
 
+  press = gtk_gesture_multi_press_new (calib_area->window);
+  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (press), GDK_BUTTON_PRIMARY);
+  g_signal_connect (press, "pressed",
+                    G_CALLBACK (on_gesture_press), calib_area);
+
   gtk_window_fullscreen_on_monitor (GTK_WINDOW (calib_area->window), screen, n_monitor);
 
   visual = gdk_screen_get_rgba_visual (screen);
   if (visual != NULL)
     gtk_widget_set_visual (GTK_WIDGET (calib_area->window), visual);
 
-  gtk_widget_show_all (calib_area->window);
-  clutter_actor_hide (calib_area->action_layer);
+  gtk_widget_show (calib_area->window);
 
   return calib_area;
 }
@@ -780,10 +420,6 @@ calib_area_free (CalibArea *area)
 {
   g_return_if_fail (area != NULL);
 
-  g_clear_object (&area->icon_success);
-  g_clear_object (&area->clock_timeline);
-  g_clear_object (&area->error_msg_timeline);
-  g_clear_object (&area->helper_msg_timeline);
   gtk_widget_destroy (area->window);
   g_free (area);
 }
diff --git a/panels/wacom/calibrator/calibrator.css b/panels/wacom/calibrator/calibrator.css
new file mode 100644
index 000000000..bfb0574ce
--- /dev/null
+++ b/panels/wacom/calibrator/calibrator.css
@@ -0,0 +1,47 @@
+window {
+    background-color: #000;
+}
+
+* {
+    color: #fff;
+}
+
+label {
+    font-size: larger;
+}
+
+#title {
+    font-weight: bold;
+    color: #888;
+}
+
+#error {
+    font-weight: bold;
+}
+
+#target {
+    background-image: url('target.svg');
+    background-repeat: no-repeat;
+    background-position: 50% 50%;
+}
+
+@keyframes target-enabled-animation {
+    0%   { background-size: 0px }
+    90%  { background-size: 120px }
+    100% { background-size: 100px }
+}
+
+@keyframes target-disabled-animation {
+    0%   { background-size: 100px }
+    100% { background-size: 0px }
+}
+
+#target:not(disabled) {
+    animation: target-enabled-animation 1 ease 0.5s;
+    background-size: 100px;
+}
+
+#target:disabled {
+    animation: target-disabled-animation 1 ease 0.2s;
+    background-size: 0px;
+}
diff --git a/panels/wacom/calibrator/calibrator.ui b/panels/wacom/calibrator/calibrator.ui
new file mode 100644
index 000000000..5ec412c34
--- /dev/null
+++ b/panels/wacom/calibrator/calibrator.ui
@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkWindow" id="window">
+    <property name="can_focus">False</property>
+    <child>
+      <placeholder/>
+    </child>
+    <child>
+      <object class="GtkStack" id="stack">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="transition_duration">0</property>
+        <child>
+          <object class="GtkGrid">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="row_homogeneous">True</property>
+            <property name="column_homogeneous">True</property>
+            <child>
+              <object class="GtkBox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkBox" id="box1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="CcClock" id="clock">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkBox" id="box2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <object class="GtkRevealer" id="title_revealer">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="transition_duration">300</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="name">title</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="label" translatable="yes">Screen Calibration</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRevealer" id="subtitle_revealer">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="transition_duration">300</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="name">subtitle</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="label" translatable="yes">Please tap the target markers as they 
appear on screen to calibrate the tablet.</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRevealer" id="error_revealer">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="transition_type">crossfade</property>
+                        <property name="transition_duration">500</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="name">error</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="label" translatable="yes">Mis-click detected, 
restarting…</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+                <property name="width">8</property>
+                <property name="height">8</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="target3">
+                <property name="name">target</property>
+                <property name="width_request">100</property>
+                <property name="height_request">100</property>
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <property name="can_focus">False</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">6</property>
+                <property name="width">2</property>
+                <property name="height">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="target4">
+                <property name="name">target</property>
+                <property name="width_request">100</property>
+                <property name="height_request">100</property>
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <property name="can_focus">False</property>
+              </object>
+              <packing>
+                <property name="left_attach">6</property>
+                <property name="top_attach">6</property>
+                <property name="width">2</property>
+                <property name="height">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="target1">
+                <property name="name">target</property>
+                <property name="width_request">100</property>
+                <property name="height_request">100</property>
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <property name="can_focus">False</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+                <property name="width">2</property>
+                <property name="height">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="target2">
+                <property name="name">target</property>
+                <property name="width_request">100</property>
+                <property name="height_request">100</property>
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <property name="can_focus">False</property>
+              </object>
+              <packing>
+                <property name="left_attach">6</property>
+                <property name="top_attach">0</property>
+                <property name="width">2</property>
+                <property name="height">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkRevealer">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="transition_type">none</property>
+                <property name="transition_duration">0</property>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+                <property name="width">8</property>
+                <property name="height">8</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="name">page0</property>
+            <property name="title" translatable="yes">page0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkImage">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="pixel_size">300</property>
+            <property name="icon_name">emblem-ok-symbolic</property>
+          </object>
+          <packing>
+            <property name="name">page1</property>
+            <property name="title" translatable="yes">page1</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+  <object class="GtkSizeGroup">
+    <property name="mode">vertical</property>
+    <widgets>
+      <widget name="box1"/>
+      <widget name="box2"/>
+    </widgets>
+  </object>
+</interface>
diff --git a/panels/wacom/calibrator/cc-clock.c b/panels/wacom/calibrator/cc-clock.c
new file mode 100644
index 000000000..a93ac576e
--- /dev/null
+++ b/panels/wacom/calibrator/cc-clock.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright © 2018 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Joaquim Rocha <jrocha redhat com>
+ *          Carlos Garnacho <carlosg gnome org>
+ */
+#include "config.h"
+#include "cc-clock.h"
+
+#include <math.h>
+
+#define CLOCK_RADIUS       50
+#define CLOCK_LINE_WIDTH   10
+#define CLOCK_LINE_PADDING 10
+#define EXTRA_SPACE        2
+
+typedef struct _CcClock CcClock;
+
+struct _CcClock
+{
+  GtkWidget parent_instance;
+  guint duration;
+  gint64 start_time;
+  gboolean running;
+};
+
+enum {
+  PROP_DURATION = 1,
+  N_PROPS
+};
+
+static GParamSpec *props[N_PROPS] = { 0, };
+
+enum {
+  FINISHED,
+  N_SIGNALS
+};
+
+static guint signals[N_SIGNALS] = { 0, };
+
+G_DEFINE_TYPE (CcClock, cc_clock, GTK_TYPE_WIDGET)
+
+static gint64
+cc_clock_get_time_diff (CcClock *clock)
+{
+  GdkFrameClock *frame_clock;
+  gint64 current_time;
+
+  frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (clock));
+  current_time = gdk_frame_clock_get_frame_time (frame_clock);
+
+  return current_time - clock->start_time;
+}
+
+static gdouble
+cc_clock_get_angle (CcClock *clock)
+{
+  gint64 time_diff;
+
+  time_diff = cc_clock_get_time_diff (clock);
+
+  if (time_diff > clock->duration * 1000)
+    return 360;
+
+  return ((gdouble) time_diff / (clock->duration * 1000)) * 360;
+}
+
+static gboolean
+cc_clock_draw (GtkWidget *widget,
+               cairo_t   *cr)
+{
+  GtkAllocation allocation;
+  gdouble angle;
+
+  gtk_widget_get_allocation (widget, &allocation);
+  angle = cc_clock_get_angle (CC_CLOCK (widget));
+
+  cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+  cairo_paint (cr);
+  cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+
+  /* Draw the clock background */
+  cairo_arc (cr, allocation.width / 2, allocation.height / 2, CLOCK_RADIUS / 2, 0.0, 2.0 * M_PI);
+  cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
+  cairo_fill_preserve (cr);
+  cairo_stroke (cr);
+
+  cairo_set_line_width (cr, CLOCK_LINE_WIDTH);
+
+  cairo_arc (cr,
+             allocation.width / 2,
+             allocation.height / 2,
+             (CLOCK_RADIUS - CLOCK_LINE_WIDTH - CLOCK_LINE_PADDING) / 2,
+             3 * M_PI_2,
+             3 * M_PI_2 + angle * M_PI / 180.0);
+  cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+  cairo_stroke (cr);
+
+  return TRUE;
+}
+
+static void
+cc_clock_stop (CcClock *clock)
+{
+  GdkFrameClock *frame_clock;
+
+  if (!clock->running)
+    return;
+
+  frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (clock));
+
+  gdk_frame_clock_end_updating (frame_clock);
+  clock->running = FALSE;
+}
+
+static void
+on_frame_clock_update (CcClock *clock)
+{
+  gint64 time_diff;
+
+  if (!clock->running)
+    return;
+
+  time_diff = cc_clock_get_time_diff (clock);
+
+  if (time_diff > clock->duration * 1000)
+    {
+      g_signal_emit (clock, signals[FINISHED], 0);
+      cc_clock_stop (clock);
+    }
+
+  gtk_widget_queue_draw (GTK_WIDGET (clock));
+}
+
+static void
+cc_clock_map (GtkWidget *widget)
+{
+  GdkFrameClock *frame_clock;
+
+  GTK_WIDGET_CLASS (cc_clock_parent_class)->map (widget);
+
+  frame_clock = gtk_widget_get_frame_clock (widget);
+  g_signal_connect_object (frame_clock, "update",
+                           G_CALLBACK (on_frame_clock_update),
+                           widget, G_CONNECT_SWAPPED);
+  cc_clock_reset (CC_CLOCK (widget));
+}
+
+static void
+cc_clock_set_property (GObject      *object,
+                       guint         prop_id,
+                       const GValue *value,
+                       GParamSpec   *pspec)
+{
+  CcClock *clock = CC_CLOCK (object);
+
+  switch (prop_id)
+    {
+    case PROP_DURATION:
+      clock->duration = g_value_get_uint (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+cc_clock_get_property (GObject    *object,
+                       guint       prop_id,
+                       GValue     *value,
+                       GParamSpec *pspec)
+{
+  CcClock *clock = CC_CLOCK (object);
+
+  switch (prop_id)
+    {
+    case PROP_DURATION:
+      g_value_set_uint (value, clock->duration);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+cc_clock_get_preferred_width (GtkWidget *widget,
+                              gint      *minimum,
+                              gint      *natural)
+{
+  if (minimum)
+    *minimum = CLOCK_RADIUS + EXTRA_SPACE;
+  if (natural)
+    *natural = CLOCK_RADIUS + EXTRA_SPACE;
+}
+
+static void
+cc_clock_get_preferred_height (GtkWidget *widget,
+                               gint      *minimum,
+                               gint      *natural)
+{
+  if (minimum)
+    *minimum = CLOCK_RADIUS + EXTRA_SPACE;
+  if (natural)
+    *natural = CLOCK_RADIUS + EXTRA_SPACE;
+}
+
+static void
+cc_clock_class_init (CcClockClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->set_property = cc_clock_set_property;
+  object_class->get_property = cc_clock_get_property;
+
+  widget_class->map = cc_clock_map;
+  widget_class->draw = cc_clock_draw;
+  widget_class->get_preferred_width = cc_clock_get_preferred_width;
+  widget_class->get_preferred_height = cc_clock_get_preferred_height;
+
+  signals[FINISHED] =
+    g_signal_new ("finished",
+                  CC_TYPE_CLOCK,
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+
+  props[PROP_DURATION] =
+    g_param_spec_uint ("duration",
+                       "Duration",
+                       "Duration",
+                       0, G_MAXUINT, 0,
+                       G_PARAM_READWRITE |
+                       G_PARAM_STATIC_STRINGS |
+                       G_PARAM_CONSTRUCT_ONLY);
+
+  g_object_class_install_properties (object_class, N_PROPS, props);
+}
+
+static void
+cc_clock_init (CcClock *clock)
+{
+  gtk_widget_set_has_window (GTK_WIDGET (clock), FALSE);
+}
+
+GtkWidget *
+cc_clock_new (guint duration)
+{
+  return g_object_new (CC_TYPE_CLOCK,
+                       "duration", duration,
+                       NULL);
+}
+
+void
+cc_clock_reset (CcClock *clock)
+{
+  GdkFrameClock *frame_clock;
+
+  if (!gtk_widget_get_mapped (GTK_WIDGET (clock)))
+    return;
+
+  frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (clock));
+
+  cc_clock_stop (clock);
+
+  clock->running = TRUE;
+  clock->start_time = g_get_monotonic_time ();
+  gdk_frame_clock_begin_updating (frame_clock);
+}
+
+void
+cc_clock_set_duration (CcClock *clock,
+                       guint    duration)
+{
+  clock->duration = duration;
+  g_object_notify (G_OBJECT (clock), "duration");
+  cc_clock_reset (clock);
+}
+
+guint
+cc_clock_get_duration (CcClock *clock)
+{
+  return clock->duration;
+}
diff --git a/panels/wacom/calibrator/cc-clock-actor.h b/panels/wacom/calibrator/cc-clock.h
similarity index 54%
rename from panels/wacom/calibrator/cc-clock-actor.h
rename to panels/wacom/calibrator/cc-clock.h
index f6e2b2e97..1e7e182f4 100644
--- a/panels/wacom/calibrator/cc-clock-actor.h
+++ b/panels/wacom/calibrator/cc-clock.h
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2013 Red Hat, Inc.
+ * Copyright © 2018 Red Hat, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -14,22 +14,29 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
- * Author: Joaquim Rocha <jrocha redhat com>
+ * Author: Carlos Garnacho <carlosg gnome org>
  */
 
-#ifndef __CC_CLOCK_ACTOR_H__
-#define __CC_CLOCK_ACTOR_H__
+#ifndef __CC_CLOCK_H__
+#define __CC_CLOCK_H__
 
 #include <glib.h>
-#include <clutter/clutter.h>
+#include <gtk/gtk.h>
 
 G_BEGIN_DECLS
 
-#define CC_CLOCK_ACTOR_TYPE (cc_clock_actor_get_type ())
-G_DECLARE_FINAL_TYPE (CcClockActor, cc_clock_actor, CC, CLOCK_ACTOR, ClutterActor)
+#define CC_TYPE_CLOCK (cc_clock_get_type ())
 
-ClutterActor * cc_clock_actor_new      (void);
+G_DECLARE_FINAL_TYPE (CcClock, cc_clock, CC, CLOCK, GtkWidget)
 
-G_END_DECLS
+GtkWidget * cc_clock_new          (guint duration);
 
-#endif /* __CC_CLOCK_ACTOR_H__ */
+void        cc_clock_reset        (CcClock *clock);
+
+void        cc_clock_set_duration (CcClock *clock,
+                                   guint    duration);
+guint       cc_clock_get_duration (CcClock *clock);
+
+GType       cc_clock_get_type     (void);
+
+#endif /* __CC_CLOCK_H__ */
diff --git a/panels/wacom/calibrator/main.c b/panels/wacom/calibrator/main.c
index 135a862c9..63efaf9f3 100644
--- a/panels/wacom/calibrator/main.c
+++ b/panels/wacom/calibrator/main.c
@@ -28,7 +28,6 @@
 #include <string.h>
 #include <dirent.h>
 #include <glib/gi18n.h>
-#include <clutter-gtk/clutter-gtk.h>
 
 #include <X11/extensions/XInput.h>
 
@@ -397,14 +396,9 @@ int main(int argc, char** argv)
     bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
     textdomain (GETTEXT_PACKAGE);
 
-    g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
+    gtk_init (&argc, &argv);
 
-    /* GTK setup */
-    if (gtk_clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
-    {
-      g_critical ("Unable to initialize Clutter");
-      return 1;
-    }
+    g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
 
     calib_area = calib_area_new (NULL,
                                 0,  /* monitor */
diff --git a/panels/wacom/calibrator/meson.build b/panels/wacom/calibrator/meson.build
index 2877904a7..f894e604b 100644
--- a/panels/wacom/calibrator/meson.build
+++ b/panels/wacom/calibrator/meson.build
@@ -3,8 +3,7 @@ calibrator_inc = include_directories('.')
 common_sources = files(
   'calibrator.c',
   'calibrator-gui.c',
-  'cc-clock-actor.c',
-  'cc-target-actor.c'
+  'cc-clock.c',
 )
 
 calibrator_deps = deps + [m_dep]
@@ -25,7 +24,7 @@ libwacom_calibrator_test = static_library(
   c_args: test_cflags
 )
 
-sources = common_sources + files('main.c')
+sources = common_sources + wacom_gresource + files('main.c')
 
 executable(
   'test-calibrator',
diff --git a/panels/wacom/calibrator/target.svg b/panels/wacom/calibrator/target.svg
new file mode 100644
index 000000000..60b4cbb0a
--- /dev/null
+++ b/panels/wacom/calibrator/target.svg
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   width="200"
+   height="200"
+   viewBox="0 0 52.916666 52.916668"
+   version="1.1"
+   id="svg8"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)"
+   sodipodi:docname="target.svg">
+  <defs
+     id="defs2" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="2.8"
+     inkscape:cx="26.277089"
+     inkscape:cy="74.824155"
+     inkscape:document-units="mm"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     units="px"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:window-width="2160"
+     inkscape:window-height="1311"
+     inkscape:window-x="0"
+     inkscape:window-y="55"
+     inkscape:window-maximized="1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid4518" />
+    <sodipodi:guide
+       position="-7.9374999,13.229167"
+       orientation="1,0"
+       id="guide4542"
+       inkscape:locked="false" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata5">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-244.08332)">
+    <path
+       
style="fill:none;stroke:#ffffff;stroke-width:0.5291667px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 0,270.54165 h 52.916667 v 0"
+       id="path4520"
+       inkscape:connector-curvature="0" />
+    <path
+       
style="fill:none;stroke:#ffffff;stroke-width:0.5291667px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 26.458334,244.08331 v 52.91667"
+       id="path4522"
+       inkscape:connector-curvature="0" />
+    <ellipse
+       style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.5291667;stroke-opacity:1"
+       id="path4530"
+       cx="26.458332"
+       cy="270.54163"
+       rx="5.2916665"
+       ry="5.2916679" />
+    <ellipse
+       
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.00000012;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path4534"
+       cx="26.458332"
+       cy="270.54163"
+       rx="15.875"
+       ry="15.875004" />
+  </g>
+</svg>
diff --git a/panels/wacom/meson.build b/panels/wacom/meson.build
index e206b00e9..5f6222071 100644
--- a/panels/wacom/meson.build
+++ b/panels/wacom/meson.build
@@ -9,6 +9,15 @@ cflags += ['-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir)]
 
 test_cflags = cflags + ['-DFAKE_AREA']
 
+wacom_gresource = gnome.compile_resources(
+  'cc-' + cappletname + '-resources',
+  cappletname + '.gresource.xml',
+    source_dir : '.',
+        c_name : 'cc_' + cappletname,
+  dependencies : resource_data,
+        export : true
+)
+
 subdir('calibrator')
 
 panels_list += cappletname
@@ -43,6 +52,9 @@ common_sources = files(
 )
 
 resource_data = files(
+  'calibrator/calibrator.ui',
+  'calibrator/calibrator.css',
+  'calibrator/target.svg',
   'button-mapping.ui',
   'gnome-wacom-properties.ui',
   'wacom-stylus-3btn.svg',
@@ -59,14 +71,7 @@ resource_data = files(
   'wacom-tablet.svg'
 )
 
-common_sources += gnome.compile_resources(
-  'cc-' + cappletname + '-resources',
-  cappletname + '.gresource.xml',
-    source_dir : '.',
-        c_name : 'cc_' + cappletname,
-  dependencies : resource_data,
-        export : true
-)
+common_sources += wacom_gresource
 
 sources = common_sources + files(
   'cc-' + cappletname + '-panel.c',
diff --git a/panels/wacom/test-wacom.c b/panels/wacom/test-wacom.c
index ffc751db2..16821b230 100644
--- a/panels/wacom/test-wacom.c
+++ b/panels/wacom/test-wacom.c
@@ -2,10 +2,8 @@
 #include "config.h"
 
 #include <glib/gi18n.h>
-#include <clutter-gtk/clutter-gtk.h>
 
 #include "cc-wacom-page.h"
-#include "clutter/clutter.h"
 
 #define FIXED_WIDTH 675
 
@@ -125,10 +123,7 @@ int main (int argc, char **argv)
        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
        textdomain (GETTEXT_PACKAGE);
 
-       if (gtk_clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) {
-               g_critical ("Unable to initialize Clutter");
-               return 1;
-        }
+       gtk_init (&argc, &argv);
 
        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
diff --git a/panels/wacom/wacom.gresource.xml b/panels/wacom/wacom.gresource.xml
index a18ffb1ed..846835fad 100644
--- a/panels/wacom/wacom.gresource.xml
+++ b/panels/wacom/wacom.gresource.xml
@@ -4,6 +4,9 @@
     <file preprocess="xml-stripblanks">gnome-wacom-properties.ui</file>
     <file preprocess="xml-stripblanks">wacom-stylus-page.ui</file>
     <file preprocess="xml-stripblanks">button-mapping.ui</file>
+    <file preprocess="xml-stripblanks">calibrator/calibrator.ui</file>
+    <file>calibrator/calibrator.css</file>
+    <file>calibrator/target.svg</file>
     <file>wacom-tablet.svg</file>
     <file>wacom-stylus.svg</file>
     <file>wacom-stylus-3btn-no-eraser.svg</file>
diff --git a/shell/cc-application.c b/shell/cc-application.c
index 8ffb2bdbf..3fb9b52b5 100644
--- a/shell/cc-application.c
+++ b/shell/cc-application.c
@@ -31,10 +31,6 @@
 #include "cc-panel-loader.h"
 #include "cc-window.h"
 
-#if defined(HAVE_WACOM) || defined(HAVE_CHEESE)
-#include <clutter-gtk/clutter-gtk.h>
-#endif /* HAVE_WACOM || HAVE_CHEESE */
-
 struct _CcApplication
 {
   GtkApplication  parent;
@@ -238,14 +234,6 @@ cc_application_startup (GApplication *application)
 
   G_APPLICATION_CLASS (cc_application_parent_class)->startup (application);
 
-#if defined(HAVE_WACOM) || defined(HAVE_CHEESE)
-  if (gtk_clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
-    {
-      g_critical ("Unable to initialize Clutter");
-      return;
-    }
-#endif /* HAVE_WACOM || HAVE_CHEESE */
-
   menu = g_menu_new ();
 
   section = g_menu_new ();


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]