Compare commits
12 Commits
wip/pango-
...
xi21
Author | SHA1 | Date | |
---|---|---|---|
|
bb99289487 | ||
|
f48204d4af | ||
|
fa3f6fa0ed | ||
|
be5f2c7cd4 | ||
|
776477ee96 | ||
|
4be23cb80c | ||
|
93162f080d | ||
|
8bc4f71f68 | ||
|
a0c29b0114 | ||
|
a898575fdd | ||
|
02f62468aa | ||
|
df3af16b3a |
@@ -1078,6 +1078,10 @@ if test "x$enable_x11_backend" == xyes; then
|
|||||||
AC_DEFINE(XINPUT_2, 1, [Define to 1 if XInput 2.0 is available]),
|
AC_DEFINE(XINPUT_2, 1, [Define to 1 if XInput 2.0 is available]),
|
||||||
X_EXTENSIONS="$X_EXTENSIONS XInput")
|
X_EXTENSIONS="$X_EXTENSIONS XInput")
|
||||||
|
|
||||||
|
gtk_save_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS -lXi"
|
||||||
|
AC_CHECK_FUNC(XIAllowTouchEvents, AC_DEFINE(XINPUT_2_1, 1, [Define to 1 if XInput 2.1 is available]))
|
||||||
|
LIBS="$gtk_save_LIBS"
|
||||||
else
|
else
|
||||||
AC_DEFINE(XINPUT_NONE, 1,
|
AC_DEFINE(XINPUT_NONE, 1,
|
||||||
[Define to 1 if no XInput should be used])
|
[Define to 1 if no XInput should be used])
|
||||||
|
@@ -28,6 +28,7 @@ demos = \
|
|||||||
links.c \
|
links.c \
|
||||||
list_store.c \
|
list_store.c \
|
||||||
menus.c \
|
menus.c \
|
||||||
|
multitouch.c \
|
||||||
offscreen_window.c \
|
offscreen_window.c \
|
||||||
offscreen_window2.c \
|
offscreen_window2.c \
|
||||||
panes.c \
|
panes.c \
|
||||||
|
514
demos/gtk-demo/multitouch.c
Normal file
514
demos/gtk-demo/multitouch.c
Normal file
@@ -0,0 +1,514 @@
|
|||||||
|
/* Multitouch
|
||||||
|
*
|
||||||
|
* Demonstrates some general multitouch event handling,
|
||||||
|
* using GdkTouchCluster in order to get grouped motion
|
||||||
|
* events for the touches within a cluster.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include "demo-common.h"
|
||||||
|
|
||||||
|
static GtkWidget *window = NULL;
|
||||||
|
static GList *shapes = NULL;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GdkTouchCluster *cluster;
|
||||||
|
GdkRGBA color;
|
||||||
|
|
||||||
|
gdouble angle;
|
||||||
|
gdouble zoom;
|
||||||
|
|
||||||
|
gdouble center_x;
|
||||||
|
gdouble center_y;
|
||||||
|
|
||||||
|
gdouble x;
|
||||||
|
gdouble y;
|
||||||
|
gdouble width;
|
||||||
|
gdouble height;
|
||||||
|
|
||||||
|
gdouble base_zoom;
|
||||||
|
gdouble base_angle;
|
||||||
|
gdouble initial_distance;
|
||||||
|
gdouble initial_angle;
|
||||||
|
|
||||||
|
GdkPoint points[4];
|
||||||
|
} ShapeInfo;
|
||||||
|
|
||||||
|
static void
|
||||||
|
calculate_rotated_point (gdouble angle,
|
||||||
|
gdouble zoom,
|
||||||
|
gdouble center_x,
|
||||||
|
gdouble center_y,
|
||||||
|
gdouble point_x,
|
||||||
|
gdouble point_y,
|
||||||
|
gdouble *ret_x,
|
||||||
|
gdouble *ret_y)
|
||||||
|
{
|
||||||
|
gdouble distance, xd, yd, ang;
|
||||||
|
|
||||||
|
if (angle == 0)
|
||||||
|
{
|
||||||
|
*ret_x = point_x;
|
||||||
|
*ret_y = point_y;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xd = center_x - point_x;
|
||||||
|
yd = center_y - point_y;
|
||||||
|
|
||||||
|
if (xd == 0 && yd == 0)
|
||||||
|
{
|
||||||
|
*ret_x = center_x;
|
||||||
|
*ret_y = center_y;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
distance = sqrt ((xd * xd) + (yd * yd));
|
||||||
|
distance *= zoom;
|
||||||
|
|
||||||
|
ang = atan2 (xd, yd);
|
||||||
|
|
||||||
|
/* Invert angle */
|
||||||
|
ang = (2 * G_PI) - ang;
|
||||||
|
|
||||||
|
/* Shift it 270° */
|
||||||
|
ang += 3 * (G_PI / 2);
|
||||||
|
|
||||||
|
/* And constraint it to 0°-360° */
|
||||||
|
ang = fmod (ang, 2 * G_PI);
|
||||||
|
ang += angle;
|
||||||
|
|
||||||
|
*ret_x = center_x + (distance * cos (ang));
|
||||||
|
*ret_y = center_y + (distance * sin (ang));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shape_info_allocate_input_rect (ShapeInfo *info)
|
||||||
|
{
|
||||||
|
gint width, height, i;
|
||||||
|
|
||||||
|
width = info->width;
|
||||||
|
height = info->height;
|
||||||
|
|
||||||
|
/* Top/left */
|
||||||
|
info->points[0].x = info->x - info->center_x;
|
||||||
|
info->points[0].y = info->y - info->center_y;
|
||||||
|
|
||||||
|
/* Top/right */
|
||||||
|
info->points[1].x = info->x - info->center_x + width;
|
||||||
|
info->points[1].y = info->y - info->center_y;
|
||||||
|
|
||||||
|
/* Bottom/right */
|
||||||
|
info->points[2].x = info->x - info->center_x + width;
|
||||||
|
info->points[2].y = info->y - info->center_y + height;
|
||||||
|
|
||||||
|
/* Bottom/left */
|
||||||
|
info->points[3].x = info->x - info->center_x;
|
||||||
|
info->points[3].y = info->y - info->center_y + height;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
gdouble ret_x, ret_y;
|
||||||
|
|
||||||
|
calculate_rotated_point (info->angle,
|
||||||
|
info->zoom,
|
||||||
|
info->x,
|
||||||
|
info->y,
|
||||||
|
(gdouble) info->points[i].x,
|
||||||
|
(gdouble) info->points[i].y,
|
||||||
|
&ret_x,
|
||||||
|
&ret_y);
|
||||||
|
|
||||||
|
info->points[i].x = (gint) ret_x;
|
||||||
|
info->points[i].y = (gint) ret_y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shape_info_bounding_rect (ShapeInfo *info,
|
||||||
|
GdkRectangle *rect)
|
||||||
|
{
|
||||||
|
gint i, left, right, top, bottom;
|
||||||
|
|
||||||
|
left = top = G_MAXINT;
|
||||||
|
right = bottom = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (info->points[i].x < left)
|
||||||
|
left = info->points[i].x;
|
||||||
|
|
||||||
|
if (info->points[i].x > right)
|
||||||
|
right = info->points[i].x;
|
||||||
|
|
||||||
|
if (info->points[i].y < top)
|
||||||
|
top = info->points[i].y;
|
||||||
|
|
||||||
|
if (info->points[i].y > bottom)
|
||||||
|
bottom = info->points[i].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
rect->x = left - 20;
|
||||||
|
rect->y = top - 20;
|
||||||
|
rect->width = right - left + 40;
|
||||||
|
rect->height = bottom - top + 40;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
shape_info_point_in (ShapeInfo *info,
|
||||||
|
gint x,
|
||||||
|
gint y)
|
||||||
|
{
|
||||||
|
GdkPoint *left, *right, *top, *bottom;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
left = right = top = bottom = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
GdkPoint *p = &info->points[i];
|
||||||
|
|
||||||
|
if (!left ||
|
||||||
|
p->x < left->x ||
|
||||||
|
(p->x == left->x && p->y > left->y))
|
||||||
|
left = p;
|
||||||
|
|
||||||
|
if (!right ||
|
||||||
|
p->x > right->x ||
|
||||||
|
(p->x == right->x && p->y < right->y))
|
||||||
|
right = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
GdkPoint *p = &info->points[i];
|
||||||
|
|
||||||
|
if (p == left || p == right)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!top ||
|
||||||
|
p->y < top->y)
|
||||||
|
top = p;
|
||||||
|
|
||||||
|
if (!bottom ||
|
||||||
|
p->y > bottom->y)
|
||||||
|
bottom = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert (left && right && top && bottom);
|
||||||
|
|
||||||
|
if (x < left->x ||
|
||||||
|
x > right->x ||
|
||||||
|
y < top->y ||
|
||||||
|
y > bottom->y)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Check whether point is above the sides
|
||||||
|
* between leftmost and topmost, and
|
||||||
|
* topmost and rightmost corners.
|
||||||
|
*/
|
||||||
|
if (x <= top->x)
|
||||||
|
{
|
||||||
|
if (left->y - ((left->y - top->y) * (((gdouble) x - left->x) / (top->x - left->x))) > y)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (top->y + ((right->y - top->y) * (((gdouble) x - top->x) / (right->x - top->x))) > y)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check whether point is below the sides
|
||||||
|
* between leftmost and bottom, and
|
||||||
|
* bottom and rightmost corners.
|
||||||
|
*/
|
||||||
|
if (x <= bottom->x)
|
||||||
|
{
|
||||||
|
if (left->y + ((bottom->y - left->y) * (((gdouble) x - left->x) / (bottom->x - left->x))) < y)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (bottom->y - ((bottom->y - right->y) * (((gdouble) x - bottom->x) / (right->x - bottom->x))) < y)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ShapeInfo *
|
||||||
|
shape_info_new (gdouble x,
|
||||||
|
gdouble y,
|
||||||
|
gdouble width,
|
||||||
|
gdouble height,
|
||||||
|
GdkRGBA *color)
|
||||||
|
{
|
||||||
|
ShapeInfo *info;
|
||||||
|
|
||||||
|
info = g_slice_new0 (ShapeInfo);
|
||||||
|
info->cluster = NULL;
|
||||||
|
info->color = *color;
|
||||||
|
|
||||||
|
info->x = x;
|
||||||
|
info->y = y;
|
||||||
|
info->width = width;
|
||||||
|
info->height = height;
|
||||||
|
|
||||||
|
info->angle = 0;
|
||||||
|
info->zoom = 1;
|
||||||
|
|
||||||
|
info->base_zoom = 1;
|
||||||
|
info->base_angle = 0;
|
||||||
|
info->initial_distance = 0;
|
||||||
|
info->initial_angle = 0;
|
||||||
|
|
||||||
|
shape_info_allocate_input_rect (info);
|
||||||
|
|
||||||
|
shapes = g_list_prepend (shapes, info);
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shape_info_free (ShapeInfo *info)
|
||||||
|
{
|
||||||
|
g_slice_free (ShapeInfo, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shape_info_draw (cairo_t *cr,
|
||||||
|
ShapeInfo *info)
|
||||||
|
{
|
||||||
|
cairo_save (cr);
|
||||||
|
|
||||||
|
cairo_translate (cr, info->points[0].x, info->points[0].y);
|
||||||
|
cairo_scale (cr, info->zoom, info->zoom);
|
||||||
|
cairo_rotate (cr, info->angle);
|
||||||
|
|
||||||
|
cairo_rectangle (cr, 0, 0, info->width, info->height);
|
||||||
|
gdk_cairo_set_source_rgba (cr, &info->color);
|
||||||
|
cairo_fill_preserve (cr);
|
||||||
|
|
||||||
|
cairo_set_line_width (cr, 6);
|
||||||
|
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||||
|
cairo_stroke (cr);
|
||||||
|
|
||||||
|
cairo_restore (cr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
draw_cb (GtkWidget *widget,
|
||||||
|
cairo_t *cr,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = shapes; l; l = l->next)
|
||||||
|
shape_info_draw (cr, l->data);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
button_press_cb (GtkWidget *widget,
|
||||||
|
GdkEvent *event,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
ShapeInfo *shape = NULL;
|
||||||
|
guint touch_id;
|
||||||
|
|
||||||
|
if (gdk_event_get_touch_id (event, &touch_id))
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = shapes; l; l = l->next)
|
||||||
|
{
|
||||||
|
ShapeInfo *info = l->data;
|
||||||
|
|
||||||
|
if (shape_info_point_in (info,
|
||||||
|
(gint) event->button.x,
|
||||||
|
(gint) event->button.y))
|
||||||
|
shape = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shape)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!shape->cluster)
|
||||||
|
shape->cluster = gdk_window_create_touch_cluster (gtk_widget_get_window (widget));
|
||||||
|
|
||||||
|
/* Only change cluster device if there were no touches or no device */
|
||||||
|
if (!gdk_touch_cluster_get_device (shape->cluster) ||
|
||||||
|
!gdk_touch_cluster_get_touches (shape->cluster))
|
||||||
|
gdk_touch_cluster_set_device (shape->cluster,
|
||||||
|
gdk_event_get_source_device (event));
|
||||||
|
|
||||||
|
gdk_touch_cluster_add_touch (shape->cluster, touch_id);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
multitouch_cb (GtkWidget *widget,
|
||||||
|
GdkEvent *event,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
ShapeInfo *info = NULL;
|
||||||
|
gboolean new_center = FALSE;
|
||||||
|
gboolean new_position = FALSE;
|
||||||
|
gdouble event_x, event_y;
|
||||||
|
cairo_region_t *region;
|
||||||
|
GdkRectangle rect;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = shapes; l; l = l->next)
|
||||||
|
{
|
||||||
|
ShapeInfo *shape = l->data;
|
||||||
|
|
||||||
|
if (event->multitouch.group == shape->cluster)
|
||||||
|
{
|
||||||
|
info = shape;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
shape_info_bounding_rect (info, &rect);
|
||||||
|
region = cairo_region_create_rectangle ((cairo_rectangle_int_t *) &rect);
|
||||||
|
|
||||||
|
if (event->multitouch.n_events == 1)
|
||||||
|
{
|
||||||
|
/* Update center if we just got to
|
||||||
|
* this situation from either way */
|
||||||
|
if (event->type == GDK_MULTITOUCH_ADDED ||
|
||||||
|
event->type == GDK_MULTITOUCH_REMOVED)
|
||||||
|
new_center = TRUE;
|
||||||
|
|
||||||
|
event_x = event->multitouch.events[0]->x;
|
||||||
|
event_y = event->multitouch.events[0]->y;
|
||||||
|
new_position = TRUE;
|
||||||
|
}
|
||||||
|
else if (event->multitouch.n_events == 2)
|
||||||
|
{
|
||||||
|
gdouble distance, angle;
|
||||||
|
|
||||||
|
gdk_events_get_center ((GdkEvent *) event->multitouch.events[0],
|
||||||
|
(GdkEvent *) event->multitouch.events[1],
|
||||||
|
&event_x, &event_y);
|
||||||
|
|
||||||
|
gdk_events_get_distance ((GdkEvent *) event->multitouch.events[0],
|
||||||
|
(GdkEvent *) event->multitouch.events[1],
|
||||||
|
&distance);
|
||||||
|
|
||||||
|
gdk_events_get_angle ((GdkEvent *) event->multitouch.events[0],
|
||||||
|
(GdkEvent *) event->multitouch.events[1],
|
||||||
|
&angle);
|
||||||
|
|
||||||
|
if (event->type == GDK_MULTITOUCH_ADDED)
|
||||||
|
{
|
||||||
|
/* Second touch was just added, update base zoom/angle */
|
||||||
|
info->base_zoom = info->zoom;
|
||||||
|
info->base_angle = info->angle;
|
||||||
|
info->initial_angle = angle;
|
||||||
|
info->initial_distance = distance;
|
||||||
|
new_center = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
info->zoom = MAX (info->base_zoom * (distance / info->initial_distance), 1.0);
|
||||||
|
info->angle = info->base_angle + (angle - info->initial_angle);
|
||||||
|
new_position = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_center)
|
||||||
|
{
|
||||||
|
gdouble origin_x, origin_y;
|
||||||
|
|
||||||
|
origin_x = info->x - info->center_x;
|
||||||
|
origin_y = info->y - info->center_y;
|
||||||
|
|
||||||
|
calculate_rotated_point (- info->angle,
|
||||||
|
1 / info->zoom,
|
||||||
|
info->x - origin_x,
|
||||||
|
info->y - origin_y,
|
||||||
|
event_x - origin_x,
|
||||||
|
event_y - origin_y,
|
||||||
|
&info->center_x,
|
||||||
|
&info->center_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_position)
|
||||||
|
{
|
||||||
|
info->x = event_x;
|
||||||
|
info->y = event_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
shape_info_allocate_input_rect (info);
|
||||||
|
|
||||||
|
shape_info_bounding_rect (info, &rect);
|
||||||
|
cairo_region_union_rectangle (region, (cairo_rectangle_int_t *) &rect);
|
||||||
|
gdk_window_invalidate_region (gtk_widget_get_window (widget), region, FALSE);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *
|
||||||
|
do_multitouch (GtkWidget *do_widget)
|
||||||
|
{
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
|
GdkRGBA color;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
gtk_window_set_screen (GTK_WINDOW (window),
|
||||||
|
gtk_widget_get_screen (do_widget));
|
||||||
|
|
||||||
|
gtk_widget_add_events (window,
|
||||||
|
GDK_TOUCH_MASK |
|
||||||
|
GDK_POINTER_MOTION_MASK |
|
||||||
|
GDK_BUTTON_PRESS_MASK |
|
||||||
|
GDK_BUTTON_RELEASE_MASK);
|
||||||
|
|
||||||
|
gtk_widget_set_app_paintable (window, TRUE);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
gdk_rgba_parse (&color, "red");
|
||||||
|
color.alpha = 0.5;
|
||||||
|
shape_info_new (100, 50, 100, 140, &color);
|
||||||
|
|
||||||
|
gdk_rgba_parse (&color, "green");
|
||||||
|
color.alpha = 0.5;
|
||||||
|
shape_info_new (200, 100, 120, 90, &color);
|
||||||
|
|
||||||
|
gdk_rgba_parse (&color, "blue");
|
||||||
|
color.alpha = 0.5;
|
||||||
|
shape_info_new (150, 190, 140, 90, &color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gtk_widget_get_visible (window))
|
||||||
|
gtk_widget_show (window);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gtk_widget_destroy (window);
|
||||||
|
window = NULL;
|
||||||
|
|
||||||
|
g_list_foreach (shapes, (GFunc) shape_info_free, NULL);
|
||||||
|
g_list_free (shapes);
|
||||||
|
shapes = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
@@ -33,6 +33,7 @@
|
|||||||
<xi:include href="xml/windows.xml" />
|
<xi:include href="xml/windows.xml" />
|
||||||
<xi:include href="xml/events.xml" />
|
<xi:include href="xml/events.xml" />
|
||||||
<xi:include href="xml/event_structs.xml" />
|
<xi:include href="xml/event_structs.xml" />
|
||||||
|
<xi:include href="xml/touchcluster.xml" />
|
||||||
<xi:include href="xml/keys.xml" />
|
<xi:include href="xml/keys.xml" />
|
||||||
<xi:include href="xml/selections.xml" />
|
<xi:include href="xml/selections.xml" />
|
||||||
<xi:include href="xml/dnd.xml" />
|
<xi:include href="xml/dnd.xml" />
|
||||||
|
@@ -770,6 +770,7 @@ gdk_event_request_motions
|
|||||||
gdk_events_get_angle
|
gdk_events_get_angle
|
||||||
gdk_events_get_center
|
gdk_events_get_center
|
||||||
gdk_events_get_distance
|
gdk_events_get_distance
|
||||||
|
gdk_event_get_touch_id
|
||||||
|
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
gdk_event_handler_set
|
gdk_event_handler_set
|
||||||
@@ -817,6 +818,7 @@ GdkEventWindowState
|
|||||||
GdkEventSetting
|
GdkEventSetting
|
||||||
GdkEventOwnerChange
|
GdkEventOwnerChange
|
||||||
GdkEventGrabBroken
|
GdkEventGrabBroken
|
||||||
|
GdkEventMultiTouch
|
||||||
|
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
GdkScrollDirection
|
GdkScrollDirection
|
||||||
@@ -844,6 +846,29 @@ gdk_event_get_type
|
|||||||
gdk_owner_change_get_type
|
gdk_owner_change_get_type
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<TITLE>Multitouch</TITLE>
|
||||||
|
<FILE>touchcluster</FILE>
|
||||||
|
GdkTouchCluster
|
||||||
|
gdk_touch_cluster_add_touch
|
||||||
|
gdk_touch_cluster_remove_touch
|
||||||
|
gdk_touch_cluster_remove_all
|
||||||
|
gdk_touch_cluster_set_device
|
||||||
|
gdk_touch_cluster_get_device
|
||||||
|
gdk_touch_cluster_get_touches
|
||||||
|
|
||||||
|
<SUBSECTION>
|
||||||
|
gdk_window_create_touch_cluster
|
||||||
|
gdk_window_remove_touch_cluster
|
||||||
|
|
||||||
|
<SUBSECTION Standard>
|
||||||
|
GDK_TYPE_TOUCH_CLUSTER
|
||||||
|
|
||||||
|
<SUBSECTION Private>
|
||||||
|
gdk_touch_cluster_get_type
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<TITLE>Cursors</TITLE>
|
<TITLE>Cursors</TITLE>
|
||||||
<FILE>cursors</FILE>
|
<FILE>cursors</FILE>
|
||||||
|
@@ -9,5 +9,6 @@ gdk_display_manager_get_type
|
|||||||
gdk_drag_context_get_type
|
gdk_drag_context_get_type
|
||||||
gdk_keymap_get_type
|
gdk_keymap_get_type
|
||||||
gdk_screen_get_type
|
gdk_screen_get_type
|
||||||
|
gdk_touch_cluster_get_type
|
||||||
gdk_visual_get_type
|
gdk_visual_get_type
|
||||||
gdk_window_get_type
|
gdk_window_get_type
|
||||||
|
@@ -88,6 +88,7 @@ gdk_public_h_sources = \
|
|||||||
gdkselection.h \
|
gdkselection.h \
|
||||||
gdktestutils.h \
|
gdktestutils.h \
|
||||||
gdkthreads.h \
|
gdkthreads.h \
|
||||||
|
gdktouchcluster.h \
|
||||||
gdktypes.h \
|
gdktypes.h \
|
||||||
gdkvisual.h \
|
gdkvisual.h \
|
||||||
gdkwindow.h
|
gdkwindow.h
|
||||||
@@ -129,6 +130,7 @@ gdk_c_sources = \
|
|||||||
gdkrgba.c \
|
gdkrgba.c \
|
||||||
gdkscreen.c \
|
gdkscreen.c \
|
||||||
gdkselection.c \
|
gdkselection.c \
|
||||||
|
gdktouchcluster.c \
|
||||||
gdkvisual.c \
|
gdkvisual.c \
|
||||||
gdkwindow.c \
|
gdkwindow.c \
|
||||||
gdkwindowimpl.c
|
gdkwindowimpl.c
|
||||||
|
@@ -53,6 +53,7 @@
|
|||||||
#include <gdk/gdkselection.h>
|
#include <gdk/gdkselection.h>
|
||||||
#include <gdk/gdktestutils.h>
|
#include <gdk/gdktestutils.h>
|
||||||
#include <gdk/gdkthreads.h>
|
#include <gdk/gdkthreads.h>
|
||||||
|
#include <gdk/gdktouchcluster.h>
|
||||||
#include <gdk/gdktypes.h>
|
#include <gdk/gdktypes.h>
|
||||||
#include <gdk/gdkvisual.h>
|
#include <gdk/gdkvisual.h>
|
||||||
#include <gdk/gdkwindow.h>
|
#include <gdk/gdkwindow.h>
|
||||||
|
@@ -163,6 +163,7 @@ gdk_event_get_screen
|
|||||||
gdk_event_get_source_device
|
gdk_event_get_source_device
|
||||||
gdk_event_get_state
|
gdk_event_get_state
|
||||||
gdk_event_get_time
|
gdk_event_get_time
|
||||||
|
gdk_event_get_touch_id
|
||||||
gdk_event_get_type G_GNUC_CONST
|
gdk_event_get_type G_GNUC_CONST
|
||||||
gdk_event_handler_set
|
gdk_event_handler_set
|
||||||
gdk_event_mask_get_type G_GNUC_CONST
|
gdk_event_mask_get_type G_GNUC_CONST
|
||||||
@@ -318,6 +319,11 @@ gdk_threads_enter
|
|||||||
gdk_threads_init
|
gdk_threads_init
|
||||||
gdk_threads_leave
|
gdk_threads_leave
|
||||||
gdk_threads_set_lock_functions
|
gdk_threads_set_lock_functions
|
||||||
|
gdk_touch_cluster_add_touch
|
||||||
|
gdk_touch_cluster_get_device
|
||||||
|
gdk_touch_cluster_get_type G_GNUC_CONST
|
||||||
|
gdk_touch_cluster_list_touches
|
||||||
|
gdk_touch_cluster_remove_touch
|
||||||
gdk_unicode_to_keyval G_GNUC_CONST
|
gdk_unicode_to_keyval G_GNUC_CONST
|
||||||
gdk_utf8_to_string_target
|
gdk_utf8_to_string_target
|
||||||
gdk_visibility_state_get_type G_GNUC_CONST
|
gdk_visibility_state_get_type G_GNUC_CONST
|
||||||
|
@@ -61,6 +61,7 @@ typedef enum
|
|||||||
* of a stylus on a graphics tablet.
|
* of a stylus on a graphics tablet.
|
||||||
* @GDK_SOURCE_CURSOR: the device is a graphics tablet "puck" or similar device.
|
* @GDK_SOURCE_CURSOR: the device is a graphics tablet "puck" or similar device.
|
||||||
* @GDK_SOURCE_KEYBOARD: the device is a keyboard.
|
* @GDK_SOURCE_KEYBOARD: the device is a keyboard.
|
||||||
|
* @GDK_SOURCE_TOUCH: the device is a touch capable device.
|
||||||
*
|
*
|
||||||
* An enumeration describing the type of an input device in general terms.
|
* An enumeration describing the type of an input device in general terms.
|
||||||
*/
|
*/
|
||||||
@@ -70,7 +71,8 @@ typedef enum
|
|||||||
GDK_SOURCE_PEN,
|
GDK_SOURCE_PEN,
|
||||||
GDK_SOURCE_ERASER,
|
GDK_SOURCE_ERASER,
|
||||||
GDK_SOURCE_CURSOR,
|
GDK_SOURCE_CURSOR,
|
||||||
GDK_SOURCE_KEYBOARD
|
GDK_SOURCE_KEYBOARD,
|
||||||
|
GDK_SOURCE_TOUCH
|
||||||
} GdkInputSource;
|
} GdkInputSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
131
gdk/gdkevents.c
131
gdk/gdkevents.c
@@ -445,6 +445,7 @@ gdk_event_new (GdkEventType type)
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
|
case GDK_TOUCH_MOTION:
|
||||||
new_event->motion.x = 0.;
|
new_event->motion.x = 0.;
|
||||||
new_event->motion.y = 0.;
|
new_event->motion.y = 0.;
|
||||||
new_event->motion.x_root = 0.;
|
new_event->motion.x_root = 0.;
|
||||||
@@ -454,6 +455,8 @@ gdk_event_new (GdkEventType type)
|
|||||||
case GDK_2BUTTON_PRESS:
|
case GDK_2BUTTON_PRESS:
|
||||||
case GDK_3BUTTON_PRESS:
|
case GDK_3BUTTON_PRESS:
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
|
case GDK_TOUCH_PRESS:
|
||||||
|
case GDK_TOUCH_RELEASE:
|
||||||
new_event->button.x = 0.;
|
new_event->button.x = 0.;
|
||||||
new_event->button.y = 0.;
|
new_event->button.y = 0.;
|
||||||
new_event->button.x_root = 0.;
|
new_event->button.x_root = 0.;
|
||||||
@@ -558,12 +561,15 @@ gdk_event_copy (const GdkEvent *event)
|
|||||||
case GDK_2BUTTON_PRESS:
|
case GDK_2BUTTON_PRESS:
|
||||||
case GDK_3BUTTON_PRESS:
|
case GDK_3BUTTON_PRESS:
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
|
case GDK_TOUCH_PRESS:
|
||||||
|
case GDK_TOUCH_RELEASE:
|
||||||
if (event->button.axes)
|
if (event->button.axes)
|
||||||
new_event->button.axes = g_memdup (event->button.axes,
|
new_event->button.axes = g_memdup (event->button.axes,
|
||||||
sizeof (gdouble) * gdk_device_get_n_axes (event->button.device));
|
sizeof (gdouble) * gdk_device_get_n_axes (event->button.device));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
|
case GDK_TOUCH_MOTION:
|
||||||
if (event->motion.axes)
|
if (event->motion.axes)
|
||||||
new_event->motion.axes = g_memdup (event->motion.axes,
|
new_event->motion.axes = g_memdup (event->motion.axes,
|
||||||
sizeof (gdouble) * gdk_device_get_n_axes (event->motion.device));
|
sizeof (gdouble) * gdk_device_get_n_axes (event->motion.device));
|
||||||
@@ -583,6 +589,22 @@ gdk_event_copy (const GdkEvent *event)
|
|||||||
g_object_unref (new_event->selection.requestor);
|
g_object_unref (new_event->selection.requestor);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GDK_MULTITOUCH_ADDED:
|
||||||
|
case GDK_MULTITOUCH_REMOVED:
|
||||||
|
case GDK_MULTITOUCH_UPDATED:
|
||||||
|
{
|
||||||
|
GdkEventMotion **motion_events;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
motion_events = g_new0 (GdkEventMotion*, event->multitouch.n_events);
|
||||||
|
|
||||||
|
for (i = 0; i < event->multitouch.n_events; i++)
|
||||||
|
motion_events[i] = (GdkEventMotion *) gdk_event_copy ((GdkEvent *) event->multitouch.events[i]);
|
||||||
|
|
||||||
|
new_event->multitouch.events = motion_events;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -637,6 +659,8 @@ gdk_event_free (GdkEvent *event)
|
|||||||
case GDK_2BUTTON_PRESS:
|
case GDK_2BUTTON_PRESS:
|
||||||
case GDK_3BUTTON_PRESS:
|
case GDK_3BUTTON_PRESS:
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
|
case GDK_TOUCH_PRESS:
|
||||||
|
case GDK_TOUCH_RELEASE:
|
||||||
g_free (event->button.axes);
|
g_free (event->button.axes);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -647,6 +671,7 @@ gdk_event_free (GdkEvent *event)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
|
case GDK_TOUCH_MOTION:
|
||||||
g_free (event->motion.axes);
|
g_free (event->motion.axes);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -666,6 +691,20 @@ gdk_event_free (GdkEvent *event)
|
|||||||
g_object_unref (event->selection.requestor);
|
g_object_unref (event->selection.requestor);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GDK_MULTITOUCH_ADDED:
|
||||||
|
case GDK_MULTITOUCH_REMOVED:
|
||||||
|
case GDK_MULTITOUCH_UPDATED:
|
||||||
|
if (event->multitouch.events)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < event->multitouch.n_events; i++)
|
||||||
|
gdk_event_free ((GdkEvent *) event->multitouch.events[i]);
|
||||||
|
|
||||||
|
g_free (event->multitouch.events);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -692,11 +731,14 @@ gdk_event_get_time (const GdkEvent *event)
|
|||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
|
case GDK_TOUCH_MOTION:
|
||||||
return event->motion.time;
|
return event->motion.time;
|
||||||
case GDK_BUTTON_PRESS:
|
case GDK_BUTTON_PRESS:
|
||||||
case GDK_2BUTTON_PRESS:
|
case GDK_2BUTTON_PRESS:
|
||||||
case GDK_3BUTTON_PRESS:
|
case GDK_3BUTTON_PRESS:
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
|
case GDK_TOUCH_PRESS:
|
||||||
|
case GDK_TOUCH_RELEASE:
|
||||||
return event->button.time;
|
return event->button.time;
|
||||||
case GDK_SCROLL:
|
case GDK_SCROLL:
|
||||||
return event->scroll.time;
|
return event->scroll.time;
|
||||||
@@ -722,6 +764,10 @@ gdk_event_get_time (const GdkEvent *event)
|
|||||||
case GDK_DROP_START:
|
case GDK_DROP_START:
|
||||||
case GDK_DROP_FINISHED:
|
case GDK_DROP_FINISHED:
|
||||||
return event->dnd.time;
|
return event->dnd.time;
|
||||||
|
case GDK_MULTITOUCH_ADDED:
|
||||||
|
case GDK_MULTITOUCH_REMOVED:
|
||||||
|
case GDK_MULTITOUCH_UPDATED:
|
||||||
|
return event->multitouch.time;
|
||||||
case GDK_CLIENT_EVENT:
|
case GDK_CLIENT_EVENT:
|
||||||
case GDK_VISIBILITY_NOTIFY:
|
case GDK_VISIBILITY_NOTIFY:
|
||||||
case GDK_CONFIGURE:
|
case GDK_CONFIGURE:
|
||||||
@@ -767,12 +813,15 @@ gdk_event_get_state (const GdkEvent *event,
|
|||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
|
case GDK_TOUCH_MOTION:
|
||||||
*state = event->motion.state;
|
*state = event->motion.state;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case GDK_BUTTON_PRESS:
|
case GDK_BUTTON_PRESS:
|
||||||
case GDK_2BUTTON_PRESS:
|
case GDK_2BUTTON_PRESS:
|
||||||
case GDK_3BUTTON_PRESS:
|
case GDK_3BUTTON_PRESS:
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
|
case GDK_TOUCH_PRESS:
|
||||||
|
case GDK_TOUCH_RELEASE:
|
||||||
*state = event->button.state;
|
*state = event->button.state;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case GDK_SCROLL:
|
case GDK_SCROLL:
|
||||||
@@ -786,6 +835,11 @@ gdk_event_get_state (const GdkEvent *event,
|
|||||||
case GDK_LEAVE_NOTIFY:
|
case GDK_LEAVE_NOTIFY:
|
||||||
*state = event->crossing.state;
|
*state = event->crossing.state;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
case GDK_MULTITOUCH_ADDED:
|
||||||
|
case GDK_MULTITOUCH_REMOVED:
|
||||||
|
case GDK_MULTITOUCH_UPDATED:
|
||||||
|
*state = event->multitouch.state;
|
||||||
|
return TRUE;
|
||||||
case GDK_PROPERTY_NOTIFY:
|
case GDK_PROPERTY_NOTIFY:
|
||||||
case GDK_VISIBILITY_NOTIFY:
|
case GDK_VISIBILITY_NOTIFY:
|
||||||
case GDK_CLIENT_EVENT:
|
case GDK_CLIENT_EVENT:
|
||||||
@@ -861,10 +915,13 @@ gdk_event_get_coords (const GdkEvent *event,
|
|||||||
case GDK_2BUTTON_PRESS:
|
case GDK_2BUTTON_PRESS:
|
||||||
case GDK_3BUTTON_PRESS:
|
case GDK_3BUTTON_PRESS:
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
|
case GDK_TOUCH_PRESS:
|
||||||
|
case GDK_TOUCH_RELEASE:
|
||||||
x = event->button.x;
|
x = event->button.x;
|
||||||
y = event->button.y;
|
y = event->button.y;
|
||||||
break;
|
break;
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
|
case GDK_TOUCH_MOTION:
|
||||||
x = event->motion.x;
|
x = event->motion.x;
|
||||||
y = event->motion.y;
|
y = event->motion.y;
|
||||||
break;
|
break;
|
||||||
@@ -904,6 +961,7 @@ gdk_event_get_root_coords (const GdkEvent *event,
|
|||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
|
case GDK_TOUCH_MOTION:
|
||||||
x = event->motion.x_root;
|
x = event->motion.x_root;
|
||||||
y = event->motion.y_root;
|
y = event->motion.y_root;
|
||||||
break;
|
break;
|
||||||
@@ -915,6 +973,8 @@ gdk_event_get_root_coords (const GdkEvent *event,
|
|||||||
case GDK_2BUTTON_PRESS:
|
case GDK_2BUTTON_PRESS:
|
||||||
case GDK_3BUTTON_PRESS:
|
case GDK_3BUTTON_PRESS:
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
|
case GDK_TOUCH_PRESS:
|
||||||
|
case GDK_TOUCH_RELEASE:
|
||||||
x = event->button.x_root;
|
x = event->button.x_root;
|
||||||
y = event->button.y_root;
|
y = event->button.y_root;
|
||||||
break;
|
break;
|
||||||
@@ -972,7 +1032,8 @@ gdk_event_get_axis (const GdkEvent *event,
|
|||||||
|
|
||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
|
case GDK_TOUCH_MOTION:
|
||||||
x = event->motion.x;
|
x = event->motion.x;
|
||||||
y = event->motion.y;
|
y = event->motion.y;
|
||||||
break;
|
break;
|
||||||
@@ -982,6 +1043,8 @@ gdk_event_get_axis (const GdkEvent *event,
|
|||||||
break;
|
break;
|
||||||
case GDK_BUTTON_PRESS:
|
case GDK_BUTTON_PRESS:
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
|
case GDK_TOUCH_PRESS:
|
||||||
|
case GDK_TOUCH_RELEASE:
|
||||||
x = event->button.x;
|
x = event->button.x;
|
||||||
y = event->button.y;
|
y = event->button.y;
|
||||||
break;
|
break;
|
||||||
@@ -1003,12 +1066,15 @@ gdk_event_get_axis (const GdkEvent *event,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else if (event->type == GDK_BUTTON_PRESS ||
|
else if (event->type == GDK_BUTTON_PRESS ||
|
||||||
event->type == GDK_BUTTON_RELEASE)
|
event->type == GDK_BUTTON_RELEASE ||
|
||||||
|
event->type == GDK_TOUCH_PRESS ||
|
||||||
|
event->type == GDK_TOUCH_RELEASE)
|
||||||
{
|
{
|
||||||
device = event->button.device;
|
device = event->button.device;
|
||||||
axes = event->button.axes;
|
axes = event->button.axes;
|
||||||
}
|
}
|
||||||
else if (event->type == GDK_MOTION_NOTIFY)
|
else if (event->type == GDK_MOTION_NOTIFY ||
|
||||||
|
event->type == GDK_TOUCH_MOTION)
|
||||||
{
|
{
|
||||||
device = event->motion.device;
|
device = event->motion.device;
|
||||||
axes = event->motion.axes;
|
axes = event->motion.axes;
|
||||||
@@ -1045,12 +1111,15 @@ gdk_event_set_device (GdkEvent *event,
|
|||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
|
case GDK_TOUCH_MOTION:
|
||||||
event->motion.device = device;
|
event->motion.device = device;
|
||||||
break;
|
break;
|
||||||
case GDK_BUTTON_PRESS:
|
case GDK_BUTTON_PRESS:
|
||||||
case GDK_2BUTTON_PRESS:
|
case GDK_2BUTTON_PRESS:
|
||||||
case GDK_3BUTTON_PRESS:
|
case GDK_3BUTTON_PRESS:
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
|
case GDK_TOUCH_PRESS:
|
||||||
|
case GDK_TOUCH_RELEASE:
|
||||||
event->button.device = device;
|
event->button.device = device;
|
||||||
break;
|
break;
|
||||||
case GDK_SCROLL:
|
case GDK_SCROLL:
|
||||||
@@ -1060,6 +1129,10 @@ gdk_event_set_device (GdkEvent *event,
|
|||||||
case GDK_PROXIMITY_OUT:
|
case GDK_PROXIMITY_OUT:
|
||||||
event->proximity.device = device;
|
event->proximity.device = device;
|
||||||
break;
|
break;
|
||||||
|
case GDK_MULTITOUCH_ADDED:
|
||||||
|
case GDK_MULTITOUCH_REMOVED:
|
||||||
|
case GDK_MULTITOUCH_UPDATED:
|
||||||
|
event->multitouch.device = device;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1092,17 +1165,24 @@ gdk_event_get_device (const GdkEvent *event)
|
|||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
|
case GDK_TOUCH_MOTION:
|
||||||
return event->motion.device;
|
return event->motion.device;
|
||||||
case GDK_BUTTON_PRESS:
|
case GDK_BUTTON_PRESS:
|
||||||
case GDK_2BUTTON_PRESS:
|
case GDK_2BUTTON_PRESS:
|
||||||
case GDK_3BUTTON_PRESS:
|
case GDK_3BUTTON_PRESS:
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
|
case GDK_TOUCH_PRESS:
|
||||||
|
case GDK_TOUCH_RELEASE:
|
||||||
return event->button.device;
|
return event->button.device;
|
||||||
case GDK_SCROLL:
|
case GDK_SCROLL:
|
||||||
return event->scroll.device;
|
return event->scroll.device;
|
||||||
case GDK_PROXIMITY_IN:
|
case GDK_PROXIMITY_IN:
|
||||||
case GDK_PROXIMITY_OUT:
|
case GDK_PROXIMITY_OUT:
|
||||||
return event->proximity.device;
|
return event->proximity.device;
|
||||||
|
case GDK_MULTITOUCH_ADDED:
|
||||||
|
case GDK_MULTITOUCH_REMOVED:
|
||||||
|
case GDK_MULTITOUCH_UPDATED:
|
||||||
|
return event->multitouch.device;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1111,10 +1191,13 @@ gdk_event_get_device (const GdkEvent *event)
|
|||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
|
case GDK_TOUCH_MOTION:
|
||||||
case GDK_BUTTON_PRESS:
|
case GDK_BUTTON_PRESS:
|
||||||
case GDK_2BUTTON_PRESS:
|
case GDK_2BUTTON_PRESS:
|
||||||
case GDK_3BUTTON_PRESS:
|
case GDK_3BUTTON_PRESS:
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
|
case GDK_TOUCH_PRESS:
|
||||||
|
case GDK_TOUCH_RELEASE:
|
||||||
case GDK_ENTER_NOTIFY:
|
case GDK_ENTER_NOTIFY:
|
||||||
case GDK_LEAVE_NOTIFY:
|
case GDK_LEAVE_NOTIFY:
|
||||||
case GDK_FOCUS_CHANGE:
|
case GDK_FOCUS_CHANGE:
|
||||||
@@ -1130,6 +1213,9 @@ gdk_event_get_device (const GdkEvent *event)
|
|||||||
case GDK_GRAB_BROKEN:
|
case GDK_GRAB_BROKEN:
|
||||||
case GDK_KEY_PRESS:
|
case GDK_KEY_PRESS:
|
||||||
case GDK_KEY_RELEASE:
|
case GDK_KEY_RELEASE:
|
||||||
|
case GDK_MULTITOUCH_ADDED:
|
||||||
|
case GDK_MULTITOUCH_REMOVED:
|
||||||
|
case GDK_MULTITOUCH_UPDATED:
|
||||||
{
|
{
|
||||||
GdkDisplay *display;
|
GdkDisplay *display;
|
||||||
GdkDeviceManager *device_manager;
|
GdkDeviceManager *device_manager;
|
||||||
@@ -1446,6 +1532,45 @@ gdk_event_get_screen (const GdkEvent *event)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_event_get_touch_id:
|
||||||
|
* @event: a #GdkEvent
|
||||||
|
* @touch_id: return location of the touch ID of a touch event
|
||||||
|
*
|
||||||
|
* If @event if of type %GDK_TOUCH_MOTION, %GDK_TOUCH_PRESS or
|
||||||
|
* %GDK_TOUCH_RELEASE, fills in @touch_id and returns %TRUE,
|
||||||
|
* else it returns %FALSE.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the touch ID can be extracted from @event.
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
gdk_event_get_touch_id (const GdkEvent *event,
|
||||||
|
guint *touch_id)
|
||||||
|
{
|
||||||
|
if (!event)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (event->type == GDK_TOUCH_MOTION)
|
||||||
|
{
|
||||||
|
if (touch_id)
|
||||||
|
*touch_id = event->motion.touch_id;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else if (event->type == GDK_TOUCH_PRESS ||
|
||||||
|
event->type == GDK_TOUCH_RELEASE)
|
||||||
|
{
|
||||||
|
if (touch_id)
|
||||||
|
*touch_id = event->button.touch_id;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (touch_id)
|
||||||
|
*touch_id = 0;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gdk_set_show_events:
|
* gdk_set_show_events:
|
||||||
* @show_events: %TRUE to output event debugging information.
|
* @show_events: %TRUE to output event debugging information.
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#include <gdk/gdktypes.h>
|
#include <gdk/gdktypes.h>
|
||||||
#include <gdk/gdkdnd.h>
|
#include <gdk/gdkdnd.h>
|
||||||
#include <gdk/gdkdevice.h>
|
#include <gdk/gdkdevice.h>
|
||||||
|
#include <gdk/gdktouchcluster.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@@ -93,6 +94,7 @@ typedef struct _GdkEventDND GdkEventDND;
|
|||||||
typedef struct _GdkEventWindowState GdkEventWindowState;
|
typedef struct _GdkEventWindowState GdkEventWindowState;
|
||||||
typedef struct _GdkEventSetting GdkEventSetting;
|
typedef struct _GdkEventSetting GdkEventSetting;
|
||||||
typedef struct _GdkEventGrabBroken GdkEventGrabBroken;
|
typedef struct _GdkEventGrabBroken GdkEventGrabBroken;
|
||||||
|
typedef struct _GdkEventMultiTouch GdkEventMultiTouch;
|
||||||
|
|
||||||
typedef union _GdkEvent GdkEvent;
|
typedef union _GdkEvent GdkEvent;
|
||||||
|
|
||||||
@@ -213,6 +215,12 @@ typedef GdkFilterReturn (*GdkFilterFunc) (GdkXEvent *xevent,
|
|||||||
* was added in 2.8.
|
* was added in 2.8.
|
||||||
* @GDK_DAMAGE: the content of the window has been changed. This event type
|
* @GDK_DAMAGE: the content of the window has been changed. This event type
|
||||||
* was added in 2.14.
|
* was added in 2.14.
|
||||||
|
* @GDK_TOUCH_MOTION: A touch device has been updated.
|
||||||
|
* @GDK_TOUCH_PRESS: A new touch stream has just started.
|
||||||
|
* @GDK_TOUCH_RELEASE: A touch stream has finished.
|
||||||
|
* @GDK_MULTITOUCH_ADDED: A touch ID was added to a #GdkTouchCluster
|
||||||
|
* @GDK_MULTITOUCH_UPDATED: A touch within a #GdkTouchCluster has been updated.
|
||||||
|
* @GDK_MULTITOUCH_REMOVED: A touch ID was removed from a #GdkTouchCluster.
|
||||||
* @GDK_EVENT_LAST: marks the end of the GdkEventType enumeration. Added in 2.18
|
* @GDK_EVENT_LAST: marks the end of the GdkEventType enumeration. Added in 2.18
|
||||||
*
|
*
|
||||||
* Specifies the type of the event.
|
* Specifies the type of the event.
|
||||||
@@ -260,6 +268,12 @@ typedef enum
|
|||||||
GDK_OWNER_CHANGE = 34,
|
GDK_OWNER_CHANGE = 34,
|
||||||
GDK_GRAB_BROKEN = 35,
|
GDK_GRAB_BROKEN = 35,
|
||||||
GDK_DAMAGE = 36,
|
GDK_DAMAGE = 36,
|
||||||
|
GDK_TOUCH_MOTION = 37,
|
||||||
|
GDK_TOUCH_PRESS = 38,
|
||||||
|
GDK_TOUCH_RELEASE = 39,
|
||||||
|
GDK_MULTITOUCH_ADDED = 40,
|
||||||
|
GDK_MULTITOUCH_UPDATED = 41,
|
||||||
|
GDK_MULTITOUCH_REMOVED = 42,
|
||||||
GDK_EVENT_LAST /* helper variable for decls */
|
GDK_EVENT_LAST /* helper variable for decls */
|
||||||
} GdkEventType;
|
} GdkEventType;
|
||||||
|
|
||||||
@@ -500,8 +514,9 @@ struct _GdkEventVisibility
|
|||||||
* screen.
|
* screen.
|
||||||
* @y_root: the y coordinate of the pointer relative to the root of the
|
* @y_root: the y coordinate of the pointer relative to the root of the
|
||||||
* screen.
|
* screen.
|
||||||
|
* @touch_id: touch ID, only meaningful if event is of type %GDK_TOUCH_MOTION.
|
||||||
*
|
*
|
||||||
* Generated when the pointer moves.
|
* Generated when the pointer/touch moves.
|
||||||
*/
|
*/
|
||||||
struct _GdkEventMotion
|
struct _GdkEventMotion
|
||||||
{
|
{
|
||||||
@@ -516,6 +531,56 @@ struct _GdkEventMotion
|
|||||||
gint16 is_hint;
|
gint16 is_hint;
|
||||||
GdkDevice *device;
|
GdkDevice *device;
|
||||||
gdouble x_root, y_root;
|
gdouble x_root, y_root;
|
||||||
|
guint touch_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GdkEventMultiTouch:
|
||||||
|
* @type: the type of the event (%GDK_MULTITOUCH_ADDED, %GDK_MULTITOUCH_UPDATED
|
||||||
|
* or %GDK_MULTITOUCH_REMOVED).
|
||||||
|
* @window: the window which received the event.
|
||||||
|
* @send_event: %TRUE if the event was sent explicitly (e.g. using
|
||||||
|
* <function>XSendEvent</function>).
|
||||||
|
* @time: the time of the event in milliseconds.
|
||||||
|
* @state: (type GdkModifierType): a bit-mask representing the state of
|
||||||
|
* the modifier keys (e.g. Control, Shift and Alt) and the pointer
|
||||||
|
* buttons. See #GdkModifierType.
|
||||||
|
* @device: the device where the event originated.
|
||||||
|
* @group: the #GdkTouchCluster containing the touches that generated this event
|
||||||
|
* @events: an array of events of type %GDK_TOUCH_MOTION for the touches in @group
|
||||||
|
* @updated_touch_id: the touch ID that caused this event to be generated
|
||||||
|
* @n_events: the number of events in @events
|
||||||
|
* @n_updated_event: the index in @events of the event corresponding to
|
||||||
|
* @updated_touch_id, or -1 for %GDK_MULTITOUCH_REMOVED events.
|
||||||
|
*
|
||||||
|
* Used for multitouch events. The @type field will be one of
|
||||||
|
* %GDK_MULTITOUCH_ADDED, %GDK_MULTITOUCH_UPDATED or
|
||||||
|
* %GDK_MULTITOUCH_REMOVED.
|
||||||
|
*
|
||||||
|
* Multitouch events group the events from the touches in a
|
||||||
|
* #GdkTouchCluster, so one of these events is generated
|
||||||
|
* whenever a touch ID generates a new event, or a touch ID
|
||||||
|
* is added or removed.
|
||||||
|
*
|
||||||
|
* For any given touch ID, %GDK_MULTITOUCH_ADDED and
|
||||||
|
* %GDK_MULTITOUCH_REMOVED events are always paired,
|
||||||
|
* with any number of %GDK_MULTITOUCH_UPDATED
|
||||||
|
* events in between. The minimum event stream is an
|
||||||
|
* added/removed pair.
|
||||||
|
*/
|
||||||
|
struct _GdkEventMultiTouch
|
||||||
|
{
|
||||||
|
GdkEventType type;
|
||||||
|
GdkWindow *window;
|
||||||
|
gint8 send_event;
|
||||||
|
guint32 time;
|
||||||
|
guint state;
|
||||||
|
GdkDevice *device;
|
||||||
|
GdkTouchCluster *group;
|
||||||
|
GdkEventMotion **events;
|
||||||
|
guint updated_touch_id;
|
||||||
|
gint8 n_events;
|
||||||
|
gint8 n_updated_event;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -542,6 +607,8 @@ struct _GdkEventMotion
|
|||||||
* screen.
|
* screen.
|
||||||
* @y_root: the y coordinate of the pointer relative to the root of the
|
* @y_root: the y coordinate of the pointer relative to the root of the
|
||||||
* screen.
|
* screen.
|
||||||
|
* @touch_id: touch ID, only meaningful if event is of type %GDK_TOUCH_PRESS
|
||||||
|
* or %GDK_TOUCH_RELEASE.
|
||||||
*
|
*
|
||||||
* Used for button press and button release events. The
|
* Used for button press and button release events. The
|
||||||
* @type field will be one of %GDK_BUTTON_PRESS,
|
* @type field will be one of %GDK_BUTTON_PRESS,
|
||||||
@@ -591,6 +658,7 @@ struct _GdkEventButton
|
|||||||
guint button;
|
guint button;
|
||||||
GdkDevice *device;
|
GdkDevice *device;
|
||||||
gdouble x_root, y_root;
|
gdouble x_root, y_root;
|
||||||
|
guint touch_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1034,6 +1102,7 @@ union _GdkEvent
|
|||||||
GdkEventWindowState window_state;
|
GdkEventWindowState window_state;
|
||||||
GdkEventSetting setting;
|
GdkEventSetting setting;
|
||||||
GdkEventGrabBroken grab_broken;
|
GdkEventGrabBroken grab_broken;
|
||||||
|
GdkEventMultiTouch multitouch;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gdk_event_get_type (void) G_GNUC_CONST;
|
GType gdk_event_get_type (void) G_GNUC_CONST;
|
||||||
@@ -1087,6 +1156,9 @@ void gdk_event_set_screen (GdkEvent *event,
|
|||||||
GdkScreen *screen);
|
GdkScreen *screen);
|
||||||
GdkScreen *gdk_event_get_screen (const GdkEvent *event);
|
GdkScreen *gdk_event_get_screen (const GdkEvent *event);
|
||||||
|
|
||||||
|
gboolean gdk_event_get_touch_id (const GdkEvent *event,
|
||||||
|
guint *touch_id);
|
||||||
|
|
||||||
void gdk_set_show_events (gboolean show_events);
|
void gdk_set_show_events (gboolean show_events);
|
||||||
gboolean gdk_get_show_events (void);
|
gboolean gdk_get_show_events (void);
|
||||||
|
|
||||||
|
@@ -248,6 +248,12 @@ struct _GdkWindow
|
|||||||
GHashTable *source_event_masks;
|
GHashTable *source_event_masks;
|
||||||
gulong device_added_handler_id;
|
gulong device_added_handler_id;
|
||||||
gulong device_changed_handler_id;
|
gulong device_changed_handler_id;
|
||||||
|
|
||||||
|
/* Store of latest per-touch events, keys are
|
||||||
|
* GdkDevices, values are hashtables of touchID/info
|
||||||
|
*/
|
||||||
|
GHashTable *touch_event_tracker;
|
||||||
|
GList *touch_clusters;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GDK_WINDOW_TYPE(d) (((GDK_WINDOW (d)))->window_type)
|
#define GDK_WINDOW_TYPE(d) (((GDK_WINDOW (d)))->window_type)
|
||||||
|
350
gdk/gdktouchcluster.c
Normal file
350
gdk/gdktouchcluster.c
Normal file
@@ -0,0 +1,350 @@
|
|||||||
|
/* GDK - The GIMP Drawing Kit
|
||||||
|
* Copyright (C) 2011 Carlos Garnacho <carlosg@gnome.org>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gdktouchcluster.h"
|
||||||
|
#include "gdkintl.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:touchcluster
|
||||||
|
* @Short_description: Multitouch handling
|
||||||
|
* @Title: Multitouch
|
||||||
|
* @See_also: #GdkEventMultiTouch
|
||||||
|
*
|
||||||
|
* #GdkTouchCluster is an object that gathers touch IDs from a
|
||||||
|
* touch-enabled slave #GdkDevice, in order to send
|
||||||
|
* #GdkEventMultiTouch<!-- --> events whenever a contained touch ID
|
||||||
|
* is updated.
|
||||||
|
*
|
||||||
|
* #GdkTouchCluster<!-- -->s are always associated to a window,
|
||||||
|
* you need to create them through gdk_window_create_touch_cluster(),
|
||||||
|
* and free them through gdk_window_remove_touch_cluster().
|
||||||
|
*
|
||||||
|
* Touch IDs from devices can be obtained from %GDK_TOUCH_PRESS,
|
||||||
|
* %GDK_TOUCH_MOTION or %GDK_TOUCH_RELEASE events through
|
||||||
|
* gdk_event_get_touch_id(), and then be added via
|
||||||
|
* gdk_touch_cluster_add_touch(). Note that touch IDs are
|
||||||
|
* highly transitive, even be an incrementable number only
|
||||||
|
* identifying the current touch event stream, so touch IDs
|
||||||
|
* should always be gotten from these events.
|
||||||
|
*
|
||||||
|
* Anytime a touch ID is within a cluster, no %GDK_TOUCH_PRESS,
|
||||||
|
* %GDK_TOUCH_MOTION or %GDK_TOUCH_RELEASE events will happen
|
||||||
|
* for the individual touch. The event will be available instead
|
||||||
|
* as part of the #GdkMultitouchEvent that will be emitted. This
|
||||||
|
* will hold true until gdk_touch_cluster_remove_touch() is
|
||||||
|
* called for it. Note that GTK+ will automatically take a
|
||||||
|
* touch ID out of any cluster if %GDK_TOUCH_RELEASE is gotten
|
||||||
|
* internally.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct GdkTouchClusterPrivate GdkTouchClusterPrivate;
|
||||||
|
|
||||||
|
struct GdkTouchClusterPrivate
|
||||||
|
{
|
||||||
|
GdkDevice *device;
|
||||||
|
GList *touches;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_DEVICE
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TOUCH_ADDED,
|
||||||
|
TOUCH_REMOVED,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals [LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
|
static void gdk_touch_cluster_finalize (GObject *object);
|
||||||
|
static void gdk_touch_cluster_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec);
|
||||||
|
static void gdk_touch_cluster_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec);
|
||||||
|
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdkTouchCluster, gdk_touch_cluster, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_touch_cluster_class_init (GdkTouchClusterClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = gdk_touch_cluster_finalize;
|
||||||
|
object_class->get_property = gdk_touch_cluster_get_property;
|
||||||
|
object_class->set_property = gdk_touch_cluster_set_property;
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_DEVICE,
|
||||||
|
g_param_spec_object ("device",
|
||||||
|
P_("Device"),
|
||||||
|
P_("Device attached to the cluster"),
|
||||||
|
GDK_TYPE_DEVICE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
signals[TOUCH_ADDED] =
|
||||||
|
g_signal_new (g_intern_static_string ("touch-added"),
|
||||||
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GdkTouchClusterClass, touch_added),
|
||||||
|
NULL, NULL,
|
||||||
|
g_cclosure_marshal_VOID__UINT,
|
||||||
|
G_TYPE_NONE, 1, G_TYPE_UINT);
|
||||||
|
signals[TOUCH_REMOVED] =
|
||||||
|
g_signal_new (g_intern_static_string ("touch-removed"),
|
||||||
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GdkTouchClusterClass, touch_removed),
|
||||||
|
NULL, NULL,
|
||||||
|
g_cclosure_marshal_VOID__UINT,
|
||||||
|
G_TYPE_NONE, 1, G_TYPE_UINT);
|
||||||
|
|
||||||
|
g_type_class_add_private (object_class, sizeof (GdkTouchClusterPrivate));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_touch_cluster_init (GdkTouchCluster *cluster)
|
||||||
|
{
|
||||||
|
cluster->priv = G_TYPE_INSTANCE_GET_PRIVATE (cluster,
|
||||||
|
GDK_TYPE_TOUCH_CLUSTER,
|
||||||
|
GdkTouchClusterPrivate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_touch_cluster_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdkTouchClusterPrivate *priv;
|
||||||
|
|
||||||
|
priv = GDK_TOUCH_CLUSTER (object)->priv;
|
||||||
|
g_list_free (priv->touches);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdk_touch_cluster_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_touch_cluster_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdkTouchClusterPrivate *priv;
|
||||||
|
|
||||||
|
priv = GDK_TOUCH_CLUSTER (object)->priv;
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_DEVICE:
|
||||||
|
gdk_touch_cluster_set_device (GDK_TOUCH_CLUSTER (object),
|
||||||
|
g_value_get_object (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_touch_cluster_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdkTouchClusterPrivate *priv;
|
||||||
|
|
||||||
|
priv = GDK_TOUCH_CLUSTER (object)->priv;
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_DEVICE:
|
||||||
|
g_value_set_object (value, priv->device);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_touch_cluster_add_touch:
|
||||||
|
* @cluster: a #GdkTouchCluster
|
||||||
|
* @touch_id: a touch ID from a touch event
|
||||||
|
*
|
||||||
|
* Adds a touch ID to @cluster, so it will generate a
|
||||||
|
* %GDK_MULTITOUCH_ADDED event, followed by %GDK_MULTITOUCH_UPDATED
|
||||||
|
* events whenever this touch ID is updated.
|
||||||
|
*
|
||||||
|
* If @touch_id already pertained to another #GdkTouchCluster, it
|
||||||
|
* will be removed from it, generating a %GDK_MULTITOUCH_REMOVED
|
||||||
|
* for that another cluster.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
gdk_touch_cluster_add_touch (GdkTouchCluster *cluster,
|
||||||
|
guint touch_id)
|
||||||
|
{
|
||||||
|
GdkTouchClusterPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (GDK_IS_TOUCH_CLUSTER (cluster));
|
||||||
|
|
||||||
|
priv = cluster->priv;
|
||||||
|
|
||||||
|
if (!g_list_find (priv->touches, GUINT_TO_POINTER (touch_id)))
|
||||||
|
{
|
||||||
|
priv->touches = g_list_prepend (priv->touches, GUINT_TO_POINTER (touch_id));
|
||||||
|
g_signal_emit (cluster, signals [TOUCH_ADDED], 0, touch_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_touch_cluster_remove_touch:
|
||||||
|
* @cluster: a #GdkTouchCluster
|
||||||
|
* @touch_id: a touch ID from a touch event
|
||||||
|
*
|
||||||
|
* Removes a touch ID from @cluster, generating a %GDK_MULTITOUCH_REMOVED
|
||||||
|
* event for @cluster, and causing any further input from @touch_id
|
||||||
|
* to be reported trough %GDK_TOUCH_MOTION events.
|
||||||
|
*
|
||||||
|
* <note><para>
|
||||||
|
* Note that GTK+ automatically removes a touch ID from any cluster
|
||||||
|
* if a %GDK_TOUCH_RELEASE event is gotten internally.
|
||||||
|
* </para></note>
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
gdk_touch_cluster_remove_touch (GdkTouchCluster *cluster,
|
||||||
|
guint touch_id)
|
||||||
|
{
|
||||||
|
GdkTouchClusterPrivate *priv;
|
||||||
|
GList *link;
|
||||||
|
|
||||||
|
g_return_if_fail (GDK_IS_TOUCH_CLUSTER (cluster));
|
||||||
|
|
||||||
|
priv = cluster->priv;
|
||||||
|
|
||||||
|
link = g_list_find (priv->touches, GUINT_TO_POINTER (touch_id));
|
||||||
|
|
||||||
|
if (link)
|
||||||
|
{
|
||||||
|
priv->touches = g_list_remove_link (priv->touches, link);
|
||||||
|
g_signal_emit (cluster, signals [TOUCH_REMOVED], 0, touch_id);
|
||||||
|
g_list_free1 (link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_touch_cluster_remove_all:
|
||||||
|
* @cluster: a #GdkTouchCluster
|
||||||
|
*
|
||||||
|
* Removes all touch IDs from @cluster.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
gdk_touch_cluster_remove_all (GdkTouchCluster *cluster)
|
||||||
|
{
|
||||||
|
GdkTouchClusterPrivate *priv;
|
||||||
|
GList *link;
|
||||||
|
|
||||||
|
g_return_if_fail (GDK_IS_TOUCH_CLUSTER (cluster));
|
||||||
|
|
||||||
|
priv = cluster->priv;
|
||||||
|
link = priv->touches;
|
||||||
|
|
||||||
|
while (link)
|
||||||
|
{
|
||||||
|
priv->touches = g_list_remove_link (priv->touches, link);
|
||||||
|
g_signal_emit (cluster, signals [TOUCH_REMOVED], 0, link->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free (priv->touches);
|
||||||
|
priv->touches = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_touch_cluster_get_touches:
|
||||||
|
* @cluster: a #GdkTouchCluster
|
||||||
|
*
|
||||||
|
* Returns a const list of touch IDs as #guint.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): A list of touch IDs.
|
||||||
|
**/
|
||||||
|
GList *
|
||||||
|
gdk_touch_cluster_get_touches (GdkTouchCluster *cluster)
|
||||||
|
{
|
||||||
|
GdkTouchClusterPrivate *priv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDK_IS_TOUCH_CLUSTER (cluster), NULL);
|
||||||
|
|
||||||
|
priv = cluster->priv;
|
||||||
|
return priv->touches;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_touch_cluster_set_device:
|
||||||
|
* @cluster: a #GdkTouchCluster
|
||||||
|
* @device: a #GdkDevice
|
||||||
|
*
|
||||||
|
* Sets the current device associated to @cluster, all contained
|
||||||
|
* touch IDs must pertain to this device. As a consequence,
|
||||||
|
* gdk_touch_cluster_remove_all() will be called on @cluster
|
||||||
|
* if the current device changes.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
gdk_touch_cluster_set_device (GdkTouchCluster *cluster,
|
||||||
|
GdkDevice *device)
|
||||||
|
{
|
||||||
|
GdkTouchClusterPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (GDK_IS_TOUCH_CLUSTER (cluster));
|
||||||
|
g_return_if_fail (!device || GDK_IS_DEVICE (device));
|
||||||
|
|
||||||
|
priv = cluster->priv;
|
||||||
|
|
||||||
|
if (priv->device != device)
|
||||||
|
gdk_touch_cluster_remove_all (cluster);
|
||||||
|
|
||||||
|
priv->device = device;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_touch_cluster_get_device:
|
||||||
|
* @cluster: a #GdkTouchCluster
|
||||||
|
*
|
||||||
|
* Returns the slave/floating device this touch cluster pertains to,
|
||||||
|
* only touch IDs from this device can be included in @cluster.
|
||||||
|
* the #GdkDevice will typically have the %GDK_SOURCE_TOUCH input source.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): The #GdkDevice generating the contained touch IDs
|
||||||
|
**/
|
||||||
|
GdkDevice *
|
||||||
|
gdk_touch_cluster_get_device (GdkTouchCluster *cluster)
|
||||||
|
{
|
||||||
|
GdkTouchClusterPrivate *priv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDK_IS_TOUCH_CLUSTER (cluster), NULL);
|
||||||
|
|
||||||
|
priv = cluster->priv;
|
||||||
|
return priv->device;
|
||||||
|
}
|
69
gdk/gdktouchcluster.h
Normal file
69
gdk/gdktouchcluster.h
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
/* GDK - The GIMP Drawing Kit
|
||||||
|
* Copyright (C) 2011 Carlos Garnacho <carlosg@gnome.org>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDK_TOUCH_CLUSTER_H__
|
||||||
|
#define __GDK_TOUCH_CLUSTER_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <gdk/gdkdevice.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDK_TYPE_TOUCH_CLUSTER (gdk_touch_cluster_get_type ())
|
||||||
|
#define GDK_TOUCH_CLUSTER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_TOUCH_CLUSTER, GdkTouchCluster))
|
||||||
|
#define GDK_IS_TOUCH_CLUSTER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_TOUCH_CLUSTER))
|
||||||
|
|
||||||
|
typedef struct _GdkTouchCluster GdkTouchCluster;
|
||||||
|
typedef struct _GdkTouchClusterClass GdkTouchClusterClass;
|
||||||
|
|
||||||
|
struct _GdkTouchCluster
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
gpointer priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GdkTouchClusterClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
void (* touch_added) (GdkTouchCluster *cluster,
|
||||||
|
guint touch_id);
|
||||||
|
void (* touch_removed) (GdkTouchCluster *cluster,
|
||||||
|
guint touch_id);
|
||||||
|
|
||||||
|
gpointer padding[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gdk_touch_cluster_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
void gdk_touch_cluster_add_touch (GdkTouchCluster *cluster,
|
||||||
|
guint touch_id);
|
||||||
|
void gdk_touch_cluster_remove_touch (GdkTouchCluster *cluster,
|
||||||
|
guint touch_id);
|
||||||
|
void gdk_touch_cluster_remove_all (GdkTouchCluster *cluster);
|
||||||
|
|
||||||
|
GList * gdk_touch_cluster_get_touches (GdkTouchCluster *cluster);
|
||||||
|
|
||||||
|
void gdk_touch_cluster_set_device (GdkTouchCluster *cluster,
|
||||||
|
GdkDevice *device);
|
||||||
|
GdkDevice * gdk_touch_cluster_get_device (GdkTouchCluster *cluster);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDK_TOUCH_CLUSTER_H__ */
|
@@ -288,6 +288,7 @@ typedef enum
|
|||||||
* @GDK_SUBSTRUCTURE_MASK: receive events about window configuration changes of
|
* @GDK_SUBSTRUCTURE_MASK: receive events about window configuration changes of
|
||||||
* child windows
|
* child windows
|
||||||
* @GDK_SCROLL_MASK: receive scroll events
|
* @GDK_SCROLL_MASK: receive scroll events
|
||||||
|
* @GDK_TOUCH_MASK: receive (multi)touch events
|
||||||
* @GDK_ALL_EVENTS_MASK: the combination of all the above event masks.
|
* @GDK_ALL_EVENTS_MASK: the combination of all the above event masks.
|
||||||
*
|
*
|
||||||
* A set of bit-flags to indicate which events a window is to receive.
|
* A set of bit-flags to indicate which events a window is to receive.
|
||||||
@@ -327,7 +328,8 @@ typedef enum
|
|||||||
GDK_PROXIMITY_OUT_MASK = 1 << 19,
|
GDK_PROXIMITY_OUT_MASK = 1 << 19,
|
||||||
GDK_SUBSTRUCTURE_MASK = 1 << 20,
|
GDK_SUBSTRUCTURE_MASK = 1 << 20,
|
||||||
GDK_SCROLL_MASK = 1 << 21,
|
GDK_SCROLL_MASK = 1 << 21,
|
||||||
GDK_ALL_EVENTS_MASK = 0x3FFFFE
|
GDK_TOUCH_MASK = 1 << 22,
|
||||||
|
GDK_ALL_EVENTS_MASK = 0x3FFFFF
|
||||||
} GdkEventMask;
|
} GdkEventMask;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
478
gdk/gdkwindow.c
478
gdk/gdkwindow.c
@@ -213,6 +213,11 @@ typedef struct {
|
|||||||
int dx, dy; /* The amount that the source was moved to reach dest_region */
|
int dx, dy; /* The amount that the source was moved to reach dest_region */
|
||||||
} GdkWindowRegionMove;
|
} GdkWindowRegionMove;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GdkEvent *event; /* latest event for touch */
|
||||||
|
GdkTouchCluster *cluster; /* touch cluster the ID currently pertains to */
|
||||||
|
} TouchEventInfo;
|
||||||
|
|
||||||
/* Global info */
|
/* Global info */
|
||||||
|
|
||||||
static void gdk_window_drop_cairo_surface (GdkWindow *private);
|
static void gdk_window_drop_cairo_surface (GdkWindow *private);
|
||||||
@@ -567,6 +572,12 @@ gdk_window_finalize (GObject *object)
|
|||||||
if (window->devices_inside)
|
if (window->devices_inside)
|
||||||
g_list_free (window->devices_inside);
|
g_list_free (window->devices_inside);
|
||||||
|
|
||||||
|
if (window->touch_event_tracker)
|
||||||
|
g_hash_table_destroy (window->touch_event_tracker);
|
||||||
|
|
||||||
|
g_list_foreach (window->touch_clusters, (GFunc) g_object_unref, NULL);
|
||||||
|
g_list_free (window->touch_clusters);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8066,6 +8077,12 @@ static const guint type_masks[] = {
|
|||||||
0, /* GDK_OWNER_CHANGE = 34 */
|
0, /* GDK_OWNER_CHANGE = 34 */
|
||||||
0, /* GDK_GRAB_BROKEN = 35 */
|
0, /* GDK_GRAB_BROKEN = 35 */
|
||||||
0, /* GDK_DAMAGE = 36 */
|
0, /* GDK_DAMAGE = 36 */
|
||||||
|
GDK_TOUCH_MASK, /* GDK_TOUCH_MOTION = 37 */
|
||||||
|
GDK_TOUCH_MASK, /* GDK_TOUCH_PRESS = 38 */
|
||||||
|
GDK_TOUCH_MASK, /* GDK_TOUCH_RELEASE = 39 */
|
||||||
|
GDK_TOUCH_MASK, /* GDK_MULTITOUCH_ADDED = 40 */
|
||||||
|
GDK_TOUCH_MASK, /* GDK_MULTITOUCH_REMOVED = 41 */
|
||||||
|
GDK_TOUCH_MASK /* GDK_MULTITOUCH_UPDATED = 42 */
|
||||||
};
|
};
|
||||||
G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
|
G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
|
||||||
|
|
||||||
@@ -8097,6 +8114,8 @@ is_button_type (GdkEventType type)
|
|||||||
type == GDK_2BUTTON_PRESS ||
|
type == GDK_2BUTTON_PRESS ||
|
||||||
type == GDK_3BUTTON_PRESS ||
|
type == GDK_3BUTTON_PRESS ||
|
||||||
type == GDK_BUTTON_RELEASE ||
|
type == GDK_BUTTON_RELEASE ||
|
||||||
|
type == GDK_TOUCH_PRESS ||
|
||||||
|
type == GDK_TOUCH_RELEASE ||
|
||||||
type == GDK_SCROLL;
|
type == GDK_SCROLL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8104,6 +8123,7 @@ static gboolean
|
|||||||
is_motion_type (GdkEventType type)
|
is_motion_type (GdkEventType type)
|
||||||
{
|
{
|
||||||
return type == GDK_MOTION_NOTIFY ||
|
return type == GDK_MOTION_NOTIFY ||
|
||||||
|
type == GDK_TOUCH_MOTION ||
|
||||||
type == GDK_ENTER_NOTIFY ||
|
type == GDK_ENTER_NOTIFY ||
|
||||||
type == GDK_LEAVE_NOTIFY;
|
type == GDK_LEAVE_NOTIFY;
|
||||||
}
|
}
|
||||||
@@ -8166,6 +8186,7 @@ _gdk_make_event (GdkWindow *window,
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
|
case GDK_TOUCH_MOTION:
|
||||||
event->motion.time = the_time;
|
event->motion.time = the_time;
|
||||||
event->motion.axes = NULL;
|
event->motion.axes = NULL;
|
||||||
event->motion.state = the_state;
|
event->motion.state = the_state;
|
||||||
@@ -8248,6 +8269,79 @@ _gdk_make_event (GdkWindow *window,
|
|||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GdkEvent *
|
||||||
|
gdk_make_multitouch_event (GdkWindow *window,
|
||||||
|
GdkEventType type,
|
||||||
|
GdkTouchCluster *cluster,
|
||||||
|
GdkDevice *device,
|
||||||
|
guint touch_id,
|
||||||
|
GdkEvent *event_in_queue)
|
||||||
|
{
|
||||||
|
GdkEvent *mt_event, *event = NULL;
|
||||||
|
gint i, n_touches, n_updated = -1;
|
||||||
|
GdkEventMotion **subevents;
|
||||||
|
TouchEventInfo *info;
|
||||||
|
GHashTable *by_touch;
|
||||||
|
GList *touches;
|
||||||
|
|
||||||
|
if (!window->touch_event_tracker)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
by_touch = g_hash_table_lookup (window->touch_event_tracker, device);
|
||||||
|
|
||||||
|
if (by_touch)
|
||||||
|
{
|
||||||
|
info = g_hash_table_lookup (by_touch, GUINT_TO_POINTER (touch_id));
|
||||||
|
if (info)
|
||||||
|
event = info->event;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!event)
|
||||||
|
{
|
||||||
|
g_warning ("Creating a multitouch event but no input was pre-recorded");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate multitouch event */
|
||||||
|
mt_event = _gdk_make_event (window, type, event_in_queue, FALSE);
|
||||||
|
mt_event->multitouch.time = event->motion.time;
|
||||||
|
mt_event->multitouch.state = event->motion.state;
|
||||||
|
gdk_event_set_device (mt_event, gdk_event_get_device (event));
|
||||||
|
gdk_event_set_source_device (mt_event, gdk_event_get_source_device (event));
|
||||||
|
|
||||||
|
mt_event->multitouch.group = cluster;
|
||||||
|
|
||||||
|
/* Fill in individual motion sub-events */
|
||||||
|
touches = gdk_touch_cluster_get_touches (cluster);
|
||||||
|
n_touches = g_list_length (touches);
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
subevents = g_new0 (GdkEventMotion *, n_touches);
|
||||||
|
|
||||||
|
while (touches)
|
||||||
|
{
|
||||||
|
TouchEventInfo *subevent_info;
|
||||||
|
GdkEvent *subevent;
|
||||||
|
|
||||||
|
subevent_info = g_hash_table_lookup (by_touch, touches->data);
|
||||||
|
subevent = gdk_event_copy (subevent_info->event);
|
||||||
|
subevents[i] = (GdkEventMotion *) subevent;
|
||||||
|
|
||||||
|
if (subevent->motion.touch_id == touch_id)
|
||||||
|
n_updated = i;
|
||||||
|
|
||||||
|
touches = touches->next;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
mt_event->multitouch.events = subevents;
|
||||||
|
mt_event->multitouch.n_updated_event = n_updated;
|
||||||
|
mt_event->multitouch.n_events = n_touches;
|
||||||
|
mt_event->multitouch.updated_touch_id = touch_id;
|
||||||
|
|
||||||
|
return mt_event;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
send_crossing_event (GdkDisplay *display,
|
send_crossing_event (GdkDisplay *display,
|
||||||
GdkWindow *toplevel,
|
GdkWindow *toplevel,
|
||||||
@@ -9092,6 +9186,127 @@ get_event_window (GdkDisplay *display,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TouchEventInfo *
|
||||||
|
touch_event_info_new (void)
|
||||||
|
{
|
||||||
|
return g_slice_new0 (TouchEventInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
touch_event_info_free (TouchEventInfo *info)
|
||||||
|
{
|
||||||
|
if (info->event)
|
||||||
|
gdk_event_free (info->event);
|
||||||
|
g_slice_free (TouchEventInfo, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TouchEventInfo *
|
||||||
|
touch_event_info_lookup (GdkWindow *window,
|
||||||
|
GdkDevice *device,
|
||||||
|
guint touch_id,
|
||||||
|
gboolean create)
|
||||||
|
{
|
||||||
|
TouchEventInfo *info;
|
||||||
|
GHashTable *by_touch;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!window->touch_event_tracker))
|
||||||
|
window->touch_event_tracker = g_hash_table_new_full (NULL, NULL, NULL,
|
||||||
|
(GDestroyNotify) g_hash_table_destroy);
|
||||||
|
|
||||||
|
by_touch = g_hash_table_lookup (window->touch_event_tracker, device);
|
||||||
|
|
||||||
|
if (!by_touch)
|
||||||
|
{
|
||||||
|
by_touch = g_hash_table_new_full (NULL, NULL, NULL,
|
||||||
|
(GDestroyNotify) touch_event_info_free);
|
||||||
|
g_hash_table_insert (window->touch_event_tracker, device, by_touch);
|
||||||
|
}
|
||||||
|
|
||||||
|
info = g_hash_table_lookup (by_touch, GUINT_TO_POINTER (touch_id));
|
||||||
|
|
||||||
|
if (create && !info)
|
||||||
|
{
|
||||||
|
info = touch_event_info_new ();
|
||||||
|
g_hash_table_insert (by_touch, GUINT_TO_POINTER (touch_id), info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stores touch event for posterior multitouch
|
||||||
|
* events generation, takes ownership of event
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
store_touch_event (GdkWindow *window,
|
||||||
|
GdkEvent *event,
|
||||||
|
guint touch_id)
|
||||||
|
{
|
||||||
|
GdkDevice *device, *source_device;
|
||||||
|
TouchEventInfo *info;
|
||||||
|
|
||||||
|
if (event->type != GDK_TOUCH_PRESS &&
|
||||||
|
event->type != GDK_TOUCH_RELEASE &&
|
||||||
|
event->type != GDK_TOUCH_MOTION)
|
||||||
|
return;
|
||||||
|
|
||||||
|
device = gdk_event_get_device (event);
|
||||||
|
source_device = gdk_event_get_source_device (event);
|
||||||
|
|
||||||
|
if (event->type == GDK_TOUCH_PRESS ||
|
||||||
|
event->type == GDK_TOUCH_RELEASE)
|
||||||
|
{
|
||||||
|
GdkEvent *new_event;
|
||||||
|
|
||||||
|
/* Create GDK_TOUCH_MOTION event from the available data */
|
||||||
|
new_event = gdk_event_new (GDK_TOUCH_MOTION);
|
||||||
|
|
||||||
|
if (event->button.window)
|
||||||
|
new_event->motion.window = g_object_ref (event->button.window);
|
||||||
|
|
||||||
|
new_event->motion.send_event = event->button.send_event;
|
||||||
|
new_event->motion.time = event->button.time;
|
||||||
|
new_event->motion.x = event->button.x;
|
||||||
|
new_event->motion.y = event->button.y;
|
||||||
|
new_event->motion.x_root = event->button.x_root;
|
||||||
|
new_event->motion.y_root = event->button.y_root;
|
||||||
|
new_event->motion.state = event->button.state;
|
||||||
|
new_event->motion.touch_id = event->button.touch_id;
|
||||||
|
new_event->motion.is_hint = FALSE;
|
||||||
|
|
||||||
|
gdk_event_set_device (new_event, device);
|
||||||
|
gdk_event_set_source_device (new_event, source_device);
|
||||||
|
|
||||||
|
new_event->motion.axes = g_memdup (event->button.axes,
|
||||||
|
sizeof (gdouble) * gdk_device_get_n_axes (device));
|
||||||
|
|
||||||
|
gdk_event_free (event);
|
||||||
|
event = new_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
info = touch_event_info_lookup (window, source_device, touch_id, TRUE);
|
||||||
|
info->event = event;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkTouchCluster *
|
||||||
|
_gdk_window_lookup_touch_cluster (GdkWindow *window,
|
||||||
|
GdkEvent *event)
|
||||||
|
{
|
||||||
|
TouchEventInfo *info;
|
||||||
|
GdkDevice *device;
|
||||||
|
guint touch_id;
|
||||||
|
|
||||||
|
if (!gdk_event_get_touch_id (event, &touch_id))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
device = gdk_event_get_source_device (event);
|
||||||
|
info = touch_event_info_lookup (window, device, touch_id, FALSE);
|
||||||
|
|
||||||
|
if (!info)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return info->cluster;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
proxy_pointer_event (GdkDisplay *display,
|
proxy_pointer_event (GdkDisplay *display,
|
||||||
GdkEvent *source_event,
|
GdkEvent *source_event,
|
||||||
@@ -9229,7 +9444,8 @@ proxy_pointer_event (GdkDisplay *display,
|
|||||||
serial, non_linear);
|
serial, non_linear);
|
||||||
_gdk_display_set_window_under_pointer (display, device, pointer_window);
|
_gdk_display_set_window_under_pointer (display, device, pointer_window);
|
||||||
}
|
}
|
||||||
else if (source_event->type == GDK_MOTION_NOTIFY)
|
else if (source_event->type == GDK_MOTION_NOTIFY ||
|
||||||
|
source_event->type == GDK_TOUCH_MOTION)
|
||||||
{
|
{
|
||||||
GdkWindow *event_win;
|
GdkWindow *event_win;
|
||||||
guint evmask;
|
guint evmask;
|
||||||
@@ -9248,6 +9464,15 @@ proxy_pointer_event (GdkDisplay *display,
|
|||||||
gdk_window_get_device_events (event_win, device) == 0)
|
gdk_window_get_device_events (event_win, device) == 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
/* Block motion events coming from touch devices, only if
|
||||||
|
* the event mask allows both motion and touch events, since
|
||||||
|
* the latter will come right after.
|
||||||
|
*/
|
||||||
|
if ((evmask & GDK_TOUCH_MASK) &&
|
||||||
|
gdk_device_get_source (source_device) == GDK_SOURCE_TOUCH &&
|
||||||
|
source_event->type == GDK_MOTION_NOTIFY)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
is_hint = FALSE;
|
is_hint = FALSE;
|
||||||
|
|
||||||
if (event_win &&
|
if (event_win &&
|
||||||
@@ -9268,21 +9493,60 @@ proxy_pointer_event (GdkDisplay *display,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event_win && !display->ignore_core_events)
|
if (!event_win)
|
||||||
{
|
return TRUE;
|
||||||
event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
|
|
||||||
event->motion.time = time_;
|
if (!display->ignore_core_events)
|
||||||
convert_toplevel_coords_to_window (event_win,
|
{
|
||||||
toplevel_x, toplevel_y,
|
GdkTouchCluster *cluster = NULL;
|
||||||
&event->motion.x, &event->motion.y);
|
GdkEventType event_type;
|
||||||
event->motion.x_root = source_event->motion.x_root;
|
guint touch_id;
|
||||||
event->motion.y_root = source_event->motion.y_root;
|
|
||||||
event->motion.state = state;
|
if (gdk_event_get_touch_id (source_event, &touch_id))
|
||||||
event->motion.is_hint = is_hint;
|
cluster = _gdk_window_lookup_touch_cluster (event_win, source_event);
|
||||||
event->motion.device = source_event->motion.device;
|
|
||||||
|
if (cluster)
|
||||||
|
event_type = GDK_TOUCH_MOTION;
|
||||||
|
else
|
||||||
|
event_type = source_event->type;
|
||||||
|
|
||||||
|
event = gdk_event_new (event_type);
|
||||||
|
event->any.window = g_object_ref (event_win);
|
||||||
|
event->any.send_event = source_event->any.send_event;
|
||||||
|
event->motion.time = time_;
|
||||||
|
convert_toplevel_coords_to_window (event_win,
|
||||||
|
toplevel_x, toplevel_y,
|
||||||
|
&event->motion.x, &event->motion.y);
|
||||||
|
event->motion.x_root = source_event->motion.x_root;
|
||||||
|
event->motion.y_root = source_event->motion.y_root;
|
||||||
|
event->motion.state = state;
|
||||||
|
event->motion.is_hint = is_hint;
|
||||||
|
event->motion.device = source_event->motion.device;
|
||||||
event->motion.axes = g_memdup (source_event->motion.axes,
|
event->motion.axes = g_memdup (source_event->motion.axes,
|
||||||
sizeof (gdouble) * gdk_device_get_n_axes (source_event->motion.device));
|
sizeof (gdouble) * gdk_device_get_n_axes (source_event->motion.device));
|
||||||
|
event->motion.touch_id = touch_id;
|
||||||
gdk_event_set_source_device (event, source_device);
|
gdk_event_set_source_device (event, source_device);
|
||||||
|
|
||||||
|
if (cluster)
|
||||||
|
{
|
||||||
|
store_touch_event (event_win, event, touch_id);
|
||||||
|
|
||||||
|
/* Event is not added to the queue, instead it's stored
|
||||||
|
* in order to generate a multitouch event for the touch
|
||||||
|
* ID's cluster.
|
||||||
|
*/
|
||||||
|
gdk_make_multitouch_event (event_win, GDK_MULTITOUCH_UPDATED,
|
||||||
|
cluster, source_device, touch_id,
|
||||||
|
source_event);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
store_touch_event (event_win, gdk_event_copy (event), touch_id);
|
||||||
|
|
||||||
|
/* Just insert the event */
|
||||||
|
_gdk_event_queue_insert_after (gdk_window_get_display (event_win),
|
||||||
|
source_event, event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9299,7 +9563,8 @@ proxy_pointer_event (GdkDisplay *display,
|
|||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
proxy_button_event (GdkEvent *source_event,
|
proxy_button_event (GdkEvent *source_event,
|
||||||
gulong serial)
|
gulong serial,
|
||||||
|
gboolean *handle_ungrab)
|
||||||
{
|
{
|
||||||
GdkWindow *toplevel_window, *event_window;
|
GdkWindow *toplevel_window, *event_window;
|
||||||
GdkWindow *event_win;
|
GdkWindow *event_win;
|
||||||
@@ -9313,6 +9578,7 @@ proxy_button_event (GdkEvent *source_event,
|
|||||||
GdkDisplay *display;
|
GdkDisplay *display;
|
||||||
GdkWindow *w;
|
GdkWindow *w;
|
||||||
GdkDevice *device, *source_device;
|
GdkDevice *device, *source_device;
|
||||||
|
GdkEventMask evmask;
|
||||||
|
|
||||||
type = source_event->any.type;
|
type = source_event->any.type;
|
||||||
event_window = source_event->any.window;
|
event_window = source_event->any.window;
|
||||||
@@ -9325,6 +9591,7 @@ proxy_button_event (GdkEvent *source_event,
|
|||||||
toplevel_window = convert_native_coords_to_toplevel (event_window,
|
toplevel_window = convert_native_coords_to_toplevel (event_window,
|
||||||
toplevel_x, toplevel_y,
|
toplevel_x, toplevel_y,
|
||||||
&toplevel_x, &toplevel_y);
|
&toplevel_x, &toplevel_y);
|
||||||
|
*handle_ungrab = TRUE;
|
||||||
|
|
||||||
if (type == GDK_BUTTON_PRESS &&
|
if (type == GDK_BUTTON_PRESS &&
|
||||||
!source_event->any.send_event &&
|
!source_event->any.send_event &&
|
||||||
@@ -9368,7 +9635,20 @@ proxy_button_event (GdkEvent *source_event,
|
|||||||
device,
|
device,
|
||||||
pointer_window,
|
pointer_window,
|
||||||
type, state,
|
type, state,
|
||||||
NULL, serial);
|
&evmask, serial);
|
||||||
|
|
||||||
|
/* Block button press/release events coming from touch devices, only if
|
||||||
|
* the event mask allows both normal and touch events, since
|
||||||
|
* the latter will come right after.
|
||||||
|
*/
|
||||||
|
if ((evmask & GDK_TOUCH_MASK) &&
|
||||||
|
gdk_device_get_source (source_device) == GDK_SOURCE_TOUCH &&
|
||||||
|
source_event->type != GDK_TOUCH_PRESS &&
|
||||||
|
source_event->type != GDK_TOUCH_RELEASE)
|
||||||
|
{
|
||||||
|
*handle_ungrab = FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (event_win == NULL || display->ignore_core_events)
|
if (event_win == NULL || display->ignore_core_events)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -9383,6 +9663,8 @@ proxy_button_event (GdkEvent *source_event,
|
|||||||
{
|
{
|
||||||
case GDK_BUTTON_PRESS:
|
case GDK_BUTTON_PRESS:
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
|
case GDK_TOUCH_PRESS:
|
||||||
|
case GDK_TOUCH_RELEASE:
|
||||||
event->button.button = source_event->button.button;
|
event->button.button = source_event->button.button;
|
||||||
convert_toplevel_coords_to_window (event_win,
|
convert_toplevel_coords_to_window (event_win,
|
||||||
toplevel_x, toplevel_y,
|
toplevel_x, toplevel_y,
|
||||||
@@ -9393,12 +9675,13 @@ proxy_button_event (GdkEvent *source_event,
|
|||||||
event->button.device = source_event->button.device;
|
event->button.device = source_event->button.device;
|
||||||
event->button.axes = g_memdup (source_event->button.axes,
|
event->button.axes = g_memdup (source_event->button.axes,
|
||||||
sizeof (gdouble) * gdk_device_get_n_axes (source_event->button.device));
|
sizeof (gdouble) * gdk_device_get_n_axes (source_event->button.device));
|
||||||
|
event->button.touch_id = source_event->button.touch_id;
|
||||||
|
|
||||||
gdk_event_set_source_device (event, source_device);
|
gdk_event_set_source_device (event, source_device);
|
||||||
|
|
||||||
if (type == GDK_BUTTON_PRESS)
|
if (type == GDK_BUTTON_PRESS)
|
||||||
_gdk_event_button_generate (display, event);
|
_gdk_event_button_generate (display, event);
|
||||||
return TRUE;
|
break;
|
||||||
|
|
||||||
case GDK_SCROLL:
|
case GDK_SCROLL:
|
||||||
event->scroll.direction = source_event->scroll.direction;
|
event->scroll.direction = source_event->scroll.direction;
|
||||||
@@ -9410,12 +9693,39 @@ proxy_button_event (GdkEvent *source_event,
|
|||||||
event->scroll.state = state;
|
event->scroll.state = state;
|
||||||
event->scroll.device = source_event->scroll.device;
|
event->scroll.device = source_event->scroll.device;
|
||||||
gdk_event_set_source_device (event, source_device);
|
gdk_event_set_source_device (event, source_device);
|
||||||
return TRUE;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == GDK_TOUCH_RELEASE)
|
||||||
|
{
|
||||||
|
GdkTouchCluster *cluster;
|
||||||
|
GHashTable *by_touch;
|
||||||
|
guint touch_id;
|
||||||
|
|
||||||
|
touch_id = source_event->button.touch_id;
|
||||||
|
|
||||||
|
/* Remove the touch ID from any touch cluster it could pertain to */
|
||||||
|
cluster = _gdk_window_lookup_touch_cluster (event_win, source_event);
|
||||||
|
|
||||||
|
if (cluster)
|
||||||
|
gdk_touch_cluster_remove_touch (cluster, touch_id);
|
||||||
|
|
||||||
|
/* Remove in any case the touch ID from the event tracker */
|
||||||
|
by_touch = g_hash_table_lookup (event_win->touch_event_tracker, source_device);
|
||||||
|
|
||||||
|
if (by_touch)
|
||||||
|
g_hash_table_remove (by_touch, GUINT_TO_POINTER (touch_id));
|
||||||
|
|
||||||
|
/* Only remove the grab if it was the last pending touch on the window */
|
||||||
|
*handle_ungrab = (g_hash_table_size (by_touch) == 0);
|
||||||
|
}
|
||||||
|
else if (type == GDK_TOUCH_PRESS)
|
||||||
|
store_touch_event (event_win, gdk_event_copy (event),
|
||||||
|
event->button.touch_id);
|
||||||
|
|
||||||
return TRUE; /* Always unlink original, we want to obey the emulated event mask */
|
return TRUE; /* Always unlink original, we want to obey the emulated event mask */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9504,7 +9814,7 @@ _gdk_windowing_got_event (GdkDisplay *display,
|
|||||||
GdkDeviceGrabInfo *button_release_grab;
|
GdkDeviceGrabInfo *button_release_grab;
|
||||||
GdkPointerWindowInfo *pointer_info;
|
GdkPointerWindowInfo *pointer_info;
|
||||||
GdkDevice *device, *source_device;
|
GdkDevice *device, *source_device;
|
||||||
gboolean is_toplevel;
|
gboolean is_toplevel, handle_ungrab = TRUE;
|
||||||
|
|
||||||
if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
|
if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
|
||||||
display->last_event_time = gdk_event_get_time (event);
|
display->last_event_time = gdk_event_get_time (event);
|
||||||
@@ -9630,7 +9940,9 @@ _gdk_windowing_got_event (GdkDisplay *display,
|
|||||||
pointer_info->toplevel_y = y;
|
pointer_info->toplevel_y = y;
|
||||||
gdk_event_get_state (event, &pointer_info->state);
|
gdk_event_get_state (event, &pointer_info->state);
|
||||||
if (event->type == GDK_BUTTON_PRESS ||
|
if (event->type == GDK_BUTTON_PRESS ||
|
||||||
event->type == GDK_BUTTON_RELEASE)
|
event->type == GDK_BUTTON_RELEASE ||
|
||||||
|
event->type == GDK_TOUCH_PRESS ||
|
||||||
|
event->type == GDK_TOUCH_RELEASE)
|
||||||
pointer_info->button = event->button.button;
|
pointer_info->button = event->button.button;
|
||||||
|
|
||||||
if (device &&
|
if (device &&
|
||||||
@@ -9645,9 +9957,12 @@ _gdk_windowing_got_event (GdkDisplay *display,
|
|||||||
serial);
|
serial);
|
||||||
else if (is_button_type (event->type))
|
else if (is_button_type (event->type))
|
||||||
unlink_event = proxy_button_event (event,
|
unlink_event = proxy_button_event (event,
|
||||||
serial);
|
serial,
|
||||||
|
&handle_ungrab);
|
||||||
|
|
||||||
if (event->type == GDK_BUTTON_RELEASE &&
|
if (handle_ungrab &&
|
||||||
|
(event->type == GDK_BUTTON_RELEASE ||
|
||||||
|
event->type == GDK_TOUCH_RELEASE) &&
|
||||||
!event->any.send_event)
|
!event->any.send_event)
|
||||||
{
|
{
|
||||||
button_release_grab =
|
button_release_grab =
|
||||||
@@ -10886,3 +11201,124 @@ gdk_property_delete (GdkWindow *window,
|
|||||||
{
|
{
|
||||||
GDK_WINDOW_IMPL_GET_CLASS (window->impl)->delete_property (window, property);
|
GDK_WINDOW_IMPL_GET_CLASS (window->impl)->delete_property (window, property);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
touch_cluster_touch_added (GdkTouchCluster *cluster,
|
||||||
|
guint touch_id,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GdkWindow *window;
|
||||||
|
TouchEventInfo *info;
|
||||||
|
GHashTable *by_touch;
|
||||||
|
GdkDevice *device;
|
||||||
|
|
||||||
|
device = gdk_touch_cluster_get_device (cluster);
|
||||||
|
|
||||||
|
if (!device)
|
||||||
|
return;
|
||||||
|
|
||||||
|
window = user_data;
|
||||||
|
by_touch = g_hash_table_lookup (window->touch_event_tracker, device);
|
||||||
|
g_assert (by_touch != NULL);
|
||||||
|
|
||||||
|
info = g_hash_table_lookup (by_touch, GUINT_TO_POINTER (touch_id));
|
||||||
|
|
||||||
|
if (info->cluster == cluster)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (info->cluster)
|
||||||
|
{
|
||||||
|
/* Remove touch from old cluster, but keep the stored data around */
|
||||||
|
g_hash_table_steal (by_touch, GUINT_TO_POINTER (touch_id));
|
||||||
|
|
||||||
|
gdk_touch_cluster_remove_touch (info->cluster, touch_id);
|
||||||
|
|
||||||
|
g_hash_table_insert (by_touch,
|
||||||
|
GUINT_TO_POINTER (touch_id),
|
||||||
|
info);
|
||||||
|
}
|
||||||
|
|
||||||
|
info->cluster = cluster;
|
||||||
|
gdk_make_multitouch_event (window, GDK_MULTITOUCH_ADDED,
|
||||||
|
cluster, device, touch_id,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
touch_cluster_touch_removed (GdkTouchCluster *cluster,
|
||||||
|
guint touch_id,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GdkWindow *window;
|
||||||
|
GdkDevice *device;
|
||||||
|
GHashTable *by_touch;
|
||||||
|
|
||||||
|
window = user_data;
|
||||||
|
device = gdk_touch_cluster_get_device (cluster);
|
||||||
|
by_touch = g_hash_table_lookup (window->touch_event_tracker, device);
|
||||||
|
|
||||||
|
g_assert (by_touch != NULL);
|
||||||
|
|
||||||
|
gdk_make_multitouch_event (window, GDK_MULTITOUCH_REMOVED,
|
||||||
|
cluster, device, touch_id,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_hash_table_remove (by_touch, GUINT_TO_POINTER (touch_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_window_create_touch_cluster:
|
||||||
|
* @window: a #GdkWindow
|
||||||
|
*
|
||||||
|
* Creates a #GdkTouchCluster associated to @window.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): a newly created @GdkTouchCluster. This
|
||||||
|
* object is owned by @window and must be freed through
|
||||||
|
* gdk_window_remove_touch_cluster().
|
||||||
|
**/
|
||||||
|
GdkTouchCluster *
|
||||||
|
gdk_window_create_touch_cluster (GdkWindow *window)
|
||||||
|
{
|
||||||
|
GdkTouchCluster *cluster;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
|
||||||
|
|
||||||
|
cluster = g_object_new (GDK_TYPE_TOUCH_CLUSTER, NULL);
|
||||||
|
g_signal_connect (cluster, "touch-added",
|
||||||
|
G_CALLBACK (touch_cluster_touch_added), window);
|
||||||
|
g_signal_connect (cluster, "touch-removed",
|
||||||
|
G_CALLBACK (touch_cluster_touch_removed), window);
|
||||||
|
|
||||||
|
window->touch_clusters = g_list_prepend (window->touch_clusters, cluster);
|
||||||
|
|
||||||
|
return cluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdk_window_remove_touch_cluster:
|
||||||
|
* @window: a #GdkWindow
|
||||||
|
* @cluster: a #GdkTouchCluster from @window
|
||||||
|
*
|
||||||
|
* Removes @cluster from @window. All contained touches will be
|
||||||
|
* removed one by one, causing %GDK_MULTITOUCH_REMOVED events
|
||||||
|
* for these before destroying @cluster.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
gdk_window_remove_touch_cluster (GdkWindow *window,
|
||||||
|
GdkTouchCluster *cluster)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDK_IS_WINDOW (window));
|
||||||
|
g_return_if_fail (GDK_IS_TOUCH_CLUSTER (cluster));
|
||||||
|
|
||||||
|
if (!window->touch_clusters ||
|
||||||
|
!g_list_find (window->touch_clusters, cluster))
|
||||||
|
return;
|
||||||
|
|
||||||
|
gdk_touch_cluster_remove_all (cluster);
|
||||||
|
|
||||||
|
g_signal_handlers_disconnect_by_func (cluster, "touch-added", window);
|
||||||
|
g_signal_handlers_disconnect_by_func (cluster, "touch-removed", window);
|
||||||
|
|
||||||
|
window->touch_clusters = g_list_remove (window->touch_clusters, cluster);
|
||||||
|
g_object_unref (cluster);
|
||||||
|
}
|
||||||
|
@@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <gdk/gdktypes.h>
|
#include <gdk/gdktypes.h>
|
||||||
#include <gdk/gdkevents.h>
|
#include <gdk/gdkevents.h>
|
||||||
|
#include <gdk/gdktouchcluster.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@@ -862,6 +863,11 @@ void gdk_window_set_support_multidevice (GdkWindow *window,
|
|||||||
gboolean support_multidevice);
|
gboolean support_multidevice);
|
||||||
gboolean gdk_window_get_support_multidevice (GdkWindow *window);
|
gboolean gdk_window_get_support_multidevice (GdkWindow *window);
|
||||||
|
|
||||||
|
/* Multitouch support */
|
||||||
|
GdkTouchCluster * gdk_window_create_touch_cluster (GdkWindow *window);
|
||||||
|
void gdk_window_remove_touch_cluster (GdkWindow *window,
|
||||||
|
GdkTouchCluster *cluster);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GDK_WINDOW_H__ */
|
#endif /* __GDK_WINDOW_H__ */
|
||||||
|
@@ -687,6 +687,17 @@ _gdk_x11_device_xi2_translate_event_mask (GdkEventMask event_mask,
|
|||||||
XISetMask (mask, XI_FocusOut);
|
XISetMask (mask, XI_FocusOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef XINPUT_2_1
|
||||||
|
if (event_mask & GDK_TOUCH_MASK)
|
||||||
|
{
|
||||||
|
XISetMask (mask, XI_TouchBegin);
|
||||||
|
XISetMask (mask, XI_TouchMotion);
|
||||||
|
XISetMask (mask, XI_TouchMotionUnowned);
|
||||||
|
XISetMask (mask, XI_TouchEnd);
|
||||||
|
XISetMask (mask, XI_TouchOwnership);
|
||||||
|
}
|
||||||
|
#endif /* XINPUT_2_1 */
|
||||||
|
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -47,7 +47,11 @@ _gdk_x11_device_manager_new (GdkDisplay *display)
|
|||||||
int major, minor;
|
int major, minor;
|
||||||
|
|
||||||
major = 2;
|
major = 2;
|
||||||
|
#ifdef XINPUT_2_1
|
||||||
|
minor = 1;
|
||||||
|
#else
|
||||||
minor = 0;
|
minor = 0;
|
||||||
|
#endif /* XINPUT_2_1 */
|
||||||
|
|
||||||
if (!_gdk_disable_multidevice &&
|
if (!_gdk_disable_multidevice &&
|
||||||
XIQueryVersion (xdisplay, &major, &minor) != BadRequest)
|
XIQueryVersion (xdisplay, &major, &minor) != BadRequest)
|
||||||
|
@@ -147,8 +147,10 @@ _gdk_x11_device_manager_xi2_select_events (GdkDeviceManager *device_manager,
|
|||||||
static void
|
static void
|
||||||
translate_valuator_class (GdkDisplay *display,
|
translate_valuator_class (GdkDisplay *display,
|
||||||
GdkDevice *device,
|
GdkDevice *device,
|
||||||
XIValuatorClassInfo *info,
|
Atom valuator_label,
|
||||||
gint n_valuator)
|
gdouble min,
|
||||||
|
gdouble max,
|
||||||
|
gdouble resolution)
|
||||||
{
|
{
|
||||||
static gboolean initialized = FALSE;
|
static gboolean initialized = FALSE;
|
||||||
static Atom label_atoms [GDK_AXIS_LAST] = { 0 };
|
static Atom label_atoms [GDK_AXIS_LAST] = { 0 };
|
||||||
@@ -169,24 +171,19 @@ translate_valuator_class (GdkDisplay *display,
|
|||||||
|
|
||||||
for (i = GDK_AXIS_IGNORE; i <= GDK_AXIS_LAST; i++)
|
for (i = GDK_AXIS_IGNORE; i <= GDK_AXIS_LAST; i++)
|
||||||
{
|
{
|
||||||
if (label_atoms[i] == info->label)
|
if (label_atoms[i] == valuator_label)
|
||||||
{
|
{
|
||||||
use = i;
|
use = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->label != None)
|
if (valuator_label != None)
|
||||||
label = gdk_x11_xatom_to_atom_for_display (display, info->label);
|
label = gdk_x11_xatom_to_atom_for_display (display, valuator_label);
|
||||||
else
|
else
|
||||||
label = GDK_NONE;
|
label = GDK_NONE;
|
||||||
|
|
||||||
_gdk_device_add_axis (device,
|
_gdk_device_add_axis (device, label, use, min, max, resolution);
|
||||||
label,
|
|
||||||
use,
|
|
||||||
info->min,
|
|
||||||
info->max,
|
|
||||||
info->resolution);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -195,7 +192,7 @@ translate_device_classes (GdkDisplay *display,
|
|||||||
XIAnyClassInfo **classes,
|
XIAnyClassInfo **classes,
|
||||||
guint n_classes)
|
guint n_classes)
|
||||||
{
|
{
|
||||||
gint i, n_valuator = 0;
|
gint i;
|
||||||
|
|
||||||
g_object_freeze_notify (G_OBJECT (device));
|
g_object_freeze_notify (G_OBJECT (device));
|
||||||
|
|
||||||
@@ -217,11 +214,28 @@ translate_device_classes (GdkDisplay *display,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XIValuatorClass:
|
case XIValuatorClass:
|
||||||
translate_valuator_class (display, device,
|
{
|
||||||
(XIValuatorClassInfo *) class_info,
|
XIValuatorClassInfo *valuator_info = (XIValuatorClassInfo *) class_info;
|
||||||
n_valuator);
|
translate_valuator_class (display, device,
|
||||||
n_valuator++;
|
valuator_info->label,
|
||||||
|
valuator_info->min,
|
||||||
|
valuator_info->max,
|
||||||
|
valuator_info->resolution);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
#ifdef XINPUT_2_1
|
||||||
|
case XITouchValuatorClass:
|
||||||
|
{
|
||||||
|
XITouchValuatorClassInfo *valuator_info = (XITouchValuatorClassInfo *) class_info;
|
||||||
|
|
||||||
|
translate_valuator_class (display, device,
|
||||||
|
valuator_info->label,
|
||||||
|
valuator_info->min,
|
||||||
|
valuator_info->max,
|
||||||
|
valuator_info->resolution);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* XINPUT_2_1 */
|
||||||
default:
|
default:
|
||||||
/* Ignore */
|
/* Ignore */
|
||||||
break;
|
break;
|
||||||
@@ -256,6 +270,8 @@ create_device (GdkDeviceManager *device_manager,
|
|||||||
else if (strstr (tmp_name, "wacom") ||
|
else if (strstr (tmp_name, "wacom") ||
|
||||||
strstr (tmp_name, "pen"))
|
strstr (tmp_name, "pen"))
|
||||||
input_source = GDK_SOURCE_PEN;
|
input_source = GDK_SOURCE_PEN;
|
||||||
|
else if (strstr (tmp_name, "multitouch"))
|
||||||
|
input_source = GDK_SOURCE_TOUCH;
|
||||||
else
|
else
|
||||||
input_source = GDK_SOURCE_MOUSE;
|
input_source = GDK_SOURCE_MOUSE;
|
||||||
|
|
||||||
@@ -883,6 +899,12 @@ get_event_window (GdkEventTranslator *translator,
|
|||||||
case XI_ButtonPress:
|
case XI_ButtonPress:
|
||||||
case XI_ButtonRelease:
|
case XI_ButtonRelease:
|
||||||
case XI_Motion:
|
case XI_Motion:
|
||||||
|
#ifdef XINPUT_2_1
|
||||||
|
case XI_TouchMotion:
|
||||||
|
case XI_TouchMotionUnowned:
|
||||||
|
case XI_TouchBegin:
|
||||||
|
case XI_TouchEnd:
|
||||||
|
#endif /* XINPUT_2_1 */
|
||||||
{
|
{
|
||||||
XIDeviceEvent *xev = (XIDeviceEvent *) ev;
|
XIDeviceEvent *xev = (XIDeviceEvent *) ev;
|
||||||
|
|
||||||
@@ -1063,56 +1085,54 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
|
|||||||
break;
|
break;
|
||||||
case XI_ButtonPress:
|
case XI_ButtonPress:
|
||||||
case XI_ButtonRelease:
|
case XI_ButtonRelease:
|
||||||
|
#ifdef XINPUT_2_1
|
||||||
|
case XI_TouchBegin:
|
||||||
|
case XI_TouchEnd:
|
||||||
|
#endif /* XINPUT_2_1 */
|
||||||
{
|
{
|
||||||
XIDeviceEvent *xev = (XIDeviceEvent *) ev;
|
XIDeviceEvent *xev = (XIDeviceEvent *) ev;
|
||||||
GdkDevice *source_device;
|
GdkDevice *source_device;
|
||||||
|
|
||||||
switch (xev->detail)
|
if (ev->evtype == XI_ButtonPress &&
|
||||||
|
(xev->detail >= 4 && xev->detail <= 7))
|
||||||
{
|
{
|
||||||
case 4:
|
/* Button presses of button 4-7 are scroll events */
|
||||||
case 5:
|
event->scroll.type = GDK_SCROLL;
|
||||||
case 6:
|
|
||||||
case 7:
|
|
||||||
/* Button presses of button 4-7 are scroll events */
|
|
||||||
if (ev->evtype == XI_ButtonPress)
|
|
||||||
{
|
|
||||||
event->scroll.type = GDK_SCROLL;
|
|
||||||
|
|
||||||
if (xev->detail == 4)
|
if (xev->detail == 4)
|
||||||
event->scroll.direction = GDK_SCROLL_UP;
|
event->scroll.direction = GDK_SCROLL_UP;
|
||||||
else if (xev->detail == 5)
|
else if (xev->detail == 5)
|
||||||
event->scroll.direction = GDK_SCROLL_DOWN;
|
event->scroll.direction = GDK_SCROLL_DOWN;
|
||||||
else if (xev->detail == 6)
|
else if (xev->detail == 6)
|
||||||
event->scroll.direction = GDK_SCROLL_LEFT;
|
event->scroll.direction = GDK_SCROLL_LEFT;
|
||||||
else
|
else
|
||||||
event->scroll.direction = GDK_SCROLL_RIGHT;
|
event->scroll.direction = GDK_SCROLL_RIGHT;
|
||||||
|
|
||||||
event->scroll.window = window;
|
event->scroll.window = window;
|
||||||
event->scroll.time = xev->time;
|
event->scroll.time = xev->time;
|
||||||
event->scroll.x = (gdouble) xev->event_x;
|
event->scroll.x = (gdouble) xev->event_x;
|
||||||
event->scroll.y = (gdouble) xev->event_y;
|
event->scroll.y = (gdouble) xev->event_y;
|
||||||
event->scroll.x_root = (gdouble) xev->root_x;
|
event->scroll.x_root = (gdouble) xev->root_x;
|
||||||
event->scroll.y_root = (gdouble) xev->root_y;
|
event->scroll.y_root = (gdouble) xev->root_y;
|
||||||
|
|
||||||
event->scroll.device = g_hash_table_lookup (device_manager->id_table,
|
event->scroll.device = g_hash_table_lookup (device_manager->id_table,
|
||||||
GUINT_TO_POINTER (xev->deviceid));
|
GUINT_TO_POINTER (xev->deviceid));
|
||||||
|
|
||||||
source_device = g_hash_table_lookup (device_manager->id_table,
|
source_device = g_hash_table_lookup (device_manager->id_table,
|
||||||
GUINT_TO_POINTER (xev->sourceid));
|
GUINT_TO_POINTER (xev->sourceid));
|
||||||
gdk_event_set_source_device (event, source_device);
|
gdk_event_set_source_device (event, source_device);
|
||||||
|
|
||||||
event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
|
event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
|
||||||
break;
|
}
|
||||||
}
|
else
|
||||||
/* Button presses of button 4-7 are scroll events, so ignore the release */
|
{
|
||||||
else if (ev->evtype == XI_ButtonRelease)
|
#ifdef XINPUT_2_1
|
||||||
{
|
if (ev->evtype == XI_TouchBegin ||
|
||||||
return_val = FALSE;
|
ev->evtype == XI_TouchEnd)
|
||||||
break;
|
event->button.type = (ev->evtype == XI_TouchBegin) ? GDK_TOUCH_PRESS : GDK_TOUCH_RELEASE;
|
||||||
}
|
else
|
||||||
/* else (XI_ButtonRelease) fall thru */
|
#endif /* XINPUT_2_1 */
|
||||||
default:
|
event->button.type = (ev->evtype == XI_ButtonPress) ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE;
|
||||||
event->button.type = (ev->evtype == XI_ButtonPress) ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE;
|
|
||||||
|
|
||||||
event->button.window = window;
|
event->button.window = window;
|
||||||
event->button.time = xev->time;
|
event->button.time = xev->time;
|
||||||
@@ -1144,7 +1164,17 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
|
|||||||
}
|
}
|
||||||
|
|
||||||
event->button.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
|
event->button.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
|
||||||
event->button.button = xev->detail;
|
|
||||||
|
#ifdef XINPUT_2_1
|
||||||
|
if (ev->evtype == XI_TouchBegin ||
|
||||||
|
ev->evtype == XI_TouchEnd)
|
||||||
|
{
|
||||||
|
event->button.button = 1;
|
||||||
|
event->button.touch_id = xev->detail;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* XINPUT_2_1 */
|
||||||
|
event->button.button = xev->detail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (return_val == FALSE)
|
if (return_val == FALSE)
|
||||||
@@ -1161,11 +1191,32 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case XI_Motion:
|
case XI_Motion:
|
||||||
|
#ifdef XINPUT_2_1
|
||||||
|
case XI_TouchMotion:
|
||||||
|
case XI_TouchMotionUnowned:
|
||||||
|
/* FIXME: Unowned events should be rollback-able,
|
||||||
|
* the easiest way to go could be just storing the
|
||||||
|
* events so they can be replayed in arrival order
|
||||||
|
* when an ownership event arrives, needs further
|
||||||
|
* investigation though.
|
||||||
|
*/
|
||||||
|
#endif /* XINPUT_2_1 */
|
||||||
{
|
{
|
||||||
XIDeviceEvent *xev = (XIDeviceEvent *) ev;
|
XIDeviceEvent *xev = (XIDeviceEvent *) ev;
|
||||||
GdkDevice *source_device;
|
GdkDevice *source_device;
|
||||||
|
|
||||||
event->motion.type = GDK_MOTION_NOTIFY;
|
if (ev->evtype == XI_Motion)
|
||||||
|
{
|
||||||
|
event->motion.touch_id = 0;
|
||||||
|
event->motion.type = GDK_MOTION_NOTIFY;
|
||||||
|
}
|
||||||
|
#ifdef XINPUT_2_1
|
||||||
|
else
|
||||||
|
{
|
||||||
|
event->motion.touch_id = xev->detail;
|
||||||
|
event->motion.type = GDK_TOUCH_MOTION;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
event->motion.window = window;
|
event->motion.window = window;
|
||||||
|
|
||||||
@@ -1252,6 +1303,7 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
|
|||||||
|
|
||||||
return_val = FALSE;
|
return_val = FALSE;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return_val = FALSE;
|
return_val = FALSE;
|
||||||
break;
|
break;
|
||||||
@@ -1297,7 +1349,8 @@ gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator)
|
|||||||
GDK_BUTTON2_MOTION_MASK |
|
GDK_BUTTON2_MOTION_MASK |
|
||||||
GDK_BUTTON3_MOTION_MASK |
|
GDK_BUTTON3_MOTION_MASK |
|
||||||
GDK_BUTTON_MOTION_MASK |
|
GDK_BUTTON_MOTION_MASK |
|
||||||
GDK_FOCUS_CHANGE_MASK);
|
GDK_FOCUS_CHANGE_MASK |
|
||||||
|
GDK_TOUCH_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -1869,6 +1869,12 @@ gtk_main_do_event (GdkEvent *event)
|
|||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
case GDK_PROXIMITY_IN:
|
case GDK_PROXIMITY_IN:
|
||||||
case GDK_PROXIMITY_OUT:
|
case GDK_PROXIMITY_OUT:
|
||||||
|
case GDK_TOUCH_MOTION:
|
||||||
|
case GDK_TOUCH_PRESS:
|
||||||
|
case GDK_TOUCH_RELEASE:
|
||||||
|
case GDK_MULTITOUCH_ADDED:
|
||||||
|
case GDK_MULTITOUCH_REMOVED:
|
||||||
|
case GDK_MULTITOUCH_UPDATED:
|
||||||
gtk_propagate_event (grab_widget, event);
|
gtk_propagate_event (grab_widget, event);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1912,6 +1918,7 @@ gtk_main_do_event (GdkEvent *event)
|
|||||||
|| event->type == GDK_DRAG_ENTER
|
|| event->type == GDK_DRAG_ENTER
|
||||||
|| event->type == GDK_GRAB_BROKEN
|
|| event->type == GDK_GRAB_BROKEN
|
||||||
|| event->type == GDK_MOTION_NOTIFY
|
|| event->type == GDK_MOTION_NOTIFY
|
||||||
|
|| event->type == GDK_TOUCH_MOTION
|
||||||
|| event->type == GDK_SCROLL)
|
|| event->type == GDK_SCROLL)
|
||||||
{
|
{
|
||||||
_gtk_tooltip_handle_event (event);
|
_gtk_tooltip_handle_event (event);
|
||||||
|
@@ -471,6 +471,7 @@ enum {
|
|||||||
QUERY_TOOLTIP,
|
QUERY_TOOLTIP,
|
||||||
DRAG_FAILED,
|
DRAG_FAILED,
|
||||||
STYLE_UPDATED,
|
STYLE_UPDATED,
|
||||||
|
MULTITOUCH_EVENT,
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2844,6 +2845,15 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
|||||||
G_TYPE_BOOLEAN, 1,
|
G_TYPE_BOOLEAN, 1,
|
||||||
GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
|
GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
|
||||||
|
|
||||||
|
widget_signals[MULTITOUCH_EVENT] =
|
||||||
|
g_signal_new (I_("multitouch-event"),
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GtkWidgetClass, multitouch_event),
|
||||||
|
_gtk_boolean_handled_accumulator, NULL,
|
||||||
|
_gtk_marshal_BOOLEAN__BOXED,
|
||||||
|
G_TYPE_BOOLEAN, 1,
|
||||||
|
GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
|
||||||
/**
|
/**
|
||||||
* GtkWidget::query-tooltip:
|
* GtkWidget::query-tooltip:
|
||||||
* @widget: the object which received the signal
|
* @widget: the object which received the signal
|
||||||
@@ -5993,15 +6003,18 @@ gtk_widget_event_internal (GtkWidget *widget,
|
|||||||
case GDK_BUTTON_PRESS:
|
case GDK_BUTTON_PRESS:
|
||||||
case GDK_2BUTTON_PRESS:
|
case GDK_2BUTTON_PRESS:
|
||||||
case GDK_3BUTTON_PRESS:
|
case GDK_3BUTTON_PRESS:
|
||||||
|
case GDK_TOUCH_PRESS:
|
||||||
signal_num = BUTTON_PRESS_EVENT;
|
signal_num = BUTTON_PRESS_EVENT;
|
||||||
break;
|
break;
|
||||||
case GDK_SCROLL:
|
case GDK_SCROLL:
|
||||||
signal_num = SCROLL_EVENT;
|
signal_num = SCROLL_EVENT;
|
||||||
break;
|
break;
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
|
case GDK_TOUCH_RELEASE:
|
||||||
signal_num = BUTTON_RELEASE_EVENT;
|
signal_num = BUTTON_RELEASE_EVENT;
|
||||||
break;
|
break;
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
|
case GDK_TOUCH_MOTION:
|
||||||
signal_num = MOTION_NOTIFY_EVENT;
|
signal_num = MOTION_NOTIFY_EVENT;
|
||||||
break;
|
break;
|
||||||
case GDK_DELETE:
|
case GDK_DELETE:
|
||||||
@@ -6069,6 +6082,11 @@ gtk_widget_event_internal (GtkWidget *widget,
|
|||||||
case GDK_DAMAGE:
|
case GDK_DAMAGE:
|
||||||
signal_num = DAMAGE_EVENT;
|
signal_num = DAMAGE_EVENT;
|
||||||
break;
|
break;
|
||||||
|
case GDK_MULTITOUCH_ADDED:
|
||||||
|
case GDK_MULTITOUCH_REMOVED:
|
||||||
|
case GDK_MULTITOUCH_UPDATED:
|
||||||
|
signal_num = MULTITOUCH_EVENT;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
g_warning ("gtk_widget_event(): unhandled event type: %d", event->type);
|
g_warning ("gtk_widget_event(): unhandled event type: %d", event->type);
|
||||||
signal_num = -1;
|
signal_num = -1;
|
||||||
|
@@ -423,6 +423,10 @@ struct _GtkWidgetClass
|
|||||||
|
|
||||||
void (* style_updated) (GtkWidget *widget);
|
void (* style_updated) (GtkWidget *widget);
|
||||||
|
|
||||||
|
/* Multitouch */
|
||||||
|
gboolean (* multitouch_event) (GtkWidget *widget,
|
||||||
|
GdkEventMultiTouch *event);
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
|
|
||||||
/* Padding for future expansion */
|
/* Padding for future expansion */
|
||||||
@@ -433,7 +437,6 @@ struct _GtkWidgetClass
|
|||||||
void (*_gtk_reserved5) (void);
|
void (*_gtk_reserved5) (void);
|
||||||
void (*_gtk_reserved6) (void);
|
void (*_gtk_reserved6) (void);
|
||||||
void (*_gtk_reserved7) (void);
|
void (*_gtk_reserved7) (void);
|
||||||
void (*_gtk_reserved8) (void);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GtkWidgetAuxInfo
|
struct _GtkWidgetAuxInfo
|
||||||
|
Reference in New Issue
Block a user