Skip to content

Improve Topmost Feature #3728

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 14, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Flow.Launcher.Infrastructure/UserSettings/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ public bool HideNotifyIcon
public bool LeaveCmdOpen { get; set; }
public bool HideWhenDeactivated { get; set; } = true;

private bool _showAtTopmost = true;
private bool _showAtTopmost = false;
public bool ShowAtTopmost
{
get => _showAtTopmost;
Expand Down
23 changes: 23 additions & 0 deletions Flow.Launcher/Converters/BoolNegationConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using System.Globalization;
using System.Windows.Data;

namespace Flow.Launcher.Converters
{
public class BoolNegationConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool b)
return !b;
return value;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool b)
return !b;
return value;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Return a sentinel value for non-boolean inputs to avoid runtime binding errors

Convert/ConvertBack currently return the original value when it is not a bool.
For bindings where the target expects a bool, returning, e.g. a string will raise a runtime error and WPF will silently dump a binding‐error in the output window.

-            if (value is bool b)
-                return !b;
-            return value;
+            if (value is bool b)
+                return !b;
+            return DependencyProperty.UnsetValue;   // let WPF decide what to do

You may need using System.Windows; for DependencyProperty.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public class BoolNegationConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool b)
return !b;
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool b)
return !b;
return value;
}
}
public class BoolNegationConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool b)
return !b;
return DependencyProperty.UnsetValue; // let WPF decide what to do
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool b)
return !b;
return DependencyProperty.UnsetValue; // let WPF decide what to do
}
}
🤖 Prompt for AI Agents
In Flow.Launcher/Converters/BoolNegationConverter.cs around lines 7 to 22, the
Convert and ConvertBack methods return the original value when it is not a bool,
which can cause runtime binding errors in WPF if the target expects a bool. To
fix this, modify both methods to return DependencyProperty.UnsetValue for
non-boolean inputs instead of the original value. Add "using System.Windows;" if
needed to access DependencyProperty.

}
4 changes: 2 additions & 2 deletions Flow.Launcher/Languages/en.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@
<system:String x:Key="historyResultsForHomePage">Show History Results in Home Page</system:String>
<system:String x:Key="historyResultsCountForHomePage">Maximum History Results Shown in Home Page</system:String>
<system:String x:Key="homeToggleBoxToolTip">This can only be edited if plugin supports Home feature and Home Page is enabled.</system:String>
<system:String x:Key="showAtTopmost">Show Search Window at Topmost</system:String>
<system:String x:Key="showAtTopmostToolTip">Show search window above other windows</system:String>
<system:String x:Key="showAtTopmost">Keep on top</system:String>
<system:String x:Key="showAtTopmostToolTip">Keeps the search window on top even after it loses focus.</system:String>

<!-- Setting Plugin -->
<system:String x:Key="searchplugin">Search Plugin</system:String>
Expand Down
28 changes: 15 additions & 13 deletions Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
mc:Ignorable="d">
<ui:Page.Resources>
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
<converters:BoolNegationConverter x:Key="BoolNegationConverter" />
</ui:Page.Resources>
<ScrollViewer
Margin="0"
Expand Down Expand Up @@ -63,12 +64,23 @@
OnContent="{DynamicResource enable}" />
</cc:Card>

<cc:Card Title="{DynamicResource hideFlowLauncherWhenLoseFocus}" Margin="0 14 0 0">
<ui:ToggleSwitch
<cc:ExCard Title="{DynamicResource hideFlowLauncherWhenLoseFocus}" Margin="0 14 0 0">
<cc:ExCard.SideContent>
<ui:ToggleSwitch
IsOn="{Binding Settings.HideWhenDeactivated}"
OffContent="{DynamicResource disable}"
OnContent="{DynamicResource enable}" />
</cc:Card>
</cc:ExCard.SideContent>
<cc:Card
Title="{DynamicResource showAtTopmost}"
Type="InsideFit"
Sub="{DynamicResource showAtTopmostToolTip}">
<ui:ToggleSwitch
IsOn="{Binding Settings.ShowAtTopmost}"
OffContent="{DynamicResource disable}"
OnContent="{DynamicResource enable}" IsEnabled="{Binding Settings.HideWhenDeactivated, Converter={StaticResource BoolNegationConverter}}"/>
</cc:Card>
</cc:ExCard>

<cc:Card Title="{DynamicResource hideNotifyIcon}" Sub="{DynamicResource hideNotifyIconToolTip}">
<ui:ToggleSwitch
Expand All @@ -77,16 +89,6 @@
OnContent="{DynamicResource enable}" />
</cc:Card>

<cc:Card
Title="{DynamicResource showAtTopmost}"
Margin="0 14 0 0"
Icon="&#xE923;"
Sub="{DynamicResource showAtTopmostToolTip}">
<ui:ToggleSwitch
IsOn="{Binding Settings.ShowAtTopmost}"
OffContent="{DynamicResource disable}"
OnContent="{DynamicResource enable}" />
</cc:Card>

<cc:CardGroup Margin="0 14 0 0">
<cc:Card Title="{DynamicResource SearchWindowPosition}" Icon="&#xe7f4;">
Expand Down
Loading