From ba265448dfd0ac2cc6ccab1ed8b1e7d8739bf4e9 Mon Sep 17 00:00:00 2001 From: Jim Nelson Date: Wed, 28 Jan 2015 15:55:38 -0800 Subject: [PATCH] Don't select new conversation when conversation removed: Bug #743064 Selection change processing is now done in idle handler by ConversationListView to allow for back-to-back selection changes to be processed one time only, as well as to allow for ConversationMonitor signals to be handled in any order (by ConversationListStore and others). --- .../conversation-list-view.vala | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/client/conversation-list/conversation-list-view.vala b/src/client/conversation-list/conversation-list-view.vala index 08cf5f1b..a5cee8f8 100644 --- a/src/client/conversation-list/conversation-list-view.vala +++ b/src/client/conversation-list/conversation-list-view.vala @@ -19,6 +19,7 @@ public class ConversationListView : Gtk.TreeView { private Gee.Set? current_visible_conversations = null; private Geary.Scheduler.Scheduled? scheduled_update_visible_conversations = null; private Gtk.Menu? context_menu = null; + private uint selection_changed_id = 0; public signal void conversations_selected(Gee.Set selected); @@ -112,7 +113,7 @@ public class ConversationListView : Gtk.TreeView { private void on_conversation_removed(Geary.App.Conversation conversation) { if (!GearyApplication.instance.config.autoselect) - unselect_all(); + get_selection().unselect_all(); } private void on_conversations_added_began() { @@ -311,9 +312,29 @@ public class ConversationListView : Gtk.TreeView { return get_all_selected_paths().nth_data(0); } - // Gtk.TreeSelection can fire its "changed" signal even when nothing's changed, so look for that - // and prevent to avoid subscribers from doing the same things multiple times private void on_selection_changed() { + if (selection_changed_id != 0) + Source.remove(selection_changed_id); + + // Schedule processing selection changes at low idle for two reasons: (a) if a lot of + // changes come in back-to-back, this allows for all that activity to settle before + // updating state and firing signals (which results in a lot of I/O), and (b) it means + // the ConversationMonitor's signals may be processed in any order by this class and the + // ConversationListView and not result in a lot of screen flashing and (again) unnecessary + // I/O as both classes update selection state. + selection_changed_id = Idle.add(() => { + // no longer scheduled + selection_changed_id = 0; + + do_selection_changed(); + + return false; + }, Priority.LOW); + } + + // Gtk.TreeSelection can fire its "changed" signal even when nothing's changed, so look for that + // to avoid subscribers from doing the same things (in particular, I/O) multiple times + private void do_selection_changed() { // if the ConversationListStore is clearing, then this is called repeatedly as the elements // are removed, causing signals to fire and a flurry of I/O that is immediately cancelled // this prevents that, merely firing the signal once to indicate all selections are