forked from AuroraMiddleware/gtk
gdk: 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.
This commit is contained in:
parent
b5cfdf2db4
commit
c72a77b04c
@ -1049,12 +1049,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);
|
||||
|
208
gdk/gdkwindow.c
208
gdk/gdkwindow.c
@ -8156,6 +8156,8 @@ is_button_type (GdkEventType type)
|
||||
type == GDK_2BUTTON_PRESS ||
|
||||
type == GDK_3BUTTON_PRESS ||
|
||||
type == GDK_BUTTON_RELEASE ||
|
||||
type == GDK_TOUCH_BEGIN ||
|
||||
type == GDK_TOUCH_END ||
|
||||
type == GDK_SCROLL;
|
||||
}
|
||||
|
||||
@ -8163,6 +8165,7 @@ static gboolean
|
||||
is_motion_type (GdkEventType type)
|
||||
{
|
||||
return type == GDK_MOTION_NOTIFY ||
|
||||
type == GDK_TOUCH_UPDATE ||
|
||||
type == GDK_ENTER_NOTIFY ||
|
||||
type == GDK_LEAVE_NOTIFY;
|
||||
}
|
||||
@ -9109,18 +9112,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)
|
||||
GdkEventSequence *sequence,
|
||||
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, sequence, 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;
|
||||
@ -9320,14 +9342,19 @@ proxy_pointer_event (GdkDisplay *display,
|
||||
serial, non_linear);
|
||||
_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_UPDATE)
|
||||
{
|
||||
GdkWindow *event_win;
|
||||
guint evmask;
|
||||
gboolean is_hint;
|
||||
GdkEventSequence *sequence;
|
||||
|
||||
sequence = gdk_event_get_event_sequence (source_event);
|
||||
|
||||
event_win = get_event_window (display,
|
||||
device,
|
||||
sequence,
|
||||
pointer_window,
|
||||
source_event->type,
|
||||
state,
|
||||
@ -9351,6 +9378,7 @@ proxy_pointer_event (GdkDisplay *display,
|
||||
toplevel_x, toplevel_y,
|
||||
state, time_, NULL,
|
||||
serial, FALSE);
|
||||
|
||||
is_hint = FALSE;
|
||||
|
||||
if (event_win &&
|
||||
@ -9371,21 +9399,34 @@ proxy_pointer_event (GdkDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
if (event_win && !display->ignore_core_events)
|
||||
{
|
||||
event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
|
||||
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;
|
||||
if (!event_win)
|
||||
return TRUE;
|
||||
|
||||
if (!display->ignore_core_events)
|
||||
{
|
||||
GdkEventType event_type;
|
||||
|
||||
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,
|
||||
sizeof (gdouble) * gdk_device_get_n_axes (source_event->motion.device));
|
||||
gdk_event_set_source_device (event, source_device);
|
||||
|
||||
/* Just insert the event */
|
||||
_gdk_event_queue_insert_after (gdk_window_get_display (event_win),
|
||||
source_event, event);
|
||||
}
|
||||
}
|
||||
|
||||
@ -9417,6 +9458,8 @@ proxy_button_event (GdkEvent *source_event,
|
||||
GdkDisplay *display;
|
||||
GdkWindow *w;
|
||||
GdkDevice *device, *source_device;
|
||||
GdkEventMask evmask;
|
||||
GdkEventSequence *sequence;
|
||||
|
||||
type = source_event->any.type;
|
||||
event_window = source_event->any.window;
|
||||
@ -9429,9 +9472,13 @@ proxy_button_event (GdkEvent *source_event,
|
||||
toplevel_window = convert_native_coords_to_toplevel (event_window,
|
||||
toplevel_x, toplevel_y,
|
||||
&toplevel_x, &toplevel_y);
|
||||
|
||||
sequence = gdk_event_get_event_sequence (source_event);
|
||||
|
||||
pointer_info = _gdk_display_get_pointer_info (display, device);
|
||||
|
||||
if (type == GDK_BUTTON_PRESS &&
|
||||
if ((type == GDK_BUTTON_PRESS ||
|
||||
type == GDK_TOUCH_BEGIN) &&
|
||||
!source_event->any.send_event &&
|
||||
_gdk_display_has_device_grab (display, device, serial) == NULL)
|
||||
{
|
||||
@ -9446,23 +9493,46 @@ 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_BEGIN &&
|
||||
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_BEGIN &&
|
||||
pointer_window->event_mask & GDK_TOUCH_MASK)
|
||||
{
|
||||
_gdk_display_add_touch_grab (display, device, sequence,
|
||||
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,
|
||||
@ -9471,9 +9541,10 @@ proxy_button_event (GdkEvent *source_event,
|
||||
|
||||
event_win = get_event_window (display,
|
||||
device,
|
||||
pointer_window,
|
||||
type, state,
|
||||
NULL, serial);
|
||||
sequence,
|
||||
pointer_window,
|
||||
type, state,
|
||||
&evmask, serial);
|
||||
|
||||
if (event_win == NULL || display->ignore_core_events)
|
||||
return TRUE;
|
||||
@ -9523,7 +9594,6 @@ proxy_button_event (GdkEvent *source_event,
|
||||
event->button.device = source_event->button.device;
|
||||
event->button.axes = g_memdup (source_event->button.axes,
|
||||
sizeof (gdouble) * gdk_device_get_n_axes (source_event->button.device));
|
||||
|
||||
gdk_event_set_source_device (event, source_device);
|
||||
|
||||
if (type == GDK_BUTTON_PRESS)
|
||||
@ -9547,6 +9617,40 @@ proxy_button_event (GdkEvent *source_event,
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case GDK_TOUCH_BEGIN:
|
||||
case GDK_TOUCH_END:
|
||||
convert_toplevel_coords_to_window (event_win,
|
||||
toplevel_x, toplevel_y,
|
||||
&event->button.x, &event->button.y);
|
||||
event->touch.x_root = source_event->touch.x_root;
|
||||
event->touch.y_root = source_event->touch.y_root;
|
||||
event->touch.state = state;
|
||||
event->touch.device = source_event->touch.device;
|
||||
event->touch.axes = g_memdup (source_event->touch.axes,
|
||||
sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
|
||||
event->touch.sequence = source_event->touch.sequence;
|
||||
|
||||
gdk_event_set_source_device (event, source_device);
|
||||
|
||||
if ((type == GDK_TOUCH_END &&
|
||||
_gdk_event_get_pointer_emulated (source_event)) &&
|
||||
pointer_window == pointer_info->window_under_pointer &&
|
||||
gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN)
|
||||
{
|
||||
/* Synthesize a leave notify event
|
||||
* whenever a touch device is released
|
||||
*/
|
||||
pointer_info->need_touch_press_enter = TRUE;
|
||||
_gdk_synthesize_crossing_events (display,
|
||||
pointer_window, NULL,
|
||||
device, source_device,
|
||||
GDK_CROSSING_TOUCH_END,
|
||||
toplevel_x, toplevel_y,
|
||||
state, time_, NULL,
|
||||
serial, FALSE);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case GDK_SCROLL:
|
||||
event->scroll.direction = source_event->scroll.direction;
|
||||
convert_toplevel_coords_to_window (event_win,
|
||||
@ -9804,16 +9908,32 @@ _gdk_windowing_got_event (GdkDisplay *display,
|
||||
else if (is_button_type (event->type))
|
||||
unlink_event = proxy_button_event (event, serial);
|
||||
|
||||
if (event->type == GDK_BUTTON_RELEASE && !event->any.send_event)
|
||||
if ((event->type == GDK_BUTTON_RELEASE ||
|
||||
event->type == GDK_TOUCH_END) &&
|
||||
!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)
|
||||
GdkEventSequence *sequence;
|
||||
|
||||
sequence = gdk_event_get_event_sequence (event);
|
||||
if (event->type == GDK_TOUCH_END && sequence)
|
||||
{
|
||||
button_release_grab->serial_end = serial;
|
||||
button_release_grab->implicit_ungrab = FALSE;
|
||||
_gdk_display_device_grab_update (display, device, source_device, serial);
|
||||
_gdk_display_end_touch_grab (display, device, sequence);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1339,6 +1339,14 @@ rewrite_event_for_window (GdkEvent *event,
|
||||
new_window,
|
||||
&event->motion.x, &event->motion.y);
|
||||
break;
|
||||
case GDK_TOUCH_BEGIN:
|
||||
case GDK_TOUCH_UPDATE:
|
||||
case GDK_TOUCH_END:
|
||||
case GDK_TOUCH_CANCEL:
|
||||
rewrite_events_translate (event->any.window,
|
||||
new_window,
|
||||
&event->touch.x, &event->touch.y);
|
||||
break;
|
||||
case GDK_KEY_PRESS:
|
||||
case GDK_KEY_RELEASE:
|
||||
case GDK_PROXIMITY_IN:
|
||||
@ -1384,6 +1392,10 @@ rewrite_event_for_grabs (GdkEvent *event)
|
||||
case GDK_PROXIMITY_OUT:
|
||||
case GDK_KEY_PRESS:
|
||||
case GDK_KEY_RELEASE:
|
||||
case GDK_TOUCH_BEGIN:
|
||||
case GDK_TOUCH_UPDATE:
|
||||
case GDK_TOUCH_END:
|
||||
case GDK_TOUCH_CANCEL:
|
||||
display = gdk_window_get_display (event->any.window);
|
||||
device = gdk_event_get_device (event);
|
||||
|
||||
@ -1643,6 +1655,7 @@ gtk_main_do_event (GdkEvent *event)
|
||||
case GDK_BUTTON_PRESS:
|
||||
case GDK_2BUTTON_PRESS:
|
||||
case GDK_3BUTTON_PRESS:
|
||||
case GDK_TOUCH_BEGIN:
|
||||
if (!_gtk_propagate_captured_event (grab_widget, event, topmost_widget))
|
||||
gtk_propagate_event (grab_widget, event);
|
||||
break;
|
||||
@ -1693,6 +1706,9 @@ gtk_main_do_event (GdkEvent *event)
|
||||
case GDK_BUTTON_RELEASE:
|
||||
case GDK_PROXIMITY_IN:
|
||||
case GDK_PROXIMITY_OUT:
|
||||
case GDK_TOUCH_UPDATE:
|
||||
case GDK_TOUCH_END:
|
||||
case GDK_TOUCH_CANCEL:
|
||||
if (!_gtk_propagate_captured_event (grab_widget, event, topmost_widget))
|
||||
gtk_propagate_event (grab_widget, event);
|
||||
break;
|
||||
@ -1743,6 +1759,7 @@ gtk_main_do_event (GdkEvent *event)
|
||||
|| event->type == GDK_DRAG_ENTER
|
||||
|| event->type == GDK_GRAB_BROKEN
|
||||
|| event->type == GDK_MOTION_NOTIFY
|
||||
|| event->type == GDK_TOUCH_UPDATE
|
||||
|| event->type == GDK_SCROLL)
|
||||
{
|
||||
_gtk_tooltip_handle_event (event);
|
||||
|
Loading…
Reference in New Issue
Block a user