From 8a08e03cf95173b8c6c84166190832e5199b4118 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 28 Mar 2025 15:52:31 +0800 Subject: [PATCH 1/2] Bind to vm --- Flow.Launcher/MainWindow.xaml | 5 ++++- Flow.Launcher/ViewModel/MainViewModel.cs | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index 087b2e9985f..34b376cc9af 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -290,7 +290,9 @@ + Opacity="{Binding ClockPanelOpacity}" + Style="{DynamicResource ClockPanel}" + Visibility="{Binding ClockPanelVisibility}"> diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 6bfde42c51a..1631ff7c3eb 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -760,7 +760,10 @@ private ResultsViewModel SelectedResults public event VisibilityChangedEventHandler VisibilityChanged; + public Visibility ClockPanelVisibility { get; set; } public Visibility SearchIconVisibility { get; set; } + public double ClockPanelOpacity { get; set; } = 1; + public double SearchIconOpacity { get; set; } = 1; public double MainWindowWidth { From 693ba52fbc3e83775840e2f5591d88372b4dff4b Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 28 Mar 2025 16:13:02 +0800 Subject: [PATCH 2/2] Fix first-time window flicker & clock panel flicker issue --- Flow.Launcher/MainWindow.xaml.cs | 53 +++++------------------ Flow.Launcher/ViewModel/MainViewModel.cs | 55 +++++++++++++++++++++--- 2 files changed, 61 insertions(+), 47 deletions(-) diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 7b3814c874c..86b65386eed 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -166,22 +166,6 @@ private async void OnLoaded(object sender, RoutedEventArgs _) { if (_viewModel.MainWindowVisibilityStatus) { - // Set clock and search icon opacity - var opacity = _settings.UseAnimation ? 0.0 : 1.0; - ClockPanel.Opacity = opacity; - SearchIcon.Opacity = opacity; - - // Set clock and search icon visibility - ClockPanel.Visibility = string.IsNullOrEmpty(_viewModel.QueryText) ? Visibility.Visible : Visibility.Collapsed; - if (_viewModel.PluginIconSource != null) - { - SearchIcon.Opacity = 0.0; - } - else - { - _viewModel.SearchIconVisibility = Visibility.Visible; - } - // Play sound effect before activing the window if (_settings.UseSound) { @@ -214,21 +198,6 @@ private async void OnLoaded(object sender, RoutedEventArgs _) // Update activate times _settings.ActivateTimes++; } - else - { - // Set clock and search icon opacity - var opacity = _settings.UseAnimation ? 0.0 : 1.0; - ClockPanel.Opacity = opacity; - SearchIcon.Opacity = opacity; - - // Set clock and search icon visibility - ClockPanel.Visibility = Visibility.Hidden; - _viewModel.SearchIconVisibility = Visibility.Hidden; - - // Force UI update - ClockPanel.UpdateLayout(); - SearchIcon.UpdateLayout(); - } }); break; } @@ -329,8 +298,8 @@ private async void OnDeactivated(object sender, EventArgs e) _settings.WindowLeft = Left; _settings.WindowTop = Top; - ClockPanel.Opacity = 0.0; - SearchIcon.Opacity = 0.0; + _viewModel.ClockPanelOpacity = 0.0; + _viewModel.SearchIconOpacity = 0.0; // This condition stops extra hide call when animator is on, // which causes the toggling to occasional hide instead of show. @@ -908,28 +877,28 @@ private void UpdateClockPanelVisibility() var animationDuration = TimeSpan.FromMilliseconds(animationLength * 2 / 3); // ✅ Conditions for showing ClockPanel (No query input & ContextMenu, History are closed) - bool shouldShowClock = QueryTextBox.Text.Length == 0 && + var shouldShowClock = QueryTextBox.Text.Length == 0 && ContextMenu.Visibility != Visibility.Visible && History.Visibility != Visibility.Visible; // ✅ 1. When ContextMenu opens, immediately set Visibility.Hidden (force hide without animation) if (ContextMenu.Visibility == Visibility.Visible) { - ClockPanel.Visibility = Visibility.Hidden; - ClockPanel.Opacity = 0.0; // Set to 0 in case Opacity animation affects it + _viewModel.ClockPanelVisibility = Visibility.Hidden; + _viewModel.ClockPanelOpacity = 0.0; // Set to 0 in case Opacity animation affects it return; } // ✅ 2. When ContextMenu is closed, keep it Hidden if there's text in the query (remember previous state) if (ContextMenu.Visibility != Visibility.Visible && QueryTextBox.Text.Length > 0) { - ClockPanel.Visibility = Visibility.Hidden; - ClockPanel.Opacity = 0.0; + _viewModel.ClockPanelVisibility = Visibility.Hidden; + _viewModel.ClockPanelOpacity = 0.0; return; } // ✅ 3. When hiding ClockPanel (apply fade-out animation) - if ((!shouldShowClock) && ClockPanel.Visibility == Visibility.Visible && !_isClockPanelAnimating) + if ((!shouldShowClock) && _viewModel.ClockPanelVisibility == Visibility.Visible && !_isClockPanelAnimating) { _isClockPanelAnimating = true; @@ -943,7 +912,7 @@ private void UpdateClockPanelVisibility() fadeOut.Completed += (s, e) => { - ClockPanel.Visibility = Visibility.Hidden; // ✅ Completely hide after animation + _viewModel.ClockPanelVisibility = Visibility.Hidden; // ✅ Completely hide after animation _isClockPanelAnimating = false; }; @@ -951,13 +920,13 @@ private void UpdateClockPanelVisibility() } // ✅ 4. When showing ClockPanel (apply fade-in animation) - else if (shouldShowClock && ClockPanel.Visibility != Visibility.Visible && !_isClockPanelAnimating) + else if (shouldShowClock && _viewModel.ClockPanelVisibility != Visibility.Visible && !_isClockPanelAnimating) { _isClockPanelAnimating = true; Application.Current.Dispatcher.Invoke(() => { - ClockPanel.Visibility = Visibility.Visible; // ✅ Set Visibility to Visible first + _viewModel.ClockPanelVisibility = Visibility.Visible; // ✅ Set Visibility to Visible first var fadeIn = new DoubleAnimation { diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 1631ff7c3eb..18ee2cb5b65 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -10,6 +10,7 @@ using System.Windows; using System.Windows.Input; using System.Windows.Media; +using System.Windows.Threading; using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core.Plugin; @@ -1453,8 +1454,30 @@ public bool ShouldIgnoreHotkeys() public void Show() { - // 📌 Remove DWM Cloak (Make the window visible normally) - Win32Helper.DWMSetCloakForWindow(Application.Current.MainWindow, false); + Application.Current.Dispatcher.Invoke(() => + { + if (Application.Current.MainWindow is MainWindow mainWindow) + { + // 📌 Remove DWM Cloak (Make the window visible normally) + Win32Helper.DWMSetCloakForWindow(mainWindow, false); + + // Set clock and search icon opacity + var opacity = Settings.UseAnimation ? 0.0 : 1.0; + ClockPanelOpacity = opacity; + SearchIconOpacity = opacity; + + // Set clock and search icon visibility + ClockPanelVisibility = string.IsNullOrEmpty(QueryText) ? Visibility.Visible : Visibility.Collapsed; + if (PluginIconSource != null) + { + SearchIconOpacity = 0.0; + } + else + { + SearchIconVisibility = Visibility.Visible; + } + } + }, DispatcherPriority.Render); // Update WPF properties MainWindowVisibility = Visibility.Visible; @@ -1470,9 +1493,6 @@ public void Show() public async void Hide() { - // 📌 Apply DWM Cloak (Completely hide the window) - Win32Helper.DWMSetCloakForWindow(Application.Current.MainWindow, true); - lastHistoryIndex = 1; if (ExternalPreviewVisible) @@ -1507,11 +1527,36 @@ public async void Hide() break; } + Application.Current.Dispatcher.Invoke(() => + { + if (Application.Current.MainWindow is MainWindow mainWindow) + { + // Set clock and search icon opacity + var opacity = Settings.UseAnimation ? 0.0 : 1.0; + ClockPanelOpacity = opacity; + SearchIconOpacity = opacity; + + // Set clock and search icon visibility + ClockPanelVisibility = Visibility.Hidden; + SearchIconVisibility = Visibility.Hidden; + + // Force UI update + mainWindow.ClockPanel.UpdateLayout(); + mainWindow.SearchIcon.UpdateLayout(); + + // 📌 Apply DWM Cloak (Completely hide the window) + Win32Helper.DWMSetCloakForWindow(mainWindow, true); + } + }, DispatcherPriority.Render); + if (StartWithEnglishMode) { Win32Helper.RestorePreviousKeyboardLayout(); } + // Delay for a while to make sure clock will not flicker + await Task.Delay(50); + // Update WPF properties //MainWindowOpacity = 0; MainWindowVisibilityStatus = false;