diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2013-06-17 22:18:02 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2013-06-17 22:18:02 +0800 |
commit | 340c64e42d3018942af7bd1ac696d660e57ec082 (patch) | |
tree | 775cd1bcde0eb1d4edd643c91b65a6302a532db1 | |
parent | 0c2b350db0029ff07fff8b2d5d55a9aedafbfe17 (diff) | |
download | gsoc2013-evolution-340c64e42d3018942af7bd1ac696d660e57ec082.tar.gz gsoc2013-evolution-340c64e42d3018942af7bd1ac696d660e57ec082.tar.zst gsoc2013-evolution-340c64e42d3018942af7bd1ac696d660e57ec082.zip |
Bug 702454 - EMailBrowser fails to show message
This reworks the MessageList regen scheduling to be a little more
intuitive, at least to me. We now set the RegenData immediately, but
start the actual regen operation from an idle callback. That way the
caller has the remainder of this main loop iteration to make further
MessageList changes without triggering additional regens.
I think what was happening before was we were triggering multiple regen
operations as we were configuring the EMailBrowser, with each new regen
cancelling the previous, and the message UID to select wound up getting
paired with one of the cancelled regen operations. This resulted in no
message UID ever getting selected in the EMailBrowser.
-rw-r--r-- | mail/message-list.c | 81 |
1 files changed, 44 insertions, 37 deletions
diff --git a/mail/message-list.c b/mail/message-list.c index ffa20e166f..ada7f11871 100644 --- a/mail/message-list.c +++ b/mail/message-list.c @@ -97,7 +97,7 @@ struct _MessageListPrivate { /* For message list regeneration. */ GMutex regen_lock; RegenData *regen_data; - guint regen_timeout_id; + guint regen_idle_id; struct _MLSelection clipboard; gboolean destroyed; @@ -5499,7 +5499,7 @@ message_list_regen_done_cb (GObject *source_object, } static gboolean -message_list_regen_timeout_cb (gpointer user_data) +message_list_regen_idle_cb (gpointer user_data) { GSimpleAsyncResult *simple; RegenData *regen_data; @@ -5510,7 +5510,7 @@ message_list_regen_timeout_cb (gpointer user_data) cancellable = e_activity_get_cancellable (regen_data->activity); g_mutex_lock (®en_data->message_list->priv->regen_lock); - regen_data->message_list->priv->regen_timeout_id = 0; + regen_data->message_list->priv->regen_idle_id = 0; g_mutex_unlock (®en_data->message_list->priv->regen_lock); if (g_cancellable_is_cancelled (cancellable)) { @@ -5536,9 +5536,9 @@ mail_regen_cancel (MessageList *message_list) if (message_list->priv->regen_data != NULL) regen_data = regen_data_ref (message_list->priv->regen_data); - if (message_list->priv->regen_timeout_id > 0) { - g_source_remove (message_list->priv->regen_timeout_id); - message_list->priv->regen_timeout_id = 0; + if (message_list->priv->regen_idle_id > 0) { + g_source_remove (message_list->priv->regen_idle_id); + message_list->priv->regen_idle_id = 0; } g_mutex_unlock (&message_list->priv->regen_lock); @@ -5571,6 +5571,28 @@ mail_regen_list (MessageList *message_list, return; } + g_mutex_lock (&message_list->priv->regen_lock); + + old_regen_data = message_list->priv->regen_data; + + /* If a regen is scheduled but not yet started, just + * apply the argument values without cancelling it. */ + if (message_list->priv->regen_idle_id > 0) { + g_return_if_fail (old_regen_data != NULL); + + if (g_strcmp0 (search, old_regen_data->search) != 0) { + g_free (old_regen_data->search); + old_regen_data->search = g_strdup (search); + } + + old_regen_data->folder_changed = folder_changed; + + /* Avoid cancelling on the way out. */ + old_regen_data = NULL; + + goto exit; + } + cancellable = g_cancellable_new (); new_regen_data = regen_data_new (message_list, cancellable); @@ -5592,36 +5614,27 @@ mail_regen_list (MessageList *message_list, regen_data_ref (new_regen_data), (GDestroyNotify) regen_data_unref); - /* Swap the old regen data (if present) for the new regen data. */ - - g_mutex_lock (&message_list->priv->regen_lock); + /* Set the RegenData immediately, but start the actual regen + * operation from an idle callback. That way the caller has + * the remainder of this main loop iteration to make further + * MessageList changes without triggering additional regens. */ - old_regen_data = message_list->priv->regen_data; message_list->priv->regen_data = regen_data_ref (new_regen_data); - if (message_list->priv->regen_timeout_id > 0) { - g_source_remove (message_list->priv->regen_timeout_id); - message_list->priv->regen_timeout_id = 0; - } + message_list->priv->regen_idle_id = + g_idle_add_full ( + G_PRIORITY_DEFAULT_IDLE, + message_list_regen_idle_cb, + g_object_ref (simple), + (GDestroyNotify) g_object_unref); - /* Start the regen after a short timeout, so normal updates - * are immediate. XXX Do we still need to do this timeout? - * What are "normal" updates? */ - if (old_regen_data != NULL) { - message_list->priv->regen_timeout_id = - g_timeout_add_full ( - G_PRIORITY_DEFAULT, 50, - message_list_regen_timeout_cb, - g_object_ref (simple), - (GDestroyNotify) g_object_unref); - } else { - g_simple_async_result_run_in_thread ( - simple, - message_list_regen_thread, - G_PRIORITY_DEFAULT, - cancellable); - } + g_object_unref (simple); + + regen_data_unref (new_regen_data); + g_object_unref (cancellable); + +exit: g_mutex_unlock (&message_list->priv->regen_lock); /* Cancel outside the lock, since this will emit a signal. */ @@ -5629,10 +5642,4 @@ mail_regen_list (MessageList *message_list, e_activity_cancel (old_regen_data->activity); regen_data_unref (old_regen_data); } - - g_object_unref (simple); - - regen_data_unref (new_regen_data); - - g_object_unref (cancellable); } |