[gtk+/xi2: 1189/1239] GdkDisplay, GdkWindow: Free resources on ::device-removed.



commit 411a68d7bed4f36b1d721b9860b614f664134caa
Author: Carlos Garnacho <carlos gnome org>
Date:   Sat Sep 19 13:01:04 2009 +0200

    GdkDisplay, GdkWindow: Free resources on ::device-removed.

 gdk/gdkdisplay.c         |   51 +++++++++++++++++++++++++++++++++++++++++++--
 gdk/gdkwindow.c          |   26 +++++++++++++++++++++++
 gdk/x11/gdkdisplay-x11.c |    1 +
 3 files changed, 75 insertions(+), 3 deletions(-)
---
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index 0b8651a..f4eb449 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -33,12 +33,13 @@
 #include "gdkalias.h"
 
 enum {
+  OPENED,
   CLOSED,
   LAST_SIGNAL
 };
 
-static void gdk_display_dispose    (GObject         *object);
-static void gdk_display_finalize   (GObject         *object);
+static void gdk_display_dispose     (GObject         *object);
+static void gdk_display_finalize    (GObject         *object);
 
 static void        multihead_get_device_state           (GdkDisplay       *display,
                                                          GdkDevice        *device,
@@ -146,11 +147,24 @@ static void
 gdk_display_class_init (GdkDisplayClass *class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (class);
-  
+
   object_class->finalize = gdk_display_finalize;
   object_class->dispose = gdk_display_dispose;
 
   /**
+   * GdkDisplay::opened.
+   * @display: the object on which the signal is emitted
+   *
+   */
+  signals[OPENED] =
+    g_signal_new (g_intern_static_string ("opened"),
+		  G_OBJECT_CLASS_TYPE (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
+  /**
    * GdkDisplay::closed:
    * @display: the object on which the signal is emitted
    * @is_error: %TRUE if the display was closed due to an error
@@ -201,6 +215,29 @@ free_device_grabs_foreach (gpointer key,
 }
 
 static void
+device_removed_cb (GdkDeviceManager *device_manager,
+                   GdkDevice        *device,
+                   GdkDisplay       *display)
+{
+  g_hash_table_remove (display->multiple_click_info, device);
+  g_hash_table_remove (display->device_grabs, device);
+  g_hash_table_remove (display->pointers_info, device);
+
+  /* FIXME: change core pointer and remove from device list */
+}
+
+static void
+gdk_display_opened (GdkDisplay *display)
+{
+  GdkDeviceManager *device_manager;
+
+  device_manager = gdk_display_get_device_manager (display);
+
+  g_signal_connect (device_manager, "device-removed",
+                    G_CALLBACK (device_removed_cb), display);
+}
+
+static void
 gdk_display_init (GdkDisplay *display)
 {
   _gdk_displays = g_slist_prepend (_gdk_displays, display);
@@ -217,12 +254,18 @@ gdk_display_init (GdkDisplay *display)
 
   display->multiple_click_info = g_hash_table_new_full (NULL, NULL, NULL,
                                                         (GDestroyNotify) g_free);
+
+  g_signal_connect (display, "opened",
+                    G_CALLBACK (gdk_display_opened), NULL);
 }
 
 static void
 gdk_display_dispose (GObject *object)
 {
   GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
+  GdkDeviceManager *device_manager;
+
+  device_manager = gdk_display_get_device_manager (GDK_DISPLAY_OBJECT (object));
 
   g_list_foreach (display->queued_events, (GFunc)gdk_event_free, NULL);
   g_list_free (display->queued_events);
@@ -241,6 +284,8 @@ gdk_display_dispose (GObject *object)
                                                  NULL);
     }
 
+  g_signal_handlers_disconnect_by_func (device_manager, device_removed_cb, object);
+
   G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
 }
 
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 78b37b3..3152975 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -553,10 +553,30 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
 }
 
 static void
+device_removed_cb (GdkDeviceManager *device_manager,
+                   GdkDevice        *device,
+                   GdkWindow        *window)
+{
+  GdkWindowObject *private;
+
+  private = (GdkWindowObject *) window;
+
+  private->devices_inside = g_list_remove (private->devices_inside, device);
+  g_hash_table_remove (private->device_cursor, device);
+
+  if (private->device_events)
+    g_hash_table_remove (private->device_events, device);
+}
+
+static void
 gdk_window_finalize (GObject *object)
 {
   GdkWindow *window = GDK_WINDOW (object);
   GdkWindowObject *obj = (GdkWindowObject *) object;
+  GdkDeviceManager *device_manager;
+
+  device_manager = gdk_display_get_device_manager (GDK_WINDOW_DISPLAY (window));
+  g_signal_handlers_disconnect_by_func (device_manager, device_removed_cb, window);
 
   if (!GDK_WINDOW_DESTROYED (window))
     {
@@ -1201,6 +1221,7 @@ gdk_window_new (GdkWindow     *parent,
   gboolean native;
   GdkEventMask event_mask;
   GdkWindow *real_parent;
+  GdkDeviceManager *device_manager;
 
   g_return_val_if_fail (attributes != NULL, NULL);
 
@@ -1376,6 +1397,11 @@ gdk_window_new (GdkWindow     *parent,
 
   private->device_cursor = g_hash_table_new_full (NULL, NULL, NULL,
                                                   (GDestroyNotify) gdk_cursor_unref);
+
+  device_manager = gdk_display_get_device_manager (GDK_WINDOW_DISPLAY (parent));
+  g_signal_connect (device_manager, "device-removed",
+                    G_CALLBACK (device_removed_cb), window);
+
   return window;
 }
 
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index eb82d72..477dcce 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -1411,6 +1411,7 @@ gdk_display_open (const gchar *display_name)
     gdk_display_request_selection_notification (display, 
 						GDK_SCREEN_X11 (display_x11->screens[i])->cm_selection_atom);
 
+  g_signal_emit_by_name (display, "opened");
   g_signal_emit_by_name (gdk_display_manager_get(),
 			 "display_opened", display);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]