#include typedef struct { gdouble x, y; gdouble old_x, old_y; gdouble r, g, b; GdkEventSequence *seq; } TouchData; GList *touch_list = NULL; cairo_surface_t *image = NULL; cairo_t *icr; GRand *randseed; gboolean on_touch (GtkWidget *widget, GdkEventTouch *event, gpointer user_data) { static gint count = 0; GList *lst; TouchData *data; GdkEventMotion *mevent = (GdkEventMotion *) event; g_printerr ("on_touch: event type %d\n", event->type); switch (event->type) { case GDK_TOUCH_BEGIN: data = g_malloc (sizeof (TouchData)); data->old_x = event->axes[0]; data->old_y = event->axes[1]; data->x = event->axes[0]; data->y = event->axes[1]; data->r = g_rand_double (randseed); data->g = g_rand_double (randseed); data->b = g_rand_double (randseed); data->seq = event->sequence; touch_list = g_list_append (touch_list, data); // g_printerr ("touch begin: %.2f, %.2f (%p, %p)\n", event->axes[0], event->axes[1], event->device, event->sequence); count ++; break; case GDK_TOUCH_UPDATE: lst = touch_list; while (lst) { data = (TouchData*) lst->data; if (data->seq == event->sequence) { data->old_x = data->x; data->old_y = data->y; data->x = event->axes[0]; data->y = event->axes[1]; g_printerr ("%.2f, %.2f\n", data->x, data->y); cairo_set_line_width (icr, 30); cairo_set_source_rgb (icr, data->r, data->g, data->b); cairo_move_to (icr, data->old_x, data->old_y); cairo_line_to (icr, data->x, data->y); cairo_stroke (icr); break; } lst = lst->next; } cairo_surface_flush (image); gtk_widget_queue_draw (widget); break; case GDK_TOUCH_END: case GDK_TOUCH_CANCEL: lst = touch_list; while(lst) { data = (TouchData*) lst->data; if (data->seq == event->sequence) { touch_list = g_list_remove (touch_list, data); g_free (data); break; } lst = lst->next; } count--; break; case GDK_MOTION_NOTIFY: // return FALSE; cairo_set_source_rgb (icr, 1.0, 1.0, 1.0); cairo_set_line_width (icr, event->axes[2] * 100); cairo_move_to (icr, event->axes[0], event->axes[1]); cairo_line_to (icr, event->axes[0] + 0.0001, event->axes[1]); cairo_stroke (icr); cairo_surface_flush (image); gtk_widget_queue_draw (widget); break; default: g_printerr ("Unknown touch type %d\n", event->type); } // g_printerr ("%d\n", count); return TRUE; } gboolean on_draw (GtkWidget *widget, cairo_t *cr) { cairo_set_source_surface (cr, image, 0, 0); cairo_paint (cr); return FALSE; } void list_devices () { GdkDisplay *display; GdkDeviceManager *manager; GList *l, *devices; display = gdk_display_get_default (); manager = gdk_display_get_device_manager (display); devices = gdk_device_manager_list_devices (manager, GDK_DEVICE_TYPE_SLAVE); for (l = devices; l; l = g_list_next (l)) { GdkDevice *device = l->data; g_printerr ("%s (type %d, %d)\n", gdk_device_get_name (device), gdk_device_get_source (device), gdk_device_get_mode (device) ); if (gdk_device_get_source (device) == GDK_SOURCE_PEN || gdk_device_get_source (device) == GDK_SOURCE_ERASER || gdk_device_get_source (device) == GDK_SOURCE_TOUCHSCREEN) { gdk_device_set_mode (device, GDK_MODE_SCREEN); } } } int main (int argc, char *argv[]) { GtkWidget *window; gtk_init (&argc, &argv); list_devices (); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_set_events (window, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_TOUCH_MASK); image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 1820, 980); icr = cairo_create (image); cairo_set_source_rgb (icr, 0.0, 0.0, 0.0); cairo_paint (icr); cairo_set_line_width (icr, 30); cairo_set_line_cap (icr, CAIRO_LINE_CAP_ROUND); cairo_surface_flush (image); g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); g_signal_connect (window, "touch-event", G_CALLBACK (on_touch), NULL); g_signal_connect (window, "button-press-event", G_CALLBACK (on_touch), NULL); g_signal_connect (window, "button-release-event", G_CALLBACK (on_touch), NULL); g_signal_connect (window, "motion-notify-event", G_CALLBACK (on_touch), NULL); g_signal_connect (window, "draw", G_CALLBACK (on_draw), NULL); gtk_window_set_default_size (GTK_WINDOW (window), 1820, 980); gtk_widget_set_app_paintable (window, TRUE); randseed = g_rand_new (); gtk_widget_show (window); gtk_main (); return 0; }