[tomboy] Delay most work until after tray icon appears for 0.65 second startup



commit 5620e88354b6e3f0e2ad7ee31394981251945792
Author: Sandy Armstrong <sanfordarmstrong gmail com>
Date:   Sun Jan 24 17:32:54 2010 -0800

    Delay most work until after tray icon appears for 0.65 second startup
    
    Refactor NoteManager to push its work to an Initialize method, and
    provide Invoke methods that allow code to be executed only when the
    NoteManager is fully initialized.
    
    Use these Invoke methods to make clicking the tray icon and using global
    keybindings safe.  RemoteControl work is on the way.
    
    Also delay SyncManager and ApplicationAddin initialization.

 Tomboy/Applet.cs         |   37 ++++++++++++++++----------
 Tomboy/NoteManager.cs    |   65 +++++++++++++++++++++++++++++++++++++--------
 Tomboy/PrefsKeybinder.cs |   22 ++++++++++-----
 Tomboy/Tomboy.cs         |   25 ++++++++++++-----
 Tomboy/Tray.cs           |   16 +++++-----
 5 files changed, 115 insertions(+), 50 deletions(-)
---
diff --git a/Tomboy/Applet.cs b/Tomboy/Applet.cs
index 05c1973..dab49f1 100644
--- a/Tomboy/Applet.cs
+++ b/Tomboy/Applet.cs
@@ -188,19 +188,24 @@ namespace Tomboy
 
 		void ButtonPress (object sender, Gtk.ButtonPressEventArgs args)
 		{
+
 			Gtk.Widget parent = (Gtk.Widget) sender;
 
 			switch (args.Event.Button) {
 			case 1:
-				TomboyTrayUtils.UpdateTomboyTrayMenu (tray, parent);
-				GuiUtils.PopupMenu (tray.TomboyTrayMenu, args.Event);
+				manager.GtkInvoke (() => {
+					TomboyTrayUtils.UpdateTomboyTrayMenu (tray, parent);
+					GuiUtils.PopupMenu (tray.TomboyTrayMenu, args.Event);
+				});
 				args.RetVal = true;
 				break;
 			case 2:
 				if ((bool) Preferences.Get (Preferences.ENABLE_ICON_PASTE)) {
 					// Give some visual feedback
 					Gtk.Drag.Highlight (this);
-					args.RetVal = PastePrimaryClipboard ();
+					manager.GtkInvoke (() => {
+						args.RetVal = PastePrimaryClipboard ();
+					});
 					Gtk.Drag.Unhighlight (this);
 				}
 				break;
@@ -276,11 +281,13 @@ namespace Tomboy
 
 		public void ShowMenu (bool select_first_item)
 		{
-			TomboyTrayUtils.UpdateTomboyTrayMenu (tray, this);
-			if (select_first_item)
-				tray.TomboyTrayMenu.SelectFirst (false);
+			manager.GtkInvoke (() => {
+				TomboyTrayUtils.UpdateTomboyTrayMenu (tray, this);
+				if (select_first_item)
+					tray.TomboyTrayMenu.SelectFirst (false);
 
-			GuiUtils.PopupMenu (tray.TomboyTrayMenu, null);
+				GuiUtils.PopupMenu (tray.TomboyTrayMenu, null);
+			});
 		}
 
 		// Support dropping text/uri-lists and _NETSCAPE_URLs currently.
@@ -329,13 +336,15 @@ namespace Tomboy
 				more_than_one = true;
 			}
 
-			Note link_note = manager.FindByUri (NoteManager.StartNoteUri);
-			if (link_note != null) {
-				link_note.Window.Present ();
-				PrependTimestampedText (link_note,
-				                        DateTime.Now,
-				                        insert_text.ToString ());
-			}
+			manager.GtkInvoke (() => {
+				Note link_note = manager.FindByUri (NoteManager.StartNoteUri);
+				if (link_note != null) {
+					link_note.Window.Present ();
+					PrependTimestampedText (link_note,
+					                        DateTime.Now,
+					                        insert_text.ToString ());
+				}
+			});
 		}
 
 		void InitPixbuf ()
diff --git a/Tomboy/NoteManager.cs b/Tomboy/NoteManager.cs
index 76c6a07..c2850ea 100644
--- a/Tomboy/NoteManager.cs
+++ b/Tomboy/NoteManager.cs
@@ -2,6 +2,8 @@
 using System;
 using System.IO;
 using System.Collections.Generic;
+using System.Threading;
+
 using Mono.Unix;
 
 namespace Tomboy
@@ -20,16 +22,6 @@ namespace Tomboy
 
 		static string start_note_uri = String.Empty;
 
-		static NoteManager ()
-		{
-			// Watch the START_NOTE_URI setting and update it so that the
-			// StartNoteUri property doesn't generate a call to
-			// Preferences.Get () each time it's accessed.
-			start_note_uri =
-			        Preferences.Get (Preferences.START_NOTE_URI) as string;
-			Preferences.SettingChanged += OnSettingChanged;
-		}
-
 		static void OnSettingChanged (object sender, NotifyEventArgs args)
 		{
 			switch (args.Key) {
@@ -39,8 +31,8 @@ namespace Tomboy
 			}
 		}
 
-public NoteManager (string directory) :
-		this (directory, Path.Combine (directory, "Backup"))
+		public NoteManager (string directory) :
+			this (directory, Path.Combine (directory, "Backup"))
 		{
 		}
 
@@ -50,6 +42,45 @@ public NoteManager (string directory) :
 
 			notes_dir = directory;
 			backup_dir = backup_directory;
+		}
+
+		public bool Initialized {
+			get; private set;
+		}
+
+		/// <summary>
+		/// Use Gtk.Application.Invoke to invoke the Action delegate
+		/// once this NoteManager is initialized. If this NoteManager
+		/// is already initialized, Gtk.Application.Invoke is *not*
+		/// used (for performance reasons).  In other words, this method
+		/// should only be called from the GTK+ main thread.
+		/// </summary>
+		public void GtkInvoke (Action a)
+		{
+			if (!Initialized)
+				new Thread (() => {
+					while (!Initialized)
+						;
+					Gtk.Application.Invoke ((o, e) => a ());
+				}).Start ();
+			else
+				a ();
+		}
+
+		public void Invoke (Action a)
+		{
+			if (!Initialized)
+				new Thread (() => {
+					while (!Initialized)
+						;
+					a ();
+				}).Start ();
+			else
+				a ();
+		}
+
+		public void Initialize ()
+		{
 			notes = new List<Note> ();
 
 			string conf_dir = Services.NativeApplication.ConfigurationDirectory;
@@ -160,6 +191,7 @@ Ciao!");
 			}
 
 			Tomboy.ExitingEvent += OnExitingEvent;
+			Initialized = true;
 		}
 		
 		
@@ -600,6 +632,15 @@ Ciao!");
 		public static string StartNoteUri
 		{
 			get {
+				if (String.IsNullOrEmpty (start_note_uri)) {
+					// Watch the START_NOTE_URI setting and update it so that the
+					// StartNoteUri property doesn't generate a call to
+					// Preferences.Get () each time it's accessed.
+					start_note_uri =
+					        Preferences.Get (Preferences.START_NOTE_URI) as string;
+					Preferences.SettingChanged -= OnSettingChanged;
+					Preferences.SettingChanged += OnSettingChanged;
+				}
 				return start_note_uri;
 			}
 		}
