summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pitt <martin.pitt@ubuntu.com>2012-01-18 16:51:13 +0100
committerVincent Untz <vuntz@gnome.org>2012-01-30 15:05:40 +0100
commit040a3b358840a8ef32f9f64792bb41a5327cd81c (patch)
tree3d626f7874a2e202ad17567252e5f838140f5db0
parent085a93c7fd1f235def445823b06ffef5b6343810 (diff)
downloadlibwnck-040a3b358840a8ef32f9f64792bb41a5327cd81c.tar.gz
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
-rw-r--r--libwnck/application.c23
-rw-r--r--libwnck/class-group.c19
-rw-r--r--libwnck/private.h6
-rw-r--r--libwnck/screen.c39
-rw-r--r--libwnck/util.c20
-rw-r--r--libwnck/util.h2
-rw-r--r--libwnck/window.c16
-rw-r--r--libwnck/xutils.c31
-rw-r--r--libwnck/xutils.h8
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);