diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c index bb4be5f6b2..5684247ca0 100644 --- a/gdk/gdkdisplay.c +++ b/gdk/gdkdisplay.c @@ -186,6 +186,7 @@ gdk_display_init (GdkDisplay *display) display->double_click_time = 250; display->double_click_distance = 5; + display->touch_implicit_grabs = g_array_new (FALSE, FALSE, sizeof (GdkTouchGrabInfo)); display->device_grabs = g_hash_table_new (NULL, NULL); display->motion_hint_info = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_free); @@ -234,6 +235,8 @@ gdk_display_finalize (GObject *object) NULL); g_hash_table_destroy (display->device_grabs); + g_array_free (display->touch_implicit_grabs, TRUE); + g_hash_table_destroy (display->motion_hint_info); g_hash_table_destroy (display->pointers_info); g_hash_table_destroy (display->multiple_click_info); @@ -692,6 +695,79 @@ _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); + g_array_remove_index_fast (display->touch_implicit_grabs, i); + } + else + i++; + } +} + +void +_gdk_display_add_touch_grab (GdkDisplay *display, + GdkDevice *device, + GdkEventSequence *sequence, + GdkWindow *window, + GdkWindow *native_window, + GdkEventMask event_mask, + unsigned long serial, + guint32 time) +{ + GdkTouchGrabInfo info; + + info.device = device; + info.sequence = sequence; + info.window = g_object_ref (window); + info.native_window = g_object_ref (native_window); + info.serial = serial; + info.event_mask = event_mask; + info.time = time; + + g_array_append_val (display->touch_implicit_grabs, info); +} + +gboolean +_gdk_display_end_touch_grab (GdkDisplay *display, + GdkDevice *device, + GdkEventSequence *sequence) +{ + guint i; + + for (i = 0; i < display->touch_implicit_grabs->len; i++) + { + GdkTouchGrabInfo *info; + + info = &g_array_index (display->touch_implicit_grabs, + GdkTouchGrabInfo, i); + + if (info->device == device && info->sequence == sequence) + { + g_array_remove_index_fast (display->touch_implicit_grabs, i); + return TRUE; + } + } + + return FALSE; +} + /* _gdk_synthesize_crossing_events only works inside one toplevel. This function splits things into two calls if needed, converting the coordinates to the right toplevel */ @@ -1037,6 +1113,33 @@ _gdk_display_has_device_grab (GdkDisplay *display, return NULL; } +GdkTouchGrabInfo * +_gdk_display_has_touch_grab (GdkDisplay *display, + GdkDevice *device, + GdkEventSequence *sequence, + gulong serial) +{ + guint i; + + for (i = 0; i < display->touch_implicit_grabs->len; i++) + { + GdkTouchGrabInfo *info; + + info = &g_array_index (display->touch_implicit_grabs, + GdkTouchGrabInfo, i); + + if (info->device == device && info->sequence == sequence) + { + if (serial >= info->serial) + return info; + else + return NULL; + } + } + + return NULL; +} + /* Returns true if last grab was ended * If if_child is non-NULL, end the grab only if the grabbed * window is the same as if_child or a descendant of it */ diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h index 62c2cc067b..8713cf7be3 100644 --- a/gdk/gdkdisplayprivate.h +++ b/gdk/gdkdisplayprivate.h @@ -58,6 +58,19 @@ typedef struct guint implicit : 1; } GdkDeviceGrabInfo; +/* Tracks information about a touch implicit grab on this display */ +typedef struct +{ + GdkDevice *device; + GdkEventSequence *sequence; + + GdkWindow *window; + GdkWindow *native_window; + gulong serial; + guint event_mask; + guint32 time; +} GdkTouchGrabInfo; + /* Tracks information about which window and position the pointer last was in. * This is useful when we need to synthesize events later. * Note that we track toplevel_under_pointer using enter/leave events, @@ -103,6 +116,7 @@ struct _GdkDisplay guint closed : 1; /* Whether this display has been closed */ guint ignore_core_events : 1; /* Don't send core motion and button event */ + GArray *touch_implicit_grabs; GHashTable *device_grabs; GHashTable *motion_hint_info; GdkDeviceManager *device_manager; @@ -260,6 +274,21 @@ gboolean _gdk_display_end_device_grab (GdkDisplay *display gboolean _gdk_display_check_grab_ownership (GdkDisplay *display, GdkDevice *device, gulong serial); +void _gdk_display_add_touch_grab (GdkDisplay *display, + GdkDevice *device, + GdkEventSequence *sequence, + GdkWindow *window, + GdkWindow *native_window, + GdkEventMask event_mask, + unsigned long serial_start, + guint32 time); +GdkTouchGrabInfo * _gdk_display_has_touch_grab (GdkDisplay *display, + GdkDevice *device, + GdkEventSequence *sequence, + gulong serial); +gboolean _gdk_display_end_touch_grab (GdkDisplay *display, + GdkDevice *device, + GdkEventSequence *sequence); void _gdk_display_enable_motion_hints (GdkDisplay *display, GdkDevice *device); GdkPointerWindowInfo * _gdk_display_get_pointer_info (GdkDisplay *display,