diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 136440a6547..25d9c5d2dbe 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -58,7 +58,6 @@ public partial class MainWindow : IDisposable // Window Animation private const double DefaultRightMargin = 66; //* this value from base.xaml - private bool _animating; private bool _isClockPanelAnimating = false; // IDisposable @@ -76,7 +75,7 @@ public MainWindow() DataContext = _viewModel; InitializeComponent(); - UpdatePosition(true); + UpdatePosition(); InitSoundEffects(); DataObject.AddPastingHandler(QueryTextBox, QueryTextBox_OnPaste); @@ -112,7 +111,7 @@ private async void OnLoaded(object sender, RoutedEventArgs _) } // Hide window if need - UpdatePosition(true); + UpdatePosition(); if (_settings.HideOnStartup) { _viewModel.Hide(); @@ -139,7 +138,7 @@ private async void OnLoaded(object sender, RoutedEventArgs _) InitProgressbarAnimation(); // Force update position - UpdatePosition(true); + UpdatePosition(); // Refresh frame await Ioc.Default.GetRequiredService().RefreshFrameAsync(); @@ -167,7 +166,7 @@ private async void OnLoaded(object sender, RoutedEventArgs _) SoundPlay(); } - UpdatePosition(false); + UpdatePosition(); _viewModel.ResetPreview(); Activate(); QueryTextBox.Focus(); @@ -234,7 +233,7 @@ private async void OnLoaded(object sender, RoutedEventArgs _) // Detect History.Visibility changes DependencyPropertyDescriptor - .FromProperty(VisibilityProperty, typeof(StackPanel)) // History는 StackPanel이라고 가정 + .FromProperty(VisibilityProperty, typeof(StackPanel)) .AddValueChanged(History, (s, e) => UpdateClockPanelVisibility()); } @@ -269,8 +268,6 @@ private void OnClosed(object sender, EventArgs e) private void OnLocationChanged(object sender, EventArgs e) { - if (_animating) return; - if (_settings.SearchWindowScreen == SearchWindowScreens.RememberLastLaunchLocation) { _settings.WindowLeft = Left; @@ -282,9 +279,11 @@ private async void OnDeactivated(object sender, EventArgs e) { _settings.WindowLeft = Left; _settings.WindowTop = Top; + ClockPanel.Opacity = 0; SearchIcon.Opacity = 0; - //This condition stops extra hide call when animator is on, + + // This condition stops extra hide call when animator is on, // which causes the toggling to occasional hide instead of show. if (_viewModel.MainWindowVisibilityStatus) { @@ -292,7 +291,6 @@ private async void OnDeactivated(object sender, EventArgs e) // This also stops the mainwindow from flickering occasionally after Settings window is opened // and always after Settings window is closed. if (_settings.UseAnimation) - await Task.Delay(100); if (_settings.HideWhenDeactivated && !_viewModel.ExternalPreviewVisible) @@ -590,13 +588,8 @@ private void UpdateNotifyIconText() #region Window Position - private void UpdatePosition(bool force) + private void UpdatePosition() { - if (_animating && !force) - { - return; - } - // Initialize call twice to work around multi-display alignment issue- https://github.com/Flow-Launcher/Flow.Launcher/issues/2910 InitializePosition(); InitializePosition(); @@ -770,19 +763,17 @@ private void InitProgressbarAnimation() private void WindowAnimation() { - if (_animating) - return; - _isArrowKeyPressed = true; - _animating = true; - UpdatePosition(false); - ClockPanel.Opacity = 0; - SearchIcon.Opacity = 0; - + UpdatePosition(); + + var opacity = _settings.UseAnimation ? 0.0 : 1.0; + ClockPanel.Opacity = opacity; + SearchIcon.Opacity = opacity; + var clocksb = new Storyboard(); var iconsb = new Storyboard(); - CircleEase easing = new CircleEase { EasingMode = EasingMode.EaseInOut }; + var easing = new CircleEase { EasingMode = EasingMode.EaseInOut }; var animationLength = _settings.AnimationSpeed switch { @@ -810,7 +801,7 @@ private void WindowAnimation() FillBehavior = FillBehavior.HoldEnd }; - double TargetIconOpacity = GetOpacityFromStyle(SearchIcon.Style, 1.0); + var TargetIconOpacity = GetOpacityFromStyle(SearchIcon.Style, 1.0); var IconOpacity = new DoubleAnimation { @@ -821,7 +812,7 @@ private void WindowAnimation() FillBehavior = FillBehavior.HoldEnd }; - double rightMargin = GetThicknessFromStyle(ClockPanel.Style, new Thickness(0, 0, DefaultRightMargin, 0)).Right; + var rightMargin = GetThicknessFromStyle(ClockPanel.Style, new Thickness(0, 0, DefaultRightMargin, 0)).Right; var thicknessAnimation = new ThicknessAnimation { @@ -848,16 +839,11 @@ private void WindowAnimation() clocksb.Children.Add(ClockOpacity); iconsb.Children.Add(IconMotion); iconsb.Children.Add(IconOpacity); - - clocksb.Completed += (_, _) => _animating = false; + _settings.WindowLeft = Left; _isArrowKeyPressed = false; - - if (QueryTextBox.Text.Length == 0) - { - clocksb.Begin(ClockPanel); - } - + + clocksb.Begin(ClockPanel); iconsb.Begin(SearchIcon); } diff --git a/Flow.Launcher/Resources/Dark.xaml b/Flow.Launcher/Resources/Dark.xaml index 25cc8e878e3..f1ebba080a2 100644 --- a/Flow.Launcher/Resources/Dark.xaml +++ b/Flow.Launcher/Resources/Dark.xaml @@ -115,6 +115,8 @@ + + diff --git a/Flow.Launcher/Resources/Light.xaml b/Flow.Launcher/Resources/Light.xaml index b9f65ce9650..12b35971d20 100644 --- a/Flow.Launcher/Resources/Light.xaml +++ b/Flow.Launcher/Resources/Light.xaml @@ -107,6 +107,7 @@ + diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index a81d9e0d108..6d629de6329 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -18,6 +18,8 @@ Loaded="OnLoaded" MouseDown="window_MouseDown" ResizeMode="CanResize" + SnapsToDevicePixels="True" + UseLayoutRounding="True" StateChanged="Window_StateChanged" Top="{Binding SettingWindowTop, Mode=TwoWay}" WindowStartupLocation="Manual" @@ -54,6 +56,7 @@ Width="16" Height="16" Margin="10 4 4 4" + RenderOptions.BitmapScalingMode="HighQuality" Source="/Images/app.png" /> Force query even when Query Text doesn't change public void ChangeQueryText(string queryText, bool isReQuery = false) { - Application.Current.Dispatcher.Invoke(() => + _ = ChangeQueryTextAsync(queryText, isReQuery); + } + + /// + /// Async version of + /// + private async Task ChangeQueryTextAsync(string queryText, bool isReQuery = false) + { + await Application.Current.Dispatcher.InvokeAsync(async () => { BackToQueryResults(); @@ -644,7 +652,7 @@ public void ChangeQueryText(string queryText, bool isReQuery = false) } else if (isReQuery) { - Query(isReQuery: true); + await QueryAsync(isReQuery: true); } QueryTextCursorMovedToEnd = true; @@ -1016,10 +1024,15 @@ private bool QueryResultsPreviewed() #region Query private void Query(bool isReQuery = false) + { + _ = QueryAsync(isReQuery); + } + + private async Task QueryAsync(bool isReQuery = false) { if (QueryResultsSelected()) { - _ = QueryResultsAsync(isReQuery); + await QueryResultsAsync(isReQuery); } else if (ContextMenuSelected()) { @@ -1053,10 +1066,10 @@ private void QueryContextMenu() ( r => { - var match = StringMatcher.FuzzySearch(query, r.Title); + var match = App.API.FuzzySearch(query, r.Title); if (!match.IsSearchPrecisionScoreMet()) { - match = StringMatcher.FuzzySearch(query, r.SubTitle); + match = App.API.FuzzySearch(query, r.SubTitle); } if (!match.IsSearchPrecisionScoreMet()) return false; @@ -1098,7 +1111,7 @@ private void QueryHistory() Action = _ => { SelectedResults = Results; - ChangeQueryText(h.Query); + App.API.ChangeQuery(h.Query); return false; } }; @@ -1109,8 +1122,8 @@ private void QueryHistory() { var filtered = results.Where ( - r => StringMatcher.FuzzySearch(query, r.Title).IsSearchPrecisionScoreMet() || - StringMatcher.FuzzySearch(query, r.SubTitle).IsSearchPrecisionScoreMet() + r => App.API.FuzzySearch(query, r.Title).IsSearchPrecisionScoreMet() || + App.API.FuzzySearch(query, r.SubTitle).IsSearchPrecisionScoreMet() ).ToList(); History.AddResults(filtered, id); } @@ -1429,36 +1442,57 @@ public bool ShouldIgnoreHotkeys() #region Public Methods - public void Show() +#pragma warning disable VSTHRD100 // Avoid async void methods + + public async void Show() { - Application.Current.Dispatcher.Invoke(() => + await Application.Current.Dispatcher.InvokeAsync(() => { if (Application.Current.MainWindow is MainWindow mainWindow) { // 📌 Remove DWM Cloak (Make the window visible normally) Win32Helper.DWMSetCloakForWindow(mainWindow, false); + // Clock and SearchIcon hide when show situation + var opacity = Settings.UseAnimation ? 0.0 : 1.0; + mainWindow.ClockPanel.Opacity = opacity; + mainWindow.SearchIcon.Opacity = opacity; + + if (QueryText.Length != 0) + { + mainWindow.ClockPanel.Visibility = Visibility.Collapsed; + } + else + { + mainWindow.ClockPanel.Visibility = Visibility.Visible; + } + + if (PluginIconSource != null) + { + mainWindow.SearchIcon.Opacity = 0; + } + else + { + SearchIconVisibility = Visibility.Visible; + } + // 📌 Restore UI elements - mainWindow.ClockPanel.Visibility = Visibility.Visible; //mainWindow.SearchIcon.Visibility = Visibility.Visible; - SearchIconVisibility = Visibility.Visible; } + }, DispatcherPriority.Render); - // Update WPF properties - MainWindowVisibility = Visibility.Visible; - MainWindowOpacity = 1; - MainWindowVisibilityStatus = true; - VisibilityChanged?.Invoke(this, new VisibilityChangedEventArgs { IsVisible = true }); + // Update WPF properties + MainWindowVisibility = Visibility.Visible; + MainWindowOpacity = 1; + MainWindowVisibilityStatus = true; + VisibilityChanged?.Invoke(this, new VisibilityChangedEventArgs { IsVisible = true }); - if (StartWithEnglishMode) - { - Win32Helper.SwitchToEnglishKeyboardLayout(true); - } - }); + if (StartWithEnglishMode) + { + Win32Helper.SwitchToEnglishKeyboardLayout(true); + } } -#pragma warning disable VSTHRD100 // Avoid async void methods - public async void Hide() { lastHistoryIndex = 1; @@ -1473,52 +1507,47 @@ public async void Hide() SelectedResults = Results; } - // 📌 Immediately apply text reset + force UI update - if (Settings.LastQueryMode == LastQueryMode.Empty) - { - ChangeQueryText(string.Empty); - await Task.Delay(1); // Wait for one frame to ensure UI reflects changes - Application.Current.Dispatcher.Invoke(Application.Current.MainWindow.UpdateLayout); // Force UI update - } - switch (Settings.LastQueryMode) { + case LastQueryMode.Empty: + await ChangeQueryTextAsync(string.Empty); + break; case LastQueryMode.Preserved: case LastQueryMode.Selected: - LastQuerySelected = (Settings.LastQueryMode == LastQueryMode.Preserved); + LastQuerySelected = Settings.LastQueryMode == LastQueryMode.Preserved; break; - case LastQueryMode.ActionKeywordPreserved: case LastQueryMode.ActionKeywordSelected: var newQuery = _lastQuery.ActionKeyword; + if (!string.IsNullOrEmpty(newQuery)) newQuery += " "; - ChangeQueryText(newQuery); + await ChangeQueryTextAsync(newQuery); if (Settings.LastQueryMode == LastQueryMode.ActionKeywordSelected) LastQuerySelected = false; break; } - if (Application.Current.MainWindow is MainWindow mainWindow) + await Application.Current.Dispatcher.InvokeAsync(() => { - // 📌 Set Opacity of icon and clock to 0 and apply Visibility.Hidden - Application.Current.Dispatcher.Invoke(() => + if (Application.Current.MainWindow is MainWindow mainWindow) { - mainWindow.ClockPanel.Opacity = 0; - mainWindow.SearchIcon.Opacity = 0; + // 📌 Set Opacity of icon and clock to 0 and apply Visibility.Hidden + var opacity = Settings.UseAnimation ? 0.0 : 1.0; + mainWindow.ClockPanel.Opacity = opacity; + mainWindow.SearchIcon.Opacity = opacity; mainWindow.ClockPanel.Visibility = Visibility.Hidden; - //mainWindow.SearchIcon.Visibility = Visibility.Hidden; SearchIconVisibility = Visibility.Hidden; // Force UI update mainWindow.ClockPanel.UpdateLayout(); mainWindow.SearchIcon.UpdateLayout(); - }, DispatcherPriority.Render); - // 📌 Apply DWM Cloak (Completely hide the window) - Win32Helper.DWMSetCloakForWindow(mainWindow, true); - } + // 📌 Apply DWM Cloak (Completely hide the window) + Win32Helper.DWMSetCloakForWindow(mainWindow, true); + } + }); if (StartWithEnglishMode) {