From c5635c1e3e452c4f446752be34ff18e868bb2f8b Mon Sep 17 00:00:00 2001 From: Hao Liu Date: Wed, 9 Apr 2025 10:30:25 +0800 Subject: [PATCH] [Keyboard Manager] Functional Improvements on new KBM UX (#38652) * Make Disable toggle button functional in Shortcuts page * Clean up main window and aggregate Constants * Update key remapping naming * Fix the key visual stretch out issue when the shortcut contains too many keys * Refactor code structure * fix wrapping in dialog * update naming * Implement Keyboard hook to get the user input of remappings * Implement Reset for InputControl to make sure InputControl can have correct status for various dialog --- .../KeyboardManagerEditorLibraryWrapper.cpp | 4 +- .../KeyboardManagerEditorLibraryWrapper.h | 4 +- .../KeyboardManagerEditorUI/App.xaml.cs | 24 +- .../Helpers/EditorConstants.cs | 19 + .../Helpers/Remapping.cs | 26 +- .../Interop/KeyboardManagerInterop.cs | 34 +- .../Interop/KeyboardMappingService.cs | 9 +- .../KeyboardManagerEditorUI.csproj | 3 +- .../KeyboardManagerEditorUI/MainWindow.xaml | 1 + .../MainWindow.xaml.cs | 4 +- .../Pages/Programs.xaml | 2 +- .../Pages/{Shortcuts.xaml => Remappings.xaml} | 36 +- .../{Shortcuts.xaml.cs => Remappings.xaml.cs} | 98 ++--- .../KeyboardManagerEditorUI/Pages/Text.xaml | 2 +- .../KeyboardManagerEditorUI/Pages/URLs.xaml | 2 +- .../Styles/InputControl.xaml | 23 +- .../Styles/InputControl.xaml.cs | 341 +++++++++++++----- 17 files changed, 411 insertions(+), 221 deletions(-) create mode 100644 src/modules/keyboardmanager/KeyboardManagerEditorUI/Helpers/EditorConstants.cs rename src/modules/keyboardmanager/KeyboardManagerEditorUI/Pages/{Shortcuts.xaml => Remappings.xaml} (85%) rename src/modules/keyboardmanager/KeyboardManagerEditorUI/Pages/{Shortcuts.xaml.cs => Remappings.xaml.cs} (65%) diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorLibraryWrapper/KeyboardManagerEditorLibraryWrapper.cpp b/src/modules/keyboardmanager/KeyboardManagerEditorLibraryWrapper/KeyboardManagerEditorLibraryWrapper.cpp index 63a66e631f..2d5e30a506 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorLibraryWrapper/KeyboardManagerEditorLibraryWrapper.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEditorLibraryWrapper/KeyboardManagerEditorLibraryWrapper.cpp @@ -46,7 +46,7 @@ extern "C" return static_cast(mapping->singleKeyReMap.size()); } - bool GetSingleKeyRemap(void* config, int index, KeyboardMapping* mapping) + bool GetSingleKeyRemap(void* config, int index, SingleKeyMapping* mapping) { auto mappingConfig = static_cast(config); @@ -65,11 +65,13 @@ extern "C" const auto& kv = allMappings[index]; mapping->originalKey = static_cast(kv.first); + // Remap to single key if (kv.second.index() == 0) { mapping->targetKey = AllocateAndCopyString(std::to_wstring(std::get(kv.second))); mapping->isShortcut = false; } + // Remap to shortcut else if (kv.second.index() == 1) { mapping->targetKey = AllocateAndCopyString(std::get(kv.second).ToHstringVK().c_str()); diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorLibraryWrapper/KeyboardManagerEditorLibraryWrapper.h b/src/modules/keyboardmanager/KeyboardManagerEditorLibraryWrapper/KeyboardManagerEditorLibraryWrapper.h index 3b2050b5fe..7d6dc4713c 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorLibraryWrapper/KeyboardManagerEditorLibraryWrapper.h +++ b/src/modules/keyboardmanager/KeyboardManagerEditorLibraryWrapper/KeyboardManagerEditorLibraryWrapper.h @@ -10,7 +10,7 @@ struct KeyNamePair wchar_t keyName[64]; }; -struct KeyboardMapping +struct SingleKeyMapping { int originalKey; wchar_t* targetKey; @@ -43,7 +43,7 @@ extern "C" __declspec(dllexport) bool SaveMappingSettings(void* config); __declspec(dllexport) int GetSingleKeyRemapCount(void* config); - __declspec(dllexport) bool GetSingleKeyRemap(void* config, int index, KeyboardMapping* mapping); + __declspec(dllexport) bool GetSingleKeyRemap(void* config, int index, SingleKeyMapping* mapping); __declspec(dllexport) int GetSingleKeyToTextRemapCount(void* config); __declspec(dllexport) bool GetSingleKeyToTextRemap(void* config, int index, KeyboardTextMapping* mapping); diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorUI/App.xaml.cs b/src/modules/keyboardmanager/KeyboardManagerEditorUI/App.xaml.cs index 3b2138615d..ae1855da79 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorUI/App.xaml.cs +++ b/src/modules/keyboardmanager/KeyboardManagerEditorUI/App.xaml.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; using System.Threading.Tasks; +using KeyboardManagerEditorUI.Helpers; using ManagedCommon; using Microsoft.UI; using Microsoft.UI.Dispatching; @@ -42,7 +43,6 @@ namespace KeyboardManagerEditorUI Task.Run(() => { Logger.InitializeLogger("\\Keyboard Manager\\WinUI3Editor\\Logs"); - Logger.LogInfo("keyboard-manager WinUI3 editor logger is initialized"); }); UnhandledException += App_UnhandledException; @@ -58,30 +58,24 @@ namespace KeyboardManagerEditorUI var appWindow = window.AppWindow; - var windowSize = new Windows.Graphics.SizeInt32(960, 600); + var windowSize = new Windows.Graphics.SizeInt32(EditorConstants.DefaultEditorWindowWidth, EditorConstants.DefaultEditorWindowHeight); appWindow.Resize(windowSize); - Task.Run(() => + window.DispatcherQueue.TryEnqueue(() => { - App.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() + window.Activate(); + window.DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () => { - Source = new Uri("ms-appx:///Styles/CommonStyle.xaml"), - }); - }).ContinueWith(_ => - { - window.DispatcherQueue.TryEnqueue(() => - { - window.Activate(); - window.DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () => - { - (window.Content as FrameworkElement)?.UpdateLayout(); - }); + (window.Content as FrameworkElement)?.UpdateLayout(); }); }); Logger.LogInfo("keyboard-manager WinUI3 editor window is launched"); } + /// + /// Log the unhandled exception for the editor. + /// private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e) { Logger.LogError("Unhandled exception", e.Exception); diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorUI/Helpers/EditorConstants.cs b/src/modules/keyboardmanager/KeyboardManagerEditorUI/Helpers/EditorConstants.cs new file mode 100644 index 0000000000..bca4057952 --- /dev/null +++ b/src/modules/keyboardmanager/KeyboardManagerEditorUI/Helpers/EditorConstants.cs @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace KeyboardManagerEditorUI.Helpers +{ + public static class EditorConstants + { + // Default window size + public const int DefaultEditorWindowWidth = 960; + public const int DefaultEditorWindowHeight = 600; + } +} diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorUI/Helpers/Remapping.cs b/src/modules/keyboardmanager/KeyboardManagerEditorUI/Helpers/Remapping.cs index 97164a32e2..3ab3b165f7 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorUI/Helpers/Remapping.cs +++ b/src/modules/keyboardmanager/KeyboardManagerEditorUI/Helpers/Remapping.cs @@ -4,13 +4,15 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; namespace KeyboardManagerEditorUI.Helpers { - public class Remapping + public partial class Remapping : INotifyPropertyChanged { public List OriginalKeys { get; set; } = new List(); @@ -20,6 +22,26 @@ namespace KeyboardManagerEditorUI.Helpers public string AppName { get; set; } = "All Apps"; - public bool IsEnabled { get; set; } = true; + private bool IsEnabledValue { get; set; } = true; + + public event PropertyChangedEventHandler? PropertyChanged; + + public bool IsEnabled + { + get => IsEnabledValue; + set + { + if (IsEnabledValue != value) + { + IsEnabledValue = value; + OnPropertyChanged(); + } + } + } + + private void OnPropertyChanged([CallerMemberName] string propertyName = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } } } diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorUI/Interop/KeyboardManagerInterop.cs b/src/modules/keyboardmanager/KeyboardManagerEditorUI/Interop/KeyboardManagerInterop.cs index 205e9c861d..59a7063c6c 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorUI/Interop/KeyboardManagerInterop.cs +++ b/src/modules/keyboardmanager/KeyboardManagerEditorUI/Interop/KeyboardManagerInterop.cs @@ -34,17 +34,14 @@ namespace KeyboardManagerEditorUI.Interop [DllImport(DllName)] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool GetSingleKeyRemap(IntPtr config, int index, ref KeyboardMapping mapping); + internal static extern bool GetSingleKeyRemap(IntPtr config, int index, ref SingleKeyMapping mapping); [DllImport(DllName)] internal static extern int GetSingleKeyToTextRemapCount(IntPtr config); [DllImport(DllName)] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool GetSingleKeyToTextRemap( - IntPtr config, - int index, - ref KeyboardTextMapping mapping); + internal static extern bool GetSingleKeyToTextRemap(IntPtr config, int index, ref KeyboardTextMapping mapping); [DllImport(DllName)] internal static extern int GetShortcutRemapCount(IntPtr config); @@ -58,11 +55,7 @@ namespace KeyboardManagerEditorUI.Interop [DllImport(DllName)] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool GetShortcutRemapByType( - IntPtr config, - int operationType, - int index, - ref ShortcutMapping mapping); + internal static extern bool GetShortcutRemapByType(IntPtr config, int operationType, int index, ref ShortcutMapping mapping); [DllImport(DllName)] [return: MarshalAs(UnmanagedType.Bool)] @@ -70,10 +63,7 @@ namespace KeyboardManagerEditorUI.Interop [DllImport(DllName)] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool AddSingleKeyToShortcutRemap( - IntPtr config, - int originalKey, - [MarshalAs(UnmanagedType.LPWStr)] string targetKeys); + internal static extern bool AddSingleKeyToShortcutRemap(IntPtr config, int originalKey, [MarshalAs(UnmanagedType.LPWStr)] string targetKeys); [DllImport(DllName)] [return: MarshalAs(UnmanagedType.Bool)] @@ -84,27 +74,29 @@ namespace KeyboardManagerEditorUI.Interop [MarshalAs(UnmanagedType.LPWStr)] string targetApp); [DllImport(DllName)] - internal static extern int GetKeyCodeFromName( - [MarshalAs(UnmanagedType.LPWStr)] string keyName); + internal static extern int GetKeyCodeFromName([MarshalAs(UnmanagedType.LPWStr)] string keyName); + + [DllImport(DllName, CharSet = CharSet.Unicode)] + internal static extern void GetKeyDisplayName(int keyCode, [Out] StringBuilder keyName, int maxLength); [DllImport(DllName)] internal static extern void FreeString(IntPtr str); - public static string GetStringAndFree(IntPtr ptr) + public static string GetStringAndFree(IntPtr handle) { - if (ptr == IntPtr.Zero) + if (handle == IntPtr.Zero) { return string.Empty; } - string? result = Marshal.PtrToStringUni(ptr); - FreeString(ptr); + string? result = Marshal.PtrToStringUni(handle); + FreeString(handle); return result ?? string.Empty; } } [StructLayout(LayoutKind.Sequential)] - public struct KeyboardMapping + public struct SingleKeyMapping { public int OriginalKey; public IntPtr TargetKey; diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorUI/Interop/KeyboardMappingService.cs b/src/modules/keyboardmanager/KeyboardManagerEditorUI/Interop/KeyboardMappingService.cs index f3104f72b0..7bf9255e1a 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorUI/Interop/KeyboardMappingService.cs +++ b/src/modules/keyboardmanager/KeyboardManagerEditorUI/Interop/KeyboardMappingService.cs @@ -34,7 +34,7 @@ namespace KeyboardManagerEditorUI.Interop for (int i = 0; i < count; i++) { - var mapping = default(KeyboardMapping); + var mapping = default(SingleKeyMapping); if (KeyboardManagerInterop.GetSingleKeyRemap(_configHandle, i, ref mapping)) { result.Add(new KeyMapping @@ -124,6 +124,13 @@ namespace KeyboardManagerEditorUI.Interop return result; } + public string GetKeyDisplayName(int keyCode) + { + var keyName = new StringBuilder(64); + KeyboardManagerInterop.GetKeyDisplayName(keyCode, keyName, keyName.Capacity); + return keyName.ToString(); + } + public bool AddSingleKeyMapping(int originalKey, int targetKey) { return KeyboardManagerInterop.AddSingleKeyRemap(_configHandle, originalKey, targetKey); diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorUI/KeyboardManagerEditorUI.csproj b/src/modules/keyboardmanager/KeyboardManagerEditorUI/KeyboardManagerEditorUI.csproj index c27d5dc358..08e67981dc 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorUI/KeyboardManagerEditorUI.csproj +++ b/src/modules/keyboardmanager/KeyboardManagerEditorUI/KeyboardManagerEditorUI.csproj @@ -26,7 +26,6 @@ - @@ -77,7 +76,7 @@ - + MSBuild:Compile diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorUI/MainWindow.xaml b/src/modules/keyboardmanager/KeyboardManagerEditorUI/MainWindow.xaml index 7c6c4fd5d2..daaa8607ba 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorUI/MainWindow.xaml +++ b/src/modules/keyboardmanager/KeyboardManagerEditorUI/MainWindow.xaml @@ -40,6 +40,7 @@ IsBackButtonVisible="Collapsed" IsBackEnabled="False" IsPaneToggleButtonVisible="False" + IsSettingsVisible="False" PaneDisplayMode="Top" SelectionChanged="RootView_SelectionChanged"> diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorUI/MainWindow.xaml.cs b/src/modules/keyboardmanager/KeyboardManagerEditorUI/MainWindow.xaml.cs index 15ffda49ff..892ee2e800 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorUI/MainWindow.xaml.cs +++ b/src/modules/keyboardmanager/KeyboardManagerEditorUI/MainWindow.xaml.cs @@ -28,6 +28,8 @@ namespace KeyboardManagerEditorUI this.InitializeComponent(); this.ExtendsContentIntoTitleBar = true; this.SetTitleBar(titleBar); + + // Set the default page RootView.SelectedItem = RootView.MenuItems[0]; } @@ -37,7 +39,7 @@ namespace KeyboardManagerEditorUI { switch ((string)selectedItem.Tag) { - case "Remappings": NavigationFrame.Navigate(typeof(Pages.Shortcuts)); break; + case "Remappings": NavigationFrame.Navigate(typeof(Pages.Remappings)); break; case "Programs": NavigationFrame.Navigate(typeof(Pages.Programs)); break; case "Text": NavigationFrame.Navigate(typeof(Pages.Text)); break; case "URLs": NavigationFrame.Navigate(typeof(Pages.URLs)); break; diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorUI/Pages/Programs.xaml b/src/modules/keyboardmanager/KeyboardManagerEditorUI/Pages/Programs.xaml index 464b52a04c..ebd8563780 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorUI/Pages/Programs.xaml +++ b/src/modules/keyboardmanager/KeyboardManagerEditorUI/Pages/Programs.xaml @@ -23,7 +23,7 @@ Click="NewShortcutBtn_Click"> diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorUI/Pages/Shortcuts.xaml b/src/modules/keyboardmanager/KeyboardManagerEditorUI/Pages/Remappings.xaml similarity index 85% rename from src/modules/keyboardmanager/KeyboardManagerEditorUI/Pages/Shortcuts.xaml rename to src/modules/keyboardmanager/KeyboardManagerEditorUI/Pages/Remappings.xaml index 69eb38287b..255a55efa7 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorUI/Pages/Shortcuts.xaml +++ b/src/modules/keyboardmanager/KeyboardManagerEditorUI/Pages/Remappings.xaml @@ -1,8 +1,9 @@