Skip to content

Commit 0a497d8

Browse files
authored
Merge pull request #3390 from Flow-Launcher/fix_hide_window_startup
Fix hide window startup
2 parents fe62a03 + 91e2366 commit 0a497d8

File tree

2 files changed

+90
-91
lines changed

2 files changed

+90
-91
lines changed

Flow.Launcher/MainWindow.xaml.cs

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,16 @@ private async void OnLoaded(object sender, RoutedEventArgs _)
101101
// Check first launch
102102
if (_settings.FirstLaunch)
103103
{
104+
// Set First Launch to false
104105
_settings.FirstLaunch = false;
106+
107+
// Set Backdrop Type to Acrylic for Windows 11 when First Launch. Default is None
108+
if (Win32Helper.IsBackdropSupported()) _settings.BackdropType = BackdropTypes.Acrylic;
109+
110+
// Save settings
105111
App.API.SaveAppAllSettings();
106-
/* Set Backdrop Type to Acrylic for Windows 11 when First Launch. Default is None. */
107-
if (OperatingSystem.IsWindowsVersionAtLeast(10, 0, 22000))
108-
_settings.BackdropType = BackdropTypes.Acrylic;
112+
113+
// Show Welcome Window
109114
var WelcomeWindow = new WelcomeWindow();
110115
WelcomeWindow.Show();
111116
}
@@ -161,24 +166,68 @@ private async void OnLoaded(object sender, RoutedEventArgs _)
161166
{
162167
if (_viewModel.MainWindowVisibilityStatus)
163168
{
169+
// Set clock and search icon opacity
170+
var opacity = _settings.UseAnimation ? 0.0 : 1.0;
171+
ClockPanel.Opacity = opacity;
172+
SearchIcon.Opacity = opacity;
173+
174+
// Set clock and search icon visibility
175+
ClockPanel.Visibility = string.IsNullOrEmpty(_viewModel.QueryText) ? Visibility.Visible : Visibility.Collapsed;
176+
if (_viewModel.PluginIconSource != null)
177+
{
178+
SearchIcon.Opacity = 0.0;
179+
}
180+
else
181+
{
182+
_viewModel.SearchIconVisibility = Visibility.Visible;
183+
}
184+
185+
// Play sound effect before activing the window
164186
if (_settings.UseSound)
165187
{
166188
SoundPlay();
167189
}
168190

191+
// Update position & Activate
169192
UpdatePosition();
170-
_viewModel.ResetPreview();
171193
Activate();
172-
QueryTextBox.Focus();
173-
_settings.ActivateTimes++;
194+
195+
// Reset preview
196+
_viewModel.ResetPreview();
197+
198+
// Select last query if need
174199
if (!_viewModel.LastQuerySelected)
175200
{
176201
QueryTextBox.SelectAll();
177202
_viewModel.LastQuerySelected = true;
178203
}
179204

205+
// Focus query box
206+
QueryTextBox.Focus();
207+
208+
// Play window animation
180209
if (_settings.UseAnimation)
210+
{
181211
WindowAnimation();
212+
}
213+
214+
// Update activate times
215+
_settings.ActivateTimes++;
216+
}
217+
else
218+
{
219+
// Set clock and search icon opacity
220+
var opacity = _settings.UseAnimation ? 0.0 : 1.0;
221+
ClockPanel.Opacity = opacity;
222+
SearchIcon.Opacity = opacity;
223+
224+
// Set clock and search icon visibility
225+
ClockPanel.Visibility = Visibility.Hidden;
226+
_viewModel.SearchIconVisibility = Visibility.Hidden;
227+
228+
// Force UI update
229+
ClockPanel.UpdateLayout();
230+
SearchIcon.UpdateLayout();
182231
}
183232
});
184233
break;
@@ -191,7 +240,6 @@ private async void OnLoaded(object sender, RoutedEventArgs _)
191240
Dispatcher.Invoke(() => QueryTextBox.CaretIndex = QueryTextBox.Text.Length);
192241
_viewModel.QueryTextCursorMovedToEnd = false;
193242
}
194-
195243
break;
196244
case nameof(MainViewModel.GameModeStatus):
197245
_notifyIcon.Icon = _viewModel.GameModeStatus
@@ -248,7 +296,8 @@ private async void OnClosing(object sender, CancelEventArgs e)
248296
Notification.Uninstall();
249297
// After plugins are all disposed, we can close the main window
250298
_canClose = true;
251-
Close();
299+
// Use this instead of Close() to avoid InvalidOperationException when calling Close() in OnClosing event
300+
Application.Current.Shutdown();
252301
}
253302
}
254303

