diff options
author | Milan Crha <mcrha@redhat.com> | 2013-10-18 22:20:51 +0800 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2013-10-18 22:20:51 +0800 |
commit | 431d7188c500d2879b015a308513e7388be19b00 (patch) | |
tree | 7c2e4dc175e2142f5d01660c67ef7a6434f78ed2 | |
parent | 7cc6ab171116a07482120a0f766299e9697026c0 (diff) | |
download | gsoc2013-evolution-431d7188c500d2879b015a308513e7388be19b00.tar.gz gsoc2013-evolution-431d7188c500d2879b015a308513e7388be19b00.tar.zst gsoc2013-evolution-431d7188c500d2879b015a308513e7388be19b00.zip |
Bug #710171 - EShellTaskbar: Gtk+ functions called out of the main thread
-rw-r--r-- | shell/e-shell-taskbar.c | 106 |
1 files changed, 96 insertions, 10 deletions
diff --git a/shell/e-shell-taskbar.c b/shell/e-shell-taskbar.c index cda9fee8e0..53db054cfa 100644 --- a/shell/e-shell-taskbar.c +++ b/shell/e-shell-taskbar.c @@ -53,6 +53,10 @@ struct _EShellTaskbarPrivate { GHashTable *proxy_table; gint fixed_height; + + /* Basically the main() thread, aka UI thread, where the gtk calls + * can be done. */ + GThread *main_thread; }; enum { @@ -68,29 +72,78 @@ G_DEFINE_TYPE_WITH_CODE ( G_IMPLEMENT_INTERFACE ( E_TYPE_EXTENSIBLE, NULL)) +typedef struct { + EShellTaskbar *shell_taskbar; + EActivity *activity; + GtkWidget *proxy; /* not referenced */ +} EShellTaskbarIdleData; + +static void +shell_taskbar_free_idle_data (gpointer data) +{ + EShellTaskbarIdleData *idle_data = data; + + g_clear_object (&idle_data->shell_taskbar); + g_clear_object (&idle_data->activity); + g_free (idle_data); +} + +static void +shell_taskbar_remove_proxy_container (EShellTaskbar *shell_taskbar, + GtkWidget *proxy) +{ + GList *children; + GtkContainer *container; + + container = GTK_CONTAINER (shell_taskbar->priv->hbox); + gtk_container_remove (container, proxy); + + children = gtk_container_get_children (container); + + if (children == NULL) + gtk_widget_hide (GTK_WIDGET (container)); + + g_list_free (children); +} + +static gboolean +shell_taskbar_remove_proxy_container_idle_cb (gpointer user_data) +{ + EShellTaskbarIdleData *idle_data = user_data; + + g_return_val_if_fail (idle_data != NULL, FALSE); + g_return_val_if_fail (idle_data->shell_taskbar != NULL, FALSE); + g_return_val_if_fail (idle_data->proxy != NULL, FALSE); + + shell_taskbar_remove_proxy_container (idle_data->shell_taskbar, idle_data->proxy); + + return FALSE; +} + static void shell_taskbar_weak_notify_cb (EShellTaskbar *shell_taskbar, GObject *where_the_activity_was) { GtkWidget *proxy; - GtkContainer *container; GHashTable *proxy_table; - GList *children; proxy_table = shell_taskbar->priv->proxy_table; proxy = g_hash_table_lookup (proxy_table, where_the_activity_was); g_hash_table_remove (proxy_table, where_the_activity_was); g_return_if_fail (proxy != NULL); - container = GTK_CONTAINER (shell_taskbar->priv->hbox); - gtk_container_remove (container, proxy); - - children = gtk_container_get_children (container); + if (shell_taskbar->priv->main_thread == g_thread_self ()) { + shell_taskbar_remove_proxy_container (shell_taskbar, proxy); + } else { + EShellTaskbarIdleData *idle_data; - if (children == NULL) - gtk_widget_hide (GTK_WIDGET (container)); + idle_data = g_new0 (EShellTaskbarIdleData, 1); + idle_data->shell_taskbar = g_object_ref (shell_taskbar); + idle_data->proxy = proxy; - g_list_free (children); + g_idle_add_full (G_PRIORITY_DEFAULT, shell_taskbar_remove_proxy_container_idle_cb, + idle_data, shell_taskbar_free_idle_data); + } } static void @@ -132,6 +185,38 @@ shell_taskbar_activity_add (EShellTaskbar *shell_taskbar, } static gboolean +shell_taskbar_add_activity_idle_cb (gpointer user_data) +{ + EShellTaskbarIdleData *idle_data = user_data; + + g_return_val_if_fail (idle_data != NULL, FALSE); + g_return_val_if_fail (idle_data->shell_taskbar != NULL, FALSE); + g_return_val_if_fail (idle_data->activity != NULL, FALSE); + + shell_taskbar_activity_add (idle_data->shell_taskbar, idle_data->activity); + + return FALSE; +} + +static void +shell_taskbar_activity_added_cb (EShellTaskbar *shell_taskbar, + EActivity *activity) +{ + if (shell_taskbar->priv->main_thread == g_thread_self ()) { + shell_taskbar_activity_add (shell_taskbar, activity); + } else { + EShellTaskbarIdleData *idle_data; + + idle_data = g_new0 (EShellTaskbarIdleData, 1); + idle_data->shell_taskbar = g_object_ref (shell_taskbar); + idle_data->activity = g_object_ref (activity); + + g_idle_add_full (G_PRIORITY_DEFAULT, shell_taskbar_add_activity_idle_cb, + idle_data, shell_taskbar_free_idle_data); + } +} + +static gboolean shell_taskbar_weak_unref (EActivity *activity, EActivityProxy *proxy, EShellTaskbar *shell_taskbar) @@ -263,7 +348,7 @@ shell_taskbar_constructed (GObject *object) g_signal_connect_swapped ( shell_backend, "activity-added", - G_CALLBACK (shell_taskbar_activity_add), shell_taskbar); + G_CALLBACK (shell_taskbar_activity_added_cb), shell_taskbar); e_extensible_load_extensions (E_EXTENSIBLE (object)); @@ -382,6 +467,7 @@ e_shell_taskbar_init (EShellTaskbar *shell_taskbar) shell_taskbar->priv = E_SHELL_TASKBAR_GET_PRIVATE (shell_taskbar); shell_taskbar->priv->proxy_table = g_hash_table_new (NULL, NULL); + shell_taskbar->priv->main_thread = g_thread_self (); gtk_box_set_spacing (GTK_BOX (shell_taskbar), 12); |