Skip to content

Commit e68526b

Browse files
authored
CmdPal: Add configuration option for Escape key behavior (#43354)
## Summary of the Pull Request This PR adds a new option to the **General** page in **Settings**: Escape key behavior — a dropdown with the following choices: - Clear search first, then go back - Current behavior. - If the search box contains text, it is cleared; otherwise goes back. - On the home page, CmdPal is dismissed. - Go back - Leaves the search text intact. - If the page is not transient, the search text reappears when returning. - On the home page, CmdPal is dismissed. - Hide window and go home (Always dismiss) - Immediately dismisses CmdPal and navigates to the home page. - Ignores the **Go home when activated** setting. - Search text is cleared. - Hide window - Just hides the window. - Intended to be used with #43355. This implementation preserves existing behavior, except for **Always dismiss**, which always forces navigation to the home page. ## Pictures? Pictures! <img width="1305" height="892" alt="image" src="https://github.com/user-attachments/assets/562e5604-1da6-4fc6-8358-5053df9c573d" /> <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #38311 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed
1 parent 995a699 commit e68526b

File tree

10 files changed

+93
-22
lines changed

10 files changed

+93
-22
lines changed

src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/DismissMessage.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,4 @@
44

55
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
66

7-
public record DismissMessage()
8-
{
9-
}
7+
public record DismissMessage(bool ForceGoHome = false);

src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/NavigateBackMessage.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,4 @@
44

55
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
66

7-
public record NavigateBackMessage(bool FromBackspace = false)
8-
{
9-
}
7+
public record NavigateBackMessage(bool FromBackspace = false);

src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/ShellViewModel.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ private void UnsafeHandleCommandResult(ICommandResult? result)
378378
{
379379
// Reset the palette to the main page and dismiss
380380
GoHome(withAnimation: false, focusSearch: false);
381-
WeakReferenceMessenger.Default.Send<DismissMessage>();
381+
WeakReferenceMessenger.Default.Send(new DismissMessage());
382382
break;
383383
}
384384

@@ -398,7 +398,7 @@ private void UnsafeHandleCommandResult(ICommandResult? result)
398398
case CommandResultKind.Hide:
399399
{
400400
// Keep this page open, but hide the palette.
401-
WeakReferenceMessenger.Default.Send<DismissMessage>();
401+
WeakReferenceMessenger.Default.Send(new DismissMessage());
402402
break;
403403
}
404404

src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public partial class SettingsModel : ObservableObject
6060

6161
public TimeSpan AutoGoHomeInterval { get; set; } = Timeout.InfiniteTimeSpan;
6262

63+
public EscapeKeyBehavior EscapeKeyBehaviorSetting { get; set; } = EscapeKeyBehavior.ClearSearchFirstThenGoBack;
64+
6365
// END SETTINGS
6466
///////////////////////////////////////////////////////////////////////////
6567

@@ -282,3 +284,11 @@ public enum MonitorBehavior
282284
InPlace = 3,
283285
ToLast = 4,
284286
}
287+
288+
public enum EscapeKeyBehavior
289+
{
290+
ClearSearchFirstThenGoBack = 0,
291+
AlwaysGoBack = 1,
292+
AlwaysDismiss = 2,
293+
AlwaysHide = 3,
294+
}

src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,16 @@ public int AutoGoBackIntervalIndex
160160
}
161161
}
162162

163+
public int EscapeKeyBehaviorIndex
164+
{
165+
get => (int)_settings.EscapeKeyBehaviorSetting;
166+
set
167+
{
168+
_settings.EscapeKeyBehaviorSetting = (EscapeKeyBehavior)value;
169+
Save();
170+
}
171+
}
172+
163173
public ObservableCollection<ProviderSettingsViewModel> CommandProviders { get; } = [];
164174

165175
public SettingsExtensionsViewModel Extensions { get; }

src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml.cs

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
using Microsoft.CmdPal.Core.ViewModels;
88
using Microsoft.CmdPal.Core.ViewModels.Commands;
99
using Microsoft.CmdPal.Core.ViewModels.Messages;
10-
using Microsoft.CmdPal.UI.Messages;
10+
using Microsoft.CmdPal.Ext.ClipboardHistory.Messages;
11+
using Microsoft.CmdPal.UI.ViewModels;
1112
using Microsoft.CmdPal.UI.Views;
13+
using Microsoft.Extensions.DependencyInjection;
1214
using Microsoft.UI.Dispatching;
1315
using Microsoft.UI.Input;
1416
using Microsoft.UI.Xaml;
@@ -49,6 +51,8 @@ public sealed partial class SearchBar : UserControl,
4951
// 0.6+ suggestions
5052
private string? _textToSuggest;
5153

