diff options
author | Martin Pitt <martin.pitt@ubuntu.com> | 2012-01-18 16:51:13 +0100 |
---|---|---|
committer | Vincent Untz <vuntz@gnome.org> | 2012-01-30 15:05:40 +0100 |
commit | 040a3b358840a8ef32f9f64792bb41a5327cd81c (patch) | |
tree | 3d626f7874a2e202ad17567252e5f838140f5db0 | |
parent | 085a93c7fd1f235def445823b06ffef5b6343810 (diff) | |
download | libwnck-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.c | 23 | ||||
-rw-r--r-- | libwnck/class-group.c | 19 | ||||
-rw-r--r-- | libwnck/private.h | 6 | ||||
-rw-r--r-- | libwnck/screen.c | 39 | ||||
-rw-r--r-- | libwnck/util.c | 20 | ||||
-rw-r--r-- | libwnck/util.h | 2 | ||||
-rw-r--r-- | libwnck/window.c | 16 | ||||
-rw-r--r-- | libwnck/xutils.c | 31 | ||||
-rw-r--r-- | 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); |