[gtk+/multitouch: 40/40] demos: Demonstrate further features in the multitouch demo
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/multitouch: 40/40] demos: Demonstrate further features in the multitouch demo
- Date: Thu, 5 Jan 2012 11:44:05 +0000 (UTC)
commit cde4c76f51efbfa1633e6175bc2717b4a37dbd54
Author: Carlos Garnacho <carlosg gnome org>
Date: Thu Jan 5 01:15:01 2012 +0100
demos: Demonstrate further features in the multitouch demo
Now that GtkButton and GtkScale are multitouch approved, it's
sufficient to enable GDK_TOUCH_MASK on them to have them deal
with multitouch devices.
The scales set rgba of the currently selected rectangle, and
the button adds more rectangles, those can be manipulated
simultaneously together with the rectangles, the only limit
is the number of touches the touchscreen hw is able to detect.
demos/gtk-demo/multitouch.c | 267 ++++++++++++++++++++++++++++++++++++-------
1 files changed, 225 insertions(+), 42 deletions(-)
---
diff --git a/demos/gtk-demo/multitouch.c b/demos/gtk-demo/multitouch.c
index dfb6262..a85161f 100644
--- a/demos/gtk-demo/multitouch.c
+++ b/demos/gtk-demo/multitouch.c
@@ -2,15 +2,31 @@
*
* Demonstrates some general multitouch event handling,
* using GdkTouchCluster in order to get grouped motion
- * events for the touches within a cluster.
+ * events for the touches within a cluster. Each of the
+ * created rectangles has one of those GdkTouchCluster
+ * objects.
+ *
+ * Touch events are also enabled on additional widgets,
+ * enabling simultaneous touch interaction on those. Not
+ * all widgets are prepared for multitouch interaction,
+ * as there are constraints that not all widgets may
+ * apply to.
*/
#include <math.h>
#include <gtk/gtk.h>
#include "demo-common.h"
+#define RECT_BORDER_WIDTH 6
+
static GtkWidget *window = NULL;
-static GList *shapes = NULL;
+static GtkWidget *area = NULL;
+static GtkWidget *red = NULL;
+static GtkWidget *green = NULL;
+static GtkWidget *blue = NULL;
+static GtkWidget *alpha = NULL;
+
+static GQueue *shapes = NULL;
typedef struct {
GdkTouchCluster *cluster;
@@ -265,7 +281,7 @@ shape_info_new (gdouble x,
shape_info_allocate_input_rect (info);
- shapes = g_list_prepend (shapes, info);
+ g_queue_push_tail (shapes, info);
return info;
}
@@ -282,21 +298,66 @@ shape_info_draw (cairo_t *cr,
{
cairo_save (cr);
- cairo_translate (cr, info->points[0].x, info->points[0].y);
+ cairo_translate (cr,
+ info->points[0].x + RECT_BORDER_WIDTH / 2,
+ info->points[0].y + RECT_BORDER_WIDTH / 2);
+
cairo_scale (cr, info->zoom, info->zoom);
cairo_rotate (cr, info->angle);
- cairo_rectangle (cr, 0, 0, info->width, info->height);
+ cairo_rectangle (cr, 0, 0,
+ info->width - RECT_BORDER_WIDTH,
+ info->height - RECT_BORDER_WIDTH);
gdk_cairo_set_source_rgba (cr, &info->color);
cairo_fill_preserve (cr);
- cairo_set_line_width (cr, 6);
+ cairo_set_line_width (cr, RECT_BORDER_WIDTH);
cairo_set_source_rgb (cr, 0, 0, 0);
cairo_stroke (cr);
cairo_restore (cr);
}
+static void
+shape_update_scales (ShapeInfo *info)
+{
+ gtk_range_set_value (GTK_RANGE (red), info->color.red);
+ gtk_range_set_value (GTK_RANGE (green), info->color.green);
+ gtk_range_set_value (GTK_RANGE (blue), info->color.blue);
+ gtk_range_set_value (GTK_RANGE (alpha), info->color.alpha);
+}
+
+static void
+range_value_changed_cb (GtkRange *range,
+ gpointer user_data)
+{
+ GtkWidget *widget;
+ GdkRectangle rect;
+ ShapeInfo *shape;
+ gdouble value;
+
+ widget = GTK_WIDGET (range);
+ shape = g_queue_peek_head (shapes);
+
+ if (!shape)
+ return;
+
+ value = gtk_range_get_value (range);
+
+ if (widget == red)
+ shape->color.red = value;
+ else if (widget == green)
+ shape->color.green = value;
+ else if (widget == blue)
+ shape->color.blue = value;
+ else if (widget == alpha)
+ shape->color.alpha = value;
+
+ shape_info_bounding_rect (shape, &rect);
+ gdk_window_invalidate_rect (gtk_widget_get_window (area),
+ &rect, FALSE);
+}
+
static gboolean
draw_cb (GtkWidget *widget,
cairo_t *cr,
@@ -304,9 +365,16 @@ draw_cb (GtkWidget *widget,
{
GList *l;
- for (l = shapes; l; l = l->next)
+ cairo_save (cr);
+
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+
+ for (l = shapes->tail; l; l = l->prev)
shape_info_draw (cr, l->data);
+ cairo_restore (cr);
+
return FALSE;
}
@@ -322,7 +390,7 @@ button_press_cb (GtkWidget *widget,
{
GList *l;
- for (l = shapes; l; l = l->next)
+ for (l = shapes->tail; l; l = l->prev)
{
ShapeInfo *info = l->data;
@@ -335,6 +403,12 @@ button_press_cb (GtkWidget *widget,
if (!shape)
return FALSE;
+ /* Put on top */
+ g_queue_remove (shapes, shape);
+ g_queue_push_head (shapes, shape);
+
+ shape_update_scales (shape);
+
if (!shape->cluster)
shape->cluster = gdk_window_create_touch_cluster (gtk_widget_get_window (widget));
@@ -364,7 +438,7 @@ multitouch_cb (GtkWidget *widget,
GdkRectangle rect;
GList *l;
- for (l = shapes; l; l = l->next)
+ for (l = shapes->head; l; l = l->next)
{
ShapeInfo *shape = l->data;
@@ -456,47 +530,156 @@ multitouch_cb (GtkWidget *widget,
return TRUE;
}
+static void
+window_destroyed_cb (GtkWidget *widget,
+ gpointer user_data)
+{
+ g_queue_foreach (shapes, (GFunc) shape_info_free, NULL);
+ g_queue_free (shapes);
+
+ shapes = NULL;
+ window = NULL;
+}
+
+static void
+new_rectangle_clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ GdkRectangle rect;
+ ShapeInfo *info;
+ GdkRGBA color;
+
+ color.red = color.green = color.blue = color.alpha = 0.5;
+ info = shape_info_new (0, 0, 100, 150, &color);
+
+ shape_info_bounding_rect (info, &rect);
+ gdk_window_invalidate_rect (gtk_widget_get_window (area), &rect, FALSE);
+}
+
GtkWidget *
-do_multitouch (GtkWidget *do_widget)
+create_drawing_area (void)
{
- if (!window)
- {
- GdkRGBA color;
+ area = gtk_drawing_area_new ();
+
+ gtk_widget_add_events (area,
+ GDK_TOUCH_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK);
+
+ gtk_widget_set_size_request (area, 600, 600);
+
+ g_signal_connect (area, "draw",
+ G_CALLBACK (draw_cb), NULL);
+ g_signal_connect (area, "button-press-event",
+ G_CALLBACK (button_press_cb), NULL);
+ g_signal_connect (area, "multitouch-event",
+ G_CALLBACK (multitouch_cb), NULL);
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title (GTK_WINDOW (window), "Multitouch demo");
- gtk_window_set_default_size (GTK_WINDOW (window), 600, 600);
+ return area;
+}
- gtk_window_set_screen (GTK_WINDOW (window),
- gtk_widget_get_screen (do_widget));
+GtkWidget *
+create_scale (void)
+{
+ GtkWidget *scale;
- gtk_widget_add_events (window,
- GDK_TOUCH_MASK |
- GDK_POINTER_MOTION_MASK |
- GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK);
+ scale = gtk_scale_new_with_range (GTK_ORIENTATION_VERTICAL, 0, 1, 0.01);
+ gtk_range_set_inverted (GTK_RANGE (scale), TRUE);
- gtk_widget_set_app_paintable (window, TRUE);
+ gtk_widget_set_vexpand (scale, TRUE);
+ gtk_widget_set_margin_left (scale, 15);
+ gtk_widget_set_margin_right (scale, 15);
- g_signal_connect (window, "draw",
- G_CALLBACK (draw_cb), NULL);
- g_signal_connect (window, "button-press-event",
- G_CALLBACK (button_press_cb), NULL);
- g_signal_connect (window, "multitouch-event",
- G_CALLBACK (multitouch_cb), NULL);
+ gtk_widget_add_events (scale, GDK_TOUCH_MASK);
- gdk_rgba_parse (&color, "red");
- color.alpha = 0.5;
- shape_info_new (100, 50, 100, 140, &color);
+ g_signal_connect (scale, "value-changed",
+ G_CALLBACK (range_value_changed_cb), NULL);
+ return scale;
+}
- gdk_rgba_parse (&color, "green");
- color.alpha = 0.5;
- shape_info_new (200, 100, 120, 90, &color);
+GtkWidget *
+create_window (void)
+{
+ GtkWidget *grid, *label, *button;
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (window), "Multitouch demo");
+ g_signal_connect (window, "destroy",
+ G_CALLBACK (window_destroyed_cb), NULL);
+
+ grid = gtk_grid_new ();
+ gtk_container_add (GTK_CONTAINER (window), grid);
+
+ area = create_drawing_area ();
+ gtk_grid_attach (GTK_GRID (grid),
+ area, 0, 0, 1, 3);
+ gtk_widget_set_hexpand (area, TRUE);
+ gtk_widget_set_vexpand (area, TRUE);
+
+ /* "red" label/scale */
+ label = gtk_label_new ("Red");
+ gtk_widget_set_vexpand (label, FALSE);
+ gtk_grid_attach (GTK_GRID (grid),
+ label, 1, 0, 1, 1);
+
+ red = create_scale ();
+ gtk_grid_attach (GTK_GRID (grid),
+ red, 1, 1, 1, 1);
+
+ /* "green" label/scale */
+ label = gtk_label_new ("Green");
+ gtk_widget_set_vexpand (label, FALSE);
+ gtk_grid_attach (GTK_GRID (grid),
+ label, 2, 0, 1, 1);
+
+ green = create_scale ();
+ gtk_grid_attach (GTK_GRID (grid),
+ green, 2, 1, 1, 1);
+
+ /* "blue" label/scale */
+ label = gtk_label_new ("Blue");
+ gtk_widget_set_vexpand (label, FALSE);
+ gtk_grid_attach (GTK_GRID (grid),
+ label, 3, 0, 1, 1);
+
+ blue = create_scale ();
+ gtk_grid_attach (GTK_GRID (grid),
+ blue, 3, 1, 1, 1);
+
+ /* "alpha" label/scale */
+ label = gtk_label_new ("Alpha");
+ gtk_widget_set_vexpand (label, FALSE);
+ gtk_grid_attach (GTK_GRID (grid),
+ label, 4, 0, 1, 1);
+
+ alpha = create_scale ();
+ gtk_grid_attach (GTK_GRID (grid),
+ alpha, 4, 1, 1, 1);
+
+ /* button */
+ button = gtk_button_new_from_stock (GTK_STOCK_NEW);
+ gtk_widget_add_events (button, GDK_TOUCH_MASK);
+ gtk_grid_attach (GTK_GRID (grid),
+ button, 1, 2, 4, 1);
+ gtk_widget_set_vexpand (button, FALSE);
+
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (new_rectangle_clicked_cb), NULL);
+
+ gtk_widget_show_all (grid);
- gdk_rgba_parse (&color, "blue");
- color.alpha = 0.5;
- shape_info_new (150, 190, 140, 90, &color);
- }
+ return window;
+}
+
+GtkWidget *
+do_multitouch (GtkWidget *do_widget)
+{
+ if (!shapes)
+ shapes = g_queue_new ();
+
+ if (!window)
+ window = create_window ();
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
@@ -505,8 +688,8 @@ do_multitouch (GtkWidget *do_widget)
gtk_widget_destroy (window);
window = NULL;
- g_list_foreach (shapes, (GFunc) shape_info_free, NULL);
- g_list_free (shapes);
+ g_queue_foreach (shapes, (GFunc) shape_info_free, NULL);
+ g_queue_free (shapes);
shapes = NULL;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]