in src/modules/keyboardmanager/KeyboardManagerEditorLibrary/ShortcutControl.cpp [287:504]
void ShortcutControl::CreateDetectShortcutWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, KBMEditor::KeyboardManagerState& keyboardManagerState, const int colIndex, StackPanel table, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, StackPanel row, TextBox targetApp, bool isHybridControl, bool isSingleKeyWindow, HWND parentWindow, RemapBuffer& remapBuffer)
{
// ContentDialog for detecting shortcuts. This is the parent UI element.
ContentDialog detectShortcutBox;
// ContentDialog requires manually setting the XamlRoot (https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.contentdialog#contentdialog-in-appwindow-or-xaml-islands)
detectShortcutBox.XamlRoot(xamlRoot);
detectShortcutBox.Title(box_value(GET_RESOURCE_STRING(IDS_TYPESHORTCUT_TITLE)));
detectShortcutBox.IsPrimaryButtonEnabled(false);
detectShortcutBox.IsSecondaryButtonEnabled(false);
// Get the linked stack panel for the "Type shortcut" button that was clicked
StackPanel linkedShortcutStackPanel = UIHelpers::GetSiblingElement(sender).as<StackPanel>();
auto unregisterKeys = [&keyboardManagerState]() {
keyboardManagerState.ClearRegisteredKeyDelays();
};
auto selectDetectedShortcutAndResetKeys = [&keyboardManagerState](DWORD key) {
keyboardManagerState.SelectDetectedShortcut(key);
keyboardManagerState.ResetDetectedShortcutKey(key);
};
auto onPressEnter = [linkedShortcutStackPanel,
detectShortcutBox,
&keyboardManagerState,
unregisterKeys,
colIndex,
table,
targetApp,
&keyDropDownControlObjects,
row,
isHybridControl,
isSingleKeyWindow,
&remapBuffer] {
// Save the detected shortcut in the linked text block
Shortcut detectedShortcutKeys = keyboardManagerState.GetDetectedShortcut();
if (!detectedShortcutKeys.IsEmpty())
{
// The shortcut buffer gets set in this function
KeyDropDownControl::AddShortcutToControl(detectedShortcutKeys, table, linkedShortcutStackPanel, keyboardManagerState, colIndex, keyDropDownControlObjects, remapBuffer, row, targetApp, isHybridControl, isSingleKeyWindow);
}
// Hide the type shortcut UI
detectShortcutBox.Hide();
};
auto onReleaseEnter = [&keyboardManagerState,
unregisterKeys,
isSingleKeyWindow,
parentWindow] {
// Reset the keyboard manager UI state
keyboardManagerState.ResetUIState();
if (isSingleKeyWindow)
{
// Revert UI state back to Edit Keyboard window
keyboardManagerState.SetUIState(KBMEditor::KeyboardManagerUIState::EditKeyboardWindowActivated, parentWindow);
}
else
{
// Revert UI state back to Edit Shortcut window
keyboardManagerState.SetUIState(KBMEditor::KeyboardManagerUIState::EditShortcutsWindowActivated, parentWindow);
}
unregisterKeys();
};
auto onAccept = [onPressEnter,
onReleaseEnter] {
onPressEnter();
onReleaseEnter();
};
TextBlock primaryButtonText;
primaryButtonText.Text(GET_RESOURCE_STRING(IDS_OK_BUTTON));
Button primaryButton;
primaryButton.HorizontalAlignment(HorizontalAlignment::Stretch);
primaryButton.Margin({ 2, 2, 2, 2 });
primaryButton.Content(primaryButtonText);
// OK button
primaryButton.Click([onAccept](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
onAccept();
});
// NOTE: UnregisterKeys should never be called on the DelayThread, as it will re-enter the mutex. To avoid this it is run on the dispatcher thread
keyboardManagerState.RegisterKeyDelay(
VK_RETURN,
selectDetectedShortcutAndResetKeys,
[primaryButton, onPressEnter, detectShortcutBox](DWORD) {
detectShortcutBox.Dispatcher().RunAsync(
Windows::UI::Core::CoreDispatcherPriority::Normal,
[primaryButton, onPressEnter] {
// Use the base medium low brush to be consistent with the theme
primaryButton.Background(Windows::UI::Xaml::Application::Current().Resources().Lookup(box_value(L"SystemControlBackgroundBaseMediumLowBrush")).as<Windows::UI::Xaml::Media::SolidColorBrush>());
onPressEnter();
});
},
[onReleaseEnter, detectShortcutBox](DWORD) {
detectShortcutBox.Dispatcher().RunAsync(
Windows::UI::Core::CoreDispatcherPriority::Normal,
[onReleaseEnter]() {
onReleaseEnter();
});
});
TextBlock cancelButtonText;
cancelButtonText.Text(GET_RESOURCE_STRING(IDS_CANCEL_BUTTON));
auto onCancel = [&keyboardManagerState,
detectShortcutBox,
unregisterKeys,
isSingleKeyWindow,
parentWindow] {
detectShortcutBox.Hide();
// Reset the keyboard manager UI state
keyboardManagerState.ResetUIState();
if (isSingleKeyWindow)
{
// Revert UI state back to Edit Keyboard window
keyboardManagerState.SetUIState(KBMEditor::KeyboardManagerUIState::EditKeyboardWindowActivated, parentWindow);
}
else
{
// Revert UI state back to Edit Shortcut window
keyboardManagerState.SetUIState(KBMEditor::KeyboardManagerUIState::EditShortcutsWindowActivated, parentWindow);
}
unregisterKeys();
};
Button cancelButton;
cancelButton.HorizontalAlignment(HorizontalAlignment::Stretch);
cancelButton.Margin({ 2, 2, 2, 2 });
cancelButton.Content(cancelButtonText);
// Cancel button
cancelButton.Click([onCancel](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
onCancel();
});
// NOTE: UnregisterKeys should never be called on the DelayThread, as it will re-enter the mutex. To avoid this it is run on the dispatcher thread
keyboardManagerState.RegisterKeyDelay(
VK_ESCAPE,
selectDetectedShortcutAndResetKeys,
[onCancel, detectShortcutBox](DWORD) {
detectShortcutBox.Dispatcher().RunAsync(
Windows::UI::Core::CoreDispatcherPriority::Normal,
[onCancel] {
onCancel();
});
},
nullptr);
// StackPanel parent for the displayed text in the dialog
Windows::UI::Xaml::Controls::StackPanel stackPanel;
detectShortcutBox.Content(stackPanel);
// Header textblock
TextBlock text;
text.Text(GET_RESOURCE_STRING(IDS_TYPESHORTCUT_HEADER));
text.Margin({ 0, 0, 0, 10 });
stackPanel.Children().Append(text);
// Target StackPanel to place the selected key - first row (for 1-3 keys)
Windows::UI::Xaml::Controls::StackPanel keyStackPanel1;
keyStackPanel1.Orientation(Orientation::Horizontal);
stackPanel.Children().Append(keyStackPanel1);
// Target StackPanel to place the selected key - second row (for 4-5 keys)
Windows::UI::Xaml::Controls::StackPanel keyStackPanel2;
keyStackPanel2.Orientation(Orientation::Horizontal);
keyStackPanel2.Margin({ 0, 20, 0, 0 });
keyStackPanel2.Visibility(Visibility::Collapsed);
stackPanel.Children().Append(keyStackPanel2);
TextBlock holdEscInfo;
holdEscInfo.Text(GET_RESOURCE_STRING(IDS_TYPE_HOLDESC));
holdEscInfo.FontSize(12);
holdEscInfo.Margin({ 0, 20, 0, 0 });
stackPanel.Children().Append(holdEscInfo);
TextBlock holdEnterInfo;
holdEnterInfo.Text(GET_RESOURCE_STRING(IDS_TYPE_HOLDENTER));
holdEnterInfo.FontSize(12);
holdEnterInfo.Margin({ 0, 0, 0, 0 });
stackPanel.Children().Append(holdEnterInfo);
ColumnDefinition primaryButtonColumn;
ColumnDefinition cancelButtonColumn;
Grid buttonPanel;
buttonPanel.Margin({ 0, 20, 0, 0 });
buttonPanel.HorizontalAlignment(HorizontalAlignment::Stretch);
buttonPanel.ColumnDefinitions().Append(primaryButtonColumn);
buttonPanel.ColumnDefinitions().Append(cancelButtonColumn);
buttonPanel.SetColumn(primaryButton, 0);
buttonPanel.SetColumn(cancelButton, 1);
buttonPanel.Children().Append(primaryButton);
buttonPanel.Children().Append(cancelButton);
stackPanel.Children().Append(buttonPanel);
try
{
// If a layout update has been triggered by other methods (e.g.: adapting to zoom level), this may throw an exception.
stackPanel.UpdateLayout();
}
catch (...)
{
}
// Configure the keyboardManagerState to store the UI information.
keyboardManagerState.ConfigureDetectShortcutUI(keyStackPanel1, keyStackPanel2);
// Show the dialog
detectShortcutBox.ShowAsync();
}