[gtk+/touch-for-3.4-2: 32/44] gdk: handle implicit touch grabs
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/touch-for-3.4-2: 32/44] gdk: handle implicit touch grabs
- Date: Thu, 1 Mar 2012 20:28:52 +0000 (UTC)
commit 8e9f61669700f8aa26a2ad428f5a4d030dcf0595
Author: Carlos Garnacho <carlosg gnome org>
Date: Thu Dec 29 00:06:45 2011 +0100
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.
gdk/gdkdisplay.c | 11 ++-
gdk/gdkwindow.c | 210 ++++++++++++++++++++++++++++++++++++++++++------------
gtk/gtkmain.c | 17 +++++
3 files changed, 189 insertions(+), 49 deletions(-)
---
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index 5684247..b62b810 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -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);
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index a0d6749..1f95ea7 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -8152,6 +8152,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;
}
@@ -8159,6 +8161,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;
}
@@ -9105,18 +9108,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;
@@ -9316,14 +9338,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,
@@ -9347,6 +9374,7 @@ proxy_pointer_event (GdkDisplay *display,
toplevel_x, toplevel_y,
state, time_, NULL,
serial, FALSE);
+
is_hint = FALSE;
if (event_win &&
@@ -9367,21 +9395,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);
}
}
@@ -9413,6 +9454,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;
@@ -9425,9 +9468,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)
{
@@ -9442,23 +9489,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;
-
- _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_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,
@@ -9467,9 +9537,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;
@@ -9519,7 +9590,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)
@@ -9543,6 +9613,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,
@@ -9800,16 +9904,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)
+ {
+ _gdk_display_end_touch_grab (display, device, sequence);
+ }
+
+ if (event->type == GDK_BUTTON_RELEASE ||
+ _gdk_event_get_pointer_emulated (event))
{
- button_release_grab->serial_end = serial;
- button_release_grab->implicit_ungrab = FALSE;
- _gdk_display_device_grab_update (display, device, source_device, serial);
+ 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);
+ }
}
}
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 68ecbfe..65df934 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]