[libwnck] core: Add wnck_shutdown()



commit 040a3b358840a8ef32f9f64792bb41a5327cd81c
Author: Martin Pitt <martin pitt ubuntu com>
Date:   Wed Jan 18 16:51:13 2012 +0100

    core: Add wnck_shutdown()
    
    Add wnck_shutdown() method that stops listening to events and tear down all
    resources from libwnck. This should be done if you are not going to need the
    state change notifications for an extended period of time, to avoid wakeups
    with every key and focus event. After this all Wnck object references you might
    still hold are invalid.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=642692

 libwnck/application.c |   23 ++++++++++++++++++++++-
 libwnck/class-group.c |   19 +++++++++++++++++++
 libwnck/private.h     |    6 ++++++
 libwnck/screen.c      |   39 ++++++++++++++++++++++++++++++++++++++-
 libwnck/util.c        |   20 ++++++++++++++++++++
 libwnck/util.h        |    2 ++
 libwnck/window.c      |   16 ++++++++++++++--
 libwnck/xutils.c      |   31 +++++++++++++++++++++++++------
 libwnck/xutils.h      |    8 +++++---
 9 files changed, 151 insertions(+), 13 deletions(-)
---
diff --git a/libwnck/application.c b/libwnck/application.c
index 1c05419..9171549 100644
--- a/libwnck/application.c
+++ b/libwnck/application.c
@@ -557,7 +557,8 @@ _wnck_application_create (Window      xwindow,
    */
   _wnck_select_input (xscreen,
                       application->priv->xwindow,
-                      WNCK_APP_WINDOW_EVENT_MASK);
+                      WNCK_APP_WINDOW_EVENT_MASK,
+                      TRUE);
 
   return application;
 }
@@ -676,6 +677,26 @@ _wnck_application_process_property_notify (WnckApplication *app,
 }
 
 static void
