wacom: Re-write gui_gtk in Clutter to introduce animations
The name of the file was also changed to calibratorgui.c/h to avoid it being inconsistent, this way it is no longer dependent on the the technology. https://bugzilla.gnome.org/show_bug.cgi?id=667797
This commit is contained in:
parent
11382d241a
commit
d78bc9772a
15 changed files with 1366 additions and 611 deletions
12
configure.ac
12
configure.ac
|
@ -292,16 +292,20 @@ case $host_os in
|
|||
PKG_CHECK_MODULES(WACOM_PANEL, $COMMON_MODULES
|
||||
gnome-settings-daemon >= $GSD_REQUIRED_VERSION
|
||||
xi >= 1.2 x11 libwacom >= $LIBWACOM_REQUIRED_VERSION
|
||||
gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION)
|
||||
AC_DEFINE(BUILD_WACOM, 1, [Define to 1 to build the Wacom panel])
|
||||
have_wacom=yes
|
||||
gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION
|
||||
clutter-gtk-1.0
|
||||
clutter-1.0 >= $CLUTTER_REQUIRED_VERSION, [have_wacom=yes], [have_wacom=no])
|
||||
if test x${have_wacom} = xyes; then
|
||||
AC_DEFINE(BUILD_WACOM, 1, [Define to 1 to build the Wacom panel])
|
||||
AC_DEFINE(HAVE_WACOM, 1, [Define to 1 is Wacom is supportted])
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
have_wacom=no
|
||||
;;
|
||||
esac
|
||||
AM_CONDITIONAL(BUILD_WACOM, [test x"$have_wacom" = x"yes"])
|
||||
AM_CONDITIONAL(BUILD_WACOM, [test x${have_wacom} = xyes])
|
||||
|
||||
# Kerberos kerberos support
|
||||
AC_PATH_PROG(KRB5_CONFIG, krb5-config, no)
|
||||
|
|
|
@ -13,8 +13,12 @@ noinst_LTLIBRARIES = libwacom-calibrator.la libwacom-calibrator-test.la
|
|||
libwacom_calibrator_la_SOURCES = \
|
||||
calibrator.c \
|
||||
calibrator.h \
|
||||
gui_gtk.c \
|
||||
gui_gtk.h
|
||||
calibrator-gui.c \
|
||||
calibrator-gui.h \
|
||||
cc-clock-actor.c \
|
||||
cc-clock-actor.h \
|
||||
cc-target-actor.c \
|
||||
cc-target-actor.h
|
||||
|
||||
libwacom_calibrator_la_LIBADD = $(PANEL_LIBS) $(WACOM_PANEL_LIBS)
|
||||
libwacom_calibrator_la_LDFLAGS = $(PANEL_LDFLAGS)
|
||||
|
@ -31,8 +35,12 @@ test_calibrator_SOURCES = \
|
|||
main.c \
|
||||
calibrator.c \
|
||||
calibrator.h \
|
||||
gui_gtk.c \
|
||||
gui_gtk.h
|
||||
calibrator-gui.c \
|
||||
calibrator-gui.h \
|
||||
cc-clock-actor.c \
|
||||
cc-clock-actor.h \
|
||||
cc-target-actor.c \
|
||||
cc-target-actor.h
|
||||
|
||||
test_calibrator_CPPFLAGS = $(INCLUDES)
|
||||
test_calibrator_LDADD = $(PANEL_LIBS) $(WACOM_PANEL_LIBS)
|
||||
|
|
787
panels/wacom/calibrator/calibrator-gui.c
Normal file
787
panels/wacom/calibrator/calibrator-gui.c
Normal file
|
@ -0,0 +1,787 @@
|
|||
/*
|
||||
* Copyright © 2013 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Joaquim Rocha <jrocha@redhat.com>
|
||||
* (based on previous work by Tias Guns and Soren Hauberg)
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#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"
|
||||
|
||||
struct CalibArea
|
||||
{
|
||||
struct Calib calibrator;
|
||||
XYinfo axis;
|
||||
gboolean swap;
|
||||
gboolean success;
|
||||
int device_id;
|
||||
|
||||
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;
|
||||
GdkPixbuf *icon_success;
|
||||
|
||||
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 /* 5000 = 5 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)
|
||||
{
|
||||
int delta_x;
|
||||
int delta_y;
|
||||
|
||||
calib_area->display_width = width;
|
||||
calib_area->display_height = height;
|
||||
|
||||
/* Compute absolute circle centers */
|
||||
delta_x = calib_area->display_width/NUM_BLOCKS;
|
||||
delta_y = calib_area->display_height/NUM_BLOCKS;
|
||||
|
||||
calib_area->X[UL] = delta_x;
|
||||
calib_area->Y[UL] = delta_y;
|
||||
|
||||
calib_area->X[UR] = calib_area->display_width - delta_x - 1;
|
||||
calib_area->Y[UR] = delta_y;
|
||||
|
||||
calib_area->X[LL] = delta_x;
|
||||
calib_area->Y[LL] = calib_area->display_height - delta_y - 1;
|
||||
|
||||
calib_area->X[LR] = calib_area->display_width - delta_x - 1;
|
||||
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 (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)
|
||||
{
|
||||
resize_display (area);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_delete_event (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
CalibArea *area)
|
||||
{
|
||||
clutter_timeline_stop (CLUTTER_TIMELINE (area->clock_timeline));
|
||||
|
||||
gtk_widget_hide (area->window);
|
||||
|
||||
(*area->callback) (area, area->user_data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
draw_success_end_wait_callback (CalibArea *area)
|
||||
{
|
||||
on_delete_event (NULL, NULL, area);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
set_success (CalibArea *area)
|
||||
{
|
||||
ClutterImage *image;
|
||||
GdkPixbuf *icon = area->icon_success;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
set_success (area);
|
||||
g_timeout_add (END_TIME,
|
||||
(GSourceFunc) draw_success_end_wait_callback,
|
||||
area);
|
||||
}
|
||||
else
|
||||
{
|
||||
on_delete_event (NULL, NULL, 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));
|
||||
}
|
||||
|
||||
static void
|
||||
on_error_message_transparent (ClutterTimeline *timeline,
|
||||
CalibArea *area)
|
||||
{
|
||||
clutter_actor_hide (area->error_text);
|
||||
}
|
||||
|
||||
static void
|
||||
hide_error_message (CalibArea *area)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_button_press_event(ClutterActor *actor,
|
||||
ClutterButtonEvent *event,
|
||||
CalibArea *area)
|
||||
{
|
||||
gint num_clicks;
|
||||
gboolean success;
|
||||
|
||||
if (area->success)
|
||||
return FALSE;
|
||||
|
||||
/* Check matching device ID if a device ID was provided */
|
||||
if (area->device_id > -1)
|
||||
{
|
||||
GdkDevice *device;
|
||||
|
||||
device = gdk_event_get_source_device ((GdkEvent *) event);
|
||||
if (device != NULL && gdk_x11_device_get_id (device) != area->device_id)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Handle click */
|
||||
clutter_timeline_stop (CLUTTER_TIMELINE (area->clock_timeline));
|
||||
clutter_timeline_start (CLUTTER_TIMELINE (area->clock_timeline));
|
||||
success = add_click(&area->calibrator,
|
||||
(int) event->x,
|
||||
(int) event->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);
|
||||
}
|
||||
|
||||
/* Are we done yet? */
|
||||
if (num_clicks >= 4)
|
||||
{
|
||||
set_calibration_status (area);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
cc_target_actor_move (CC_TARGET_ACTOR (area->target),
|
||||
area->X[num_clicks],
|
||||
area->Y[num_clicks]);
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_key_release_event(ClutterActor *actor,
|
||||
ClutterKeyEvent *event,
|
||||
CalibArea *area)
|
||||
{
|
||||
if (area->success ||
|
||||
event->type != CLUTTER_KEY_RELEASE ||
|
||||
event->keyval != CLUTTER_KEY_Escape)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
on_delete_event (area->window, NULL, area);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_focus_out_event (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
CalibArea *area)
|
||||
{
|
||||
if (area->success)
|
||||
return FALSE;
|
||||
|
||||
/* If the calibrator window loses focus, simply bail out... */
|
||||
on_delete_event (widget, NULL, area);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_timeout (ClutterTimeline *timeline,
|
||||
CalibArea *area)
|
||||
{
|
||||
set_calibration_status (area);
|
||||
}
|
||||
|
||||
static void
|
||||
show_helper_text_body (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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
static void
|
||||
on_fullscreen (GtkWindow *window,
|
||||
GdkEventWindowState *event,
|
||||
CalibArea *area)
|
||||
{
|
||||
ClutterRect rect;
|
||||
|
||||
if ((event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) == 0)
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
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));
|
||||
|
||||
show_helper_text_title (area);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
|
||||
calib_area->calibrator.geometry.x = clutter_actor_get_x (stage);
|
||||
calib_area->calibrator.geometry.y = clutter_actor_get_y (stage);
|
||||
calib_area->calibrator.geometry.width = clutter_actor_get_width (stage);
|
||||
calib_area->calibrator.geometry.height = clutter_actor_get_height (stage);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the windows and other objects required to do calibration
|
||||
* under GTK. When the window is closed (timed out, calibration finished
|
||||
* or user cancellation), callback will be called, where you should call
|
||||
* calib_area_finish().
|
||||
*/
|
||||
CalibArea *
|
||||
calib_area_new (GdkScreen *screen,
|
||||
int monitor,
|
||||
int device_id,
|
||||
FinishCallback callback,
|
||||
gpointer user_data,
|
||||
XYinfo *old_axis,
|
||||
int threshold_doubleclick,
|
||||
int threshold_misclick)
|
||||
{
|
||||
CalibArea *calib_area;
|
||||
GdkRectangle rect;
|
||||
GdkVisual *visual;
|
||||
#ifndef FAKE_AREA
|
||||
GdkWindow *window;
|
||||
GdkCursor *cursor;
|
||||
#endif /* FAKE_AREA */
|
||||
GtkWidget *clutter_embed;
|
||||
ClutterActor *stage;
|
||||
|
||||
g_return_val_if_fail (old_axis, NULL);
|
||||
g_return_val_if_fail (callback, NULL);
|
||||
|
||||
g_debug ("Current calibration: %d, %d, %d, %d\n",
|
||||
old_axis->x_min,
|
||||
old_axis->y_min,
|
||||
old_axis->x_max,
|
||||
old_axis->y_max);
|
||||
|
||||
calib_area = g_new0 (CalibArea, 1);
|
||||
calib_area->callback = callback;
|
||||
calib_area->user_data = user_data;
|
||||
calib_area->device_id = device_id;
|
||||
calib_area->calibrator.old_axis.x_min = old_axis->x_min;
|
||||
calib_area->calibrator.old_axis.x_max = old_axis->x_max;
|
||||
calib_area->calibrator.old_axis.y_min = old_axis->y_min;
|
||||
calib_area->calibrator.old_axis.y_max = old_axis->y_max;
|
||||
calib_area->calibrator.threshold_doubleclick = threshold_doubleclick;
|
||||
calib_area->calibrator.threshold_misclick = threshold_misclick;
|
||||
|
||||
calib_area->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
|
||||
#ifndef FAKE_AREA
|
||||
/* No cursor */
|
||||
gtk_widget_realize (calib_area->window);
|
||||
window = gtk_widget_get_window (calib_area->window);
|
||||
cursor = gdk_cursor_new (GDK_BLANK_CURSOR);
|
||||
gdk_window_set_cursor (window, cursor);
|
||||
g_object_unref (cursor);
|
||||
|
||||
gtk_widget_set_can_focus (calib_area->window, TRUE);
|
||||
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 ();
|
||||
gdk_screen_get_monitor_geometry (screen, monitor, &rect);
|
||||
gtk_window_move (GTK_WINDOW (calib_area->window), rect.x, rect.y);
|
||||
gtk_window_set_default_size (GTK_WINDOW (calib_area->window),
|
||||
rect.width,
|
||||
rect.height);
|
||||
|
||||
set_up_stage (calib_area, stage);
|
||||
|
||||
g_signal_connect (calib_area->window,
|
||||
"delete-event",
|
||||
G_CALLBACK (on_delete_event),
|
||||
calib_area);
|
||||
g_signal_connect (calib_area->window,
|
||||
"focus-out-event",
|
||||
G_CALLBACK(on_focus_out_event),
|
||||
calib_area);
|
||||
g_signal_connect (calib_area->window,
|
||||
"window-state-event",
|
||||
G_CALLBACK (on_fullscreen),
|
||||
calib_area);
|
||||
|
||||
gtk_window_fullscreen (GTK_WINDOW (calib_area->window));
|
||||
|
||||
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);
|
||||
|
||||
return calib_area;
|
||||
}
|
||||
|
||||
/* Finishes the calibration. Note that CalibArea
|
||||
* needs to be destroyed with calib_area_free() afterwards */
|
||||
gboolean
|
||||
calib_area_finish (CalibArea *area,
|
||||
XYinfo *new_axis,
|
||||
gboolean *swap_xy)
|
||||
{
|
||||
g_return_val_if_fail (area != NULL, FALSE);
|
||||
|
||||
*new_axis = area->axis;
|
||||
*swap_xy = area->swap;
|
||||
|
||||
if (area->success)
|
||||
g_debug ("Final calibration: %d, %d, %d, %d\n",
|
||||
new_axis->x_min,
|
||||
new_axis->y_min,
|
||||
new_axis->x_max,
|
||||
new_axis->y_max);
|
||||
else
|
||||
g_debug ("Calibration was aborted or timed out");
|
||||
|
||||
return area->success;
|
||||
}
|
||||
|
||||
void
|
||||
calib_area_free (CalibArea *area)
|
||||
{
|
||||
g_return_if_fail (area != NULL);
|
||||
|
||||
g_clear_object (&area->icon_success);
|
||||
|
||||
gtk_widget_destroy (area->window);
|
||||
g_free (area);
|
||||
}
|
||||
|
||||
void
|
||||
calib_area_get_display_size (CalibArea *area, gint *width, gint *height)
|
||||
{
|
||||
g_return_if_fail (area != NULL);
|
||||
|
||||
*width = area->display_width;
|
||||
*height = area->display_height;
|
||||
}
|
|
@ -21,8 +21,8 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _gui_gtk_h
|
||||
#define _gui_gtk_h
|
||||
#ifndef __CALIBRATOR_GUI_H__
|
||||
#define __CALIBRATOR_GUI_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
@ -53,6 +53,8 @@ gboolean calib_area_finish (CalibArea *area,
|
|||
|
||||
void calib_area_free (CalibArea *area);
|
||||
|
||||
void calib_area_get_display_size (CalibArea *area, gint *width, gint *height);
|
||||
void calib_area_get_display_size (CalibArea *area,
|
||||
gint *width,
|
||||
gint *height);
|
||||
|
||||
#endif /* _gui_gtk_h */
|
||||
#endif /* __CALIBRATOR_GUI_H__ */
|
|
@ -25,7 +25,7 @@
|
|||
#define _calibrator_h
|
||||
|
||||
#include <glib.h>
|
||||
#include "gui_gtk.h"
|
||||
#include "calibrator-gui.h"
|
||||
|
||||
/*
|
||||
* Number of blocks. We partition the screen into 'num_blocks' x 'num_blocks'
|
||||
|
|
186
panels/wacom/calibrator/cc-clock-actor.c
Normal file
186
panels/wacom/calibrator/cc-clock-actor.c
Normal file
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* Copyright © 2013 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Joaquim Rocha <jrocha@redhat.com>
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "cc-clock-actor.h"
|
||||
|
||||
#define CLOCK_RADIUS 50
|
||||
#define CLOCK_LINE_WIDTH 10
|
||||
#define CLOCK_LINE_PADDING 10
|
||||
#define CLOCK_SIZE_EXTRA
|
||||
#define ANGLE "angle"
|
||||
#define EXTRA_SPACE 2
|
||||
|
||||
G_DEFINE_TYPE (CcClockActor, cc_clock_actor, CLUTTER_TYPE_ACTOR);
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ANGLE,
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
|
||||
|
||||
static void
|
||||
draw_clock (ClutterCairoTexture *texture,
|
||||
cairo_t *cr,
|
||||
gint width,
|
||||
gint height,
|
||||
CcClockActor *self)
|
||||
{
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
|
||||
cairo_paint (cr);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
|
||||
|
||||
/* Draw the clock background */
|
||||
cairo_arc (cr, width / 2, 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,
|
||||
width / 2,
|
||||
height / 2,
|
||||
(CLOCK_RADIUS - CLOCK_LINE_WIDTH - CLOCK_LINE_PADDING) / 2,
|
||||
3 * M_PI_2,
|
||||
3 * M_PI_2 + self->angle * M_PI / 180.0);
|
||||
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_clock_actor_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcClockActor *self = CC_CLOCK_ACTOR (object);
|
||||
ClutterContent *content;
|
||||
content = clutter_actor_get_content (CLUTTER_ACTOR (self));
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_ANGLE:
|
||||
self->angle = g_value_get_float (value);
|
||||
if (content)
|
||||
clutter_content_invalidate (content);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_clock_actor_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
CcClockActor *self = CC_CLOCK_ACTOR (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_ANGLE:
|
||||
g_value_set_float (value, self->angle);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cc_clock_actor_init (CcClockActor *self)
|
||||
{
|
||||
self->angle = 0;
|
||||
|
||||
ClutterContent *content;
|
||||
content = clutter_canvas_new ();
|
||||
/* Extra space is needed because when drawing without it,
|
||||
it will miss 1 pixel in each of the edges */
|
||||
clutter_canvas_set_size (CLUTTER_CANVAS (content),
|
||||
CLOCK_RADIUS + EXTRA_SPACE,
|
||||
CLOCK_RADIUS + EXTRA_SPACE);
|
||||
clutter_actor_set_content (CLUTTER_ACTOR (self), content);
|
||||
g_signal_connect (CLUTTER_CANVAS (content),
|
||||
"draw",
|
||||
G_CALLBACK (draw_clock),
|
||||
self);
|
||||
g_object_unref (content);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_clock_actor_get_preferred_width (ClutterActor *actor,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
*min_width_p = CLOCK_RADIUS + EXTRA_SPACE;
|
||||
*natural_width_p = CLOCK_RADIUS + EXTRA_SPACE;
|
||||
}
|
||||
|
||||
static void
|
||||
cc_clock_actor_get_preferred_height (ClutterActor *actor,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
*min_height_p = CLOCK_RADIUS + EXTRA_SPACE;
|
||||
*natural_height_p = CLOCK_RADIUS + EXTRA_SPACE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cc_clock_actor_class_init (CcClockActorClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *clutter_actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
gobject_class->set_property = cc_clock_actor_set_property;
|
||||
gobject_class->get_property = cc_clock_actor_get_property;
|
||||
|
||||
clutter_actor_class->get_preferred_width = cc_clock_actor_get_preferred_width;
|
||||
clutter_actor_class->get_preferred_height = cc_clock_actor_get_preferred_height;
|
||||
|
||||
obj_properties[PROP_ANGLE] =
|
||||
g_param_spec_float (ANGLE,
|
||||
"The angle of the clock's progress",
|
||||
"Set the angle of the clock's progress",
|
||||
.0,
|
||||
360.0,
|
||||
.0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class,
|
||||
N_PROPERTIES,
|
||||
obj_properties);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
cc_clock_actor_new (void)
|
||||
{
|
||||
return g_object_new (CC_CLOCK_ACTOR_TYPE, NULL);
|
||||
}
|
56
panels/wacom/calibrator/cc-clock-actor.h
Normal file
56
panels/wacom/calibrator/cc-clock-actor.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright © 2013 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Joaquim Rocha <jrocha@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef __CC_CLOCK_ACTOR_H__
|
||||
#define __CC_CLOCK_ACTOR_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_CLOCK_ACTOR_TYPE (cc_clock_actor_get_type ())
|
||||
#define CC_CLOCK_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CC_CLOCK_ACTOR_TYPE, CcClockActor))
|
||||
#define CC_IS_CLOCK_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CC_CLOCK_ACTOR_TYPE))
|
||||
#define CC_CLOCK_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CC_CLOCK_ACTOR_TYPE, CcClockActorClass))
|
||||
#define CC_IS_CLOCK_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CC_CLOCK_ACTOR_TYPE))
|
||||
#define CC_CLOCK_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CC_CLOCK_ACTOR_TYPE, CcClockActorClass))
|
||||
|
||||
typedef struct _CcClockActor CcClockActor;
|
||||
typedef struct _CcClockActorClass CcClockActorClass;
|
||||
|
||||
struct _CcClockActor
|
||||
{
|
||||
ClutterActor parent_instance;
|
||||
|
||||
/*< private >*/
|
||||
gfloat angle;
|
||||
};
|
||||
|
||||
struct _CcClockActorClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
};
|
||||
|
||||
ClutterActor * cc_clock_actor_new (void);
|
||||
|
||||
GType cc_clock_actor_get_type (void);
|
||||
|
||||
#endif /* __CC_CLOCK_ACTOR_H__ */
|
229
panels/wacom/calibrator/cc-target-actor.c
Normal file
229
panels/wacom/calibrator/cc-target-actor.c
Normal file
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Copyright © 2013 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Joaquim Rocha <jrocha@redhat.com>
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "cc-target-actor.h"
|
||||
|
||||
#define CC_TARGET_ACTOR_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CC_TARGET_ACTOR_TYPE, CcTargetActorPrivate))
|
||||
|
||||
#define CROSS_LINES 47
|
||||
#define CROSS_CIRCLE 7
|
||||
#define CROSS_CIRCLE2 27
|
||||
#define TARGET_SHOW_ANIMATION_DURATION 500
|
||||
#define TARGET_HIDE_ANIMATION_DURATION 200
|
||||
|
||||
struct _CcTargetActorPrivate
|
||||
{
|
||||
gdouble pos_x;
|
||||
gdouble pos_y;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CcTargetActor, cc_target_actor, CLUTTER_TYPE_ACTOR);
|
||||
|
||||
static ClutterTransition *
|
||||
get_target_show_animation (ClutterActor *target, const gchar *property)
|
||||
{
|
||||
ClutterTransition *transition;
|
||||
|
||||
transition = clutter_property_transition_new (property);
|
||||
clutter_timeline_set_progress_mode (CLUTTER_TIMELINE (transition),
|
||||
CLUTTER_EASE_OUT_BACK);
|
||||
clutter_timeline_set_duration (CLUTTER_TIMELINE (transition),
|
||||
TARGET_SHOW_ANIMATION_DURATION);
|
||||
clutter_transition_set_animatable (transition,
|
||||
CLUTTER_ANIMATABLE (target));
|
||||
clutter_transition_set_from (transition, G_TYPE_FLOAT, 0.0);
|
||||
clutter_transition_set_to (transition, G_TYPE_FLOAT, 1.0);
|
||||
|
||||
return transition;
|
||||
}
|
||||
|
||||
static ClutterTransition *
|
||||
get_target_hide_animation (ClutterActor *target, const gchar *property)
|
||||
{
|
||||
ClutterTransition *transition;
|
||||
|
||||
transition = get_target_show_animation (target, property);
|
||||
clutter_timeline_set_progress_mode (CLUTTER_TIMELINE (transition),
|
||||
CLUTTER_EASE_OUT);
|
||||
clutter_timeline_set_duration (CLUTTER_TIMELINE (transition),
|
||||
TARGET_HIDE_ANIMATION_DURATION);
|
||||
clutter_transition_set_from (transition, G_TYPE_FLOAT, 1.0);
|
||||
clutter_transition_set_to (transition, G_TYPE_FLOAT, 0.0);
|
||||
|
||||
return transition;
|
||||
}
|
||||
|
||||
static void
|
||||
show_target (CcTargetActor *self)
|
||||
{
|
||||
ClutterTransition *transition;
|
||||
|
||||
transition = get_target_show_animation (CLUTTER_ACTOR (self), "scale-x");
|
||||
clutter_timeline_start (CLUTTER_TIMELINE (transition));
|
||||
|
||||
transition = get_target_show_animation (CLUTTER_ACTOR (self), "scale-y");
|
||||
clutter_timeline_start (CLUTTER_TIMELINE (transition));
|
||||
}
|
||||
|
||||
static void
|
||||
on_target_animation_complete (ClutterTimeline *timeline,
|
||||
CcTargetActor *self)
|
||||
{
|
||||
CcTargetActorPrivate *priv;
|
||||
priv = CC_TARGET_ACTOR_GET_PRIVATE (self);
|
||||
|
||||
clutter_actor_show (CLUTTER_ACTOR (self));
|
||||
clutter_actor_set_position (CLUTTER_ACTOR (self),
|
||||
priv->pos_x,
|
||||
priv->pos_y);
|
||||
|
||||
show_target (self);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_target (ClutterCairoTexture *texture,
|
||||
cairo_t *cr,
|
||||
gint width,
|
||||
gint height,
|
||||
gpointer data)
|
||||
{
|
||||
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
||||
|
||||
cairo_set_line_width(cr, 1);
|
||||
cairo_move_to(cr, 0, height / 2.0);
|
||||
cairo_rel_line_to(cr, width, 0);
|
||||
cairo_move_to(cr, width / 2.0, 0);
|
||||
cairo_rel_line_to(cr, 0, height * 2);
|
||||
cairo_stroke(cr);
|
||||
|
||||
cairo_set_line_width(cr, 2);
|
||||
cairo_arc(cr, width / 2.0, height / 2.0, CROSS_CIRCLE, 0.0, 2.0 * M_PI);
|
||||
cairo_stroke(cr);
|
||||
|
||||
cairo_set_line_width(cr, 5);
|
||||
cairo_arc(cr, width / 2.0, height / 2.0, CROSS_CIRCLE2, 0.0, 2.0 * M_PI);
|
||||
cairo_stroke(cr);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_target_actor_init (CcTargetActor *self)
|
||||
{
|
||||
ClutterContent *content;
|
||||
ClutterPoint anchor;
|
||||
CcTargetActorPrivate *priv;
|
||||
|
||||
priv = CC_TARGET_ACTOR_GET_PRIVATE (self);
|
||||
priv->pos_x = .0;
|
||||
priv->pos_y = .0;
|
||||
|
||||
content = clutter_canvas_new ();
|
||||
clutter_actor_set_content (CLUTTER_ACTOR (self), content);
|
||||
g_object_unref (content);
|
||||
|
||||
clutter_canvas_set_size (CLUTTER_CANVAS (content),
|
||||
CROSS_LINES * 2,
|
||||
CROSS_LINES * 2);
|
||||
g_signal_connect (CLUTTER_CANVAS (content),
|
||||
"draw",
|
||||
G_CALLBACK (draw_target),
|
||||
self);
|
||||
clutter_content_invalidate (content);
|
||||
|
||||
anchor.x = .5;
|
||||
anchor.y = .5;
|
||||
|
||||
g_object_set (self, "pivot-point", &anchor, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
cc_target_actor_get_preferred_width (ClutterActor *actor,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
*min_width_p = CROSS_LINES * 2;
|
||||
*natural_width_p = CROSS_LINES * 2;
|
||||
}
|
||||
|
||||
static void
|
||||
cc_target_actor_get_preferred_height (ClutterActor *actor,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
*min_height_p = CROSS_LINES * 2;
|
||||
*natural_height_p = CROSS_LINES * 2;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cc_target_actor_class_init (CcTargetActorClass *klass)
|
||||
{
|
||||
ClutterActorClass *clutter_actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
clutter_actor_class->get_preferred_width = cc_target_actor_get_preferred_width;
|
||||
clutter_actor_class->get_preferred_height = cc_target_actor_get_preferred_height;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (CcTargetActorPrivate));
|
||||
}
|
||||
|
||||
void
|
||||
cc_target_actor_move (CcTargetActor *self, gdouble x, gdouble y)
|
||||
{
|
||||
g_return_if_fail (CC_IS_TARGET_ACTOR (self));
|
||||
|
||||
CcTargetActorPrivate *priv;
|
||||
ClutterTransition *transition;
|
||||
gboolean target_visible;
|
||||
|
||||
priv = CC_TARGET_ACTOR_GET_PRIVATE (self);
|
||||
priv->pos_x = x;
|
||||
priv->pos_y = y;
|
||||
|
||||
g_object_get (self, "visible", &target_visible, NULL);
|
||||
|
||||
if (target_visible)
|
||||
{
|
||||
transition = get_target_hide_animation (CLUTTER_ACTOR (self), "scale-x");
|
||||
clutter_timeline_start (CLUTTER_TIMELINE (transition));
|
||||
transition = get_target_hide_animation (CLUTTER_ACTOR (self), "scale-y");
|
||||
clutter_timeline_start (CLUTTER_TIMELINE (transition));
|
||||
|
||||
g_signal_connect (CLUTTER_TIMELINE (transition),
|
||||
"completed",
|
||||
G_CALLBACK (on_target_animation_complete),
|
||||
self);
|
||||
}
|
||||
else
|
||||
{
|
||||
clutter_actor_show (CLUTTER_ACTOR (self));
|
||||
|
||||
clutter_actor_set_position (CLUTTER_ACTOR (self), x, y);
|
||||
|
||||
show_target (self);
|
||||
}
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
cc_target_actor_new (void)
|
||||
{
|
||||
return g_object_new (CC_TARGET_ACTOR_TYPE, NULL);
|
||||
}
|
60
panels/wacom/calibrator/cc-target-actor.h
Normal file
60
panels/wacom/calibrator/cc-target-actor.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright © 2013 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Joaquim Rocha <jrocha@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef __CC_TARGET_ACTOR_H__
|
||||
#define __CC_TARGET_ACTOR_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CC_TARGET_ACTOR_TYPE (cc_target_actor_get_type ())
|
||||
#define CC_TARGET_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CC_TARGET_ACTOR_TYPE, CcTargetActor))
|
||||
#define CC_IS_TARGET_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CC_TARGET_ACTOR_TYPE))
|
||||
#define CC_TARGET_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CC_TARGET_ACTOR_TYPE, CcTargetActorClass))
|
||||
#define CC_IS_TARGET_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CC_TARGET_ACTOR_TYPE))
|
||||
#define CC_TARGET_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CC_TARGET_ACTOR_TYPE, CcTargetActorClass))
|
||||
|
||||
typedef struct _CcTargetActor CcTargetActor;
|
||||
typedef struct _CcTargetActorClass CcTargetActorClass;
|
||||
typedef struct _CcTargetActorPrivate CcTargetActorPrivate;
|
||||
|
||||
struct _CcTargetActor
|
||||
{
|
||||
ClutterActor parent_instance;
|
||||
|
||||
/*< private >*/
|
||||
CcTargetActorPrivate *priv;
|
||||
};
|
||||
|
||||
struct _CcTargetActorClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
};
|
||||
|
||||
ClutterActor * cc_target_actor_new (void);
|
||||
void cc_target_actor_move (CcTargetActor *target,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
|
||||
GType cc_target_actor_get_type (void);
|
||||
|
||||
#endif /* __CC_TARGET_ACTOR_H__ */
|
|
@ -1,591 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2009 Tias Guns
|
||||
* Copyright (c) 2009 Soren Hauberg
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <cairo.h>
|
||||
|
||||
#include "calibrator.h"
|
||||
#include "gui_gtk.h"
|
||||
|
||||
struct CalibArea
|
||||
{
|
||||
struct Calib calibrator;
|
||||
XYinfo axis;
|
||||
gboolean swap;
|
||||
gboolean success;
|
||||
int device_id;
|
||||
|
||||
double X[4], Y[4];
|
||||
int display_width, display_height;
|
||||
int time_elapsed;
|
||||
|
||||
const char* message;
|
||||
|
||||
guint anim_id;
|
||||
|
||||
GtkWidget *window;
|
||||
GdkPixbuf *icon_success;
|
||||
|
||||
FinishCallback callback;
|
||||
gpointer user_data;
|
||||
};
|
||||
|
||||
|
||||
/* Window parameters */
|
||||
#define WINDOW_OPACITY 0.9
|
||||
|
||||
/* Timeout parameters */
|
||||
#define TIME_STEP 100 /* in milliseconds */
|
||||
#define MAX_TIME 15000 /* 5000 = 5 sec */
|
||||
#define END_TIME 750 /* 750 = 0.75 sec */
|
||||
|
||||
/* Clock appereance */
|
||||
#define CROSS_LINES 47
|
||||
#define CROSS_CIRCLE 7
|
||||
#define CROSS_CIRCLE2 27
|
||||
#define CLOCK_RADIUS 50
|
||||
#define CLOCK_LINE_WIDTH 10
|
||||
#define CLOCK_LINE_PADDING 10
|
||||
|
||||
/* 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 ICON_SUCCESS "emblem-ok-symbolic"
|
||||
#define ICON_SIZE 300
|
||||
|
||||
static void
|
||||
set_display_size(CalibArea *calib_area,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
int delta_x;
|
||||
int delta_y;
|
||||
|
||||
calib_area->display_width = width;
|
||||
calib_area->display_height = height;
|
||||
|
||||
/* Compute absolute circle centers */
|
||||
delta_x = calib_area->display_width/NUM_BLOCKS;
|
||||
delta_y = calib_area->display_height/NUM_BLOCKS;
|
||||
|
||||
calib_area->X[UL] = delta_x;
|
||||
calib_area->Y[UL] = delta_y;
|
||||
|
||||
calib_area->X[UR] = calib_area->display_width - delta_x - 1;
|
||||
calib_area->Y[UR] = delta_y;
|
||||
|
||||
calib_area->X[LL] = delta_x;
|
||||
calib_area->Y[LL] = calib_area->display_height - delta_y - 1;
|
||||
|
||||
calib_area->X[LR] = calib_area->display_width - delta_x - 1;
|
||||
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)
|
||||
{
|
||||
/* check that screensize did not change (if no manually specified geometry) */
|
||||
GtkAllocation allocation;
|
||||
gtk_widget_get_allocation(calib_area->window, &allocation);
|
||||
if (calib_area->display_width != allocation.width ||
|
||||
calib_area->display_height != allocation.height)
|
||||
{
|
||||
set_display_size(calib_area, allocation.width, allocation.height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
draw_success_icon (CalibArea *area, cairo_t *cr)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkStyleContext *context;
|
||||
gint icon_width, icon_height;
|
||||
gdouble x;
|
||||
gdouble y;
|
||||
|
||||
widget = GTK_WIDGET (area->window);
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
|
||||
icon_width = gdk_pixbuf_get_width (area->icon_success);
|
||||
icon_height = gdk_pixbuf_get_height (area->icon_success);
|
||||
|
||||
x = (area->display_width - icon_width) / 2;
|
||||
y = (area->display_height - icon_height) / 2;
|
||||
|
||||
gtk_render_icon (context, cr, area->icon_success, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
draw(GtkWidget *widget, cairo_t *cr, gpointer data)
|
||||
{
|
||||
CalibArea *calib_area = (CalibArea*)data;
|
||||
int i;
|
||||
double x;
|
||||
double y;
|
||||
PangoLayout *layout;
|
||||
PangoRectangle logical_rect;
|
||||
GtkStyleContext *context;
|
||||
char *markup;
|
||||
|
||||
resize_display(calib_area);
|
||||
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
|
||||
/* Black background and reset the operator */
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
|
||||
cairo_paint (cr);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
|
||||
|
||||
/* If calibration is successful, just draw the tick */
|
||||
if (calib_area->icon_success) {
|
||||
draw_success_icon (calib_area, cr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print the help lines */
|
||||
layout = pango_layout_new (gtk_widget_get_pango_context (widget));
|
||||
pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
|
||||
markup = g_strdup_printf ("<span foreground=\"white\"><big><b>%s</b></big>\n<big>%s</big></span>",
|
||||
_(HELP_TEXT_TITLE),
|
||||
_(HELP_TEXT_MAIN));
|
||||
pango_layout_set_markup (layout, markup, -1);
|
||||
g_free (markup);
|
||||
|
||||
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
|
||||
|
||||
x = (calib_area->display_width - logical_rect.width) / 2 + logical_rect.x;
|
||||
y = (calib_area->display_height - logical_rect.height) / 2 - logical_rect.height - 40 + logical_rect.y;
|
||||
|
||||
gtk_render_layout (context, cr,
|
||||
x + logical_rect.x,
|
||||
y + logical_rect.y,
|
||||
layout);
|
||||
g_object_unref (layout);
|
||||
|
||||
/* Draw the points */
|
||||
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
||||
|
||||
i = calib_area->calibrator.num_clicks;
|
||||
|
||||
cairo_set_line_width(cr, 1);
|
||||
cairo_move_to(cr, calib_area->X[i] - CROSS_LINES, calib_area->Y[i] - 0.5);
|
||||
cairo_rel_line_to(cr, CROSS_LINES*2, 0);
|
||||
cairo_move_to(cr, calib_area->X[i] - 0.5, calib_area->Y[i] - CROSS_LINES);
|
||||
cairo_rel_line_to(cr, 0, CROSS_LINES*2);
|
||||
cairo_stroke(cr);
|
||||
|
||||
cairo_set_line_width(cr, 2);
|
||||
cairo_arc(cr, calib_area->X[i] - 0.5, calib_area->Y[i] - 0.5, CROSS_CIRCLE, 0.0, 2.0 * M_PI);
|
||||
cairo_stroke(cr);
|
||||
|
||||
cairo_set_line_width(cr, 5);
|
||||
cairo_arc(cr, calib_area->X[i] - 0.5, calib_area->Y[i] - 0.5, CROSS_CIRCLE2, 0.0, 2.0 * M_PI);
|
||||
cairo_stroke(cr);
|
||||
|
||||
/* Draw the clock background */
|
||||
cairo_arc(cr, calib_area->display_width/2, calib_area->display_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, calib_area->display_width/2, calib_area->display_height/2, (CLOCK_RADIUS - CLOCK_LINE_WIDTH - CLOCK_LINE_PADDING)/2,
|
||||
3/2.0*M_PI, (3/2.0*M_PI) + ((double)calib_area->time_elapsed/(double)MAX_TIME) * 2*M_PI);
|
||||
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
||||
cairo_stroke(cr);
|
||||
|
||||
/* Draw the message (if any) */
|
||||
if (calib_area->message != NULL)
|
||||
{
|
||||
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
||||
|
||||
/* Frame the message */
|
||||
layout = pango_layout_new (gtk_widget_get_pango_context (widget));
|
||||
pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
|
||||
markup = g_strdup_printf ("<span foreground=\"white\"><big>%s</big></span>",
|
||||
_(calib_area->message));
|
||||
pango_layout_set_markup (layout, markup, -1);
|
||||
g_free (markup);
|
||||
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
|
||||
|
||||
x = (calib_area->display_width - logical_rect.width) / 2 + logical_rect.x;
|
||||
y = (calib_area->display_height - logical_rect.height + CLOCK_RADIUS) / 2 + 60 + logical_rect.y;
|
||||
cairo_set_line_width(cr, 2);
|
||||
cairo_rectangle(cr, x - 10 - 0.5 , y - 10 - 0.5,
|
||||
logical_rect.width + 20 + 1, logical_rect.height + 20 + 1);
|
||||
cairo_stroke (cr);
|
||||
|
||||
/* Print the message */
|
||||
gtk_render_layout (context, cr,
|
||||
x + logical_rect.x,
|
||||
y + logical_rect.y,
|
||||
layout);
|
||||
g_object_unref (layout);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
draw_message(CalibArea *calib_area,
|
||||
const char *msg)
|
||||
{
|
||||
calib_area->message = msg;
|
||||
}
|
||||
|
||||
static void
|
||||
redraw(CalibArea *calib_area)
|
||||
{
|
||||
GdkWindow *win = gtk_widget_get_window(calib_area->window);
|
||||
if (win)
|
||||
{
|
||||
GdkRectangle rect;
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = calib_area->display_width;
|
||||
rect.height = calib_area->display_height;
|
||||
gdk_window_invalidate_rect(win, &rect, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_delete_event (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
CalibArea *area)
|
||||
{
|
||||
if (area->anim_id > 0) {
|
||||
g_source_remove (area->anim_id);
|
||||
area->anim_id = 0;
|
||||
}
|
||||
|
||||
gtk_widget_hide (area->window);
|
||||
|
||||
(*area->callback) (area, area->user_data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
draw_success_end_wait_callback (CalibArea *area)
|
||||
{
|
||||
on_delete_event (NULL, NULL, area);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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) {
|
||||
redraw(area);
|
||||
g_timeout_add(END_TIME, (GSourceFunc) draw_success_end_wait_callback, area);
|
||||
} else {
|
||||
on_delete_event (NULL, NULL, area);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_button_press_event(GtkWidget *widget,
|
||||
GdkEventButton *event,
|
||||
CalibArea *area)
|
||||
{
|
||||
gboolean success;
|
||||
|
||||
if (area->success)
|
||||
return FALSE;
|
||||
|
||||
/* Check matching device ID if a device ID was provided */
|
||||
if (area->device_id > -1) {
|
||||
GdkDevice *device;
|
||||
|
||||
device = gdk_event_get_source_device ((GdkEvent *) event);
|
||||
if (device != NULL && gdk_x11_device_get_id (device) != area->device_id)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Handle click */
|
||||
area->time_elapsed = 0;
|
||||
success = add_click(&area->calibrator, (int)event->x_root, (int)event->y_root);
|
||||
|
||||
if (!success && area->calibrator.num_clicks == 0)
|
||||
draw_message(area, N_("Mis-click detected, restarting..."));
|
||||
else
|
||||
draw_message(area, NULL);
|
||||
|
||||
/* Are we done yet? */
|
||||
if (area->calibrator.num_clicks >= 4)
|
||||
{
|
||||
set_calibration_status (area);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Force a redraw */
|
||||
redraw(area);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_key_release_event(GtkWidget *widget,
|
||||
GdkEventKey *event,
|
||||
CalibArea *area)
|
||||
{
|
||||
if (area->success)
|
||||
return FALSE;
|
||||
if (event->type != GDK_KEY_RELEASE)
|
||||
return FALSE;
|
||||
if (event->keyval != GDK_KEY_Escape)
|
||||
return FALSE;
|
||||
|
||||
on_delete_event (widget, NULL, area);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_focus_out_event (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
CalibArea *area)
|
||||
{
|
||||
if (area->success)
|
||||
return FALSE;
|
||||
|
||||
/* If the calibrator window looses focus, simply bail out... */
|
||||
on_delete_event (widget, NULL, area);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_timer_signal(CalibArea *area)
|
||||
{
|
||||
GdkWindow *win;
|
||||
|
||||
area->time_elapsed += TIME_STEP;
|
||||
if (area->time_elapsed > MAX_TIME)
|
||||
{
|
||||
set_calibration_status (area);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Update clock */
|
||||
win = gtk_widget_get_window (area->window);
|
||||
if (win)
|
||||
{
|
||||
GdkRectangle rect;
|
||||
rect.x = area->display_width/2 - CLOCK_RADIUS - CLOCK_LINE_WIDTH;
|
||||
rect.y = area->display_height/2 - CLOCK_RADIUS - CLOCK_LINE_WIDTH;
|
||||
rect.width = 2 * CLOCK_RADIUS + 1 + 2 * CLOCK_LINE_WIDTH;
|
||||
rect.height = 2 * CLOCK_RADIUS + 1 + 2 * CLOCK_LINE_WIDTH;
|
||||
gdk_window_invalidate_rect(win, &rect, FALSE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the windows and other objects required to do calibration
|
||||
* under GTK. When the window is closed (timed out, calibration finished
|
||||
* or user cancellation), callback will be called, where you should call
|
||||
* calib_area_finish().
|
||||
*/
|
||||
CalibArea *
|
||||
calib_area_new (GdkScreen *screen,
|
||||
int monitor,
|
||||
int device_id,
|
||||
FinishCallback callback,
|
||||
gpointer user_data,
|
||||
XYinfo *old_axis,
|
||||
int threshold_doubleclick,
|
||||
int threshold_misclick)
|
||||
{
|
||||
CalibArea *calib_area;
|
||||
GdkRectangle rect;
|
||||
GdkWindow *window;
|
||||
GdkRGBA black;
|
||||
#ifndef FAKE_AREA
|
||||
GdkCursor *cursor;
|
||||
#endif /* FAKE_AREA */
|
||||
|
||||
g_return_val_if_fail (old_axis, NULL);
|
||||
g_return_val_if_fail (callback, NULL);
|
||||
|
||||
g_debug ("Current calibration: %d, %d, %d, %d\n",
|
||||
old_axis->x_min,
|
||||
old_axis->y_min,
|
||||
old_axis->x_max,
|
||||
old_axis->y_max);
|
||||
|
||||
calib_area = g_new0 (CalibArea, 1);
|
||||
calib_area->callback = callback;
|
||||
calib_area->user_data = user_data;
|
||||
calib_area->device_id = device_id;
|
||||
calib_area->calibrator.old_axis.x_min = old_axis->x_min;
|
||||
calib_area->calibrator.old_axis.x_max = old_axis->x_max;
|
||||
calib_area->calibrator.old_axis.y_min = old_axis->y_min;
|
||||
calib_area->calibrator.old_axis.y_max = old_axis->y_max;
|
||||
calib_area->calibrator.threshold_doubleclick = threshold_doubleclick;
|
||||
calib_area->calibrator.threshold_misclick = threshold_misclick;
|
||||
|
||||
/* Set up the window */
|
||||
calib_area->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_widget_set_app_paintable (GTK_WIDGET (calib_area->window), TRUE);
|
||||
|
||||
/* Black background */
|
||||
gdk_rgba_parse (&black, "rgb(0,0,0)");
|
||||
gtk_widget_set_opacity (GTK_WIDGET (calib_area->window), WINDOW_OPACITY);
|
||||
|
||||
gtk_widget_realize (calib_area->window);
|
||||
window = gtk_widget_get_window (calib_area->window);
|
||||
gdk_window_set_background_rgba (window, &black);
|
||||
|
||||
#ifndef FAKE_AREA
|
||||
/* No cursor (unless we're faking the area
|
||||
which might be convenient) */
|
||||
cursor = gdk_cursor_new (GDK_BLANK_CURSOR);
|
||||
gdk_window_set_cursor (window, cursor);
|
||||
g_object_unref (cursor);
|
||||
#endif /* FAKE_AREA */
|
||||
|
||||
/* Listen for mouse events */
|
||||
gtk_widget_add_events (calib_area->window, GDK_KEY_RELEASE_MASK | GDK_BUTTON_PRESS_MASK);
|
||||
gtk_widget_set_can_focus (calib_area->window, TRUE);
|
||||
gtk_window_fullscreen (GTK_WINDOW (calib_area->window));
|
||||
gtk_window_set_keep_above (GTK_WINDOW (calib_area->window), TRUE);
|
||||
|
||||
/* Connect callbacks */
|
||||
g_signal_connect (calib_area->window, "draw",
|
||||
G_CALLBACK(draw), calib_area);
|
||||
g_signal_connect (calib_area->window, "button-press-event",
|
||||
G_CALLBACK(on_button_press_event), calib_area);
|
||||
g_signal_connect (calib_area->window, "key-release-event",
|
||||
G_CALLBACK(on_key_release_event), calib_area);
|
||||
g_signal_connect (calib_area->window, "delete-event",
|
||||
G_CALLBACK(on_delete_event), calib_area);
|
||||
g_signal_connect (calib_area->window, "focus-out-event",
|
||||
G_CALLBACK(on_focus_out_event), calib_area);
|
||||
|
||||
/* Setup timer for animation */
|
||||
calib_area->anim_id = g_timeout_add(TIME_STEP, (GSourceFunc)on_timer_signal, calib_area);
|
||||
|
||||
/* Move to correct screen */
|
||||
if (screen == NULL)
|
||||
screen = gdk_screen_get_default ();
|
||||
gdk_screen_get_monitor_geometry (screen, monitor, &rect);
|
||||
gtk_window_move (GTK_WINDOW (calib_area->window), rect.x, rect.y);
|
||||
gtk_window_set_default_size (GTK_WINDOW (calib_area->window), rect.width, rect.height);
|
||||
|
||||
calib_area->calibrator.geometry.x = rect.x;
|
||||
calib_area->calibrator.geometry.y = rect.y;
|
||||
calib_area->calibrator.geometry.width = rect.width;
|
||||
calib_area->calibrator.geometry.height = rect.height;
|
||||
|
||||
gtk_widget_show_all (calib_area->window);
|
||||
|
||||
return calib_area;
|
||||
}
|
||||
|
||||
/* Finishes the calibration. Note that CalibArea
|
||||
* needs to be destroyed with calib_area_free() afterwards */
|
||||
gboolean
|
||||
calib_area_finish (CalibArea *area,
|
||||
XYinfo *new_axis,
|
||||
gboolean *swap_xy)
|
||||
{
|
||||
g_return_val_if_fail (area != NULL, FALSE);
|
||||
|
||||
*new_axis = area->axis;
|
||||
*swap_xy = area->swap;
|
||||
|
||||
if (area->success)
|
||||
g_debug ("Final calibration: %d, %d, %d, %d\n",
|
||||
new_axis->x_min,
|
||||
new_axis->y_min,
|
||||
new_axis->x_max,
|
||||
new_axis->y_max);
|
||||
else
|
||||
g_debug ("Calibration was aborted or timed out");
|
||||
|
||||
return area->success;
|
||||
}
|
||||
|
||||
void
|
||||
calib_area_free (CalibArea *area)
|
||||
{
|
||||
g_return_if_fail (area != NULL);
|
||||
|
||||
if (area->anim_id > 0) {
|
||||
g_source_remove (area->anim_id);
|
||||
area->anim_id = 0;
|
||||
}
|
||||
|
||||
if (area->icon_success)
|
||||
g_object_unref (area->icon_success);
|
||||
|
||||
gtk_widget_destroy (area->window);
|
||||
g_free (area);
|
||||
}
|
||||
|
||||
void
|
||||
calib_area_get_display_size (CalibArea *area, gint *width, gint *height)
|
||||
{
|
||||
*width = area->display_width;
|
||||
*height = area->display_height;
|
||||
}
|
|
@ -28,10 +28,11 @@
|
|||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <clutter-gtk/clutter-gtk.h>
|
||||
|
||||
#include <X11/extensions/XInput.h>
|
||||
|
||||
#include "gui_gtk.h"
|
||||
#include "calibrator-gui.h"
|
||||
#include "calibrator.h"
|
||||
|
||||
/**
|
||||
|
@ -397,7 +398,11 @@ int main(int argc, char** argv)
|
|||
g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
|
||||
|
||||
/* GTK setup */
|
||||
gtk_init(&argc, &argv);
|
||||
if (gtk_clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
{
|
||||
g_critical ("Unable to initialize Clutter");
|
||||
return 1;
|
||||
}
|
||||
|
||||
calib_area = calib_area_new (NULL,
|
||||
0, /* monitor */
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "cc-wacom-mapping-panel.h"
|
||||
#include "cc-wacom-stylus-page.h"
|
||||
#include "gsd-enums.h"
|
||||
#include "gui_gtk.h"
|
||||
#include "calibrator-gui.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <clutter-gtk/clutter-gtk.h>
|
||||
|
||||
#include "cc-wacom-page.h"
|
||||
#include "gsd-wacom-device.h"
|
||||
#include "clutter/clutter.h"
|
||||
|
||||
#define FIXED_WIDTH 675
|
||||
|
||||
|
@ -69,7 +71,10 @@ int main (int argc, char **argv)
|
|||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
textdomain (GETTEXT_PACKAGE);
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
if (gtk_clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) {
|
||||
g_critical ("Unable to initialize Clutter");
|
||||
return 1;
|
||||
}
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
|
|
|
@ -2,6 +2,7 @@ INCLUDES = \
|
|||
-I$(top_srcdir) \
|
||||
$(SHELL_CFLAGS) \
|
||||
$(CHEESE_CFLAGS) \
|
||||
$(WACOM_PANEL_CFLAGS) \
|
||||
-I$(top_srcdir)/panels/common/ \
|
||||
-I$(top_srcdir)/libgd
|
||||
|
||||
|
|
|
@ -30,9 +30,12 @@
|
|||
#include "cc-shell-log.h"
|
||||
#include "cc-window.h"
|
||||
|
||||
#if defined(HAVE_CHEESE) || defined(HAVE_WACOM)
|
||||
#include <clutter-gtk/clutter-gtk.h>
|
||||
#endif /* HAVE_CHEESE || HAVE_WACOM */
|
||||
|
||||
#ifdef HAVE_CHEESE
|
||||
#include <cheese-gtk.h>
|
||||
#include <clutter-gtk/clutter-gtk.h>
|
||||
#endif /* HAVE_CHEESE */
|
||||
|
||||
struct _CcApplicationPrivate
|
||||
|
@ -277,13 +280,13 @@ cc_application_startup (GApplication *application)
|
|||
|
||||
G_APPLICATION_CLASS (cc_application_parent_class)->startup (application);
|
||||
|
||||
#ifdef HAVE_CHEESE
|
||||
#if defined(HAVE_CHEESE) || defined(HAVE_WACOM)
|
||||
if (gtk_clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
|
||||
{
|
||||
g_critical ("Unable to initialize Clutter");
|
||||
return;
|
||||
}
|
||||
#endif /* HAVE_CHEESE */
|
||||
#endif /* HAVE_CHEESE || HAVE_WACOM */
|
||||
|
||||
/* register a symbolic icon size for use in sidebar lists */
|
||||
gtk_icon_size_register ("cc-sidebar-list", 24, 24);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue