private void App_OnStartup(object sender, StartupEventArgs e) { try { Log.Info("Boot strapping the services and UI."); // We manually close this because automatic closure steals focus from the // dynamic splash screen. splashScreen.Close(TimeSpan.FromSeconds(0.5f)); //Apply theme applyTheme(); //Define MainViewModel before services so I can setup a delegate to call into the MainViewModel //This is to work around the fact that the MainViewModel is created after the services. MainViewModel mainViewModel = null; Action <KeyValue> fireKeySelectionEvent = kv => { if (mainViewModel != null) //Access to modified closure is a good thing here, for once! { mainViewModel.FireKeySelectionEvent(kv); } }; CleanupAndPrepareCommuniKateInitialState(); ValidateDynamicKeyboardLocation(); // Handle plugins. Validate if directory exists and is accessible and pre-load all plugins, building a in-memory list of available ones. ValidatePluginsLocation(); if (Settings.Default.EnablePlugins) { PluginEngine.LoadAvailablePlugins(); } var presageInstallationProblem = PresageInstallationProblemsDetected(); //Create services var errorNotifyingServices = new List <INotifyErrors>(); IAudioService audioService = new AudioService(); IDictionaryService dictionaryService = new DictionaryService(Settings.Default.SuggestionMethod); IPublishService publishService = new PublishService(); ISuggestionStateService suggestionService = new SuggestionStateService(); ICalibrationService calibrationService = CreateCalibrationService(); ICapturingStateManager capturingStateManager = new CapturingStateManager(audioService); ILastMouseActionStateManager lastMouseActionStateManager = new LastMouseActionStateManager(); IKeyStateService keyStateService = new KeyStateService(suggestionService, capturingStateManager, lastMouseActionStateManager, calibrationService, fireKeySelectionEvent); IInputService inputService = CreateInputService(keyStateService, dictionaryService, audioService, calibrationService, capturingStateManager, errorNotifyingServices); IKeyboardOutputService keyboardOutputService = new KeyboardOutputService(keyStateService, suggestionService, publishService, dictionaryService, fireKeySelectionEvent); IMouseOutputService mouseOutputService = new MouseOutputService(publishService); errorNotifyingServices.Add(audioService); errorNotifyingServices.Add(dictionaryService); errorNotifyingServices.Add(publishService); errorNotifyingServices.Add(inputService); ReleaseKeysOnApplicationExit(keyStateService, publishService); //Compose UI var mainWindow = new MainWindow(audioService, dictionaryService, inputService, keyStateService); IWindowManipulationService mainWindowManipulationService = CreateMainWindowManipulationService(mainWindow); errorNotifyingServices.Add(mainWindowManipulationService); mainWindow.WindowManipulationService = mainWindowManipulationService; //Subscribing to the on closing events. mainWindow.Closing += dictionaryService.OnAppClosing; mainViewModel = new MainViewModel( audioService, calibrationService, dictionaryService, keyStateService, suggestionService, capturingStateManager, lastMouseActionStateManager, inputService, keyboardOutputService, mouseOutputService, mainWindowManipulationService, errorNotifyingServices); mainWindow.SetMainViewModel(mainViewModel); //Setup actions to take once main view is loaded (i.e. the view is ready, so hook up the services which kicks everything off) Action postMainViewLoaded = () => { mainViewModel.AttachErrorNotifyingServiceHandlers(); mainViewModel.AttachInputServiceEventHandlers(); }; mainWindow.AddOnMainViewLoadedAction(postMainViewLoaded); //Show the main window mainWindow.Show(); if (Settings.Default.LookToScrollShowOverlayWindow) { // Create the overlay window, but don't show it yet. It'll make itself visible when the conditions are right. new LookToScrollOverlayWindow(mainViewModel); } //Display splash screen and check for updates (and display message) after the window has been sized and positioned for the 1st time EventHandler sizeAndPositionInitialised = null; sizeAndPositionInitialised = async(_, __) => { mainWindowManipulationService.SizeAndPositionInitialised -= sizeAndPositionInitialised; //Ensure this handler only triggers once await ShowSplashScreen(inputService, audioService, mainViewModel, OptiKey.Properties.Resources.OPTIKEY_SYMBOL_DESCRIPTION); await mainViewModel.RaiseAnyPendingErrorToastNotifications(); await AttemptToStartMaryTTSService(inputService, audioService, mainViewModel); await AlertIfPresageBitnessOrBootstrapOrVersionFailure(presageInstallationProblem, inputService, audioService, mainViewModel); inputService.RequestResume(); //Start the input service await CheckForUpdates(inputService, audioService, mainViewModel); }; if (mainWindowManipulationService.SizeAndPositionIsInitialised) { sizeAndPositionInitialised(null, null); } else { mainWindowManipulationService.SizeAndPositionInitialised += sizeAndPositionInitialised; } Current.Exit += (o, args) => { mainWindowManipulationService.PersistSizeAndPosition(); Settings.Default.Save(); }; } catch (Exception ex) { Log.Error("Error starting up application", ex); throw; } }