54+
private SettingsModel Settings => App.Current.Services.GetRequiredService<SettingsModel>();
55+
5256
public PageViewModel? CurrentPageViewModel
5357
{
5458
get => (PageViewModel?)GetValue(CurrentPageViewModelProperty);
@@ -131,20 +135,39 @@ private void FilterBox_KeyDown(object sender, KeyRoutedEventArgs e)
131135
}
132136
else if (e.Key == VirtualKey.Escape)
133137
{
134-
if (string.IsNullOrEmpty(FilterBox.Text))
138+
switch (Settings.EscapeKeyBehaviorSetting)
135139
{
136-
WeakReferenceMessenger.Default.Send<NavigateBackMessage>(new());
137-
}
138-
else
139-
{
140-
// Clear the search box
141-
FilterBox.Text = string.Empty;
140+
case EscapeKeyBehavior.AlwaysGoBack:
141+
WeakReferenceMessenger.Default.Send<NavigateBackMessage>(new());
142+
break;
142143

143-
// hack TODO GH #245
144-
if (CurrentPageViewModel is not null)
145-
{
146-
CurrentPageViewModel.SearchTextBox = FilterBox.Text;
147-
}
144+
case EscapeKeyBehavior.AlwaysDismiss:
145+
WeakReferenceMessenger.Default.Send<DismissMessage>(new(ForceGoHome: true));
146+
break;
147+
148+
case EscapeKeyBehavior.AlwaysHide:
149+
WeakReferenceMessenger.Default.Send<HideWindowMessage>(new());
150+
break;
151+
152+
case EscapeKeyBehavior.ClearSearchFirstThenGoBack:
153+
default:
154+
if (string.IsNullOrEmpty(FilterBox.Text))
155+
{
156+
WeakReferenceMessenger.Default.Send<NavigateBackMessage>(new());
157+
}
158+
else
159+
{
160+
// Clear the search box
161+
FilterBox.Text = string.Empty;
162+
163+
// hack TODO GH #245
164+
if (CurrentPageViewModel is not null)
165+
{
166+
CurrentPageViewModel.SearchTextBox = FilterBox.Text;
167+
}
168+
}
169+
170+
break;
148171
}
149172

150173
e.Handled = true;

src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,11 @@ public void Receive(QuitMessage message) =>
530530

531531
public void Receive(DismissMessage message)
532532
{
533+
if (message.ForceGoHome)
534+
{
535+
WeakReferenceMessenger.Default.Send(new GoHomeMessage(false, false));
536+
}
537+
533538
// This might come in off the UI thread. Make sure to hop back.
534539
DispatcherQueue.TryEnqueue(() =>
535540
{

src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public void Receive(NavigateBackMessage message)
133133
if (!message.FromBackspace)
134134
{
135135
// If we can't go back then we must be at the top and thus escape again should quit.
136-
WeakReferenceMessenger.Default.Send<DismissMessage>();
136+
WeakReferenceMessenger.Default.Send(new DismissMessage());
137137

138138
PowerToysTelemetry.Log.WriteEvent(new CmdPalDismissedOnEsc());
139139
}

src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,15 @@
8989
<ToggleSwitch IsOn="{x:Bind viewModel.BackspaceGoesBack, Mode=TwoWay}" />
9090
</controls:SettingsCard>
9191

92+
<controls:SettingsCard x:Uid="Settings_GeneralPage_EscapeKeyBehavior_SettingsCard" HeaderIcon="{ui:FontIcon Glyph=&#xE845;}">
93+
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind viewModel.EscapeKeyBehaviorIndex, Mode=TwoWay}">
94+
<ComboBoxItem x:Uid="Settings_GeneralPage_EscapeKeyBehavior_Option_DismissEmptySearchOrGoBack" />
95+
<ComboBoxItem x:Uid="Settings_GeneralPage_EscapeKeyBehavior_Option_AlwaysGoBack" />
96+
<ComboBoxItem x:Uid="Settings_GeneralPage_EscapeKeyBehavior_Option_AlwaysDismiss" />
97+
<ComboBoxItem x:Uid="Settings_GeneralPage_EscapeKeyBehavior_Option_AlwaysHide" />
98+
</ComboBox>
99+
</controls:SettingsCard>
100+
92101
<controls:SettingsCard x:Uid="Settings_GeneralPage_SingleClickActivation_SettingsCard" HeaderIcon="{ui:FontIcon Glyph=&#xE962;}">
93102
<ToggleSwitch IsOn="{x:Bind viewModel.SingleClickActivates, Mode=TwoWay}" />
94103
</controls:SettingsCard>

src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,4 +556,22 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
556556
<data name="Settings_PageTitles_ExtensionsPage" xml:space="preserve">
557557
<value>Extensions</value>
558558
</data>
559+
<data name="Settings_GeneralPage_EscapeKeyBehavior_Option_DismissEmptySearchOrGoBack.Content" xml:space="preserve">
560+
<value>Clear search first, then go back</value>
561+
</data>
562+
<data name="Settings_GeneralPage_EscapeKeyBehavior_Option_AlwaysGoBack.Content" xml:space="preserve">
563+
<value>Go back</value>
564+
</data>
565+
<data name="Settings_GeneralPage_EscapeKeyBehavior_Option_AlwaysDismiss.Content" xml:space="preserve">
566+
<value>Hide window and go home</value>
567+
</data>
568+
<data name="Settings_GeneralPage_EscapeKeyBehavior_Option_AlwaysHide.Content" xml:space="preserve">
569+
<value>Hide window</value>
570+
</data>
571+
<data name="Settings_GeneralPage_EscapeKeyBehavior_SettingsCard.Header" xml:space="preserve">
572+
<value>Escape key behavior</value>
573+
</data>
574+
<data name="Settings_GeneralPage_EscapeKeyBehavior_SettingsCard.Description" xml:space="preserve">
575+
<value>Choose how Escape key behaves</value>
576+
</data>
559577
</root>

0 commit comments

Comments
 (0)