Make gtk_widget_set_extension_events() work on already realized widgets
authorMichael Natterer <mitch@imendio.com>
Wed, 14 Mar 2007 13:55:12 +0000 (13:55 +0000)
committerMichael Natterer <mitch@src.gnome.org>
Wed, 14 Mar 2007 13:55:12 +0000 (13:55 +0000)
2007-03-14  Michael Natterer  <mitch@imendio.com>

Make gtk_widget_set_extension_events() work on already realized
widgets (bug #379550, Tommi Komulainen)

* gdk/x11/gdkinput.c (gdk_input_set_extension_events): allow to be
called multiple times without leaking and work correctly when
already realized (don't rely on a configure event following).

* gtk/gtkwidget.c (gtk_widget_set_extension_events_internal): new
internal function which walks the GdkWindow tree and sets the
extension events on all windows that belong to the widget.

(gtk_widget_realize)
(gtk_widget_set_extension_events): use the new function.

svn path=/trunk/; revision=17515

ChangeLog
gdk/x11/gdkinput.c
gtk/gtkwidget.c

index 5bb8b14a1375f44aca08fb67b1c5a5a26980bd93..9fbc61d17ceae2c648ef2232229ff6bd850411ca 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2007-03-14  Michael Natterer  <mitch@imendio.com>
+
+       Make gtk_widget_set_extension_events() work on already realized
+       widgets (bug #379550, Tommi Komulainen)
+
+       * gdk/x11/gdkinput.c (gdk_input_set_extension_events): allow to be
+       called multiple times without leaking and work correctly when
+       already realized (don't rely on a configure event following).
+
+       * gtk/gtkwidget.c (gtk_widget_set_extension_events_internal): new
+       internal function which walks the GdkWindow tree and sets the
+       extension events on all windows that belong to the widget.
+
+       (gtk_widget_realize)
+       (gtk_widget_set_extension_events): use the new function.
+
 2007-03-14  Emmanuele Bassi  <ebassi@gnome.org>
 
        Various clean ups in the GtkRecent code. (see #338843)
index f4d30cb2090e6917b311c05bacd1e7900433eae0..8d87479f0ee750e0f8791a8fa52edfd6190ea75d 100644 (file)
@@ -313,29 +313,42 @@ gdk_input_set_extension_events (GdkWindow *window, gint mask,
   if (mode == GDK_EXTENSION_EVENTS_NONE)
     mask = 0;
 
+  iw = _gdk_input_window_find (window);
+
   if (mask != 0)
     {
-      iw = g_new(GdkInputWindow,1);
+      if (!iw)
+        {
+          iw = g_new(GdkInputWindow,1);
+
+          iw->window = window;
+          iw->mode = mode;
 
-      iw->window = window;
-      iw->mode = mode;
+          iw->obscuring = NULL;
+          iw->num_obscuring = 0;
+          iw->grabbed = FALSE;
 
-      iw->obscuring = NULL;
-      iw->num_obscuring = 0;
-      iw->grabbed = FALSE;
+          display_x11->input_windows = g_list_append(display_x11->input_windows,iw);
+        }
 
-      display_x11->input_windows = g_list_append(display_x11->input_windows,iw);
       window_private->extension_events = mask;
 
+#ifndef XINPUT_NONE
       /* Add enter window events to the event mask */
-      /* FIXME, this is not needed for XINPUT_NONE */
+      /* this is not needed for XINPUT_NONE */
       gdk_window_set_events (window,
                             gdk_window_get_events (window) | 
                             GDK_ENTER_NOTIFY_MASK);
+
+      /* we might not receive ConfigureNotify so get the root_relative_geometry
+       * now, just in case */
+      _gdk_input_get_root_relative_geometry (GDK_WINDOW_XDISPLAY (window),
+                                             GDK_WINDOW_XWINDOW (window),
+                                             &iw->root_x, &iw->root_y, NULL, NULL);
+#endif /* !XINPUT_NONE */
     }
   else
     {
-      iw = _gdk_input_window_find (window);
       if (iw)
        {
          display_x11->input_windows = g_list_remove(display_x11->input_windows,iw);
index 2ea73c258fdd31079281c5838a3083fe5dce1dc4..f93b54e0d8a55ac2f9b087c74b48acc8fca2df12 100644 (file)
@@ -2618,6 +2618,51 @@ gtk_widget_unmap (GtkWidget *widget)
     }
 }
 
+static void
+gtk_widget_set_extension_events_internal (GtkWidget        *widget,
+                                          GdkExtensionMode  mode,
+                                          GList            *window_list)
+{
+  GList *free_list = NULL;
+  GList *l;
+
+  if (window_list == NULL)
+    {
+      if (!GTK_WIDGET_NO_WINDOW (widget))
+        window_list = g_list_prepend (NULL, widget->window);
+      else
+        window_list = gdk_window_get_children (widget->window);
+
+      free_list = window_list;
+    }
+
+  for (l = window_list; l != NULL; l = l->next)
+    {
+      GdkWindow *window = l->data;
+      gpointer user_data;
+
+      gdk_window_get_user_data (window, &user_data);
+      if (user_data == widget)
+        {
+          GList *children;
+
+          gdk_input_set_extension_events (window,
+                                          gdk_window_get_events (window),
+                                          mode);
+
+          children = gdk_window_get_children (window);
+          if (children)
+            {
+              gtk_widget_set_extension_events_internal (widget, mode, children);
+              g_list_free (children);
+            }
+        }
+    }
+
+  if (free_list)
+    g_list_free (free_list);
+}
+
 /**
  * gtk_widget_realize:
  * @widget: a #GtkWidget
@@ -2645,7 +2690,6 @@ gtk_widget_unmap (GtkWidget *widget)
 void
 gtk_widget_realize (GtkWidget *widget)
 {
-  gint events;
   GdkExtensionMode mode;
   GtkWidgetShapeInfo *shape_info;
   
@@ -2691,16 +2735,9 @@ gtk_widget_realize (GtkWidget *widget)
                                             shape_info->offset_x,
                                             shape_info->offset_y);
 
-      if (!GTK_WIDGET_NO_WINDOW (widget))
-       {
-         mode = gtk_widget_get_extension_events (widget);
-         if (mode != GDK_EXTENSION_EVENTS_NONE)
-           {
-             events = gtk_widget_get_events (widget);
-             gdk_input_set_extension_events (widget->window, events, mode);
-           }
-       }
-      
+      mode = gtk_widget_get_extension_events (widget);
+      if (mode != GDK_EXTENSION_EVENTS_NONE)
+        gtk_widget_set_extension_events_internal (widget, mode, NULL);
     }
 }
 
@@ -6572,21 +6609,23 @@ gtk_widget_add_events (GtkWidget *widget,
  *
  * Sets the extension events mask to @mode. See #GdkExtensionMode
  * and gdk_input_set_extension_events().
- * 
  **/
 void
 gtk_widget_set_extension_events (GtkWidget *widget,
                                 GdkExtensionMode mode)
 {
   GdkExtensionMode *modep;
-  
+
   g_return_if_fail (GTK_IS_WIDGET (widget));
-  
+
   modep = g_object_get_qdata (G_OBJECT (widget), quark_extension_event_mode);
-  
+
   if (!modep)
     modep = g_slice_new (GdkExtensionMode);
-  
+
+  if (GTK_WIDGET_REALIZED (widget))
+    gtk_widget_set_extension_events_internal (widget, mode, NULL);
+
   *modep = mode;
   g_object_set_qdata (G_OBJECT (widget), quark_extension_event_mode, modep);
   g_object_notify (G_OBJECT (widget), "extension-events");