diff --git a/src/App.xaml.cs b/src/App.xaml.cs index 8a26a165..69b214fa 100644 --- a/src/App.xaml.cs +++ b/src/App.xaml.cs @@ -323,50 +323,53 @@ private void OnNotifyIconClick(object sender, System.Windows.Forms.MouseEventArg if (MainWindow.OwnedWindows.Cast().Any(window => window != null && window.IsDialog)) { MainWindow.Activate(); - MainWindow.Topmost = true; - MainWindow.Topmost = Settings.AlwaysOnTop; - return; } - switch (MainWindow.Visibility) + // Determine current window state + bool isWindowVisible = MainWindow.Visibility == Visibility.Visible; + bool isWindowMinimized = MainWindow.WindowState == WindowState.Minimized; + bool isWindowHidden = MainWindow.Visibility == Visibility.Hidden || MainWindow.Visibility == Visibility.Collapsed; + + if (!isWindowVisible || isWindowMinimized) { - case Visibility.Collapsed: - case Visibility.Hidden: - MainWindow.Show(); + // Restore window properly + MainWindow.ShowInTaskbar = true; + if (isWindowMinimized) + { MainWindow.WindowState = WindowState.Normal; + } + else if (isWindowHidden) + { + MainWindow.Show(); + } - MainWindow.Activate(); - MainWindow.Focus(); + MainWindow.Activate(); + MainWindow.Focus(); - MainWindow.Topmost = true; - MainWindow.Topmost = Settings.AlwaysOnTop; - MainWindow.ShowInTaskbar = true; + // Focus the Optimize button when restoring from notification area + MainWindow.Dispatcher.BeginInvoke((Action)(() => + { + var mainWindow = MainWindow as MainWindow; - // Focus the Optimize button when restoring from notification area - MainWindow.Dispatcher.BeginInvoke((Action)(() => + if (mainWindow != null) { - var mainWindow = MainWindow as MainWindow; + var optimizeButton = mainWindow.FindName("Optimize") as UIElement; - if (mainWindow != null) + if (optimizeButton != null) { - var optimizeButton = mainWindow.FindName("Optimize") as UIElement; - - if (optimizeButton != null) - { - Keyboard.Focus(optimizeButton); - FocusManager.SetFocusedElement(mainWindow, optimizeButton); - } + Keyboard.Focus(optimizeButton); + FocusManager.SetFocusedElement(mainWindow, optimizeButton); } - }), DispatcherPriority.ApplicationIdle); - break; - - case Visibility.Visible: - MainWindow.Hide(); - - MainWindow.ShowInTaskbar = false; - break; + } + }), DispatcherPriority.ApplicationIdle); + } + else + { + // Hide window + MainWindow.Hide(); + MainWindow.ShowInTaskbar = false; } ReleaseMemory(); @@ -485,8 +488,6 @@ protected override void OnStartup(StartupEventArgs startupEvent) mainWindow.Show(); mainWindow.Activate(); mainWindow.Focus(); - mainWindow.Topmost = true; - mainWindow.Topmost = Settings.AlwaysOnTop; } // Subscribe to power events diff --git a/src/Core/ObservableObject.cs b/src/Core/ObservableObject.cs index bb305f0f..47724f06 100644 --- a/src/Core/ObservableObject.cs +++ b/src/Core/ObservableObject.cs @@ -3,6 +3,7 @@ using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; +using System.Windows; namespace WinMemoryCleaner { @@ -30,7 +31,20 @@ public abstract class ObservableObject : INotifyPropertyChanged public void RaisePropertyChanged([CallerMemberName] string propertyName = null) { if (PropertyChanged != null) - PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); + { + var handler = PropertyChanged; + var args = new PropertyChangedEventArgs(propertyName); + + // Marshal to UI thread if necessary + if (Application.Current != null && Application.Current.Dispatcher != null && !Application.Current.Dispatcher.CheckAccess()) + { + Application.Current.Dispatcher.Invoke(handler, this, args); + } + else + { + handler.Invoke(this, args); + } + } } /// diff --git a/src/View/Window/MainWindow.xaml.cs b/src/View/Window/MainWindow.xaml.cs index 24f58b93..c958c37b 100644 --- a/src/View/Window/MainWindow.xaml.cs +++ b/src/View/Window/MainWindow.xaml.cs @@ -5,6 +5,7 @@ using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; +using System.Windows.Threading; namespace WinMemoryCleaner { @@ -213,8 +214,14 @@ private void OnOptimizeCommandCompleted() } else { - Thread.Sleep(1000); - App.Shutdown(); + // Use DispatcherTimer to avoid blocking the UI thread + var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(1000) }; + timer.Tick += (s, e) => + { + timer.Stop(); + App.Shutdown(); + }; + timer.Start(); } } else