@@ -280,8 +329,8 @@ private async void OnDeactivated(object sender, EventArgs e)
280329
_settings.WindowLeft = Left;
281330
_settings.WindowTop = Top;
282331

283-
ClockPanel.Opacity = 0;
284-
SearchIcon.Opacity = 0;
332+
ClockPanel.Opacity = 0.0;
333+
SearchIcon.Opacity = 0.0;
285334

286335
// This condition stops extra hide call when animator is on,
287336
// which causes the toggling to occasional hide instead of show.
@@ -291,7 +340,9 @@ private async void OnDeactivated(object sender, EventArgs e)
291340
// This also stops the mainwindow from flickering occasionally after Settings window is opened
292341
// and always after Settings window is closed.
293342
if (_settings.UseAnimation)
343+
{
294344
await Task.Delay(100);
345+
}
295346

296347
if (_settings.HideWhenDeactivated && !_viewModel.ExternalPreviewVisible)
297348
{
@@ -765,12 +816,6 @@ private void WindowAnimation()
765816
{
766817
_isArrowKeyPressed = true;
767818

768-
UpdatePosition();
769-
770-
var opacity = _settings.UseAnimation ? 0.0 : 1.0;
771-
ClockPanel.Opacity = opacity;
772-
SearchIcon.Opacity = opacity;
773-
774819
var clocksb = new Storyboard();
775820
var iconsb = new Storyboard();
776821
var easing = new CircleEase { EasingMode = EasingMode.EaseInOut };
@@ -904,6 +949,7 @@ private void UpdateClockPanelVisibility()
904949

905950
ClockPanel.BeginAnimation(OpacityProperty, fadeOut);
906951
}
952+
907953
// ✅ 4. When showing ClockPanel (apply fade-in animation)
908954
else if (shouldShowClock && ClockPanel.Visibility != Visibility.Visible && !_isClockPanelAnimating)
909955
{
@@ -927,7 +973,6 @@ private void UpdateClockPanelVisibility()
927973
}
928974
}
929975

930-
931976
private static double GetOpacityFromStyle(Style style, double defaultOpacity = 1.0)
932977
{
933978
if (style == null)

Flow.Launcher/ViewModel/MainViewModel.cs

Lines changed: 28 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
using System.Windows;
1111
using System.Windows.Input;
1212
using System.Windows.Media;
13-
using System.Windows.Threading;
1413
using CommunityToolkit.Mvvm.DependencyInjection;
1514
using CommunityToolkit.Mvvm.Input;
1615
using Flow.Launcher.Core.Plugin;
@@ -213,7 +212,8 @@ async Task UpdateActionAsync()
213212
queue.Clear();
214213
}
215214

216-
Log.Error("MainViewModel", "Unexpected ResultViewUpdate ends");
215+
if (!_disposed)
216+
Log.Error("MainViewModel", "Unexpected ResultViewUpdate ends");
217217
}
218218

219219
void continueAction(Task t)
@@ -638,25 +638,29 @@ public void ChangeQueryText(string queryText, bool isReQuery = false)
638638
/// </summary>
639639
private async Task ChangeQueryTextAsync(string queryText, bool isReQuery = false)
640640
{
641-
await Application.Current.Dispatcher.InvokeAsync(async () =>
641+
// Must check access so that we will not block the UI thread which cause window visibility issue
642+
if (!Application.Current.Dispatcher.CheckAccess())
642643
{
643-
BackToQueryResults();
644+
await Application.Current.Dispatcher.InvokeAsync(() => ChangeQueryText(queryText, isReQuery));
645+
return;
646+
}
644647

645-
if (QueryText != queryText)
646-
{
647-
// re-query is done in QueryText's setter method
648-
QueryText = queryText;
649-
// set to false so the subsequent set true triggers
650-
// PropertyChanged and MoveQueryTextToEnd is called
651-
QueryTextCursorMovedToEnd = false;
652-
}
653-
else if (isReQuery)
654-
{
655-
await QueryAsync(isReQuery: true);
656-
}
648+
BackToQueryResults();
657649

658-
QueryTextCursorMovedToEnd = true;
659-
});
650+
if (QueryText != queryText)
651+
{
652+
// re-query is done in QueryText's setter method
653+
QueryText = queryText;
654+
// set to false so the subsequent set true triggers
655+
// PropertyChanged and MoveQueryTextToEnd is called
656+
QueryTextCursorMovedToEnd = false;
657+
}
658+
else if (isReQuery)
659+
{
660+
await QueryAsync(isReQuery: true);
661+
}
662+
663+
QueryTextCursorMovedToEnd = true;
660664
}
661665

