Skip to content

Commit 21ddd70

Browse files
authored
Merge pull request #3391 from Flow-Launcher/fix_clock_flicker_issue
Fix first-time window flicker & clock panel flicker issue
2 parents 0a497d8 + 693ba52 commit 21ddd70

File tree

3 files changed

+68
-48
lines changed

3 files changed

+68
-48
lines changed

Flow.Launcher/MainWindow.xaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,9 @@
290290
<StackPanel
291291
x:Name="ClockPanel"
292292
IsHitTestVisible="False"
293-
Style="{DynamicResource ClockPanel}">
293+
Opacity="{Binding ClockPanelOpacity}"
294+
Style="{DynamicResource ClockPanel}"
295+
Visibility="{Binding ClockPanelVisibility}">
294296
<TextBlock
295297
x:Name="ClockBox"
296298
Style="{DynamicResource ClockBox}"
@@ -318,6 +320,7 @@
318320
Name="SearchIcon"
319321
Margin="0"
320322
Data="{DynamicResource SearchIconImg}"
323+
Opacity="{Binding SearchIconOpacity}"
321324
Stretch="Fill"
322325
Style="{DynamicResource SearchIconStyle}"
323326
Visibility="{Binding SearchIconVisibility}" />

Flow.Launcher/MainWindow.xaml.cs

Lines changed: 11 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -166,22 +166,6 @@ private async void OnLoaded(object sender, RoutedEventArgs _)
166166
{
167167
if (_viewModel.MainWindowVisibilityStatus)
168168
{
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-
185169
// Play sound effect before activing the window
186170
if (_settings.UseSound)
187171
{
@@ -214,21 +198,6 @@ private async void OnLoaded(object sender, RoutedEventArgs _)
214198
// Update activate times
215199
_settings.ActivateTimes++;
216200
}
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();
231-
}
232201
});
233202
break;
234203
}
@@ -329,8 +298,8 @@ private async void OnDeactivated(object sender, EventArgs e)
329298
_settings.WindowLeft = Left;
330299
_settings.WindowTop = Top;
331300

332-
ClockPanel.Opacity = 0.0;
333-
SearchIcon.Opacity = 0.0;
301+
_viewModel.ClockPanelOpacity = 0.0;
302+
_viewModel.SearchIconOpacity = 0.0;
334303

335304
// This condition stops extra hide call when animator is on,
336305
// which causes the toggling to occasional hide instead of show.
@@ -908,28 +877,28 @@ private void UpdateClockPanelVisibility()
908877
var animationDuration = TimeSpan.FromMilliseconds(animationLength * 2 / 3);
909878

910879
// ✅ Conditions for showing ClockPanel (No query input & ContextMenu, History are closed)
911-
bool shouldShowClock = QueryTextBox.Text.Length == 0 &&
880+
var shouldShowClock = QueryTextBox.Text.Length == 0 &&
912881
ContextMenu.Visibility != Visibility.Visible &&
913882
History.Visibility != Visibility.Visible;
914883

915884
// ✅ 1. When ContextMenu opens, immediately set Visibility.Hidden (force hide without animation)
916885
if (ContextMenu.Visibility == Visibility.Visible)
917886
{
918-
ClockPanel.Visibility = Visibility.Hidden;
919-
ClockPanel.Opacity = 0.0; // Set to 0 in case Opacity animation affects it
887+
_viewModel.ClockPanelVisibility = Visibility.Hidden;
888+
_viewModel.ClockPanelOpacity = 0.0; // Set to 0 in case Opacity animation affects it
920889
return;
921890
}
922891

923892
// ✅ 2. When ContextMenu is closed, keep it Hidden if there's text in the query (remember previous state)
924893
if (ContextMenu.Visibility != Visibility.Visible && QueryTextBox.Text.Length > 0)
925894
{
926-
ClockPanel.Visibility = Visibility.Hidden;
927-
ClockPanel.Opacity = 0.0;
895+
_viewModel.ClockPanelVisibility = Visibility.Hidden;
896+
_viewModel.ClockPanelOpacity = 0.0;
928897
return;
929898
}
930899

931900
// ✅ 3. When hiding ClockPanel (apply fade-out animation)
932-
if ((!shouldShowClock) && ClockPanel.Visibility == Visibility.Visible && !_isClockPanelAnimating)
901+
if ((!shouldShowClock) && _viewModel.ClockPanelVisibility == Visibility.Visible && !_isClockPanelAnimating)
933902
{
934903
_isClockPanelAnimating = true;
935904

@@ -943,21 +912,21 @@ private void UpdateClockPanelVisibility()
943912

944913
fadeOut.Completed += (s, e) =>
945914
{
946-
ClockPanel.Visibility = Visibility.Hidden; // ✅ Completely hide after animation
915+
_viewModel.ClockPanelVisibility = Visibility.Hidden; // ✅ Completely hide after animation
947916
_isClockPanelAnimating = false;
948917
};
949918

950919
ClockPanel.BeginAnimation(OpacityProperty, fadeOut);
951920
}
952921

