diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2010-12-13 02:12:43 +0100 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2010-12-15 03:17:58 +0100 |
commit | f5a20ab65a3d03fb90c27b2fa1954d965f8ad768 (patch) | |
tree | 7bc1cc9bca599dc71398d7d1af3d4669c8a60d1c | |
parent | c4a5c2ed4b8861f92104f51d9213b0c9f64e26b1 (diff) | |
download | gtk+-f5a20ab65a3d03fb90c27b2fa1954d965f8ad768.tar.gz |
Add gdk_event_[gs]et_source_device().
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.c | 19 | ||||
-rw-r--r-- | gdk/gdkevents.c | 60 | ||||
-rw-r--r-- | gdk/gdkevents.h | 3 | ||||
-rw-r--r-- | gdk/gdkinternals.h | 3 | ||||
-rw-r--r-- | gdk/gdkwindow.c | 49 | ||||
-rw-r--r-- | gdk/x11/gdkdevicemanager-xi2.c | 39 | ||||
-rw-r--r-- | gdk/x11/gdkdisplay-x11.c | 2 | ||||
-rw-r--r-- | gdk/x11/gdkmain-x11.c | 2 |
8 files changed, 144 insertions, 33 deletions
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c index 5ef630d7bb..9a083e18b7 100644 --- a/gdk/gdkdisplay.c +++ b/gdk/gdkdisplay.c @@ -1302,6 +1302,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, @@ -1337,7 +1338,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, @@ -1351,7 +1352,7 @@ synthesize_crossing_events (GdkDisplay *display, _gdk_synthesize_crossing_events (display, src_window, NULL, - device, + device, source_device, crossing_mode, x, y, state, time, @@ -1366,7 +1367,7 @@ synthesize_crossing_events (GdkDisplay *display, _gdk_synthesize_crossing_events (display, src_window, NULL, - device, + device, source_device, crossing_mode, x, y, state, time, @@ -1377,7 +1378,7 @@ synthesize_crossing_events (GdkDisplay *display, _gdk_synthesize_crossing_events (display, NULL, dest_window, - device, + device, source_device, crossing_mode, x, y, state, time, @@ -1414,6 +1415,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, @@ -1449,7 +1451,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); @@ -1500,7 +1502,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); @@ -1515,6 +1517,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; @@ -1539,7 +1542,7 @@ _gdk_display_device_grab_update (GdkDisplay *display, if (!current_grab->activated) { if (gdk_device_get_source (device) != 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; @@ -1567,7 +1570,7 @@ _gdk_display_device_grab_update (GdkDisplay *display, g_hash_table_insert (display->device_grabs, device, grabs); if (gdk_device_get_source (device) != 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 438beb8a1f..d6322db795 100644 --- a/gdk/gdkevents.c +++ b/gdk/gdkevents.c @@ -1077,6 +1077,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 fcefc6c1c8..b7e5ed37a2 100644 --- a/gdk/gdkevents.h +++ b/gdk/gdkevents.h @@ -1089,6 +1089,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 8ade0c13a3..a897181d27 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -156,6 +156,7 @@ struct _GdkEventPrivate GdkScreen *screen; gpointer windowing_data; GdkDevice *device; + GdkDevice *source_device; }; /* Tracks information about the pointer grab on this display */ @@ -440,6 +441,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); @@ -498,6 +500,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 7ac839640f..a2eb699f60 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -8335,6 +8335,7 @@ send_crossing_event (GdkDisplay *display, GdkNotifyType notify_type, GdkWindow *subwindow, GdkDevice *device, + GdkDevice *source_device, gint toplevel_x, gint toplevel_y, GdkModifierType mask, @@ -8394,6 +8395,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) @@ -8421,6 +8426,7 @@ _gdk_synthesize_crossing_events (GdkDisplay *display, GdkWindow *src, GdkWindow *dest, GdkDevice *device, + GdkDevice *source_device, GdkCrossingMode mode, gint toplevel_x, gint toplevel_y, @@ -8476,7 +8482,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, @@ -8498,7 +8504,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, @@ -8545,7 +8551,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, @@ -8567,7 +8573,7 @@ _gdk_synthesize_crossing_events (GdkDisplay *display, mode, notify_type, NULL, - device, + device, source_device, toplevel_x, toplevel_y, mask, time_, event_in_queue, @@ -8939,7 +8945,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, @@ -9055,7 +9061,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; @@ -9067,6 +9073,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, @@ -9100,7 +9107,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_, @@ -9116,7 +9123,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, @@ -9146,7 +9153,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, @@ -9156,7 +9163,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_, @@ -9175,7 +9182,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_, @@ -9236,6 +9243,7 @@ proxy_pointer_event (GdkDisplay *display, 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); } } @@ -9265,7 +9273,7 @@ proxy_button_event (GdkEvent *source_event, gdouble toplevel_x, toplevel_y; GdkDisplay *display; GdkWindow *w; - GdkDevice *device; + GdkDevice *device, *source_device; type = source_event->any.type; event_window = source_event->any.window; @@ -9273,6 +9281,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_window_get_display (source_event->any.window); toplevel_window = convert_native_coords_to_toplevel (event_window, toplevel_x, toplevel_y, @@ -9309,7 +9318,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, @@ -9346,6 +9355,8 @@ proxy_button_event (GdkEvent *source_event, 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) _gdk_event_button_generate (display, event); return TRUE; @@ -9359,6 +9370,7 @@ proxy_button_event (GdkEvent *source_event, event->scroll.y_root = source_event->scroll.y_root; event->scroll.state = state; event->scroll.device = source_event->scroll.device; + gdk_event_set_source_device (event, source_device); return TRUE; default: @@ -9452,20 +9464,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)) @@ -9510,7 +9523,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) @@ -9523,7 +9536,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); } } @@ -9645,7 +9658,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 25d7a841a6..1cc2fc2a27 100644 --- a/gdk/x11/gdkdevicemanager-xi2.c +++ b/gdk/x11/gdkdevicemanager-xi2.c @@ -641,6 +641,7 @@ translate_keyboard_string (GdkEventKey *event) static void generate_focus_event (GdkWindow *window, GdkDevice *device, + GdkDevice *source_device, gboolean in) { GdkEvent *event; @@ -650,6 +651,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); @@ -658,6 +660,7 @@ generate_focus_event (GdkWindow *window, static void handle_focus_change (GdkWindow *window, GdkDevice *device, + GdkDevice *source_device, gint detail, gint mode, gboolean in) @@ -717,7 +720,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 * @@ -916,7 +919,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; @@ -933,6 +936,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_KEY_VoidSymbol; gdk_keymap_translate_keyboard_state (keymap, @@ -961,6 +968,7 @@ gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator, case XI_ButtonRelease: { XIDeviceEvent *xev = (XIDeviceEvent *) ev; + GdkDevice *source_device; switch (xev->detail) { @@ -989,6 +997,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: @@ -1004,6 +1016,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, @@ -1036,6 +1052,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; @@ -1050,6 +1067,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 */ @@ -1075,7 +1096,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; @@ -1093,6 +1114,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); @@ -1102,12 +1127,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 bfcc358cce..27ef251919 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -1633,7 +1633,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 f9df29592f..2ce5e34875 100644 --- a/gdk/x11/gdkmain-x11.c +++ b/gdk/x11/gdkmain-x11.c @@ -136,7 +136,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 |