[gtk+/xi2: 131/148] Make GtkWidget pointer window bookkeeping multidevice-aware.
- From: Carlos Garnacho <carlosg src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gtk+/xi2: 131/148] Make GtkWidget pointer window bookkeeping multidevice-aware.
- Date: Thu, 10 Dec 2009 21:12:42 +0000 (UTC)
commit 5f9abb4f5d3c03eded8264ef7c46812cb1d6f2d7
Author: Carlos Garnacho <carlos gnome org>
Date: Fri Dec 4 10:26:59 2009 +0100
Make GtkWidget pointer window bookkeeping multidevice-aware.
gtk/gtkmain.c | 40 +++++++-----
gtk/gtkprivate.h | 1 -
gtk/gtkwidget.c | 195 +++++++++++++++++++++++++++++++++++++----------------
gtk/gtkwidget.h | 10 ++-
4 files changed, 166 insertions(+), 80 deletions(-)
---
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 0bca3da..f44061f 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -1616,14 +1616,12 @@ gtk_main_do_event (GdkEvent *event)
break;
case GDK_ENTER_NOTIFY:
- GTK_PRIVATE_SET_FLAG (event_widget, GTK_HAS_POINTER);
- _gtk_widget_set_pointer_window (event_widget, event->any.window);
+ _gtk_widget_set_device_window (event_widget, event->crossing.device, event->any.window);
if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
gtk_widget_event (grab_widget, event);
break;
case GDK_LEAVE_NOTIFY:
- GTK_PRIVATE_UNSET_FLAG (event_widget, GTK_HAS_POINTER);
if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
gtk_widget_event (grab_widget, event);
break;
@@ -1703,11 +1701,10 @@ typedef struct
static void
gtk_grab_notify_foreach (GtkWidget *child,
gpointer data)
-
{
GrabNotifyInfo *info = data;
-
gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
+ GList *devices, *d;
was_grabbed = info->was_grabbed;
is_grabbed = info->is_grabbed;
@@ -1722,30 +1719,39 @@ gtk_grab_notify_foreach (GtkWidget *child,
if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child))
gtk_container_forall (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
-
+
+ devices = _gtk_widget_list_devices (child);
+
if (is_shadowed)
{
GTK_PRIVATE_SET_FLAG (child, GTK_SHADOWED);
- if (!was_shadowed && GTK_WIDGET_HAS_POINTER (child)
- && GTK_WIDGET_IS_SENSITIVE (child))
- _gtk_widget_synthesize_crossing (child, info->new_grab_widget,
- GDK_CROSSING_GTK_GRAB);
+ if (!was_shadowed && devices &&
+ GTK_WIDGET_IS_SENSITIVE (child))
+ {
+ for (d = devices; d; d = d->next)
+ _gtk_widget_synthesize_crossing (child, info->new_grab_widget,
+ d->data, GDK_CROSSING_GTK_GRAB);
+ }
}
else
{
GTK_PRIVATE_UNSET_FLAG (child, GTK_SHADOWED);
- if (was_shadowed && GTK_WIDGET_HAS_POINTER (child)
- && GTK_WIDGET_IS_SENSITIVE (child))
- _gtk_widget_synthesize_crossing (info->old_grab_widget, child,
- info->from_grab ? GDK_CROSSING_GTK_GRAB
- : GDK_CROSSING_GTK_UNGRAB);
+ if (was_shadowed && devices &&
+ GTK_WIDGET_IS_SENSITIVE (child))
+ {
+ for (d = devices; d; d = d->next)
+ _gtk_widget_synthesize_crossing (info->old_grab_widget, child, d->data,
+ info->from_grab ? GDK_CROSSING_GTK_GRAB
+ : GDK_CROSSING_GTK_UNGRAB);
+ }
}
if (was_shadowed != is_shadowed)
_gtk_widget_grab_notify (child, was_shadowed);
-
+
g_object_unref (child);
-
+ g_list_free (devices);
+
info->was_grabbed = was_grabbed;
info->is_grabbed = is_grabbed;
}
diff --git a/gtk/gtkprivate.h b/gtk/gtkprivate.h
index 7ba5a5d..ded69e0 100644
--- a/gtk/gtkprivate.h
+++ b/gtk/gtkprivate.h
@@ -37,7 +37,6 @@ typedef enum
{
PRIVATE_GTK_USER_STYLE = 1 << 0,
PRIVATE_GTK_RESIZE_PENDING = 1 << 2,
- PRIVATE_GTK_HAS_POINTER = 1 << 3, /* If the pointer is above a window belonging to the widget */
PRIVATE_GTK_SHADOWED = 1 << 4, /* If there is a grab in effect shadowing the widget */
PRIVATE_GTK_HAS_SHAPE_MASK = 1 << 5,
PRIVATE_GTK_IN_REPARENT = 1 << 6,
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index a34ef25..74fcec0 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -8661,48 +8661,132 @@ _gtk_widget_peek_colormap (void)
}
/*
- * _gtk_widget_set_pointer_window:
+ * _gtk_widget_set_device_window:
* @widget: a #GtkWidget.
- * @pointer_window: the new pointer window.
+ * @device: a #GdkDevice.
+ * @window: the new device window.
*
- * Sets pointer window for @widget. Does not ref @pointer_window.
+ * Sets pointer window for @widget and @device. Does not ref @window.
* Actually stores it on the #GdkScreen, but you don't need to know that.
*/
void
-_gtk_widget_set_pointer_window (GtkWidget *widget,
- GdkWindow *pointer_window)
+_gtk_widget_set_device_window (GtkWidget *widget,
+ GdkDevice *device,
+ GdkWindow *window)
{
+ GdkScreen *screen;
+ GHashTable *device_window;
+
g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (GDK_IS_DEVICE (device));
+ g_return_if_fail (GDK_IS_WINDOW (window));
- if (GTK_WIDGET_REALIZED (widget))
- {
- GdkScreen *screen = gdk_drawable_get_screen (widget->window);
+ if (!GTK_WIDGET_REALIZED (widget))
+ return;
- g_object_set_qdata (G_OBJECT (screen), quark_pointer_window,
- pointer_window);
+ screen = gdk_drawable_get_screen (widget->window);
+ device_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
+
+ if (G_UNLIKELY (!device_window))
+ {
+ device_window = g_hash_table_new (NULL, NULL);
+ g_object_set_qdata_full (G_OBJECT (screen),
+ quark_pointer_window,
+ device_window,
+ (GDestroyNotify) g_hash_table_destroy);
}
+
+ g_hash_table_insert (device_window, device, window);
}
/*
- * _gtk_widget_get_pointer_window:
+ * _gtk_widget_get_device_window:
* @widget: a #GtkWidget.
+ * @device: a #GdkDevice.
*
- * Return value: the pointer window set on the #GdkScreen @widget is attached
+ * Return value: the device window set on the #GdkScreen @widget is attached
* to, or %NULL.
*/
GdkWindow *
-_gtk_widget_get_pointer_window (GtkWidget *widget)
+_gtk_widget_get_device_window (GtkWidget *widget,
+ GdkDevice *device)
{
+ GdkScreen *screen;
+ GHashTable *device_window;
+ GdkWindow *window;
+ GtkWidget *w;
+
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+ g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
- if (GTK_WIDGET_REALIZED (widget))
+ if (!GTK_WIDGET_REALIZED (widget))
+ return NULL;
+
+ screen = gdk_drawable_get_screen (widget->window);
+ device_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
+
+ if (G_UNLIKELY (!device_window))
+ return NULL;
+
+ window = g_hash_table_lookup (device_window, device);
+
+ if (!window)
+ return NULL;
+
+ gdk_window_get_user_data (window, (gpointer *) &w);
+
+ if (widget != w)
+ return NULL;
+
+ return window;
+}
+
+/*
+ * _gtk_widget_list_devices:
+ * @widget: a #GtkWidget.
+ *
+ * Returns the list of #GdkDevices that is currently on top of any widget #GdkWindow.
+ * Free the list with g_list_free(), the elements are owned by GTK+ and must not
+ * be freed.
+ */
+GList *
+_gtk_widget_list_devices (GtkWidget *widget)
+{
+ GdkScreen *screen;
+ GHashTableIter iter;
+ GHashTable *device_window;
+ GList *devices = NULL;
+ gpointer key, value;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+ if (!GTK_WIDGET_REALIZED (widget))
+ return NULL;
+
+ screen = gdk_drawable_get_screen (widget->window);
+ device_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
+
+ if (G_UNLIKELY (!device_window))
+ return NULL;
+
+ g_hash_table_iter_init (&iter, device_window);
+
+ while (g_hash_table_iter_next (&iter, &key, &value))
{
- GdkScreen *screen = gdk_drawable_get_screen (widget->window);
+ GdkDevice *device = key;
+ GdkWindow *window = value;
+ GtkWidget *w;
- return g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
+ if (window)
+ {
+ gdk_window_get_user_data (window, (gpointer *) &w);
+
+ if (widget == w)
+ devices = g_list_prepend (devices, device);
+ }
}
- return NULL;
+ return devices;
}
static void
@@ -8737,32 +8821,6 @@ synth_crossing (GtkWidget *widget,
}
/*
- * _gtk_widget_is_pointer_widget:
- * @widget: a #GtkWidget
- *
- * Returns %TRUE if the pointer window belongs to @widget.
- */
-gboolean
-_gtk_widget_is_pointer_widget (GtkWidget *widget)
-{
- if (GTK_WIDGET_HAS_POINTER (widget))
- {
- GdkWindow *win;
- GtkWidget *wid;
-
- win = _gtk_widget_get_pointer_window (widget);
- if (win)
- {
- gdk_window_get_user_data (win, (gpointer *)&wid);
- if (wid == widget)
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/*
* _gtk_widget_synthesize_crossing:
* @from: the #GtkWidget the virtual pointer is leaving.
* @to: the #GtkWidget the virtual pointer is moving to.
@@ -8794,20 +8852,30 @@ _gtk_widget_is_pointer_widget (GtkWidget *widget)
* - enter notify on real pointer window, detail Ancestor
*/
void
-_gtk_widget_synthesize_crossing (GtkWidget *from,
- GtkWidget *to,
- GdkCrossingMode mode)
+_gtk_widget_synthesize_crossing (GtkWidget *from,
+ GtkWidget *to,
+ GdkDevice *device,
+ GdkCrossingMode mode)
{
GdkWindow *from_window = NULL, *to_window = NULL;
g_return_if_fail (from != NULL || to != NULL);
if (from != NULL)
- from_window = GTK_WIDGET_HAS_POINTER (from)
- ? _gtk_widget_get_pointer_window (from) : from->window;
+ {
+ from_window = _gtk_widget_get_device_window (from, device);
+
+ if (!from_window)
+ from_window = from->window;
+ }
+
if (to != NULL)
- to_window = GTK_WIDGET_HAS_POINTER (to)
- ? _gtk_widget_get_pointer_window (to) : to->window;
+ {
+ to_window = _gtk_widget_get_device_window (to, device);
+
+ if (!to_window)
+ to_window = to->window;
+ }
if (from_window == NULL && to_window == NULL)
;
@@ -8997,15 +9065,24 @@ gtk_widget_propagate_state (GtkWidget *widget,
g_signal_emit (widget, widget_signals[STATE_CHANGED], 0, old_state);
- if (GTK_WIDGET_HAS_POINTER (widget) && !GTK_WIDGET_SHADOWED (widget))
- {
- if (!GTK_WIDGET_IS_SENSITIVE (widget))
- _gtk_widget_synthesize_crossing (widget, NULL,
- GDK_CROSSING_STATE_CHANGED);
- else if (old_state == GTK_STATE_INSENSITIVE)
- _gtk_widget_synthesize_crossing (NULL, widget,
- GDK_CROSSING_STATE_CHANGED);
- }
+ if (!GTK_WIDGET_SHADOWED (widget))
+ {
+ GList *devices, *d;
+
+ devices = _gtk_widget_list_devices (widget);
+
+ for (d = devices; d; d = d->next)
+ {
+ if (!GTK_WIDGET_IS_SENSITIVE (widget))
+ _gtk_widget_synthesize_crossing (widget, NULL, d->data,
+ GDK_CROSSING_STATE_CHANGED);
+ else if (old_state == GTK_STATE_INSENSITIVE)
+ _gtk_widget_synthesize_crossing (NULL, widget, d->data,
+ GDK_CROSSING_STATE_CHANGED);
+ }
+
+ g_list_free (devices);
+ }
if (GTK_IS_CONTAINER (widget))
{
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index daa20ae..cbe0873 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -906,12 +906,16 @@ void _gtk_widget_propagate_screen_changed (GtkWidget *widget,
GdkScreen *previous_screen);
void _gtk_widget_propagate_composited_changed (GtkWidget *widget);
-void _gtk_widget_set_pointer_window (GtkWidget *widget,
+void _gtk_widget_set_device_window (GtkWidget *widget,
+ GdkDevice *device,
GdkWindow *pointer_window);
-GdkWindow *_gtk_widget_get_pointer_window (GtkWidget *widget);
-gboolean _gtk_widget_is_pointer_widget (GtkWidget *widget);
+GdkWindow *_gtk_widget_get_device_window (GtkWidget *widget,
+ GdkDevice *device);
+GList * _gtk_widget_list_devices (GtkWidget *widget);
+
void _gtk_widget_synthesize_crossing (GtkWidget *from,
GtkWidget *to,
+ GdkDevice *device,
GdkCrossingMode mode);
GdkColormap* _gtk_widget_peek_colormap (void);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]