953922
// ✅ 4. When showing ClockPanel (apply fade-in animation)
954-
else if (shouldShowClock && ClockPanel.Visibility != Visibility.Visible && !_isClockPanelAnimating)
923+
else if (shouldShowClock && _viewModel.ClockPanelVisibility != Visibility.Visible && !_isClockPanelAnimating)
955924
{
956925
_isClockPanelAnimating = true;
957926

958927
Application.Current.Dispatcher.Invoke(() =>
959928
{
960-
ClockPanel.Visibility = Visibility.Visible; // ✅ Set Visibility to Visible first
929+
_viewModel.ClockPanelVisibility = Visibility.Visible; // ✅ Set Visibility to Visible first
961930

962931
var fadeIn = new DoubleAnimation
963932
{

Flow.Launcher/ViewModel/MainViewModel.cs

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using System.Windows;
1111
using System.Windows.Input;
1212
using System.Windows.Media;
13+
using System.Windows.Threading;
1314
using CommunityToolkit.Mvvm.DependencyInjection;
1415
using CommunityToolkit.Mvvm.Input;
1516
using Flow.Launcher.Core.Plugin;
@@ -760,7 +761,10 @@ private ResultsViewModel SelectedResults
760761

761762
public event VisibilityChangedEventHandler VisibilityChanged;
762763

764+
public Visibility ClockPanelVisibility { get; set; }
763765
public Visibility SearchIconVisibility { get; set; }
766+
public double ClockPanelOpacity { get; set; } = 1;
767+
public double SearchIconOpacity { get; set; } = 1;
764768

765769
public double MainWindowWidth
766770
{
@@ -1450,8 +1454,30 @@ public bool ShouldIgnoreHotkeys()
14501454

14511455
public void Show()
14521456
{
1453-
// 📌 Remove DWM Cloak (Make the window visible normally)
1454-
Win32Helper.DWMSetCloakForWindow(Application.Current.MainWindow, false);
1457+
Application.Current.Dispatcher.Invoke(() =>
1458+
{
1459+
if (Application.Current.MainWindow is MainWindow mainWindow)
1460+
{
1461+
// 📌 Remove DWM Cloak (Make the window visible normally)
1462+
Win32Helper.DWMSetCloakForWindow(mainWindow, false);
1463+
1464+
// Set clock and search icon opacity
1465+
var opacity = Settings.UseAnimation ? 0.0 : 1.0;
1466+
ClockPanelOpacity = opacity;
1467+
SearchIconOpacity = opacity;
1468+
1469+
// Set clock and search icon visibility
1470+
ClockPanelVisibility = string.IsNullOrEmpty(QueryText) ? Visibility.Visible : Visibility.Collapsed;
1471+
if (PluginIconSource != null)
1472+
{
1473+
SearchIconOpacity = 0.0;
1474+
}
1475+
else
1476+
{
1477+
SearchIconVisibility = Visibility.Visible;
1478+
}
1479+
}
1480+
}, DispatcherPriority.Render);
14551481

14561482
// Update WPF properties
14571483
MainWindowVisibility = Visibility.Visible;
@@ -1467,9 +1493,6 @@ public void Show()
14671493

14681494
public async void Hide()
14691495
{
1470-
// 📌 Apply DWM Cloak (Completely hide the window)
1471-
Win32Helper.DWMSetCloakForWindow(Application.Current.MainWindow, true);
1472-
14731496
lastHistoryIndex = 1;
14741497

14751498
if (ExternalPreviewVisible)
@@ -1504,11 +1527,36 @@ public async void Hide()
15041527
break;
15051528
}
15061529

1530+
Application.Current.Dispatcher.Invoke(() =>
1531+
{
1532+
if (Application.Current.MainWindow is MainWindow mainWindow)
1533+
{
1534+
// Set clock and search icon opacity
1535+
var opacity = Settings.UseAnimation ? 0.0 : 1.0;
1536+
ClockPanelOpacity = opacity;
1537+
SearchIconOpacity = opacity;
1538+
1539+
// Set clock and search icon visibility
1540+
ClockPanelVisibility = Visibility.Hidden;
1541+
SearchIconVisibility = Visibility.Hidden;
1542+
1543+
// Force UI update
1544+
mainWindow.ClockPanel.UpdateLayout();
1545+
mainWindow.SearchIcon.UpdateLayout();
1546+
1547+
// 📌 Apply DWM Cloak (Completely hide the window)
1548+
Win32Helper.DWMSetCloakForWindow(mainWindow, true);
1549+
}
1550+
}, DispatcherPriority.Render);
1551+
15071552
if (StartWithEnglishMode)
15081553
{
15091554
Win32Helper.RestorePreviousKeyboardLayout();
15101555
}
15111556

1557+
// Delay for a while to make sure clock will not flicker
1558+
await Task.Delay(50);
1559+
15121560
// Update WPF properties
15131561
//MainWindowOpacity = 0;
15141562
MainWindowVisibilityStatus = false;

0 commit comments

Comments
 (0)