diff options
Diffstat (limited to 'gdk')
-rw-r--r-- | gdk/gdk.symbols | 2 | ||||
-rw-r--r-- | gdk/gdkinternals.h | 4 | ||||
-rw-r--r-- | gdk/gdkwindow.c | 140 | ||||
-rw-r--r-- | gdk/gdkwindow.h | 6 |
4 files changed, 152 insertions, 0 deletions
diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols index 13d2349306..8d5cba8333 100644 --- a/gdk/gdk.symbols +++ b/gdk/gdk.symbols @@ -436,6 +436,7 @@ gdk_window_get_position gdk_window_get_root_coords gdk_window_get_root_origin gdk_window_get_screen +gdk_window_get_source_events gdk_window_get_state gdk_window_get_support_multidevice gdk_window_get_toplevel @@ -509,6 +510,7 @@ gdk_window_set_override_redirect gdk_window_set_role gdk_window_set_skip_pager_hint gdk_window_set_skip_taskbar_hint +gdk_window_set_source_events gdk_window_set_startup_id gdk_window_set_static_gravities gdk_window_set_support_multidevice diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index a897181d27..c98d2180c5 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -264,6 +264,10 @@ struct _GdkWindow GList *devices_inside; GHashTable *device_events; + + GHashTable *source_event_masks; + gulong device_added_handler_id; + gulong device_changed_handler_id; }; #define GDK_WINDOW_TYPE(d) (((GDK_WINDOW (d)))->window_type) diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index a2eb699f60..becfba57f5 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -576,6 +576,9 @@ gdk_window_finalize (GObject *object) if (window->device_events) g_hash_table_destroy (window->device_events); + if (window->source_event_masks) + g_hash_table_destroy (window->source_event_masks); + if (window->devices_inside) g_list_free (window->devices_inside); @@ -8906,6 +8909,143 @@ gdk_window_geometry_changed (GdkWindow *window) _gdk_synthesize_crossing_events_for_geometry_change (window); } +static void +source_events_device_added (GdkDeviceManager *device_manager, + GdkDevice *device, + gpointer user_data) +{ + GdkWindow *window; + GdkEventMask event_mask; + GdkInputSource source; + + if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_FLOATING) + return; + + window = user_data; + source = gdk_device_get_source (device); + + event_mask = GPOINTER_TO_INT (g_hash_table_lookup (window->source_event_masks, + GINT_TO_POINTER (source))); + if (event_mask) + gdk_window_set_device_events (window, device, event_mask); +} + +static void +source_events_device_changed (GdkDeviceManager *device_manager, + GdkDevice *device, + gpointer user_data) +{ + GdkDeviceType type; + GdkInputSource source; + GdkEventMask event_mask; + GdkWindow *window; + + window = user_data; + type = gdk_device_get_device_type (device); + source = gdk_device_get_source (device); + + event_mask = GPOINTER_TO_INT (g_hash_table_lookup (window->source_event_masks, + GINT_TO_POINTER (source))); + + if (!event_mask) + return; + + if (type == GDK_DEVICE_TYPE_FLOATING) + { + /* The device was just floated, enable its event mask */ + gdk_window_set_device_events (window, device, event_mask); + } + else if (type == GDK_DEVICE_TYPE_SLAVE) + gdk_window_set_device_events (window, device, 0); +} + +/** + * gdk_window_set_source_events: + * @window: a #GdkWindow + * @source: a #GdkInputSource to define the source class. + * @event_mask: event mask for @window + * + * Sets the event mask for any floating device (i.e. not attached to any + * visible pointer) that has the source defined as @source. This event + * mask will be applied both to currently existing, newly added devices + * after this call, and devices being attached/detached. + * + * Since: 3.0 + **/ +void +gdk_window_set_source_events (GdkWindow *window, + GdkInputSource source, + GdkEventMask event_mask) +{ + GdkDeviceManager *device_manager; + GdkDisplay *display; + GList *devices, *d; + guint size; + + g_return_if_fail (GDK_IS_WINDOW (window)); + + display = gdk_window_get_display (window); + device_manager = gdk_display_get_device_manager (display); + + devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING); + + /* Set event mask for existing devices */ + for (d = devices; d; d = d->next) + { + GdkDevice *device = d->data; + + if (source == gdk_device_get_source (device)) + gdk_window_set_device_events (window, device, event_mask); + } + + /* Update accounting */ + if (G_UNLIKELY (!window->source_event_masks)) + window->source_event_masks = g_hash_table_new (NULL, NULL); + + if (event_mask) + g_hash_table_insert (window->source_event_masks, + GUINT_TO_POINTER (source), + GUINT_TO_POINTER (event_mask)); + else + g_hash_table_remove (window->source_event_masks, + GUINT_TO_POINTER (source)); + + size = g_hash_table_size (window->source_event_masks); + + /* Update handler if needed */ + if (!window->device_added_handler_id && size > 0) + { + window->device_added_handler_id = + g_signal_connect (device_manager, "device-added", + G_CALLBACK (source_events_device_added), window); + window->device_changed_handler_id = + g_signal_connect (device_manager, "device-changed", + G_CALLBACK (source_events_device_changed), window); + } + else if (window->device_added_handler_id && size == 0) + g_signal_handler_disconnect (device_manager, window->device_added_handler_id); +} + +/** + * gdk_window_get_source_events: + * @window: a #GdkWindow + * @source: a #GdkInputSource to define the source class. + * + * Returns the event mask for @window corresponding to the device class specified + * by @source. + * + * Returns: source event mask for @window + **/ +GdkEventMask +gdk_window_get_source_events (GdkWindow *window, + GdkInputSource source) +{ + g_return_val_if_fail (GDK_IS_WINDOW (window), 0); + + return GPOINTER_TO_UINT (g_hash_table_lookup (window->source_event_masks, + GUINT_TO_POINTER (source))); +} + static gboolean do_synthesize_crossing_event (gpointer data) { diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h index 69fee5ad09..164281dc3c 100644 --- a/gdk/gdkwindow.h +++ b/gdk/gdkwindow.h @@ -778,6 +778,12 @@ void gdk_window_set_device_events (GdkWindow *window, GdkEventMask gdk_window_get_device_events (GdkWindow *window, GdkDevice *device); +void gdk_window_set_source_events (GdkWindow *window, + GdkInputSource source, + GdkEventMask event_mask); +GdkEventMask gdk_window_get_source_events (GdkWindow *window, + GdkInputSource source); + void gdk_window_set_icon_list (GdkWindow *window, GList *pixbufs); void gdk_window_set_icon_name (GdkWindow *window, |