662666
public bool LastQuerySelected { get; set; }
@@ -1444,43 +1448,10 @@ public bool ShouldIgnoreHotkeys()
14441448

14451449
#pragma warning disable VSTHRD100 // Avoid async void methods
14461450

1447-
public async void Show()
1451+
public void Show()
14481452
{
1449-
await Application.Current.Dispatcher.InvokeAsync(() =>
1450-
{
1451-
if (Application.Current.MainWindow is MainWindow mainWindow)
1452-
{
1453-
// 📌 Remove DWM Cloak (Make the window visible normally)
1454-
Win32Helper.DWMSetCloakForWindow(mainWindow, false);
1455-
1456-
// Clock and SearchIcon hide when show situation
1457-
var opacity = Settings.UseAnimation ? 0.0 : 1.0;
1458-
mainWindow.ClockPanel.Opacity = opacity;
1459-
mainWindow.SearchIcon.Opacity = opacity;
1460-
1461-
// QueryText sometimes is null when it is just initialized
1462-
if (QueryText != null && QueryText.Length != 0)
1463-
{
1464-
mainWindow.ClockPanel.Visibility = Visibility.Collapsed;
1465-
}
1466-
else
1467-
{
1468-
mainWindow.ClockPanel.Visibility = Visibility.Visible;
1469-
}
1470-
1471-
if (PluginIconSource != null)
1472-
{
1473-
mainWindow.SearchIcon.Opacity = 0;
1474-
}
1475-
else
1476-
{
1477-
SearchIconVisibility = Visibility.Visible;
1478-
}
1479-
1480-
// 📌 Restore UI elements
1481-
//mainWindow.SearchIcon.Visibility = Visibility.Visible;
1482-
}
1483-
}, DispatcherPriority.Render);
1453+
// 📌 Remove DWM Cloak (Make the window visible normally)
1454+
Win32Helper.DWMSetCloakForWindow(Application.Current.MainWindow, false);
14841455

14851456
// Update WPF properties
14861457
MainWindowVisibility = Visibility.Visible;
@@ -1496,6 +1467,9 @@ await Application.Current.Dispatcher.InvokeAsync(() =>
14961467

14971468
public async void Hide()
14981469
{
1470+
// 📌 Apply DWM Cloak (Completely hide the window)
1471+
Win32Helper.DWMSetCloakForWindow(Application.Current.MainWindow, true);
1472+
14991473
lastHistoryIndex = 1;
15001474

15011475
if (ExternalPreviewVisible)
@@ -1530,26 +1504,6 @@ public async void Hide()
15301504
break;
15311505
}
15321506

1533-
await Application.Current.Dispatcher.InvokeAsync(() =>
1534-
{
1535-
if (Application.Current.MainWindow is MainWindow mainWindow)
1536-
{
1537-
// 📌 Set Opacity of icon and clock to 0 and apply Visibility.Hidden
1538-
var opacity = Settings.UseAnimation ? 0.0 : 1.0;
1539-
mainWindow.ClockPanel.Opacity = opacity;
1540-
mainWindow.SearchIcon.Opacity = opacity;
1541-
mainWindow.ClockPanel.Visibility = Visibility.Hidden;
1542-
SearchIconVisibility = Visibility.Hidden;
1543-
1544-
// Force UI update
1545-
mainWindow.ClockPanel.UpdateLayout();
1546-
mainWindow.SearchIcon.UpdateLayout();
1547-
1548-
// 📌 Apply DWM Cloak (Completely hide the window)
1549-
Win32Helper.DWMSetCloakForWindow(mainWindow, true);
1550-
}
1551-
});
1552-
15531507
if (StartWithEnglishMode)
15541508
{
15551509
Win32Helper.RestorePreviousKeyboardLayout();

0 commit comments

Comments
 (0)