[gtk+/multitouch: 101/123] gdk,csw: handle implicit touch grabs
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/multitouch: 101/123] gdk,csw: handle implicit touch grabs
- Date: Mon, 16 Jan 2012 18:50:44 +0000 (UTC)
commit 61ff62b31f16f923590273f06f5b33063e5c8c10
Author: Carlos Garnacho <carlosg gnome org>
Date: Thu Dec 29 00:06:45 2011 +0100
gdk,csw: handle implicit touch grabs
If the touch sequence happens on a window with GDK_TOUCH_MASK set,
a GdkTouchGrabInfo is created to back it up. Else a device grab is
only created if the sequence emulates the pointer.
If both a device and a touch grab are present on a window, the later
of them both is obeyed, Any grab on the device happening after a
touch grab generates grab broken on all the windows an implicit
touch grab was going on, and all touches would be automatically
removed from every touch cluster.
gdk/gdkdisplay.c | 38 +++++++++++-
gdk/gdkinternals.h | 3 +
gdk/gdkwindow.c | 156 ++++++++++++++++++++++++++++++++++++++++------------
3 files changed, 157 insertions(+), 40 deletions(-)
---
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index 10b2462..a1f322f 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -697,6 +697,33 @@ _gdk_display_add_device_grab (GdkDisplay *display,
return info;
}
+static void
+_gdk_display_break_touch_grabs (GdkDisplay *display,
+ GdkDevice *device,
+ GdkWindow *new_grab_window)
+{
+ guint i = 0;
+
+ while (i < display->touch_implicit_grabs->len)
+ {
+ GdkTouchGrabInfo *info;
+
+ info = &g_array_index (display->touch_implicit_grabs,
+ GdkTouchGrabInfo, i);
+
+ if (info->device == device &&
+ info->window != new_grab_window)
+ {
+ generate_grab_broken_event (GDK_WINDOW (info->window),
+ device, TRUE, new_grab_window);
+ _gdk_window_finish_touch_id (info->window, device, info->touch_id);
+ g_array_remove_index_fast (display->touch_implicit_grabs, i);
+ }
+ else
+ i++;
+ }
+}
+
void
_gdk_display_add_touch_grab (GdkDisplay *display,
GdkDevice *device,
@@ -1025,12 +1052,15 @@ _gdk_display_device_grab_update (GdkDisplay *display,
next_grab = NULL; /* Actually its not yet active */
}
+ if (next_grab)
+ _gdk_display_break_touch_grabs (display, device, next_grab->window);
+
if ((next_grab == NULL && current_grab->implicit_ungrab) ||
- (next_grab != NULL && current_grab->window != next_grab->window))
- generate_grab_broken_event (GDK_WINDOW (current_grab->window),
+ (next_grab != NULL && current_grab->window != next_grab->window))
+ generate_grab_broken_event (GDK_WINDOW (current_grab->window),
device,
- current_grab->implicit,
- next_grab? next_grab->window : NULL);
+ current_grab->implicit,
+ next_grab? next_grab->window : NULL);
/* Remove old grab */
grabs = g_list_delete_link (grabs, grabs);
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index 150c909..50537e8 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -334,6 +334,9 @@ gboolean _gdk_window_update_viewable (GdkWindow *window);
void _gdk_window_process_updates_recurse (GdkWindow *window,
cairo_region_t *expose_region);
+gboolean _gdk_window_finish_touch_id (GdkWindow *window,
+ GdkDevice *device,
+ guint touch_id);
void _gdk_screen_close (GdkScreen *screen);
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 4368052..82ea271 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -9200,18 +9200,37 @@ _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
static GdkWindow *
get_event_window (GdkDisplay *display,
GdkDevice *device,
- GdkWindow *pointer_window,
- GdkEventType type,
- GdkModifierType mask,
- guint *evmask_out,
- gulong serial)
+ guint touch_id,
+ GdkWindow *pointer_window,
+ GdkEventType type,
+ GdkModifierType mask,
+ guint *evmask_out,
+ gulong serial)
{
guint evmask;
GdkWindow *grab_window;
GdkDeviceGrabInfo *grab;
+ GdkTouchGrabInfo *touch_grab;
+ touch_grab = _gdk_display_has_touch_grab (display, device, touch_id, serial);
grab = _gdk_display_has_device_grab (display, device, serial);
+ if (touch_grab != NULL &&
+ (!grab || grab->implicit || touch_grab->serial >= grab->serial_start))
+ {
+ evmask = touch_grab->event_mask;
+ evmask = update_evmask_for_button_motion (evmask, mask);
+
+ if (evmask & type_masks[type])
+ {
+ if (evmask_out)
+ *evmask_out = evmask;
+ return touch_grab->window;
+ }
+ else
+ return NULL;
+ }
+
if (grab != NULL && !grab->owner_events)
{
evmask = grab->event_mask;
@@ -9384,6 +9403,24 @@ _gdk_window_lookup_touch_cluster (GdkWindow *window,
return info->cluster;
}
+gboolean
+_gdk_window_finish_touch_id (GdkWindow *window,
+ GdkDevice *device,
+ guint touch_id)
+{
+ TouchEventInfo *info;
+
+ info = touch_event_info_lookup (window, device, touch_id, FALSE);
+
+ if (info)
+ {
+ gdk_touch_cluster_remove_touch (info->cluster, touch_id);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static gboolean
proxy_pointer_event (GdkDisplay *display,
GdkEvent *source_event,
@@ -9536,9 +9573,14 @@ proxy_pointer_event (GdkDisplay *display,
GdkWindow *event_win;
guint evmask;
gboolean is_hint;
+ guint touch_id;
+
+ if (!gdk_event_get_touch_id (source_event, &touch_id))
+ touch_id = 0;
event_win = get_event_window (display,
device,
+ touch_id,
pointer_window,
source_event->type,
state,
@@ -9670,6 +9712,7 @@ proxy_button_event (GdkEvent *source_event,
GdkWindow *w;
GdkDevice *device, *source_device;
GdkEventMask evmask;
+ guint touch_id;
type = source_event->any.type;
event_window = source_event->any.window;
@@ -9683,10 +9726,14 @@ proxy_button_event (GdkEvent *source_event,
toplevel_x, toplevel_y,
&toplevel_x, &toplevel_y);
+ if (!gdk_event_get_touch_id (source_event, &touch_id))
+ touch_id = 0;
+
pointer_info = _gdk_display_get_pointer_info (display, device);
*handle_ungrab = TRUE;
- if (type == GDK_BUTTON_PRESS &&
+ if ((type == GDK_BUTTON_PRESS ||
+ type == GDK_TOUCH_PRESS) &&
!source_event->any.send_event &&
_gdk_display_has_device_grab (display, device, serial) == NULL)
{
@@ -9701,23 +9748,49 @@ proxy_button_event (GdkEvent *source_event,
(parent = get_event_parent (w)) != NULL &&
parent->window_type != GDK_WINDOW_ROOT)
{
- if (w->event_mask & GDK_BUTTON_PRESS_MASK)
+ if (w->event_mask & GDK_BUTTON_PRESS_MASK &&
+ (type == GDK_BUTTON_PRESS ||
+ _gdk_event_get_pointer_emulated (source_event)))
break;
+
+ if (type == GDK_TOUCH_PRESS &&
+ w->event_mask & GDK_TOUCH_MASK)
+ break;
+
w = parent;
}
- pointer_window = (GdkWindow *)w;
-
- _gdk_display_add_device_grab (display,
- device,
- pointer_window,
- event_window,
- GDK_OWNERSHIP_NONE,
- FALSE,
- gdk_window_get_events (pointer_window),
- serial,
- time_,
- TRUE);
- _gdk_display_device_grab_update (display, device, source_device, serial);
+ pointer_window = w;
+
+ if (pointer_window)
+ {
+ if (type == GDK_TOUCH_PRESS &&
+ pointer_window->event_mask & GDK_TOUCH_MASK)
+ {
+ guint touch_id;
+
+ gdk_event_get_touch_id (source_event, &touch_id);
+ _gdk_display_add_touch_grab (display, device, touch_id,
+ pointer_window, event_window,
+ gdk_window_get_events (pointer_window),
+ serial, time_);
+ }
+ else if (type == GDK_BUTTON_PRESS ||
+ _gdk_event_get_pointer_emulated (source_event))
+ {
+ _gdk_display_add_device_grab (display,
+ device,
+ pointer_window,
+ event_window,
+ GDK_OWNERSHIP_NONE,
+ FALSE,
+ gdk_window_get_events (pointer_window),
+ serial,
+ time_,
+ TRUE);
+ _gdk_display_device_grab_update (display, device,
+ source_device, serial);
+ }
+ }
}
pointer_window = get_pointer_window (display, toplevel_window, device,
@@ -9726,9 +9799,10 @@ proxy_button_event (GdkEvent *source_event,
event_win = get_event_window (display,
device,
- pointer_window,
- type, state,
- &evmask, serial);
+ touch_id,
+ pointer_window,
+ type, state,
+ &evmask, serial);
if (event_win == NULL || display->ignore_core_events)
return TRUE;
@@ -9838,9 +9912,6 @@ proxy_button_event (GdkEvent *source_event,
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),
@@ -10098,16 +10169,29 @@ _gdk_windowing_got_event (GdkDisplay *display,
event->type == GDK_TOUCH_RELEASE) &&
!event->any.send_event)
{
- button_release_grab =
- _gdk_display_has_device_grab (display, device, serial);
- if (button_release_grab &&
- button_release_grab->implicit &&
- (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
- {
- button_release_grab->serial_end = serial;
- button_release_grab->implicit_ungrab = FALSE;
- _gdk_display_device_grab_update (display, device, source_device, serial);
- }
+ guint touch_id;
+
+ if (event->type == GDK_TOUCH_RELEASE &&
+ gdk_event_get_touch_id (event, &touch_id))
+ {
+ _gdk_display_end_touch_grab (display, device, touch_id);
+ }
+
+ if (event->type == GDK_BUTTON_RELEASE ||
+ _gdk_event_get_pointer_emulated (event))
+ {
+ button_release_grab =
+ _gdk_display_has_device_grab (display, device, serial);
+
+ if (button_release_grab &&
+ button_release_grab->implicit &&
+ (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
+ {
+ button_release_grab->serial_end = serial;
+ button_release_grab->implicit_ungrab = FALSE;
+ _gdk_display_device_grab_update (display, device, source_device, serial);
+ }
+ }
}
out:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]