903452d2df
The current versions redraws all events on every redraw, which starts getting very slow quickly. Instead simply draw only the new events except when the cairo surface got reset, in that case redraw all events again. https://bugzilla.gnome.org/show_bug.cgi?id=681584
198 lines
5.9 KiB
C
198 lines
5.9 KiB
C
/*
|
|
* Copyright (C) 2012 Collabora Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms and conditions of the GNU Lesser General Public License,
|
|
* version 2.1, as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
* Boston, MA 02111-1307, USA.
|
|
*
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <cairo.h>
|
|
#include <glib.h>
|
|
#include <clutter/clutter.h>
|
|
|
|
#define STAGE_WIDTH 800
|
|
#define STAGE_HEIGHT 550
|
|
#define NUM_COLORS 10
|
|
#define NUM_ACTORS 10
|
|
|
|
static GQueue events = G_QUEUE_INIT;
|
|
static GQueue all_events = G_QUEUE_INIT;
|
|
static gboolean new_surface = TRUE;
|
|
|
|
static const ClutterColor const static_colors[] = {
|
|
{ 0xff, 0x00, 0x00, 0xff }, /* red */
|
|
{ 0x80, 0x00, 0x00, 0xff }, /* dark red */
|
|
{ 0x00, 0xff, 0x00, 0xff }, /* green */
|
|
{ 0x00, 0x80, 0x00, 0xff }, /* dark green */
|
|
{ 0x00, 0x00, 0xff, 0xff }, /* blue */
|
|
{ 0x00, 0x00, 0x80, 0xff }, /* dark blue */
|
|
{ 0x00, 0xff, 0xff, 0xff }, /* cyan */
|
|
{ 0x00, 0x80, 0x80, 0xff }, /* dark cyan */
|
|
{ 0xff, 0x00, 0xff, 0xff }, /* magenta */
|
|
{ 0xff, 0xff, 0x00, 0xff }, /* yellow */
|
|
};
|
|
static GHashTable *sequence_to_color = NULL;
|
|
|
|
static void
|
|
canvas_paint (ClutterCairoTexture *canvas)
|
|
{
|
|
clutter_cairo_texture_invalidate (canvas);
|
|
}
|
|
|
|
static void
|
|
draw_touch (ClutterEvent *event,
|
|
cairo_t *cr)
|
|
{
|
|
ClutterEventSequence *sequence = clutter_event_get_event_sequence (event);
|
|
const ClutterColor *color;
|
|
|
|
color = g_hash_table_lookup (sequence_to_color, sequence);
|
|
if (color == NULL)
|
|
{
|
|
color = &static_colors[g_random_int_range (0, NUM_COLORS)];
|
|
g_hash_table_insert (sequence_to_color, (gpointer) sequence, (gpointer) color);
|
|
}
|
|
|
|
cairo_set_source_rgba (cr, color->red / 255,
|
|
color->green / 255,
|
|
color->blue / 255,
|
|
color->alpha / 255);
|
|
cairo_arc (cr, event->touch.x, event->touch.y, 5, 0, 2 * G_PI);
|
|
cairo_fill (cr);
|
|
}
|
|
|
|
static gboolean
|
|
draw_touches (ClutterCairoTexture *canvas,
|
|
cairo_t *cr)
|
|
{
|
|
g_queue_foreach (new_surface ? &all_events : &events, (GFunc) draw_touch, cr);
|
|
g_queue_clear (&events);
|
|
|
|
new_surface = FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static cairo_surface_t *
|
|
create_surface (ClutterCairoTexture *texture,
|
|
guint width,
|
|
guint height,
|
|
gpointer user_data)
|
|
{
|
|
new_surface = TRUE;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static gboolean
|
|
event_cb (ClutterActor *actor, ClutterEvent *event, ClutterActor *canvas)
|
|
{
|
|
ClutterEvent *copy;
|
|
|
|
if (event->type != CLUTTER_TOUCH_UPDATE)
|
|
return FALSE;
|
|
|
|
copy = clutter_event_copy (event);
|
|
g_queue_push_tail (&events, copy);
|
|
g_queue_push_tail (&all_events, copy);
|
|
clutter_actor_queue_redraw (canvas);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
rect_event_cb (ClutterActor *actor, ClutterEvent *event, gpointer data)
|
|
{
|
|
ClutterColor color;
|
|
|
|
if (event->type != CLUTTER_TOUCH_BEGIN)
|
|
return FALSE;
|
|
|
|
color = static_colors[g_random_int_range (0, NUM_COLORS)];
|
|
clutter_rectangle_set_color (CLUTTER_RECTANGLE (actor), &color);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
G_MODULE_EXPORT int
|
|
test_touch_events_main (int argc, char *argv[])
|
|
{
|
|
ClutterActor *stage, *canvas;
|
|
int i;
|
|
|
|
#ifdef CLUTTER_WINDOWING_X11
|
|
clutter_x11_enable_xinput ();
|
|
#endif
|
|
|
|
/* initialize Clutter */
|
|
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
|
return EXIT_FAILURE;
|
|
|
|
/* create a resizable stage */
|
|
stage = clutter_stage_new ();
|
|
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
|
clutter_stage_set_title (CLUTTER_STAGE (stage), "Touch events");
|
|
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
|
|
clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT);
|
|
clutter_actor_set_reactive (stage, TRUE);
|
|
clutter_actor_show (stage);
|
|
|
|
/* our 2D canvas, courtesy of Cairo */
|
|
canvas = clutter_cairo_texture_new (1, 1);
|
|
g_signal_connect (canvas, "paint", G_CALLBACK (canvas_paint), NULL);
|
|
g_signal_connect (canvas, "draw", G_CALLBACK (draw_touches), NULL);
|
|
g_signal_connect (canvas, "create-surface", G_CALLBACK (create_surface), NULL);
|
|
clutter_cairo_texture_set_auto_resize (CLUTTER_CAIRO_TEXTURE (canvas), TRUE);
|
|
clutter_actor_add_constraint (canvas,
|
|
clutter_bind_constraint_new (stage,
|
|
CLUTTER_BIND_SIZE,
|
|
0));
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (stage), canvas);
|
|
|
|
g_signal_connect (stage, "event", G_CALLBACK (event_cb), canvas);
|
|
|
|
for (i = 0; i < NUM_ACTORS; i++)
|
|
{
|
|
gfloat size = STAGE_HEIGHT / NUM_ACTORS;
|
|
ClutterColor color = static_colors[i % NUM_COLORS];
|
|
ClutterActor *rectangle = clutter_rectangle_new_with_color (&color);
|
|
|
|
/* Test that event delivery to actors work */
|
|
g_signal_connect (rectangle, "event", G_CALLBACK (rect_event_cb), NULL);
|
|
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (stage), rectangle);
|
|
clutter_actor_set_size (rectangle, size, size);
|
|
clutter_actor_set_position (rectangle, 0, i * size);
|
|
clutter_actor_set_reactive (rectangle, TRUE);
|
|
}
|
|
|
|
sequence_to_color = g_hash_table_new (NULL, NULL);
|
|
|
|
clutter_main ();
|
|
|
|
g_queue_foreach (&all_events, (GFunc) clutter_event_free, NULL);
|
|
g_queue_clear (&events);
|
|
g_queue_clear (&all_events);
|
|
g_hash_table_destroy (sequence_to_color);
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
G_MODULE_EXPORT const char *
|
|
test_touch_events_describe (void)
|
|
{
|
|
return "Draw shapes based on touch events";
|
|
}
|