summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2010-07-02 13:40:08 +0200
committerCarlos Garnacho <carlosg@gnome.org>2010-07-02 13:43:47 +0200
commitd5dda9a2f09ed2133fb1cd8c61ebf33f6127a924 (patch)
tree64469414f51164b49a7cd8887df33f0ddfa9b9e6
parentab8242c522fa80387538c32ec1d3f2a4397b4b49 (diff)
downloadgtk+-xi2-playground.tar.gz
Add gdk_event_[gs]et_source_device().xi2-playground
This function may be used to know the hardware device that triggered an event, it could resort to the master device in the few cases there's not a direct hardware device to relate to the event (i.e.: crossing events due to grabs)
-rw-r--r--gdk/gdkdisplay.c19
-rw-r--r--gdk/gdkevents.c60
-rw-r--r--gdk/gdkevents.h3
-rw-r--r--gdk/gdkinternals.h3
-rw-r--r--gdk/gdkwindow.c45
-rw-r--r--gdk/x11/gdkdevicemanager-xi2.c39
-rw-r--r--gdk/x11/gdkdisplay-x11.c2
-rw-r--r--gdk/x11/gdkmain-x11.c2
8 files changed, 140 insertions, 33 deletions
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index 0b91f88b97..a1daa56e23 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -1250,6 +1250,7 @@ _gdk_display_add_device_grab (GdkDisplay *display,
static void
synthesize_crossing_events (GdkDisplay *display,
GdkDevice *device,
+ GdkDevice *source_device,
GdkWindow *src_window,
GdkWindow *dest_window,
GdkCrossingMode crossing_mode,
@@ -1285,7 +1286,7 @@ synthesize_crossing_events (GdkDisplay *display,
_gdk_synthesize_crossing_events (display,
src_window,
dest_window,
- device,
+ device, source_device,
crossing_mode,
x, y, state,
time,
@@ -1299,7 +1300,7 @@ synthesize_crossing_events (GdkDisplay *display,
_gdk_synthesize_crossing_events (display,
src_window,
NULL,
- device,
+ device, source_device,
crossing_mode,
x, y, state,
time,
@@ -1314,7 +1315,7 @@ synthesize_crossing_events (GdkDisplay *display,
_gdk_synthesize_crossing_events (display,
src_window,
NULL,
- device,
+ device, source_device,
crossing_mode,
x, y, state,
time,
@@ -1325,7 +1326,7 @@ synthesize_crossing_events (GdkDisplay *display,
_gdk_synthesize_crossing_events (display,
NULL,
dest_window,
- device,
+ device, source_device,
crossing_mode,
x, y, state,
time,
@@ -1362,6 +1363,7 @@ get_current_toplevel (GdkDisplay *display,
static void
switch_to_pointer_grab (GdkDisplay *display,
GdkDevice *device,
+ GdkDevice *source_device,
GdkDeviceGrabInfo *grab,
GdkDeviceGrabInfo *last_grab,
guint32 time,
@@ -1397,7 +1399,7 @@ switch_to_pointer_grab (GdkDisplay *display,
src_window = info->window_under_pointer;
if (src_window != grab->window)
- synthesize_crossing_events (display, device,
+ synthesize_crossing_events (display, device, source_device,
src_window, grab->window,
GDK_CROSSING_GRAB, time, serial);
@@ -1448,7 +1450,7 @@ switch_to_pointer_grab (GdkDisplay *display,
}
if (pointer_window != last_grab->window)
- synthesize_crossing_events (display, device,
+ synthesize_crossing_events (display, device, source_device,
last_grab->window, pointer_window,
GDK_CROSSING_UNGRAB, time, serial);
@@ -1463,6 +1465,7 @@ switch_to_pointer_grab (GdkDisplay *display,
void
_gdk_display_device_grab_update (GdkDisplay *display,
GdkDevice *device,
+ GdkDevice *source_device,
gulong current_serial)
{
GdkDeviceGrabInfo *current_grab, *next_grab;
@@ -1487,7 +1490,7 @@ _gdk_display_device_grab_update (GdkDisplay *display,
if (!current_grab->activated)
{
if (device->source != GDK_SOURCE_KEYBOARD)
- switch_to_pointer_grab (display, device, current_grab, NULL, time, current_serial);
+ switch_to_pointer_grab (display, device, source_device, current_grab, NULL, time, current_serial);
}
break;
@@ -1515,7 +1518,7 @@ _gdk_display_device_grab_update (GdkDisplay *display,
g_hash_table_insert (display->device_grabs, device, grabs);
if (device->source != GDK_SOURCE_KEYBOARD)
- switch_to_pointer_grab (display, device,
+ switch_to_pointer_grab (display, device, source_device,
next_grab, current_grab,
time, current_serial);
diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c
index 470c9e9fe4..78eae5ef4e 100644
--- a/gdk/gdkevents.c
+++ b/gdk/gdkevents.c
@@ -1054,6 +1054,66 @@ gdk_event_get_device (const GdkEvent *event)
}
/**
+ * gdk_event_set_source_device:
+ * @event: a #GdkEvent
+ * @device: a #GdkDevice
+ *
+ * Sets the slave device for @event to @device. The event
+ * must have been allocated by GTK+, for instance, by
+ * gdk_event_copy().
+ *
+ * Since: 3.0
+ **/
+void
+gdk_event_set_source_device (GdkEvent *event,
+ GdkDevice *device)
+{
+ GdkEventPrivate *private;
+
+ g_return_if_fail (gdk_event_is_allocated (event));
+ g_return_if_fail (GDK_IS_DEVICE (device));
+
+ private = (GdkEventPrivate *) event;
+
+ private->source_device = device;
+}
+
+/**
+ * gdk_event_get_source_device:
+ * @event: a #GdkEvent
+ *
+ * This function returns the hardware (slave) #GdkDevice that has triggered the event,
+ * falling back to the virtual (master) device (as in gdk_event_get_device()) if the
+ * event wasn't caused by interaction with a hardware device. This may happen for
+ * example in synthesized crossing events after a #GdkWindow updates its geometry or
+ * a grab is acquired/released.
+ *
+ * If the event does not contain device field, this function will return %NULL.
+ *
+ * Returns: a #GdkDevice, or %NULL.
+ *
+ * Since: 3.0
+ **/
+GdkDevice *
+gdk_event_get_source_device (const GdkEvent *event)
+{
+ GdkEventPrivate *private;
+
+ g_return_val_if_fail (event != NULL, NULL);
+
+ if (!gdk_event_is_allocated (event))
+ return NULL;
+
+ private = (GdkEventPrivate *) event;
+
+ if (private->source_device)
+ return private->source_device;
+
+ /* Fallback to event device */
+ return gdk_event_get_device (event);
+}
+
+/**
* gdk_event_request_motions:
* @event: a valid #GdkEvent
*
diff --git a/gdk/gdkevents.h b/gdk/gdkevents.h
index 8e7735090f..70340c1393 100644
--- a/gdk/gdkevents.h
+++ b/gdk/gdkevents.h
@@ -543,6 +543,9 @@ gboolean gdk_event_get_axis (const GdkEvent *event,
void gdk_event_set_device (GdkEvent *event,
GdkDevice *device);
GdkDevice* gdk_event_get_device (const GdkEvent *event);
+void gdk_event_set_source_device (GdkEvent *event,
+ GdkDevice *device);
+GdkDevice* gdk_event_get_source_device (const GdkEvent *event);
void gdk_event_request_motions (const GdkEventMotion *event);
gboolean gdk_events_get_distance (GdkEvent *event1,
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index e31ff9a014..561212b4b5 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -158,6 +158,7 @@ struct _GdkEventPrivate
GdkScreen *screen;
gpointer windowing_data;
GdkDevice *device;
+ GdkDevice *source_device;
};
/* Tracks information about the pointer grab on this display */
@@ -597,6 +598,7 @@ void _gdk_windowing_launch_failed (GAppLaunchContext *context,
void _gdk_display_device_grab_update (GdkDisplay *display,
GdkDevice *device,
+ GdkDevice *source_device,
gulong current_serial);
GdkDeviceGrabInfo *_gdk_display_get_last_device_grab (GdkDisplay *display,
GdkDevice *device);
@@ -662,6 +664,7 @@ void _gdk_synthesize_crossing_events (GdkDisplay *display,
GdkWindow *src,
GdkWindow *dest,
GdkDevice *device,
+ GdkDevice *source_device,
GdkCrossingMode mode,
gint toplevel_x,
gint toplevel_y,
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index fdd5734868..01ea1ca9bf 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -10355,6 +10355,7 @@ send_crossing_event (GdkDisplay *display,
GdkNotifyType notify_type,
GdkWindow *subwindow,
GdkDevice *device,
+ GdkDevice *source_device,
gint toplevel_x,
gint toplevel_y,
GdkModifierType mask,
@@ -10414,6 +10415,10 @@ send_crossing_event (GdkDisplay *display,
{
event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
gdk_event_set_device (event, device);
+
+ if (source_device)
+ gdk_event_set_source_device (event, source_device);
+
event->crossing.time = time_;
event->crossing.subwindow = subwindow;
if (subwindow)
@@ -10441,6 +10446,7 @@ _gdk_synthesize_crossing_events (GdkDisplay *display,
GdkWindow *src,
GdkWindow *dest,
GdkDevice *device,
+ GdkDevice *source_device,
GdkCrossingMode mode,
gint toplevel_x,
gint toplevel_y,
@@ -10496,7 +10502,7 @@ _gdk_synthesize_crossing_events (GdkDisplay *display,
a, GDK_LEAVE_NOTIFY,
mode,
notify_type,
- NULL, device,
+ NULL, device, source_device,
toplevel_x, toplevel_y,
mask, time_,
event_in_queue,
@@ -10518,7 +10524,7 @@ _gdk_synthesize_crossing_events (GdkDisplay *display,
mode,
notify_type,
(GdkWindow *)last,
- device,
+ device, source_device,
toplevel_x, toplevel_y,
mask, time_,
event_in_queue,
@@ -10565,7 +10571,7 @@ _gdk_synthesize_crossing_events (GdkDisplay *display,
mode,
notify_type,
(GdkWindow *)next,
- device,
+ device, source_device,
toplevel_x, toplevel_y,
mask, time_,
event_in_queue,
@@ -10587,7 +10593,7 @@ _gdk_synthesize_crossing_events (GdkDisplay *display,
mode,
notify_type,
NULL,
- device,
+ device, source_device,
toplevel_x, toplevel_y,
mask, time_,
event_in_queue,
@@ -11079,7 +11085,7 @@ do_synthesize_crossing_event (gpointer data)
_gdk_synthesize_crossing_events (display,
pointer_info->window_under_pointer,
new_window_under_pointer,
- device,
+ device, NULL,
GDK_CROSSING_NORMAL,
pointer_info->toplevel_x,
pointer_info->toplevel_y,
@@ -11199,7 +11205,7 @@ proxy_pointer_event (GdkDisplay *display,
GdkWindow *toplevel_window, *event_window;
GdkWindow *pointer_window;
GdkPointerWindowInfo *pointer_info;
- GdkDevice *device;
+ GdkDevice *device, *source_device;
GdkEvent *event;
guint state;
gdouble toplevel_x, toplevel_y;
@@ -11211,6 +11217,7 @@ proxy_pointer_event (GdkDisplay *display,
gdk_event_get_state (source_event, &state);
time_ = gdk_event_get_time (source_event);
device = gdk_event_get_device (source_event);
+ source_device = gdk_event_get_source_device (source_event);
pointer_info = _gdk_display_get_pointer_info (display, device);
toplevel_window = convert_native_coords_to_toplevel (event_window,
toplevel_x, toplevel_y,
@@ -11244,7 +11251,7 @@ proxy_pointer_event (GdkDisplay *display,
_gdk_synthesize_crossing_events (display,
pointer_info->window_under_pointer,
event_window,
- device,
+ device, source_device,
source_event->crossing.mode,
toplevel_x, toplevel_y,
state, time_,
@@ -11260,7 +11267,7 @@ proxy_pointer_event (GdkDisplay *display,
source_event->crossing.mode,
source_event->crossing.detail,
NULL,
- device,
+ device, source_device,
toplevel_x, toplevel_y,
state, time_,
source_event,
@@ -11290,7 +11297,7 @@ proxy_pointer_event (GdkDisplay *display,
source_event->crossing.mode,
source_event->crossing.detail,
NULL,
- device,
+ device, source_device,
toplevel_x, toplevel_y,
state, time_,
source_event,
@@ -11300,7 +11307,7 @@ proxy_pointer_event (GdkDisplay *display,
_gdk_synthesize_crossing_events (display,
event_window,
pointer_window,
- device,
+ device, source_device,
source_event->crossing.mode,
toplevel_x, toplevel_y,
state, time_,
@@ -11319,7 +11326,7 @@ proxy_pointer_event (GdkDisplay *display,
_gdk_synthesize_crossing_events (display,
pointer_info->window_under_pointer,
pointer_window,
- device,
+ device, source_device,
GDK_CROSSING_NORMAL,
toplevel_x, toplevel_y,
state, time_,
@@ -11409,7 +11416,7 @@ proxy_button_event (GdkEvent *source_event,
gdouble toplevel_x, toplevel_y;
GdkDisplay *display;
GdkWindowObject *w;
- GdkDevice *device;
+ GdkDevice *device, *source_device;
type = source_event->any.type;
event_window = source_event->any.window;
@@ -11417,6 +11424,7 @@ proxy_button_event (GdkEvent *source_event,
gdk_event_get_state (source_event, &state);
time_ = gdk_event_get_time (source_event);
device = gdk_event_get_device (source_event);
+ source_device = gdk_event_get_source_device (source_event);
display = gdk_drawable_get_display (source_event->any.window);
toplevel_window = convert_native_coords_to_toplevel (event_window,
toplevel_x, toplevel_y,
@@ -11453,7 +11461,7 @@ proxy_button_event (GdkEvent *source_event,
serial,
time_,
TRUE);
- _gdk_display_device_grab_update (display, device, serial);
+ _gdk_display_device_grab_update (display, device, source_device, serial);
}
pointer_window = get_pointer_window (display, toplevel_window, device,
@@ -11600,20 +11608,21 @@ _gdk_windowing_got_event (GdkDisplay *display,
guint old_state, old_button;
GdkDeviceGrabInfo *button_release_grab;
GdkPointerWindowInfo *pointer_info;
- GdkDevice *device;
+ GdkDevice *device, *source_device;
gboolean is_toplevel;
if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
display->last_event_time = gdk_event_get_time (event);
device = gdk_event_get_device (event);
+ source_device = gdk_event_get_source_device (event);
if (device)
{
GdkInputMode mode;
g_object_get (device, "input-mode", &mode, NULL);
- _gdk_display_device_grab_update (display, device, serial);
+ _gdk_display_device_grab_update (display, device, source_device, serial);
if (mode == GDK_MODE_DISABLED ||
!_gdk_display_check_grab_ownership (display, device, serial))
@@ -11659,7 +11668,7 @@ _gdk_windowing_got_event (GdkDisplay *display,
serial,
gdk_event_get_time (event),
TRUE);
- _gdk_display_device_grab_update (display, device, serial);
+ _gdk_display_device_grab_update (display, device, source_device, serial);
}
if (event->type == GDK_BUTTON_RELEASE &&
!event->any.send_event)
@@ -11672,7 +11681,7 @@ _gdk_windowing_got_event (GdkDisplay *display,
{
button_release_grab->serial_end = serial;
button_release_grab->implicit_ungrab = FALSE;
- _gdk_display_device_grab_update (display, device, serial);
+ _gdk_display_device_grab_update (display, device, source_device, serial);
}
}
@@ -11794,7 +11803,7 @@ _gdk_windowing_got_event (GdkDisplay *display,
{
button_release_grab->serial_end = serial;
button_release_grab->implicit_ungrab = FALSE;
- _gdk_display_device_grab_update (display, device, serial);
+ _gdk_display_device_grab_update (display, device, source_device, serial);
}
}
diff --git a/gdk/x11/gdkdevicemanager-xi2.c b/gdk/x11/gdkdevicemanager-xi2.c
index e519cfa70f..b71bcda675 100644
--- a/gdk/x11/gdkdevicemanager-xi2.c
+++ b/gdk/x11/gdkdevicemanager-xi2.c
@@ -637,6 +637,7 @@ translate_keyboard_string (GdkEventKey *event)
static void
generate_focus_event (GdkWindow *window,
GdkDevice *device,
+ GdkDevice *source_device,
gboolean in)
{
GdkEvent *event;
@@ -646,6 +647,7 @@ generate_focus_event (GdkWindow *window,
event->focus_change.send_event = FALSE;
event->focus_change.in = in;
gdk_event_set_device (event, device);
+ gdk_event_set_source_device (event, source_device);
gdk_event_put (event);
gdk_event_free (event);
@@ -654,6 +656,7 @@ generate_focus_event (GdkWindow *window,
static void
handle_focus_change (GdkWindow *window,
GdkDevice *device,
+ GdkDevice *source_device,
gint detail,
gint mode,
gboolean in)
@@ -713,7 +716,7 @@ handle_focus_change (GdkWindow *window,
}
if (HAS_FOCUS (toplevel) != had_focus)
- generate_focus_event (window, device, (in) ? TRUE : FALSE);
+ generate_focus_event (window, device, source_device, (in) ? TRUE : FALSE);
}
static gdouble *
@@ -911,7 +914,7 @@ gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator,
XIDeviceEvent *xev = (XIDeviceEvent *) ev;
GdkKeymap *keymap = gdk_keymap_get_for_display (display);
GdkModifierType consumed, state;
- GdkDevice *device;
+ GdkDevice *device, *source_device;
event->key.type = xev->evtype == XI_KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
@@ -928,6 +931,10 @@ gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator,
GUINT_TO_POINTER (xev->deviceid));
gdk_event_set_device (event, device);
+ source_device = g_hash_table_lookup (device_manager->id_table,
+ GUINT_TO_POINTER (xev->sourceid));
+ gdk_event_set_source_device (event, source_device);
+
event->key.keyval = GDK_VoidSymbol;
gdk_keymap_translate_keyboard_state (keymap,
@@ -956,6 +963,7 @@ gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator,
case XI_ButtonRelease:
{
XIDeviceEvent *xev = (XIDeviceEvent *) ev;
+ GdkDevice *source_device;
switch (xev->detail)
{
@@ -984,6 +992,10 @@ gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator,
event->scroll.device = g_hash_table_lookup (device_manager->id_table,
GUINT_TO_POINTER (xev->deviceid));
+ source_device = g_hash_table_lookup (device_manager->id_table,
+ GUINT_TO_POINTER (xev->sourceid));
+ gdk_event_set_source_device (event, source_device);
+
event->scroll.state = gdk_device_xi2_translate_state (&xev->mods, &xev->buttons);
break;
default:
@@ -999,6 +1011,10 @@ gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator,
event->button.device = g_hash_table_lookup (device_manager->id_table,
GUINT_TO_POINTER (xev->deviceid));
+ source_device = g_hash_table_lookup (device_manager->id_table,
+ GUINT_TO_POINTER (xev->sourceid));
+ gdk_event_set_source_device (event, source_device);
+
event->button.axes = translate_axes (event->button.device,
event->button.x,
event->button.y,
@@ -1031,6 +1047,7 @@ gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator,
case XI_Motion:
{
XIDeviceEvent *xev = (XIDeviceEvent *) ev;
+ GdkDevice *source_device;
event->motion.type = GDK_MOTION_NOTIFY;
@@ -1045,6 +1062,10 @@ gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator,
event->motion.device = g_hash_table_lookup (device_manager->id_table,
GINT_TO_POINTER (xev->deviceid));
+ source_device = g_hash_table_lookup (device_manager->id_table,
+ GUINT_TO_POINTER (xev->sourceid));
+ gdk_event_set_source_device (event, source_device);
+
event->motion.state = gdk_device_xi2_translate_state (&xev->mods, &xev->buttons);
/* There doesn't seem to be motion hints in XI */
@@ -1070,7 +1091,7 @@ gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator,
case XI_Leave:
{
XIEnterEvent *xev = (XIEnterEvent *) ev;
- GdkDevice *device;
+ GdkDevice *device, *source_device;
event->crossing.type = (ev->evtype == XI_Enter) ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY;
@@ -1088,6 +1109,10 @@ gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator,
GINT_TO_POINTER (xev->deviceid));
gdk_event_set_device (event, device);
+ source_device = g_hash_table_lookup (device_manager->id_table,
+ GUINT_TO_POINTER (xev->sourceid));
+ gdk_event_set_source_device (event, source_device);
+
event->crossing.mode = translate_crossing_mode (xev->mode);
event->crossing.detail = translate_notify_type (xev->detail);
event->crossing.state = gdk_device_xi2_translate_state (&xev->mods, &xev->buttons);
@@ -1097,12 +1122,16 @@ gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator,
case XI_FocusOut:
{
XIEnterEvent *xev = (XIEnterEvent *) ev;
- GdkDevice *device;
+ GdkDevice *device, *source_device;
device = g_hash_table_lookup (device_manager->id_table,
GINT_TO_POINTER (xev->deviceid));
- handle_focus_change (window, device, xev->detail, xev->mode,
+ source_device = g_hash_table_lookup (device_manager->id_table,
+ GUINT_TO_POINTER (xev->sourceid));
+
+ handle_focus_change (window, device, source_device,
+ xev->detail, xev->mode,
(ev->evtype == XI_FocusIn) ? TRUE : FALSE);
return_val = FALSE;
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index b77c2ceae8..c8cbe66195 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -1630,7 +1630,7 @@ device_ungrab_callback (GdkDisplay *display,
{
GdkDevice *device = data;
- _gdk_display_device_grab_update (display, device, serial);
+ _gdk_display_device_grab_update (display, device, NULL, serial);
}
diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c
index a3a91cc967..9898b4eca2 100644
--- a/gdk/x11/gdkmain-x11.c
+++ b/gdk/x11/gdkmain-x11.c
@@ -135,7 +135,7 @@ has_pointer_grab_callback (GdkDisplay *display,
{
GdkDevice *device = data;
- _gdk_display_device_grab_update (display, device, serial);
+ _gdk_display_device_grab_update (display, device, NULL, serial);
}
GdkGrabStatus