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.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
154
gdk/gdkwindow.c
154
gdk/gdkwindow.c
@@ -9206,18 +9206,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;
|
||||
@@ -9390,6 +9409,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,
|
||||
@@ -9542,9 +9579,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,
|
||||
@@ -9676,6 +9718,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;
|
||||
@@ -9689,10 +9732,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)
|
||||
{
|
||||
@@ -9707,23 +9754,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;
|
||||
pointer_window = 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);
|
||||
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,
|
||||
@@ -9732,9 +9805,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;
|
||||
@@ -9844,9 +9918,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),
|
||||
@@ -10104,16 +10175,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:
|
||||
|
||||
Reference in New Issue
Block a user