Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions Flow.Launcher/MessageBoxEx.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
</Grid.RowDefinitions>

<controls:CustomWindowTitleBar
x:Name="TitleBar"
Grid.Row="0"
ShowIcon="False"
ShowTitle="False"
Expand Down
43 changes: 34 additions & 9 deletions Flow.Launcher/MessageBoxEx.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ private MessageBoxEx(MessageBoxButton button)
{
_button = button;
InitializeComponent();

// For YesNo dialogs, hide the close button to match native windows message box behavior
// https://learn.microsoft.com/en-us/dotnet/api/system.windows.messageboxbutton?view=windowsdesktop-10.0#remarks
if (_button == MessageBoxButton.YesNo)
TitleBar.ShowCloseButton = false;
}

public static MessageBoxResult Show(
Expand Down Expand Up @@ -52,6 +57,11 @@ public static MessageBoxResult Show(
_ = SetImageOfMessageBoxAsync(icon);
}
SetButtonVisibilityFocusAndResult(button, defaultResult);

// This ensures that if the message box is closed without using the answer buttons
// It will still have a meaningful result based on its type
_result = msgBox.DefaultCloseResult;

msgBox.ShowDialog();
return _result;
}
Expand Down Expand Up @@ -158,15 +168,30 @@ private async Task SetImageAsync(string imageName)
Img.Source = imageSource;
}

// What the result should be if the message box is closed outside of the direct response buttons - e.g title bar close button
// Mostly replicates System.Windows.MessageBox behavior
// https://learn.microsoft.com/en-us/dotnet/api/system.windows.messageboxresult#remarks
private MessageBoxResult DefaultCloseResult => _button switch
{
MessageBoxButton.OK => MessageBoxResult.OK,
MessageBoxButton.OKCancel => MessageBoxResult.Cancel,
MessageBoxButton.YesNoCancel => MessageBoxResult.Cancel,

// For YesNo this should only be used in a forced close edge case (e.g. alt f4)
// Most callers make the mistake of checking for No instead of not Yes - so best not to return None etc
MessageBoxButton.YesNo => MessageBoxResult.No,

// covers unsupported types, e.g. AbortRetryIgnore
_ => MessageBoxResult.None
};


private void KeyEsc_OnPress(object sender, ExecutedRoutedEventArgs e)
{
if (_button == MessageBoxButton.YesNo)
// Follow System.Windows.MessageBox behavior
return;
else if (_button == MessageBoxButton.OK)
_result = MessageBoxResult.OK;
else
_result = MessageBoxResult.Cancel;

DialogResult = false;
Close();
}
Expand All @@ -192,12 +217,12 @@ private void Button_Cancel(object sender, RoutedEventArgs e)
e.Handled = true;

if (_button == MessageBoxButton.YesNo)
// Follow System.Windows.MessageBox behavior
{
// For YesNo, the close button should be hidden and inaccessible.
App.API.LogWarn(ClassName, "Close button was invoked despite being hidden for YesNo dialog");
return;
else if (_button == MessageBoxButton.OK)
_result = MessageBoxResult.OK;
else
_result = MessageBoxResult.Cancel;
}

msgBox.Close();
msgBox = null;
}
Expand Down
21 changes: 21 additions & 0 deletions Flow.Launcher/Resources/Controls/CustomWindowTitleBar.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shell;

namespace Flow.Launcher.Resources.Controls
{
Expand Down Expand Up @@ -113,6 +114,7 @@ public WindowStateChangedEventArgs(WindowState previousState, WindowState curren

private Window _hostWindow;
private WindowState _lastNonMinimizedWindowState = WindowState.Normal;
private bool? _savedUseAeroCaptionButtons;

private Button MinimizeButtonElement => FindName("MinimizeButton") as Button;
private Button MaximizeButtonElement => FindName("MaximizeButton") as Button;
Expand Down Expand Up @@ -242,6 +244,14 @@ private void AttachToHostWindow()
return;
}

// Disable system caption buttons since this control provides custom ones
var chrome = WindowChrome.GetWindowChrome(_hostWindow);
if (chrome != null)
{
_savedUseAeroCaptionButtons = chrome.UseAeroCaptionButtons;
chrome.UseAeroCaptionButtons = false;
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
}

if (IconSource is null)
{
IconSource = _hostWindow.Icon ?? DefaultWindowIcon;
Expand Down Expand Up @@ -269,6 +279,17 @@ private void DetachFromHostWindow()
return;
}

// Restore original system caption buttons if we disabled them
if (_savedUseAeroCaptionButtons.HasValue)
{
var chrome = WindowChrome.GetWindowChrome(_hostWindow);
if (chrome != null)
{
chrome.UseAeroCaptionButtons = _savedUseAeroCaptionButtons.Value;
}
_savedUseAeroCaptionButtons = null;
}

_hostWindow.StateChanged -= HostWindow_StateChanged;
_hostWindow.Activated -= HostWindow_Activated;
_hostWindow.Closed -= HostWindow_Closed;
Expand Down
Loading