diff --git a/Tomboy/PrefsKeybinder.cs b/Tomboy/PrefsKeybinder.cs
index 24bd527..57b09ab 100644
--- a/Tomboy/PrefsKeybinder.cs
+++ b/Tomboy/PrefsKeybinder.cs
@@ -126,7 +126,7 @@ namespace Tomboy
 	public class TomboyPrefsKeybinder : PrefsKeybinder
 	{
 		NoteManager manager;
-		ITomboyTray  tray;
+		ITomboyTray tray;
 
 		public TomboyPrefsKeybinder (NoteManager manager, ITomboyTray tray)
 				: base ()
@@ -187,16 +187,20 @@ namespace Tomboy
 
 		void KeyOpenStartHere (object sender, EventArgs args)
 		{
-			Note note = manager.FindByUri (NoteManager.StartNoteUri);
-			if (note != null)
-				note.Window.Present ();
+			manager.GtkInvoke (() => {
+				Note note = manager.FindByUri (NoteManager.StartNoteUri);
+				if (note != null)
+					note.Window.Present ();
+			});
 		}
 
 		void KeyCreateNewNote (object sender, EventArgs args)
 		{
 			try {
-				Note new_note = manager.Create ();
-				new_note.Window.Show ();
+				manager.GtkInvoke (() => {
+					Note new_note = manager.Create ();
+					new_note.Window.Show ();
+				});
 			} catch {
 				// Fail silently.
 			}
@@ -214,8 +218,10 @@ namespace Tomboy
 
 		void KeyOpenRecentChanges (object sender, EventArgs args)
 		{
-			NoteRecentChanges recent = NoteRecentChanges.GetInstance (manager);
-			recent.Present ();
+			manager.GtkInvoke (() => {
+				NoteRecentChanges recent = NoteRecentChanges.GetInstance (manager);
+				recent.Present ();
+			});
 		}
 	}
 }
diff --git a/Tomboy/Tomboy.cs b/Tomboy/Tomboy.cs
index 319630b..7d5c098 100644
--- a/Tomboy/Tomboy.cs
+++ b/Tomboy/Tomboy.cs
@@ -95,20 +95,12 @@ namespace Tomboy
 			string note_path = GetNotePath (cmd_line.NotePath);
 			manager = new NoteManager (note_path);
 
-			SyncManager.Initialize ();
-
 			// Register the manager to handle remote requests.
 			RegisterRemoteControl (manager);
 
 			SetupGlobalActions ();
 			ActionManager am = Tomboy.ActionManager;
 
-			ApplicationAddin [] addins =
-			        manager.AddinManager.GetApplicationAddins ();
-			foreach (ApplicationAddin addin in addins) {
-				addin.Initialize ();
-			}
-
 #if !ENABLE_DBUS
 			if (cmd_line.NeedsExecute && RemoteControlProxy.FirstInstance) {
 				// Execute args on this instance
@@ -137,6 +129,23 @@ namespace Tomboy
 			}
 #endif
 
+			// TODO: Instead of just delaying, lazy-load
+			//       (only an issue for add-ins that need to be
+			//       available at Tomboy startup, and restoring
+			//       previously-opened notes)
+			GLib.Timeout.Add (500, () => {
+				manager.Initialize ();
+				SyncManager.Initialize ();
+
+				ApplicationAddin [] addins =
+				        manager.AddinManager.GetApplicationAddins ();
+				foreach (ApplicationAddin addin in addins) {
+					addin.Initialize ();
+				}
+
+				return false;
+			});
+
 			if (is_panel_applet) {
 				tray_icon_showing = true;
 
diff --git a/Tomboy/Tray.cs b/Tomboy/Tray.cs
index eeeac32..f6e5fc3 100644
--- a/Tomboy/Tray.cs
+++ b/Tomboy/Tray.cs
@@ -185,14 +185,14 @@ namespace Tomboy
 			if (context_menu != null)
 				context_menu.Hide ();
 
-			TomboyTrayUtils.UpdateTomboyTrayMenu (tray, null);
-			if (select_first_item)
-				tray.TomboyTrayMenu.SelectFirst (false);
-
-			
-				
-			GuiUtils.PopupMenu (tray.TomboyTrayMenu, null, 
-				new Gtk.MenuPositionFunc (GetTrayMenuPosition));
+			tray.NoteManager.GtkInvoke (() => {
+				TomboyTrayUtils.UpdateTomboyTrayMenu (tray, null);
+				if (select_first_item)
+					tray.TomboyTrayMenu.SelectFirst (false);
+
+				GuiUtils.PopupMenu (tray.TomboyTrayMenu, null,
+					new Gtk.MenuPositionFunc (GetTrayMenuPosition));
+			});
 		}
 		
 		public void GetTrayMenuPosition (Gtk.Menu menu,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]