+_wnck_app_iter_destroy_application (gpointer key,
+                                    gpointer value,
+                                    gpointer user_data)
+{
+  g_object_unref (WNCK_APPLICATION (value));
+}
+
+void
+_wnck_application_shutdown_all (void)
+{
+  if (app_hash != NULL)
+    {
+      g_hash_table_foreach (app_hash, _wnck_app_iter_destroy_application, NULL);
+      g_hash_table_destroy (app_hash);
+      app_hash = NULL;
+    }
+}
+
+
+static void
 emit_name_changed (WnckApplication *app)
 {
   g_signal_emit (G_OBJECT (app),
diff --git a/libwnck/class-group.c b/libwnck/class-group.c
index f0fee23..56e48d2 100644
--- a/libwnck/class-group.c
+++ b/libwnck/class-group.c
@@ -636,3 +636,22 @@ wnck_class_group_get_mini_icon (WnckClassGroup *class_group)
 
   return class_group->priv->mini_icon;
 }
+
+static void
+_wnck_class_iter_destroy_class_group (gpointer key,
+                                      gpointer value,
+                                      gpointer user_data)
+{
+  g_object_unref (WNCK_CLASS_GROUP (value));
+}
+
+void
+_wnck_class_group_shutdown_all (void)
+{
+  if (class_group_hash != NULL)
+    {
+      g_hash_table_foreach (class_group_hash, _wnck_class_iter_destroy_class_group, NULL);
+      g_hash_table_destroy (class_group_hash);
+      class_group_hash = NULL;
+    }
+}
diff --git a/libwnck/private.h b/libwnck/private.h
index b4d6572..4175f70 100644
--- a/libwnck/private.h
+++ b/libwnck/private.h
@@ -55,6 +55,7 @@ WnckWindow* _wnck_window_create  (Window      xwindow,
                                   WnckScreen *screen,
                                   gint        sort_order);
 void        _wnck_window_destroy (WnckWindow *window);
+void        _wnck_window_shutdown (WnckWindow *window);
 
 char*       _wnck_window_get_name_for_display (WnckWindow *window,
                                                gboolean    use_icon_name,
@@ -88,6 +89,7 @@ void _wnck_application_remove_window (WnckApplication *app,
 WnckApplication* _wnck_application_create  (Window           xwindow,
                                             WnckScreen      *screen);
 void             _wnck_application_destroy (WnckApplication *app);
+void             _wnck_application_shutdown_all (void);
 
 
 WnckClassGroup*  _wnck_class_group_create        (const char     *res_class);
@@ -96,6 +98,7 @@ void             _wnck_class_group_add_window    (WnckClassGroup *class_group,
                                                   WnckWindow     *window);
 void             _wnck_class_group_remove_window (WnckClassGroup *class_group,
                                                   WnckWindow     *window);
+void             _wnck_class_group_shutdown_all  (void);
 
 void _wnck_workspace_update_name (WnckWorkspace *workspace,
                                   const char    *name);
@@ -103,6 +106,9 @@ void _wnck_screen_change_workspace_name (WnckScreen *screen,
                                          int         number,
                                          const char *name);
 
+void _wnck_screen_shutdown              (WnckScreen *screen);
+void _wnck_screen_shutdown_all          (void);
+
 gboolean _wnck_workspace_set_geometry (WnckWorkspace *space, int w, int h);
 gboolean _wnck_workspace_set_viewport (WnckWorkspace *space, int x, int y);
 
diff --git a/libwnck/screen.c b/libwnck/screen.c
index fabbac0..11f4e30 100644
--- a/libwnck/screen.c
+++ b/libwnck/screen.c
@@ -597,7 +597,8 @@ wnck_screen_construct (Display    *display,
 
   _wnck_select_input (screen->priv->xscreen,
                       screen->priv->xroot,
-                      PropertyChangeMask);
+                      PropertyChangeMask,
+                      TRUE);
 
   screen->priv->need_update_workspace_list = TRUE;
   screen->priv->need_update_stack_list = TRUE;
@@ -2755,3 +2756,39 @@ _wnck_screen_change_workspace_name (WnckScreen *screen,
 
   g_free (names);
 }
+
+void
+_wnck_screen_shutdown (WnckScreen *screen)
+{
+  GList *item;
+  g_return_if_fail (WNCK_IS_SCREEN (screen));
+
+  _wnck_select_input (screen->priv->xscreen,
+                      screen->priv->xroot,
+                      0,
+                      FALSE);
+  for (item = screen->priv->mapped_windows; item != NULL; item = g_list_next (item))
+    _wnck_window_shutdown (WNCK_WINDOW (item->data));
+  wnck_screen_finalize (G_OBJECT (screen));
+}
+
+void
+_wnck_screen_shutdown_all (void)
+{
+  int i;
+  Display *display;
+
+  if (screens == NULL)
+    return;
+
+  display = _wnck_get_default_display ();
+
+  for (i = 0; i < ScreenCount (display); ++i)
+    {
+      if (screens[i] != NULL)
+        _wnck_screen_shutdown (screens[i]);
+    }
+
+  g_free (screens);
+  screens = NULL;
+}
diff --git a/libwnck/util.c b/libwnck/util.c
index 2977604..3172e1d 100644
--- a/libwnck/util.c
+++ b/libwnck/util.c
@@ -785,3 +785,23 @@ _wnck_stock_icons_init (void)
 
   g_object_unref (G_OBJECT (factory));
 }
+
+/**
+ * wnck_shutdown:
+ *
+ * Stop listening to events and tear down all resources from libwnck. This
+ * should be done if you are not going to need the state change notifications
+ * for an extended period of time, to avoid wakeups with every key and focus
+ * event. After this all Wnck object references you might still hold are
+ * invalid.
+ *
+ * Since: 3.4
+ */
+void
+wnck_shutdown (void)
+{
+  _wnck_event_filter_shutdown ();
+  _wnck_screen_shutdown_all ();
+  _wnck_class_group_shutdown_all ();
+  _wnck_application_shutdown_all ();
+}
diff --git a/libwnck/util.h b/libwnck/util.h
index eda722b..ee9aa3a 100644
--- a/libwnck/util.h
+++ b/libwnck/util.h
@@ -112,6 +112,8 @@ void wnck_pid_read_resource_usage (GdkDisplay        *gdk_display,
                                    gulong             pid,
                                    WnckResourceUsage *usage);
 
+void wnck_shutdown                (void);
+
 G_END_DECLS
 
 #endif /* WNCK_UTIL_H */
diff --git a/libwnck/window.c b/libwnck/window.c
index e418dcf..3c6584b 100644
--- a/libwnck/window.c
+++ b/libwnck/window.c
@@ -78,6 +78,7 @@ struct _WnckWindowPrivate
   WnckClassGroup *class_group;
   Window group_leader;
   Window transient_for;
+  int orig_event_mask;
   GdkRectangle icon_geometry;
   char *name;
   char *icon_name;
@@ -222,6 +223,7 @@ wnck_window_init (WnckWindow *window)
   window->priv->class_group = NULL;
   window->priv->group_leader = None;
   window->priv->transient_for = None;
+  window->priv->orig_event_mask = 0;
   window->priv->icon_geometry.width = -1; /* invalid cached value */
   window->priv->name = NULL;
   window->priv->icon_name = NULL;
@@ -521,9 +523,10 @@ _wnck_window_create (Window      xwindow,
    * that's why we select the union of the mask we want for Application
    * and the one we want for window
    */
-  _wnck_select_input (xscreen,
+  window->priv->orig_event_mask =_wnck_select_input (xscreen,
                       window->priv->xwindow,
-                      WNCK_APP_WINDOW_EVENT_MASK);
+                      WNCK_APP_WINDOW_EVENT_MASK,
+                      TRUE);
 
   /* Default the group leader to the window itself; it is set in
    * update_wmhints() if a different group leader is specified.
@@ -571,6 +574,8 @@ _wnck_window_create (Window      xwindow,
 void
 _wnck_window_destroy (WnckWindow *window)
 {
+  g_return_if_fail (WNCK_IS_WINDOW (window));
+
   g_return_if_fail (wnck_window_get (window->priv->xwindow) == window);
 
   g_hash_table_remove (window_hash, &window->priv->xwindow);
@@ -583,6 +588,13 @@ _wnck_window_destroy (WnckWindow *window)
   g_object_unref (G_OBJECT (window));
 }
 
+void
+_wnck_window_shutdown (WnckWindow *window)
+{
+  _wnck_select_input (WNCK_SCREEN_XSCREEN (window->priv->screen),
+          window->priv->xwindow, window->priv->orig_event_mask, FALSE);
+}
+
 static Display *
 _wnck_window_get_display (WnckWindow *window)
 {
diff --git a/libwnck/xutils.c b/libwnck/xutils.c
index 484fbc7..42b6ba8 100644
--- a/libwnck/xutils.c
+++ b/libwnck/xutils.c
@@ -789,15 +789,27 @@ filter_func (GdkXEvent  *gdkxevent,
   return GDK_FILTER_CONTINUE;
 }
 
+static gboolean _wnck_event_filter_initialized = FALSE;
+
 void
 _wnck_event_filter_init (void)
 {
-  static gboolean initialized = FALSE;
 
-  if (!initialized)
+  if (!_wnck_event_filter_initialized)
     {
       gdk_window_add_filter (NULL, filter_func, NULL);
-      initialized = TRUE;
+      _wnck_event_filter_initialized = TRUE;
+    }
+}
+
+void
+_wnck_event_filter_shutdown (void)
+{
+
+  if (_wnck_event_filter_initialized)
+    {
+      gdk_window_remove_filter (NULL, filter_func, NULL);
+      _wnck_event_filter_initialized = FALSE;
     }
 }
 
@@ -1361,13 +1373,15 @@ _wnck_get_frame_extents (Screen *screen,
   return retval;
 }
 
-void
+int
 _wnck_select_input (Screen *screen,
                     Window  xwindow,
-                    int     mask)
+                    int     mask,
+                    gboolean update)
 {
   Display   *display;
   GdkWindow *gdkwindow;
+  int old_mask = 0;
 
   display = DisplayOfScreen (screen);
 
@@ -1383,11 +1397,16 @@ _wnck_select_input (Screen *screen,
        */
       XWindowAttributes attrs;
       XGetWindowAttributes (display, xwindow, &attrs);
-      mask |= attrs.your_event_mask;
+      old_mask = attrs.your_event_mask;
+
+      if (update)
+        mask |= attrs.your_event_mask;
     }
 
   XSelectInput (display, xwindow, mask);
   _wnck_error_trap_pop (display);
+
+  return old_mask;
 }
 
 /* The icon-reading code is copied
diff --git a/libwnck/xutils.h b/libwnck/xutils.h
index 2d9cbe8..97545ae 100644
--- a/libwnck/xutils.h
+++ b/libwnck/xutils.h
@@ -93,6 +93,7 @@ int  _wnck_error_trap_pop  (Display *display);
 #define _wnck_atom_name(atom)     gdk_x11_get_xatom_name (atom)
 
 void _wnck_event_filter_init (void);
+void _wnck_event_filter_shutdown (void);
 
 int   _wnck_xid_equal (gconstpointer v1,
                        gconstpointer v2);
@@ -146,9 +147,10 @@ gboolean _wnck_get_frame_extents  (Screen *screen,
                                    int    *top_frame,
                                    int    *bottom_frame);
 
-void   _wnck_select_input     (Screen *screen,
-                               Window  xwindow,
-                               int     mask);
+int    _wnck_select_input     (Screen  *screen,
+                               Window   xwindow,
+                               int      mask,
+                               gboolean update);
 
 void   _wnck_keyboard_move    (Screen *screen,
                                Window  xwindow);



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