mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-11-23 19:49:17 +08:00
[KeyboardManager]Modernize the editor UI (#28473)
* Fix dark title bar for shortcuts window * Adjust editor sizes * Fetch accent button style from resources instead * Modernize the editor UI Reimplemented the XAML bridge to support Mica * Use fluent icons * Modernize the preview key visuals * Implement teaching tips for key drop-down messages * Fix spelling * Fix delete button alignment in keys editor * Remove trace log from bridge message handler * Add WinUI depends to installer script * Hide icon and caption from editor title bar * Update remap entries to look like cards * Use built-in content dialog buttons * Update add button * Fix spelling * Fix installer script for ARM64 * Fix spelling AGAIN * Update dev documentation * Prevent white flash on dark mode * Revert 3-key layout but make window wider * f: align webview versions * f: add pipeline exceptions for Microsoft DLLs that are not versioned * f: add vcruntime140_1_app.dll to the exception list * f: update webview versions
This commit is contained in:
parent
35b0f71317
commit
97a8aeb118
9
.github/actions/spell-check/expect.txt
vendored
9
.github/actions/spell-check/expect.txt
vendored
@ -174,6 +174,7 @@ BTNFACE
|
||||
Bto
|
||||
buf
|
||||
bugreport
|
||||
BUILDARCH
|
||||
BUILDNUMBER
|
||||
buildtask
|
||||
buildtransitive
|
||||
@ -1055,6 +1056,7 @@ majortype
|
||||
MAJORVERSION
|
||||
makecab
|
||||
MAKEINTRESOURCE
|
||||
MAKEINTRESOURCEA
|
||||
MAKEINTRESOURCEW
|
||||
makepri
|
||||
manifestdependency
|
||||
@ -1182,10 +1184,12 @@ msrc
|
||||
msstore
|
||||
mst
|
||||
msvc
|
||||
msvcp
|
||||
MTND
|
||||
Mul
|
||||
MULTIPLEUSE
|
||||
multizone
|
||||
muxc
|
||||
mvvm
|
||||
mwb
|
||||
MWBEx
|
||||
@ -1251,6 +1255,8 @@ NOCOPYBITS
|
||||
nodeca
|
||||
nodiscard
|
||||
nodoc
|
||||
NODRAWCAPTION
|
||||
NODRAWICON
|
||||
NOINHERITLAYOUT
|
||||
NOINTERFACE
|
||||
NOLINKINFO
|
||||
@ -2094,6 +2100,7 @@ VCINSTALLDIR
|
||||
vcm
|
||||
Vcpkg
|
||||
VCRT
|
||||
vcruntime
|
||||
vcvars
|
||||
VDesktop
|
||||
vdi
|
||||
@ -2276,6 +2283,8 @@ wsl
|
||||
wss
|
||||
wstr
|
||||
wsz
|
||||
WTA
|
||||
WTNCA
|
||||
wtoi
|
||||
WTS
|
||||
wtsapi
|
||||
|
@ -25,7 +25,11 @@ $nullVersionExceptions = @(
|
||||
"codicon.ttf",
|
||||
"e_sqlite3.dll",
|
||||
"vcamp140_app.dll",
|
||||
"vcruntime140_app.dll",
|
||||
"vcruntime140_1_app.dll",
|
||||
"msvcp140_app.dll",
|
||||
"marshal.dll",
|
||||
"Microsoft.Toolkit.Win32.UI.XamlHost.dll",
|
||||
"Microsoft.UI.Composition.OSSupport.dll",
|
||||
"Microsoft.UI.Windowing.dll",
|
||||
"Microsoft.UI.Xaml.Internal.dll",
|
||||
|
@ -1,10 +1,7 @@
|
||||
# Keyboard Manager UI
|
||||
|
||||
## Table of Contents:
|
||||
1. [C++ XAML Islands](#c-xaml-islands)
|
||||
1. [Debugging exceptions in XAML Islands](#debugging-exceptions-in-xaml-islands)
|
||||
2. [Build times](#build-times)
|
||||
3. [Setting custom backgrounds for Xaml Controls using brushes](#setting-custom-backgrounds-for-xaml-controls-using-brushes)
|
||||
1. [XAML Implementation](#xaml-implementation)
|
||||
2. [UI Structure](#ui-structure)
|
||||
3. [EditKeyboardWindow / EditShortcutsWindow](#editkeyboardwindow--editshortcutswindow)
|
||||
1. [OK and Cancel button](#ok-and-cancel-button)
|
||||
@ -17,28 +14,18 @@
|
||||
2. [Single Key ComboBox Selection Handler](#single-key-combobox-selection-handler)
|
||||
3. [Shortcut ComboBox Selection Handler](#shortcut-combobox-selection-handler)
|
||||
|
||||
## C++ XAML Islands
|
||||
The KBM UI is implemented as a C++ XAML Island, but all the controls are implemented in code behind rather than .xaml and .xaml.cs files. This was done as per a XAML Island Code sample and it didn't require a separate UWP project, which could be limited in terms of using hooks. There is a [tech debt item](https://github.com/microsoft/PowerToys/issues/2027) for moving this to XAML. The reason it wasn't implemented in the C# Settings was because it required communication with the low level hook thread, which could be too slow if IPC is used, since the UI needs to update on every key event.
|
||||
## XAML Implementation
|
||||
The KBM UI was originally implemented as a XAML Island, but in order to easily support Mica, which is [still an issue](https://github.com/microsoft/microsoft-ui-xaml/issues/5319), the [`XamlBridge`](https://github.com/microsoft/PowerToys/blob/b3f27057d43445abc59aa04405f7c24bb895a61c/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/XamlBridge2.cpp) was rewritten to use a [`FrameworkView`](https://github.com/microsoft/PowerToys/blob/b3f27057d43445abc59aa04405f7c24bb895a61c/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/XamlBridge2.cpp#L47C11-L49) object which is how a traditional UWP app behaves:
|
||||
1. A `CoreWindow` is created by [calling a function inside of `Windows.UI.dll` with an ordinal number of `1500`](https://github.com/microsoft/PowerToys/blob/b3f27057d43445abc59aa04405f7c24bb895a61c/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/XamlBridge2.cpp#L35-L42).
|
||||
2. A [stubbed implementation of `CoreApplicationView`](https://github.com/microsoft/PowerToys/blob/b3f27057d43445abc59aa04405f7c24bb895a61c/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/XamlBridge2.cpp#L10-L18) was created.
|
||||
3. Then [both objects are passed on to the `FrameworkView`](https://github.com/microsoft/PowerToys/blob/b3f27057d43445abc59aa04405f7c24bb895a61c/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/XamlBridge2.cpp#L47-L49) to initialize the XAML framework.
|
||||
4. Lastly, the `CoreWindow` is [attached to the editor window](https://github.com/microsoft/PowerToys/blob/b3f27057d43445abc59aa04405f7c24bb895a61c/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/XamlBridge2.cpp#L54-L61) and its `HWND` is used in-place of `DesktopWindowXamlSource`'s.
|
||||
|
||||
**Note:** For functions which take a XAML component as argument, pass it by value and not by reference. This is because `winrt` WinUI classes store their own internal references, so they are supposed to be passed by value (and internally ref counts are incremented). Passing by reference can lead to weird behavior where the object is `null`.
|
||||
Mica is then achieved by calling [`BackdropMaterial::SetApplyToRootOrPageBackground()`](https://github.com/microsoft/PowerToys/blob/b3f27057d43445abc59aa04405f7c24bb895a61c/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditKeyboardWindow.cpp#L388-L400) in both of the editor windows, or falls back to the `ApplicationPageBackgroundThemeBrush` background if Mica isn't available.
|
||||
|
||||
The windows are [created as C++ windows](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp#L128-L140) and the window sizes are set to default by [scaling them as per DPI](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp#L120-L126) using the `DPIAware::Convert` API from common lib. Since the UI is launched on a new thread, the window may not be in the foreground, so [we call `SetForegroundWindow`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp#L146-L150).
|
||||
The UI was also updated to use WinUI 2.8 to match the look and feel of the Fluent design language of Windows 11 and the rest of PowerToys. There has been talk about [migrating the implementation to XAML files instead of code-behind](https://github.com/microsoft/PowerToys/issues/2027) and [utilizing WinUI 3 going forward](https://github.com/microsoft/PowerToys/issues/15870). More about the update can be read in [here](https://github.com/microsoft/PowerToys/pull/28473).
|
||||
|
||||
`DesktopWindowXamlSource` has to be declared and [it is initialized](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp#L159-L162) using the [`XamlBridge`](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/ui/XamlBridge.cpp), and [a second window handle](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp#L161-L162) is generated for the internal Xaml Island window. Most of the code was based on the [Xaml Island Sample](https://github.com/microsoft/Xaml-Islands-Samples/blob/master/Samples/Win32/SampleCppApp/XamlBridge.cpp). The `XamlBridge` class contains code which handles initializing the Xaml Island containers as well as handling special messages like keyboard navigation, and focus between islands and between the C++ window and the island. It also has methods for clearing the xaml islands and closing the window.
|
||||
|
||||
Once the UI controls are created, the parent container is set as the content for the `DesktopWindowXamlSource` and the `XamlBridge.MessageLoop` is executed. Messages are processed by the C++ window handler like [`EditKeyboardWindowProc`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp#L364-L404). The general structure we use for this is, for any `WM_PAINT` or `WM_SIZE` message we resize the Xaml Island window. For `WM_GETMINMAXINFO` we set minimum widths so that the window cannot be resized beyond a minimum height and width. This is done to prevent the WinUI elements from overlapping and getting cropped. If it is neither of these cases we send the message to the [`XamlBridge.MessageHandler`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/XamlBridge.cpp#L291-L301) which handles Destroy, Activation and Focus. If `WM_NCDESTROY` is received when the `XamlBridge` is `nullptr`, the window thread is terminated.
|
||||
|
||||
**Note:** `ContentDialog` in Xaml Islands requires manually settings a `XamlRoot`. This can generally be done by passing the XamlRoot from a component in the main window, such as the button used to open the dialog ([`sender.as<Button>().XamlRoot()`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/ShortcutControl.cpp#L31-L32)). [These docs]((https://learn.microsoft.com/uwp/api/windows.ui.xaml.controls.contentdialog#contentdialog-in-appwindow-or-xaml-islands)) have more details about this.
|
||||
|
||||
### Debugging exceptions in XAML Islands
|
||||
Sometimes if an exception occurs in XAML Islands, the stack trace may not always point to the correct code causing the exception and instead it will point to the Xaml Island message loop. In these cases the output window in VS will generally show the correct exception.
|
||||
|
||||
### Build times
|
||||
C++ Xaml Islands generally take several minutes to build because the `pch` which contains the WinUI headers takes longer to build and compiles to a file of several GBs. To minimize the build times, multi-processor compilation within the projects have been enabled (files are distributed for compilation to the processors), and references to the Xaml headers have been removed from the .h headers files as much as possible. Since several classes of ours had class members with UI controls like `StackPanel` (which requires definitions of the classes in order to compile), we worked around this by declaring them as `IInspectable` (the equivalent of an object pointer in winrt), and initializing them to the actual control like `StackPanel` in the constructor and accessing all their member functions by inline typecasting (for `IInspectable x;` we do `x = StackPanel();` and `x.as<StackPanel>().MemberFunction()`). Check [this](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/ShortcutControl.cpp#L19-L25) for this type of usage in `ShortcutControl`.
|
||||
|
||||
### Setting custom backgrounds for Xaml Controls using brushes
|
||||
To access the brushes available on C# Xaml, it has to be done with the `Resources.Lookup` syntax:
|
||||
`primaryButton.Background(Windows::UI::Xaml::Application::Current().Resources().Lookup(box_value(L"SystemControlBackgroundBaseMediumLowBrush")).as<Windows::UI::Xaml::Media::SolidColorBrush>());`
|
||||
[**Link to the original documentation**](https://github.com/microsoft/PowerToys/blob/b3f27057d43445abc59aa04405f7c24bb895a61c/doc/devdocs/modules/keyboardmanager/keyboardmanagerui.md#c-xaml-islands)
|
||||
|
||||
## UI Structure
|
||||
The KBM UI consists of a [`Grid` with several columns](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp#L200-L218). Rows are added dynamically when [the add button is pressed](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp#L305-L309). [A vector of vector of unique pointers to `SingleKeyRemapControl`/`ShortcutControl`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp#L248-L249) is created so that references to the UI components and their data are not lost until the window is closed. [`SingleKeyRemapControl`](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/ui/SingleKeyRemapControl.cpp) is the UI class for each row of the Remap keys table, and [`ShortcutControl`](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/ui/ShortcutControl.cpp) is the UI class for each row of the Remap shortcuts table. [`KeyDropDownControl`](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/ui/KeyDropDownControl.cpp) is used for handling the ComboBox operations. Each of these two classes [have vectors of unique pointers to the `KeyDropDownControl` objects](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/ShortcutControl.h#L44-L45) so that references to the objects are active until the control is deleted.
|
||||
|
@ -17,6 +17,14 @@
|
||||
<RegistryValue Type="string" Name="Module_KeyboardManager_Editor" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<File Source="$(var.BinDir)KeyboardManagerEditor\PowerToys.KeyboardManagerEditor.exe" />
|
||||
<File Source="$(var.BinDir)KeyboardManagerEditor\Microsoft.Toolkit.Win32.UI.XamlHost.dll" />
|
||||
<File Source="$(var.BinDir)KeyboardManagerEditor\Microsoft.UI.Xaml.dll" />
|
||||
<File Source="$(var.BinDir)KeyboardManagerEditor\msvcp140_app.dll" />
|
||||
<File Source="$(var.BinDir)KeyboardManagerEditor\resources.pri" />
|
||||
<File Source="$(var.BinDir)KeyboardManagerEditor\vcruntime140_app.dll" />
|
||||
<?if $(sys.BUILDARCH) = x64 ?>
|
||||
<File Source="$(var.BinDir)KeyboardManagerEditor\vcruntime140_1_app.dll" />
|
||||
<?endif ?>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!-- Project configurations -->
|
||||
<Import Project="..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.props" Condition="Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup>
|
||||
<NoWarn>81010002</NoWarn>
|
||||
@ -98,7 +100,7 @@
|
||||
<AdditionalIncludeDirectories>./;$(SolutionDir)src\modules\;$(SolutionDir)src\modules\KeyboardManager\KeyboardManagerEditorLibrary\;$(SolutionDir)src\common\Display;$(SolutionDir)src\common\inc;$(SolutionDir)src\common\Telemetry;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>Display.lib;shcore.lib;Dbghelp.lib;dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Display.lib;shcore.lib;Dbghelp.lib;dwmapi.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(ConfigurationName);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -109,7 +111,7 @@
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>Display.lib;shcore.lib;Dbghelp.lib;dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Display.lib;shcore.lib;Dbghelp.lib;dwmapi.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(ConfigurationName);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -160,6 +162,10 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.7\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.7\build\native\Microsoft.VCRTForwarders.140.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\build\native\Microsoft.Web.WebView2.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
</ImportGroup>
|
||||
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
@ -171,5 +177,15 @@
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.7\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.7\build\native\Microsoft.VCRTForwarders.140.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\build\native\Microsoft.Web.WebView2.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
<Target Name="FakeResourcesPriMerge" BeforeTargets="FinalizeBuildStatus" DependsOnTargets="CopyFilesToOutputDirectory">
|
||||
<Message Text="Renaming Microsoft.UI.Xaml.pri to resources.pri" />
|
||||
<Move SourceFiles="$(OutDir)\Microsoft.UI.Xaml.pri" DestinationFiles="$(OutDir)\resources.pri" />
|
||||
</Target>
|
||||
</Project>
|
@ -1,4 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.8.2-prerelease.220830001" targetFramework="native" />
|
||||
<package id="Microsoft.VCRTForwarders.140" version="1.0.7" targetFramework="native" />
|
||||
<package id="Microsoft.Web.WebView2" version="1.0.2088.41" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.221104.6" targetFramework="native" />
|
||||
</packages>
|
@ -15,7 +15,7 @@
|
||||
#include "EditKeyboardWindow.h"
|
||||
#include "SingleKeyRemapControl.h"
|
||||
#include "KeyDropDownControl.h"
|
||||
#include "XamlBridge.h"
|
||||
#include "XamlBridge2.h"
|
||||
#include "Styles.h"
|
||||
#include "Dialog.h"
|
||||
#include "LoadingAndSavingRemappingHelper.h"
|
||||
@ -41,12 +41,12 @@ HWND hwndEditKeyboardNativeWindow = nullptr;
|
||||
std::mutex editKeyboardWindowMutex;
|
||||
|
||||
// Stores a pointer to the Xaml Bridge object so that it can be accessed from the window procedure
|
||||
static XamlBridge* xamlBridgePtr = nullptr;
|
||||
static XamlBridge2* xamlBridgePtr = nullptr;
|
||||
|
||||
// Theming
|
||||
ThemeListener theme_listener{};
|
||||
static ThemeListener theme_listener{};
|
||||
|
||||
void handleTheme()
|
||||
static void handleTheme()
|
||||
{
|
||||
auto theme = theme_listener.AppTheme;
|
||||
auto isDark = theme == AppTheme::Dark;
|
||||
@ -137,7 +137,7 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMan
|
||||
windowClass.lpfnWndProc = EditKeyboardWindowProc;
|
||||
windowClass.hInstance = hInst;
|
||||
windowClass.lpszClassName = szWindowClass;
|
||||
windowClass.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW);
|
||||
windowClass.hbrBackground = CreateSolidBrush((ThemeHelpers::GetAppTheme() == AppTheme::Dark) ? 0x00000000 : 0x00FFFFFF);
|
||||
windowClass.hIcon = static_cast<HICON>(LoadImageW(
|
||||
windowClass.hInstance,
|
||||
MAKEINTRESOURCE(IDS_KEYBOARDMANAGER_ICON),
|
||||
@ -196,17 +196,19 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMan
|
||||
hwndEditKeyboardNativeWindow = _hWndEditKeyboardWindow;
|
||||
hwndLock.unlock();
|
||||
|
||||
// Hide icon and caption from title bar
|
||||
const DWORD windowThemeOptionsMask = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON;
|
||||
WTA_OPTIONS windowThemeOptions{ windowThemeOptionsMask, windowThemeOptionsMask };
|
||||
SetWindowThemeAttribute(_hWndEditKeyboardWindow, WTA_NONCLIENT, &windowThemeOptions, sizeof(windowThemeOptions));
|
||||
|
||||
handleTheme();
|
||||
theme_listener.AddChangedHandler(handleTheme);
|
||||
|
||||
// Create the xaml bridge object
|
||||
XamlBridge xamlBridge(_hWndEditKeyboardWindow);
|
||||
|
||||
// DesktopSource needs to be declared before the RelativePanel xamlContainer object to avoid errors
|
||||
winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource desktopSource;
|
||||
XamlBridge2 xamlBridge(_hWndEditKeyboardWindow);
|
||||
|
||||
// Create the desktop window xaml source object and set its content
|
||||
hWndXamlIslandEditKeyboardWindow = xamlBridge.InitDesktopWindowsXamlSource(desktopSource);
|
||||
hWndXamlIslandEditKeyboardWindow = xamlBridge.InitBridge();
|
||||
|
||||
// Set the pointer to the xaml bridge object
|
||||
xamlBridgePtr = &xamlBridge;
|
||||
@ -322,11 +324,8 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMan
|
||||
|
||||
// Add remap key button
|
||||
Windows::UI::Xaml::Controls::Button addRemapKey;
|
||||
FontIcon plusSymbol;
|
||||
plusSymbol.FontFamily(Media::FontFamily(L"Segoe MDL2 Assets"));
|
||||
plusSymbol.Glyph(L"\xE710");
|
||||
addRemapKey.Content(plusSymbol);
|
||||
addRemapKey.Margin({ 10, 10, 0, 25 });
|
||||
addRemapKey.Style(AccentButtonStyle());
|
||||
addRemapKey.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
SingleKeyRemapControl::AddNewControlKeyRemapRow(keyRemapTable, keyboardRemapControlObjects);
|
||||
|
||||
@ -337,14 +336,19 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMan
|
||||
UIHelpers::SetFocusOnTypeButtonInLastRow(keyRemapTable, EditorConstants::RemapTableColCount);
|
||||
});
|
||||
|
||||
// Remap key button content
|
||||
StackPanel addRemapKeyContent;
|
||||
addRemapKeyContent.Orientation(Orientation::Horizontal);
|
||||
addRemapKeyContent.Spacing(10);
|
||||
addRemapKeyContent.Children().Append(SymbolIcon(Symbol::Add));
|
||||
TextBlock addRemapKeyText;
|
||||
addRemapKeyText.Text(GET_RESOURCE_STRING(IDS_ADD_KEY_REMAP_BUTTON));
|
||||
addRemapKeyContent.Children().Append(addRemapKeyText);
|
||||
addRemapKey.Content(addRemapKeyContent);
|
||||
|
||||
// Set accessible name for the addRemapKey button
|
||||
addRemapKey.SetValue(Automation::AutomationProperties::NameProperty(), box_value(GET_RESOURCE_STRING(IDS_ADD_KEY_REMAP_BUTTON)));
|
||||
|
||||
// Add tooltip for add button which would appear on hover
|
||||
ToolTip addRemapKeytoolTip;
|
||||
addRemapKeytoolTip.Content(box_value(GET_RESOURCE_STRING(IDS_ADD_KEY_REMAP_BUTTON)));
|
||||
ToolTipService::SetToolTip(addRemapKey, addRemapKeytoolTip);
|
||||
|
||||
// Header and example text at the top of the window
|
||||
StackPanel helperText;
|
||||
helperText.Children().Append(keyRemapInfoHeader);
|
||||
@ -381,7 +385,20 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMan
|
||||
{
|
||||
}
|
||||
|
||||
desktopSource.Content(xamlContainer);
|
||||
UserControl xamlContent;
|
||||
xamlContent.Content(xamlContainer);
|
||||
if (Windows::Foundation::Metadata::ApiInformation::IsTypePresent(L"Windows.UI.Composition.ICompositionSupportsSystemBackdrop"))
|
||||
{
|
||||
// Apply Mica
|
||||
muxc::BackdropMaterial::SetApplyToRootOrPageBackground(xamlContent, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mica isn't available
|
||||
xamlContainer.Background(Application::Current().Resources().Lookup(box_value(L"ApplicationPageBackgroundThemeBrush")).as<Media::SolidColorBrush>());
|
||||
}
|
||||
Window::Current().Content(xamlContent);
|
||||
|
||||
////End XAML Island section
|
||||
if (_hWndEditKeyboardWindow)
|
||||
{
|
||||
@ -400,9 +417,6 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMan
|
||||
hwndEditKeyboardNativeWindow = nullptr;
|
||||
keyboardManagerState.ResetUIState();
|
||||
keyboardManagerState.ClearRegisteredKeyDelays();
|
||||
|
||||
// Cannot be done in WM_DESTROY because that causes crashes due to fatal app exit
|
||||
xamlBridge.ClearXamlIslands();
|
||||
}
|
||||
|
||||
void CreateEditKeyboardWindow(HINSTANCE hInst, KBMEditor::KeyboardManagerState& keyboardManagerState, MappingConfiguration& mappingConfiguration)
|
||||
|
@ -13,9 +13,10 @@
|
||||
#include "ShortcutControl.h"
|
||||
#include "Styles.h"
|
||||
#include "UIHelpers.h"
|
||||
#include "XamlBridge.h"
|
||||
#include "XamlBridge2.h"
|
||||
#include "ShortcutErrorType.h"
|
||||
#include "EditorConstants.h"
|
||||
#include <common/Themes/theme_listener.h>
|
||||
|
||||
using namespace winrt::Windows::Foundation;
|
||||
|
||||
@ -34,7 +35,21 @@ HWND hwndEditShortcutsNativeWindow = nullptr;
|
||||
std::mutex editShortcutsWindowMutex;
|
||||
|
||||
// Stores a pointer to the Xaml Bridge object so that it can be accessed from the window procedure
|
||||
static XamlBridge* xamlBridgePtr = nullptr;
|
||||
static XamlBridge2* xamlBridgePtr = nullptr;
|
||||
|
||||
// Theming
|
||||
static ThemeListener theme_listener{};
|
||||
|
||||
static void handleTheme()
|
||||
{
|
||||
auto theme = theme_listener.AppTheme;
|
||||
auto isDark = theme == AppTheme::Dark;
|
||||
Logger::info(L"Theme is now {}", isDark ? L"Dark" : L"Light");
|
||||
if (hwndEditShortcutsNativeWindow != nullptr)
|
||||
{
|
||||
ThemeHelpers::SetImmersiveDarkMode(hwndEditShortcutsNativeWindow, isDark);
|
||||
}
|
||||
}
|
||||
|
||||
static IAsyncAction OnClickAccept(
|
||||
KBMEditor::KeyboardManagerState& keyboardManagerState,
|
||||
@ -75,7 +90,7 @@ inline void CreateEditShortcutsWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMa
|
||||
windowClass.lpfnWndProc = EditShortcutsWindowProc;
|
||||
windowClass.hInstance = hInst;
|
||||
windowClass.lpszClassName = szWindowClass;
|
||||
windowClass.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW);
|
||||
windowClass.hbrBackground = CreateSolidBrush((ThemeHelpers::GetAppTheme() == AppTheme::Dark) ? 0x00000000 : 0x00FFFFFF);
|
||||
windowClass.hIcon = static_cast<HICON>(LoadImageW(
|
||||
windowClass.hInstance,
|
||||
MAKEINTRESOURCE(IDS_KEYBOARDMANAGER_ICON),
|
||||
@ -132,14 +147,19 @@ inline void CreateEditShortcutsWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMa
|
||||
hwndEditShortcutsNativeWindow = _hWndEditShortcutsWindow;
|
||||
hwndLock.unlock();
|
||||
|
||||
// Hide icon and caption from title bar
|
||||
const DWORD windowThemeOptionsMask = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON;
|
||||
WTA_OPTIONS windowThemeOptions{ windowThemeOptionsMask, windowThemeOptionsMask };
|
||||
SetWindowThemeAttribute(_hWndEditShortcutsWindow, WTA_NONCLIENT, &windowThemeOptions, sizeof(windowThemeOptions));
|
||||
|
||||
handleTheme();
|
||||
theme_listener.AddChangedHandler(handleTheme);
|
||||
|
||||
// Create the xaml bridge object
|
||||
XamlBridge xamlBridge(_hWndEditShortcutsWindow);
|
||||
|
||||
// DesktopSource needs to be declared before the RelativePanel xamlContainer object to avoid errors
|
||||
winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource desktopSource;
|
||||
XamlBridge2 xamlBridge(_hWndEditShortcutsWindow);
|
||||
|
||||
// Create the desktop window xaml source object and set its content
|
||||
hWndXamlIslandEditShortcutsWindow = xamlBridge.InitDesktopWindowsXamlSource(desktopSource);
|
||||
hWndXamlIslandEditShortcutsWindow = xamlBridge.InitBridge();
|
||||
|
||||
// Set the pointer to the xaml bridge object
|
||||
xamlBridgePtr = &xamlBridge;
|
||||
@ -276,11 +296,8 @@ inline void CreateEditShortcutsWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMa
|
||||
|
||||
// Add shortcut button
|
||||
Windows::UI::Xaml::Controls::Button addShortcut;
|
||||
FontIcon plusSymbol;
|
||||
plusSymbol.FontFamily(Xaml::Media::FontFamily(L"Segoe MDL2 Assets"));
|
||||
plusSymbol.Glyph(L"\xE710");
|
||||
addShortcut.Content(plusSymbol);
|
||||
addShortcut.Margin({ 10, 10, 0, 25 });
|
||||
addShortcut.Style(AccentButtonStyle());
|
||||
addShortcut.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
ShortcutControl::AddNewShortcutControlRow(shortcutTable, keyboardRemapControlObjects);
|
||||
|
||||
@ -291,14 +308,19 @@ inline void CreateEditShortcutsWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMa
|
||||
UIHelpers::SetFocusOnTypeButtonInLastRow(shortcutTable, EditorConstants::ShortcutTableColCount);
|
||||
});
|
||||
|
||||
// Remap shortcut button content
|
||||
StackPanel addShortcutContent;
|
||||
addShortcutContent.Orientation(Orientation::Horizontal);
|
||||
addShortcutContent.Spacing(10);
|
||||
addShortcutContent.Children().Append(SymbolIcon(Symbol::Add));
|
||||
TextBlock addShortcutText;
|
||||
addShortcutText.Text(GET_RESOURCE_STRING(IDS_ADD_SHORTCUT_BUTTON));
|
||||
addShortcutContent.Children().Append(addShortcutText);
|
||||
addShortcut.Content(addShortcutContent);
|
||||
|
||||
// Set accessible name for the add shortcut button
|
||||
addShortcut.SetValue(Automation::AutomationProperties::NameProperty(), box_value(GET_RESOURCE_STRING(IDS_ADD_SHORTCUT_BUTTON)));
|
||||
|
||||
// Add tooltip for add button which would appear on hover
|
||||
ToolTip addShortcuttoolTip;
|
||||
addShortcuttoolTip.Content(box_value(GET_RESOURCE_STRING(IDS_ADD_SHORTCUT_BUTTON)));
|
||||
ToolTipService::SetToolTip(addShortcut, addShortcuttoolTip);
|
||||
|
||||
// Header and example text at the top of the window
|
||||
StackPanel helperText;
|
||||
helperText.Children().Append(shortcutRemapInfoHeader);
|
||||
@ -334,7 +356,19 @@ inline void CreateEditShortcutsWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMa
|
||||
{
|
||||
}
|
||||
|
||||
desktopSource.Content(xamlContainer);
|
||||
UserControl xamlContent;
|
||||
xamlContent.Content(xamlContainer);
|
||||
if (Windows::Foundation::Metadata::ApiInformation::IsTypePresent(L"Windows.UI.Composition.ICompositionSupportsSystemBackdrop"))
|
||||
{
|
||||
// Apply Mica
|
||||
muxc::BackdropMaterial::SetApplyToRootOrPageBackground(xamlContent, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mica isn't available
|
||||
xamlContainer.Background(Application::Current().Resources().Lookup(box_value(L"ApplicationPageBackgroundThemeBrush")).as<Media::SolidColorBrush>());
|
||||
}
|
||||
Window::Current().Content(xamlContent);
|
||||
|
||||
////End XAML Island section
|
||||
if (_hWndEditShortcutsWindow)
|
||||
@ -353,9 +387,6 @@ inline void CreateEditShortcutsWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMa
|
||||
hwndEditShortcutsNativeWindow = nullptr;
|
||||
keyboardManagerState.ResetUIState();
|
||||
keyboardManagerState.ClearRegisteredKeyDelays();
|
||||
|
||||
// Cannot be done in WM_DESTROY because that causes crashes due to fatal app exit
|
||||
xamlBridge.ClearXamlIslands();
|
||||
}
|
||||
|
||||
void CreateEditShortcutsWindow(HINSTANCE hInst, KBMEditor::KeyboardManagerState& keyboardManagerState, MappingConfiguration& mappingConfiguration)
|
||||
|
@ -3,12 +3,12 @@
|
||||
namespace EditorConstants
|
||||
{
|
||||
// Default window sizes
|
||||
inline const int DefaultEditKeyboardWindowWidth = 800;
|
||||
inline const int DefaultEditKeyboardWindowWidth = 960;
|
||||
inline const int DefaultEditKeyboardWindowHeight = 600;
|
||||
inline const int MinimumEditKeyboardWindowWidth = 500;
|
||||
inline const int MinimumEditKeyboardWindowHeight = 450;
|
||||
inline const int EditKeyboardTableMinWidth = 700;
|
||||
inline const int DefaultEditShortcutsWindowWidth = 1050;
|
||||
inline const int DefaultEditShortcutsWindowWidth = 1410;
|
||||
inline const int DefaultEditShortcutsWindowHeight = 600;
|
||||
inline const int MinimumEditShortcutsWindowWidth = 500;
|
||||
inline const int MinimumEditShortcutsWindowHeight = 500;
|
||||
@ -21,7 +21,9 @@ namespace EditorConstants
|
||||
inline const long RemapTableArrowColIndex = 1;
|
||||
inline const long RemapTableNewColIndex = 2;
|
||||
inline const long RemapTableRemoveColIndex = 3;
|
||||
inline const DWORD64 RemapTableDropDownWidth = 110;
|
||||
inline const DWORD64 RemapTableDropDownWidth = 160;
|
||||
inline const DWORD64 RemapTableDropDownSpacing = 10;
|
||||
inline const long RemapTargetColumnWidth = 3 * RemapTableDropDownWidth + 3 * RemapTableDropDownSpacing + 65;
|
||||
|
||||
// Shortcut table constants
|
||||
inline const long ShortcutTableColCount = 5;
|
||||
@ -32,14 +34,14 @@ namespace EditorConstants
|
||||
inline const long ShortcutTableTargetAppColIndex = 3;
|
||||
inline const long ShortcutTableRemoveColIndex = 4;
|
||||
inline const long ShortcutArrowColumnWidth = 90;
|
||||
inline const DWORD64 ShortcutTableDropDownWidth = 110;
|
||||
inline const DWORD64 ShortcutTableDropDownWidth = 160;
|
||||
inline const DWORD64 ShortcutTableDropDownSpacing = 10;
|
||||
inline const long ShortcutOriginColumnWidth = 3 * ShortcutTableDropDownWidth + 3 * ShortcutTableDropDownSpacing;
|
||||
inline const long ShortcutTargetColumnWidth = 3 * ShortcutTableDropDownWidth + 3 * ShortcutTableDropDownSpacing + 15;
|
||||
|
||||
// Drop down height used for both Edit Keyboard and Edit Shortcuts
|
||||
inline const DWORD64 TableDropDownHeight = 200;
|
||||
inline const DWORD64 TableArrowColWidth = 230;
|
||||
inline const DWORD64 TableArrowColWidth = 130;
|
||||
inline const DWORD64 TableRemoveColWidth = 20;
|
||||
inline const DWORD64 TableWarningColWidth = 20;
|
||||
inline const DWORD64 TableTargetAppColWidth = ShortcutTableDropDownWidth + TableRemoveColWidth * 2;
|
||||
|
@ -51,8 +51,10 @@ std::vector<std::pair<DWORD, std::wstring>> KeyDropDownControl::GetKeyList(bool
|
||||
void KeyDropDownControl::SetDefaultProperties(bool isShortcut, bool renderDisable)
|
||||
{
|
||||
dropDown = ComboBox();
|
||||
#ifndef USE_NEW_DROPDOWN_WARNING_TIP
|
||||
warningFlyout = Flyout();
|
||||
warningMessage = TextBlock();
|
||||
#endif
|
||||
|
||||
if (!isShortcut)
|
||||
{
|
||||
@ -77,6 +79,19 @@ void KeyDropDownControl::SetDefaultProperties(bool isShortcut, bool renderDisabl
|
||||
CheckAndUpdateKeyboardLayout(currentDropDown, isShortcut, renderDisable);
|
||||
});
|
||||
|
||||
#ifdef USE_NEW_DROPDOWN_WARNING_TIP
|
||||
// Attach the tip to the drop down
|
||||
warningTip.Target(dropDown.as<ComboBox>());
|
||||
dropDown.as<ComboBox>().Loaded([&](winrt::Windows::Foundation::IInspectable const& sender, auto args) {
|
||||
Media::VisualTreeHelper::GetChild(dropDown.as<ComboBox>(), 0).as<Grid>().Children().Append(warningTip);
|
||||
});
|
||||
|
||||
// Tip properties
|
||||
muxc::SymbolIconSource warningIcon;
|
||||
warningIcon.Symbol(Symbol::Important);
|
||||
warningTip.IconSource(warningIcon);
|
||||
warningTip.IsLightDismissEnabled(true);
|
||||
#else
|
||||
// Attach flyout to the drop down
|
||||
warningFlyout.as<Flyout>().Content(warningMessage.as<TextBlock>());
|
||||
|
||||
@ -86,6 +101,7 @@ void KeyDropDownControl::SetDefaultProperties(bool isShortcut, bool renderDisabl
|
||||
style.Setters().Append(Setter(Windows::UI::Xaml::Controls::Control::TabNavigationProperty(), winrt::box_value(Windows::UI::Xaml::Input::KeyboardNavigationMode::Cycle)));
|
||||
warningFlyout.as<Flyout>().FlyoutPresenterStyle(style);
|
||||
dropDown.as<ComboBox>().ContextFlyout().SetAttachedFlyout((FrameworkElement)dropDown.as<ComboBox>(), warningFlyout.as<Flyout>());
|
||||
#endif
|
||||
|
||||
// To set the accessible name of the combo-box (by default index 1)
|
||||
SetAccessibleNameForComboBox(dropDown.as<ComboBox>(), 1);
|
||||
@ -376,6 +392,11 @@ void KeyDropDownControl::ValidateShortcutFromDropDownList(StackPanel table, Stac
|
||||
void KeyDropDownControl::SetDropDownError(ComboBox currentDropDown, hstring message)
|
||||
{
|
||||
currentDropDown.SelectedIndex(-1);
|
||||
|
||||
#ifdef USE_NEW_DROPDOWN_WARNING_TIP
|
||||
warningTip.Title(message);
|
||||
warningTip.IsOpen(true);
|
||||
#else
|
||||
warningMessage.as<TextBlock>().Text(message);
|
||||
try
|
||||
{
|
||||
@ -386,6 +407,7 @@ void KeyDropDownControl::SetDropDownError(ComboBox currentDropDown, hstring mess
|
||||
// If it's loading and some remaps are invalid from previous configs, avoid crashing when flyouts can't be showed yet.
|
||||
Logger::error(L"Failed to show dropdown error flyout: {}", message);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Function to add a shortcut to the UI control as combo boxes
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
#include <keyboardmanager/common/Shortcut.h>
|
||||
|
||||
// Enables the WinUI teaching tip to show as the new warning flyout
|
||||
#define USE_NEW_DROPDOWN_WARNING_TIP
|
||||
|
||||
namespace KBMEditor
|
||||
{
|
||||
class KeyboardManagerState;
|
||||
@ -38,11 +41,16 @@ private:
|
||||
// Stores the previous layout
|
||||
HKL previousLayout = 0;
|
||||
|
||||
#ifdef USE_NEW_DROPDOWN_WARNING_TIP
|
||||
// Stores the teaching tip attached to the current drop down
|
||||
muxc::TeachingTip warningTip;
|
||||
#else
|
||||
// Stores the flyout warning message
|
||||
winrt::Windows::Foundation::IInspectable warningMessage;
|
||||
|
||||
// Stores the flyout attached to the current drop down
|
||||
winrt::Windows::Foundation::IInspectable warningFlyout;
|
||||
#endif
|
||||
|
||||
// Stores whether a key to shortcut warning has to be ignored
|
||||
bool ignoreKeyToShortcutWarning;
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.props" Condition="Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
@ -53,6 +55,7 @@
|
||||
<ClInclude Include="trace.h" />
|
||||
<ClInclude Include="UIHelpers.h" />
|
||||
<ClInclude Include="XamlBridge.h" />
|
||||
<ClInclude Include="XamlBridge2.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="BufferValidationHelpers.cpp" />
|
||||
@ -74,6 +77,7 @@
|
||||
<ClCompile Include="trace.cpp" />
|
||||
<ClCompile Include="UIHelpers.cpp" />
|
||||
<ClCompile Include="XamlBridge.cpp" />
|
||||
<ClCompile Include="XamlBridge2.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
@ -95,6 +99,9 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\build\native\Microsoft.Web.WebView2.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
</ImportGroup>
|
||||
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
@ -103,6 +110,11 @@
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\build\native\Microsoft.Web.WebView2.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory)\..\KeyboardManagerEditor\ resource.base.h resource.h KeyboardManagerEditor.base.rc KeyboardManagerEditor.rc" />
|
||||
|
@ -75,6 +75,9 @@
|
||||
<ClInclude Include="EditorConstants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="XamlBridge2.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
@ -128,6 +131,9 @@
|
||||
<ClCompile Include="KeyDelay.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XamlBridge2.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
@ -118,8 +118,15 @@ void KeyboardManagerState::AddKeyToLayout(const StackPanel& panel, const hstring
|
||||
|
||||
border.Padding({ 20, 10, 20, 10 });
|
||||
border.Margin({ 0, 0, 10, 0 });
|
||||
// Use the base low brush to be consistent with the theme
|
||||
border.Background(Windows::UI::Xaml::Application::Current().Resources().Lookup(box_value(L"SystemControlBackgroundBaseLowBrush")).as<Windows::UI::Xaml::Media::SolidColorBrush>());
|
||||
|
||||
// Based on settings-ui\Settings.UI\SettingsXAML\Controls\KeyVisual\KeyVisual.xaml
|
||||
border.Background(Application::Current().Resources().Lookup(box_value(L"ButtonBackground")).as<Media::Brush>());
|
||||
border.BorderBrush(Application::Current().Resources().Lookup(box_value(L"ButtonBorderBrush")).as<Media::Brush>());
|
||||
border.BorderThickness(unbox_value<Thickness>(Application::Current().Resources().Lookup(box_value(L"ButtonBorderThemeThickness"))));
|
||||
border.CornerRadius(unbox_value<CornerRadius>(Application::Current().Resources().Lookup(box_value(L"ControlCornerRadius"))));
|
||||
remapKey.Foreground(Application::Current().Resources().Lookup(box_value(L"ButtonForeground")).as<Media::Brush>());
|
||||
remapKey.FontWeight(Text::FontWeights::SemiBold());
|
||||
|
||||
remapKey.FontSize(20);
|
||||
border.HorizontalAlignment(HorizontalAlignment::Left);
|
||||
border.Child(remapKey);
|
||||
|
@ -90,13 +90,12 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
||||
newrow.emplace_back(std::make_unique<ShortcutControl>(parent, row, 1, targetAppTextBox));
|
||||
keyboardRemapControlObjects.push_back(std::move(newrow));
|
||||
|
||||
row.Padding({ 10, 10, 10, 10 });
|
||||
row.Padding({ 10, 15, 10, 5 });
|
||||
row.Margin({ 0, 0, 0, 2 });
|
||||
row.Orientation(Orientation::Horizontal);
|
||||
auto brush = Windows::UI::Xaml::Application::Current().Resources().Lookup(box_value(L"SystemControlBackgroundListLowBrush")).as<Windows::UI::Xaml::Media::SolidColorBrush>();
|
||||
if (keyboardRemapControlObjects.size() % 2)
|
||||
{
|
||||
row.Background(brush);
|
||||
}
|
||||
row.Background(Application::Current().Resources().Lookup(box_value(L"CardBackgroundFillColorDefaultBrush")).as<Media::Brush>());
|
||||
row.BorderBrush(Application::Current().Resources().Lookup(box_value(L"CardStrokeColorDefaultBrush")).as<Media::Brush>());
|
||||
row.BorderThickness({ 0, 1, 0, 1 });
|
||||
|
||||
// ShortcutControl for the original shortcut
|
||||
auto origin = keyboardRemapControlObjects.back()[0]->GetShortcutControl();
|
||||
@ -104,14 +103,13 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
||||
row.Children().Append(origin);
|
||||
|
||||
// Arrow icon
|
||||
FontIcon arrowIcon;
|
||||
arrowIcon.FontFamily(Xaml::Media::FontFamily(L"Segoe MDL2 Assets"));
|
||||
arrowIcon.Glyph(L"\xE72A");
|
||||
SymbolIcon arrowIcon(Symbol::Forward);
|
||||
arrowIcon.VerticalAlignment(VerticalAlignment::Center);
|
||||
arrowIcon.HorizontalAlignment(HorizontalAlignment::Center);
|
||||
auto arrowIconContainer = UIHelpers::GetWrapped(arrowIcon, EditorConstants::ShortcutArrowColumnWidth).as<StackPanel>();
|
||||
arrowIconContainer.Orientation(Orientation::Vertical);
|
||||
arrowIconContainer.VerticalAlignment(VerticalAlignment::Center);
|
||||
arrowIconContainer.Margin({ 0, 0, 0, 10 });
|
||||
row.Children().Append(arrowIconContainer);
|
||||
|
||||
// ShortcutControl for the new shortcut
|
||||
@ -122,6 +120,7 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
||||
targetAppTextBox.Width(EditorConstants::ShortcutTableDropDownWidth);
|
||||
targetAppTextBox.PlaceholderText(KeyboardManagerEditorStrings::DefaultAppName());
|
||||
targetAppTextBox.Text(targetAppName);
|
||||
targetAppTextBox.Margin({ 0, 0, 0, 10 });
|
||||
|
||||
// GotFocus handler will be called whenever the user tabs into or clicks on the textbox
|
||||
targetAppTextBox.GotFocus([targetAppTextBox](auto const& sender, auto const& e) {
|
||||
@ -194,13 +193,11 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
||||
|
||||
// Delete row button
|
||||
Windows::UI::Xaml::Controls::Button deleteShortcut;
|
||||
FontIcon deleteSymbol;
|
||||
deleteSymbol.FontFamily(Xaml::Media::FontFamily(L"Segoe MDL2 Assets"));
|
||||
deleteSymbol.Glyph(L"\xE74D");
|
||||
deleteShortcut.Content(deleteSymbol);
|
||||
deleteShortcut.Content(SymbolIcon(Symbol::Delete));
|
||||
deleteShortcut.Background(Media::SolidColorBrush(Colors::Transparent()));
|
||||
deleteShortcut.HorizontalAlignment(HorizontalAlignment::Center);
|
||||
deleteShortcut.Click([&, parent, row, brush, deleteShortcut](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
deleteShortcut.Margin({ 0, 0, 0, 10 });
|
||||
deleteShortcut.Click([&, parent, row, deleteShortcut](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
Button currentButton = sender.as<Button>();
|
||||
uint32_t rowIndex;
|
||||
// Get index of delete button
|
||||
@ -216,7 +213,6 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
||||
for (uint32_t i = rowIndex + 1; i < children.Size(); i++)
|
||||
{
|
||||
StackPanel row = children.GetAt(i).as<StackPanel>();
|
||||
row.Background(i % 2 ? brush : Media::SolidColorBrush(Colors::Transparent()));
|
||||
StackPanel sourceCol = row.Children().GetAt(0).as<StackPanel>();
|
||||
StackPanel targetCol = row.Children().GetAt(2).as<StackPanel>();
|
||||
TextBox targetApp = row.Children().GetAt(3).as<StackPanel>().Children().GetAt(0).as<StackPanel>().Children().GetAt(0).as<TextBox>();
|
||||
@ -294,8 +290,6 @@ void ShortcutControl::CreateDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
// ContentDialog requires manually setting the XamlRoot (https://learn.microsoft.com/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
|
||||
VariableSizedWrapGrid linkedShortcutVariableSizedWrapGrid = UIHelpers::GetSiblingElement(sender).as<VariableSizedWrapGrid>();
|
||||
@ -359,16 +353,13 @@ void ShortcutControl::CreateDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
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&) {
|
||||
detectShortcutBox.DefaultButton(ContentDialogButton::Primary);
|
||||
detectShortcutBox.PrimaryButtonText(GET_RESOURCE_STRING(IDS_OK_BUTTON));
|
||||
detectShortcutBox.PrimaryButtonClick([onAccept](winrt::Windows::Foundation::IInspectable const& sender, ContentDialogButtonClickEventArgs const& args) {
|
||||
// Cancel default dialog events
|
||||
args.Cancel(true);
|
||||
|
||||
onAccept();
|
||||
});
|
||||
|
||||
@ -376,12 +367,10 @@ void ShortcutControl::CreateDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
keyboardManagerState.RegisterKeyDelay(
|
||||
VK_RETURN,
|
||||
selectDetectedShortcutAndResetKeys,
|
||||
[primaryButton, onPressEnter, detectShortcutBox](DWORD) {
|
||||
[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] {
|
||||
onPressEnter();
|
||||
});
|
||||
},
|
||||
@ -393,9 +382,6 @@ void ShortcutControl::CreateDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
});
|
||||
});
|
||||
|
||||
TextBlock cancelButtonText;
|
||||
cancelButtonText.Text(GET_RESOURCE_STRING(IDS_CANCEL_BUTTON));
|
||||
|
||||
auto onCancel = [&keyboardManagerState,
|
||||
detectShortcutBox,
|
||||
unregisterKeys,
|
||||
@ -418,12 +404,12 @@ void ShortcutControl::CreateDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
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&) {
|
||||
detectShortcutBox.CloseButtonText(GET_RESOURCE_STRING(IDS_CANCEL_BUTTON));
|
||||
detectShortcutBox.CloseButtonClick([onCancel](winrt::Windows::Foundation::IInspectable const& sender, ContentDialogButtonClickEventArgs const& args) {
|
||||
// Cancel default dialog events
|
||||
args.Cancel(true);
|
||||
|
||||
onCancel();
|
||||
});
|
||||
|
||||
@ -474,21 +460,6 @@ void ShortcutControl::CreateDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
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.
|
||||
|
@ -84,33 +84,31 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, std::ve
|
||||
newrow.emplace_back(std::make_unique<SingleKeyRemapControl>(parent, row, 1));
|
||||
keyboardRemapControlObjects.push_back(std::move(newrow));
|
||||
|
||||
row.Padding({ 10, 10, 10, 10 });
|
||||
row.Padding({ 10, 15, 10, 5 });
|
||||
row.Margin({ 0, 0, 0, 2 });
|
||||
row.Orientation(Orientation::Horizontal);
|
||||
auto brush = Windows::UI::Xaml::Application::Current().Resources().Lookup(box_value(L"SystemControlBackgroundListLowBrush")).as<Windows::UI::Xaml::Media::SolidColorBrush>();
|
||||
if (keyboardRemapControlObjects.size() % 2)
|
||||
{
|
||||
row.Background(brush);
|
||||
}
|
||||
row.Background(Application::Current().Resources().Lookup(box_value(L"CardBackgroundFillColorDefaultBrush")).as<Media::Brush>());
|
||||
row.BorderBrush(Application::Current().Resources().Lookup(box_value(L"CardStrokeColorDefaultBrush")).as<Media::Brush>());
|
||||
row.BorderThickness({ 0, 1, 0, 1 });
|
||||
|
||||
// SingleKeyRemapControl for the original key.
|
||||
auto originalElement = keyboardRemapControlObjects.back()[0]->getSingleKeyRemapControl();
|
||||
originalElement.Width(EditorConstants::RemapTableDropDownWidth + EditorConstants::ShortcutTableDropDownSpacing);
|
||||
originalElement.Width(EditorConstants::RemapTableDropDownWidth + EditorConstants::RemapTableDropDownSpacing);
|
||||
row.Children().Append(originalElement);
|
||||
|
||||
// Arrow icon
|
||||
FontIcon arrowIcon;
|
||||
arrowIcon.FontFamily(Media::FontFamily(L"Segoe MDL2 Assets"));
|
||||
arrowIcon.Glyph(L"\xE72A");
|
||||
SymbolIcon arrowIcon(Symbol::Forward);
|
||||
arrowIcon.VerticalAlignment(VerticalAlignment::Center);
|
||||
arrowIcon.HorizontalAlignment(HorizontalAlignment::Center);
|
||||
auto arrowIconContainer = UIHelpers::GetWrapped(arrowIcon, EditorConstants::TableArrowColWidth).as<StackPanel>();
|
||||
arrowIconContainer.Orientation(Orientation::Vertical);
|
||||
arrowIconContainer.VerticalAlignment(VerticalAlignment::Center);
|
||||
arrowIconContainer.Margin({ 0, 0, 0, 10 });
|
||||
row.Children().Append(arrowIconContainer);
|
||||
|
||||
// SingleKeyRemapControl for the new remap key
|
||||
auto targetElement = keyboardRemapControlObjects.back()[1]->getSingleKeyRemapControl();
|
||||
targetElement.Width(EditorConstants::ShortcutTargetColumnWidth);
|
||||
targetElement.Width(EditorConstants::RemapTargetColumnWidth);
|
||||
row.Children().Append(targetElement);
|
||||
|
||||
// Set the key text if the two keys are not null (i.e. default args)
|
||||
@ -135,13 +133,11 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, std::ve
|
||||
|
||||
// Delete row button
|
||||
Windows::UI::Xaml::Controls::Button deleteRemapKeys;
|
||||
FontIcon deleteSymbol;
|
||||
deleteSymbol.FontFamily(Media::FontFamily(L"Segoe MDL2 Assets"));
|
||||
deleteSymbol.Glyph(L"\xE74D");
|
||||
deleteRemapKeys.Content(deleteSymbol);
|
||||
deleteRemapKeys.Content(SymbolIcon(Symbol::Delete));
|
||||
deleteRemapKeys.Background(Media::SolidColorBrush(Colors::Transparent()));
|
||||
deleteRemapKeys.HorizontalAlignment(HorizontalAlignment::Center);
|
||||
deleteRemapKeys.Click([&, parent, row, brush, deleteRemapKeys](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
deleteRemapKeys.Margin({ 0, 0, 0, 10 });
|
||||
deleteRemapKeys.Click([&, parent, row, deleteRemapKeys](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
uint32_t rowIndex;
|
||||
// Get index of delete button
|
||||
UIElementCollection children = parent.Children();
|
||||
@ -157,7 +153,6 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, std::ve
|
||||
for (uint32_t i = rowIndex + 1; i < children.Size(); i++)
|
||||
{
|
||||
StackPanel row = children.GetAt(i).as<StackPanel>();
|
||||
row.Background(i % 2 ? brush : Media::SolidColorBrush(Colors::Transparent()));
|
||||
StackPanel sourceCol = row.Children().GetAt(0).as<StackPanel>();
|
||||
StackPanel targetCol = row.Children().GetAt(2).as<StackPanel>();
|
||||
Button delButton = row.Children().GetAt(3).as<Button>();
|
||||
@ -224,8 +219,6 @@ void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::II
|
||||
// ContentDialog requires manually setting the XamlRoot (https://learn.microsoft.com/uwp/api/windows.ui.xaml.controls.contentdialog#contentdialog-in-appwindow-or-xaml-islands)
|
||||
detectRemapKeyBox.XamlRoot(xamlRoot);
|
||||
detectRemapKeyBox.Title(box_value(GET_RESOURCE_STRING(IDS_TYPEKEY_TITLE)));
|
||||
detectRemapKeyBox.IsPrimaryButtonEnabled(false);
|
||||
detectRemapKeyBox.IsSecondaryButtonEnabled(false);
|
||||
|
||||
// Get the linked text block for the "Type Key" button that was clicked
|
||||
ComboBox linkedRemapDropDown = UIHelpers::GetSiblingElement(sender).as<ComboBox>();
|
||||
@ -269,14 +262,13 @@ void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::II
|
||||
onReleaseEnter();
|
||||
};
|
||||
|
||||
TextBlock primaryButtonText;
|
||||
primaryButtonText.Text(GET_RESOURCE_STRING(IDS_OK_BUTTON));
|
||||
// OK button
|
||||
detectRemapKeyBox.DefaultButton(ContentDialogButton::Primary);
|
||||
detectRemapKeyBox.PrimaryButtonText(GET_RESOURCE_STRING(IDS_OK_BUTTON));
|
||||
detectRemapKeyBox.PrimaryButtonClick([onAccept](winrt::Windows::Foundation::IInspectable const& sender, ContentDialogButtonClickEventArgs const& args) {
|
||||
// Cancel default dialog events
|
||||
args.Cancel(true);
|
||||
|
||||
Button primaryButton;
|
||||
primaryButton.HorizontalAlignment(HorizontalAlignment::Stretch);
|
||||
primaryButton.Margin({ 2, 2, 2, 2 });
|
||||
primaryButton.Content(primaryButtonText);
|
||||
primaryButton.Click([onAccept](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
onAccept();
|
||||
});
|
||||
|
||||
@ -284,12 +276,10 @@ void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::II
|
||||
keyboardManagerState.RegisterKeyDelay(
|
||||
VK_RETURN,
|
||||
std::bind(&KBMEditor::KeyboardManagerState::SelectDetectedRemapKey, &keyboardManagerState, std::placeholders::_1),
|
||||
[primaryButton, onPressEnter, detectRemapKeyBox](DWORD) {
|
||||
[onPressEnter, detectRemapKeyBox](DWORD) {
|
||||
detectRemapKeyBox.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] {
|
||||
onPressEnter();
|
||||
});
|
||||
},
|
||||
@ -301,9 +291,6 @@ void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::II
|
||||
});
|
||||
});
|
||||
|
||||
TextBlock cancelButtonText;
|
||||
cancelButtonText.Text(GET_RESOURCE_STRING(IDS_CANCEL_BUTTON));
|
||||
|
||||
auto onCancel = [&keyboardManagerState,
|
||||
detectRemapKeyBox,
|
||||
unregisterKeys] {
|
||||
@ -317,13 +304,12 @@ void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::II
|
||||
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&) {
|
||||
detectRemapKeyBox.CloseButtonText(GET_RESOURCE_STRING(IDS_CANCEL_BUTTON));
|
||||
detectRemapKeyBox.CloseButtonClick([onCancel](winrt::Windows::Foundation::IInspectable const& sender, ContentDialogButtonClickEventArgs const& args) {
|
||||
// Cancel default dialog events
|
||||
args.Cancel(true);
|
||||
|
||||
onCancel();
|
||||
});
|
||||
|
||||
@ -367,21 +353,6 @@ void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::II
|
||||
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.
|
||||
|
@ -1,15 +1,7 @@
|
||||
#include "pch.h"
|
||||
#include "Styles.h"
|
||||
#include <common/themes/windows_colors.h>
|
||||
|
||||
Style AccentButtonStyle()
|
||||
{
|
||||
Style style{ winrt::xaml_typename<Controls::Button>() };
|
||||
style.Setters().Append(Setter{
|
||||
Controls::Control::BackgroundProperty(),
|
||||
winrt::Windows::UI::Xaml::Media::SolidColorBrush{ WindowsColors::get_accent_color() } });
|
||||
style.Setters().Append(Setter{
|
||||
Controls::Control::ForegroundProperty(),
|
||||
winrt::Windows::UI::Xaml::Media::SolidColorBrush{ winrt::Windows::UI::Colors::White() } });
|
||||
return style;
|
||||
return Application::Current().Resources().Lookup(box_value(L"AccentButtonStyle")).as<Style>();
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
#include "pch.h"
|
||||
#include "XamlBridge2.h"
|
||||
#include <CoreWindow.h> // ICoreWindowInterop
|
||||
|
||||
#include <winrt/Microsoft.Toolkit.Win32.UI.XamlHost.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.XamlTypeInfo.h>
|
||||
|
||||
namespace wac = Windows::ApplicationModel::Core;
|
||||
|
||||
// Stubbed implementation for frameworkView.Initialize()
|
||||
struct XamlBridgeCoreAppViewImpl : implements<XamlBridgeCoreAppViewImpl, wac::ICoreApplicationView>
|
||||
{
|
||||
auto CoreWindow() { return Core::CoreWindow::GetForCurrentThread(); }
|
||||
auto Activated(Windows::Foundation::TypedEventHandler<wac::CoreApplicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs> const&) { return event_token(); }
|
||||
auto Activated(event_token const&) {}
|
||||
auto IsMain() { return true; }
|
||||
auto IsHosted() { return false; }
|
||||
};
|
||||
|
||||
// Function to run the message loop for the xaml window
|
||||
void XamlBridge2::MessageLoop()
|
||||
{
|
||||
Logger::trace("XamlBridge2::MessageLoop()");
|
||||
frameworkView.Run();
|
||||
Logger::trace("XamlBridge2::MessageLoop() stopped");
|
||||
}
|
||||
|
||||
// Function to initialize the xaml bridge
|
||||
HWND XamlBridge2::InitBridge()
|
||||
{
|
||||
Logger::trace("XamlBridge2::InitBridge()");
|
||||
HRESULT hr = S_OK;
|
||||
winrt::init_apartment(apartment_type::single_threaded);
|
||||
|
||||
auto windowsUIHandle = LoadLibrary(TEXT("Windows.UI.dll"));
|
||||
auto pfnPrivateCreateCoreWindow = reinterpret_cast<fnPrivateCreateCoreWindow>(GetProcAddress(windowsUIHandle, MAKEINTRESOURCEA(1500)));
|
||||
|
||||
// Create the core window to host the XAML content
|
||||
void* pCoreWindow;
|
||||
hr = pfnPrivateCreateCoreWindow(IMMERSIVE_HOSTED, L"", 0, 0, 0, 0, 0, parentWindow, winrt::guid_of<Core::ICoreWindow>(), &pCoreWindow);
|
||||
winrt::check_hresult(hr);
|
||||
coreWindow = Core::CoreWindow(pCoreWindow, winrt::take_ownership_from_abi);
|
||||
|
||||
// Prep for the WinUI resources
|
||||
auto app = Microsoft::Toolkit::Win32::UI::XamlHost::XamlApplication({ Microsoft::UI::Xaml::XamlTypeInfo::XamlControlsXamlMetaDataProvider() });
|
||||
|
||||
// Initialize the XAML framework
|
||||
frameworkView.Initialize(*reinterpret_cast<wac::CoreApplicationView*>(&make<XamlBridgeCoreAppViewImpl>()));
|
||||
frameworkView.SetWindow(coreWindow);
|
||||
|
||||
// Add the WinUI resources
|
||||
app.Resources().MergedDictionaries().Append(muxc::XamlControlsResources());
|
||||
|
||||
auto coreWindowInterop = coreWindow.as<ICoreWindowInterop>();
|
||||
hr = coreWindowInterop->get_WindowHandle(&coreWindowHwnd);
|
||||
winrt::check_hresult(hr);
|
||||
|
||||
SetParent(coreWindowHwnd, parentWindow);
|
||||
SetWindowLong(coreWindowHwnd, GWL_STYLE, WS_CHILD | WS_VISIBLE);
|
||||
|
||||
return coreWindowHwnd;
|
||||
}
|
||||
|
||||
// Message Handler function for Xaml windows
|
||||
LRESULT XamlBridge2::MessageHandler(UINT const message, WPARAM const wParam, LPARAM const lParam) noexcept
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_ACTIVATE:
|
||||
case WM_MOVE:
|
||||
SendMessage(coreWindowHwnd, message, wParam, lParam);
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc(parentWindow, message, wParam, lParam);
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
// This class is used for handling XAML operations
|
||||
class XamlBridge2
|
||||
{
|
||||
public:
|
||||
// Function to run the message loop for the xaml window
|
||||
void MessageLoop();
|
||||
|
||||
// Constructor
|
||||
XamlBridge2(HWND parent) : parentWindow(parent) {}
|
||||
|
||||
// Function to initialize the xaml bridge
|
||||
HWND InitBridge();
|
||||
|
||||
// Message Handler function for Xaml windows
|
||||
LRESULT MessageHandler(UINT const message, WPARAM const wParam, LPARAM const lParam) noexcept;
|
||||
|
||||
private:
|
||||
// Defines the window types for core windows
|
||||
enum WINDOW_TYPE
|
||||
{
|
||||
IMMERSIVE_BODY = 0x0,
|
||||
IMMERSIVE_DOCK = 0x1,
|
||||
IMMERSIVE_HOSTED = 0x2,
|
||||
IMMERSIVE_TEST = 0x3,
|
||||
IMMERSIVE_BODY_ACTIVE = 0x4,
|
||||
IMMERSIVE_DOCK_ACTIVE = 0x5,
|
||||
NOT_IMMERSIVE = 0x6,
|
||||
};
|
||||
|
||||
// Function signature for PrivateCreateCoreWindow
|
||||
typedef HRESULT(CDECL* fnPrivateCreateCoreWindow)(WINDOW_TYPE WindowType, LPCWSTR pWindowTitle, INT X, INT Y, UINT uWidth, UINT uHeight, DWORD dwAttributes, HWND hOwnerWindow, REFIID riid, void** ppv);
|
||||
|
||||
// Stores the handle of the parent native window
|
||||
HWND parentWindow = nullptr;
|
||||
|
||||
// Stores the core window for the UI thread
|
||||
Core::CoreWindow coreWindow = nullptr;
|
||||
|
||||
// Stores the handle of the core window
|
||||
HWND coreWindowHwnd = nullptr;
|
||||
|
||||
// Stores the xaml framework view for the UI thread
|
||||
FrameworkView frameworkView;
|
||||
};
|
@ -1,4 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.8.2-prerelease.220830001" targetFramework="native" />
|
||||
<package id="Microsoft.Web.WebView2" version="1.0.2088.41" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.221104.6" targetFramework="native" />
|
||||
</packages>
|
@ -10,8 +10,10 @@
|
||||
#include <windows.ui.xaml.hosting.desktopwindowxamlsource.h>
|
||||
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <winrt/Windows.Foundation.Metadata.h>
|
||||
#include <winrt/Windows.UI.Core.h>
|
||||
#include <winrt/Windows.UI.Text.h>
|
||||
#include <winrt/Windows.ApplicationModel.Core.h>
|
||||
|
||||
#pragma push_macro("GetCurrentTime")
|
||||
#undef GetCurrentTime
|
||||
@ -21,6 +23,7 @@
|
||||
#include <winrt/Windows.UI.Xaml.Hosting.h>
|
||||
#include <winrt/Windows.UI.Xaml.Interop.h>
|
||||
#include <winrt/Windows.ui.xaml.media.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.Controls.h>
|
||||
#pragma pop_macro("GetCurrentTime")
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
@ -37,4 +40,5 @@ using namespace Windows::UI::Composition;
|
||||
using namespace Windows::UI::Xaml::Hosting;
|
||||
using namespace Windows::Foundation::Numerics;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
namespace muxc = Microsoft::UI::Xaml::Controls;
|
Loading…
Reference in New Issue
Block a user