aboutsummaryrefslogtreecommitdiffstats
path: root/shell
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2013-10-18 22:20:51 +0800
committerMilan Crha <mcrha@redhat.com>2013-10-18 22:20:51 +0800
commit431d7188c500d2879b015a308513e7388be19b00 (patch)
tree7c2e4dc175e2142f5d01660c67ef7a6434f78ed2 /shell
parent7cc6ab171116a07482120a0f766299e9697026c0 (diff)
downloadgsoc2013-evolution-431d7188c500d2879b015a308513e7388be19b00.tar
gsoc2013-evolution-431d7188c500d2879b015a308513e7388be19b00.tar.gz
gsoc2013-evolution-431d7188c500d2879b015a308513e7388be19b00.tar.bz2
gsoc2013-evolution-431d7188c500d2879b015a308513e7388be19b00.tar.lz
gsoc2013-evolution-431d7188c500d2879b015a308513e7388be19b00.tar.xz
gsoc2013-evolution-431d7188c500d2879b015a308513e7388be19b00.tar.zst
gsoc2013-evolution-431d7188c500d2879b015a308513e7388be19b00.zip
Bug #710171 - EShellTaskbar: Gtk+ functions called out of the main thread
Diffstat (limited to 'shell')
-rw-r--r--shell/e-shell-taskbar.c106
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);