2020-03-23 10:44:02 -07:00
# include "pch.h"
2020-03-05 15:52:59 -08:00
# include "EditKeyboardWindow.h"
2020-03-27 08:38:58 -07:00
# include "SingleKeyRemapControl.h"
2020-04-18 16:12:26 -07:00
# include "KeyDropDownControl.h"
2020-04-29 17:58:31 -07:00
# include "XamlBridge.h"
2020-05-05 12:30:50 -07:00
# include <keyboardmanager/common/trace.h>
2020-05-11 12:45:55 -07:00
# include <keyboardmanager/common/KeyboardManagerConstants.h>
# include <set>
# include <common/windows_colors.h>
2020-05-12 10:17:27 -07:00
# include <common/dpi_aware.h>
2020-05-11 12:45:55 -07:00
# include "Styles.h"
# include "Dialog.h"
2020-05-11 20:13:07 -07:00
# include <keyboardmanager/dll/resource.h>
2020-07-13 11:49:09 -07:00
# include "../common/shared_constants.h"
# include "keyboardmanager/common/KeyboardManagerState.h"
2020-08-13 16:32:15 -07:00
# include "LoadingAndSavingRemappingHelper.h"
2020-05-11 12:45:55 -07:00
using namespace winrt : : Windows : : Foundation ;
2020-03-05 15:52:59 -08:00
LRESULT CALLBACK EditKeyboardWindowProc ( HWND , UINT , WPARAM , LPARAM ) ;
2020-03-23 10:44:02 -07:00
// This Hwnd will be the window handler for the Xaml Island: A child window that contains Xaml.
2020-03-05 15:52:59 -08:00
HWND hWndXamlIslandEditKeyboardWindow = nullptr ;
2020-03-23 10:44:02 -07:00
// This variable is used to check if window registration has been done to avoid repeated registration leading to an error.
bool isEditKeyboardWindowRegistrationCompleted = false ;
2020-04-14 09:24:11 -07:00
// Holds the native window handle of EditKeyboard Window.
HWND hwndEditKeyboardNativeWindow = nullptr ;
std : : mutex editKeyboardWindowMutex ;
2020-04-29 17:58:31 -07:00
// Stores a pointer to the Xaml Bridge object so that it can be accessed from the window procedure
static XamlBridge * xamlBridgePtr = nullptr ;
2020-03-05 15:52:59 -08:00
2020-05-11 12:45:55 -07:00
static IAsyncOperation < bool > OrphanKeysConfirmationDialog (
KeyboardManagerState & state ,
const std : : vector < DWORD > & keys ,
XamlRoot root )
{
ContentDialog confirmationDialog ;
confirmationDialog . XamlRoot ( root ) ;
confirmationDialog . Title ( box_value ( L " The following keys are unassigned and you won't be able to use them: " ) ) ;
confirmationDialog . Content ( nullptr ) ;
confirmationDialog . IsPrimaryButtonEnabled ( true ) ;
confirmationDialog . DefaultButton ( ContentDialogButton : : Primary ) ;
confirmationDialog . PrimaryButtonText ( winrt : : hstring ( L " Continue Anyway " ) ) ;
confirmationDialog . IsSecondaryButtonEnabled ( true ) ;
confirmationDialog . SecondaryButtonText ( winrt : : hstring ( L " Cancel " ) ) ;
TextBlock orphanKeysBlock ;
std : : wstring orphanKeyString ;
for ( auto k : keys )
{
orphanKeyString . append ( state . keyboardMap . GetKeyName ( k ) ) ;
orphanKeyString . append ( L " , " ) ;
}
orphanKeyString = orphanKeyString . substr ( 0 , max ( 0 , orphanKeyString . length ( ) - 2 ) ) ;
orphanKeysBlock . Text ( winrt : : hstring ( orphanKeyString ) ) ;
orphanKeysBlock . TextWrapping ( TextWrapping : : Wrap ) ;
confirmationDialog . Content ( orphanKeysBlock ) ;
ContentDialogResult res = co_await confirmationDialog . ShowAsync ( ) ;
co_return res = = ContentDialogResult : : Primary ;
}
static IAsyncAction OnClickAccept ( KeyboardManagerState & keyboardManagerState , XamlRoot root , std : : function < void ( ) > ApplyRemappings )
{
2020-08-13 16:32:15 -07:00
KeyboardManagerHelper : : ErrorType isSuccess = LoadingAndSavingRemappingHelper : : CheckIfRemappingsAreValid ( SingleKeyRemapControl : : singleKeyRemapBuffer ) ;
2020-07-23 16:43:49 -07:00
2020-05-11 12:45:55 -07:00
if ( isSuccess ! = KeyboardManagerHelper : : ErrorType : : NoError )
{
2020-06-23 23:00:58 -04:00
if ( ! co_await Dialog : : PartialRemappingConfirmationDialog ( root , L " Some of the keys could not be remapped. Do you want to continue anyway? " ) )
2020-05-11 12:45:55 -07:00
{
co_return ;
}
}
2020-07-23 16:43:49 -07:00
2020-05-11 12:45:55 -07:00
// Check for orphaned keys
// Draw content Dialog
2020-08-13 16:32:15 -07:00
std : : vector < DWORD > orphanedKeys = LoadingAndSavingRemappingHelper : : GetOrphanedKeys ( SingleKeyRemapControl : : singleKeyRemapBuffer ) ;
2020-05-11 12:45:55 -07:00
if ( orphanedKeys . size ( ) > 0 )
{
if ( ! co_await OrphanKeysConfirmationDialog ( keyboardManagerState , orphanedKeys , root ) )
{
co_return ;
}
}
ApplyRemappings ( ) ;
}
2020-05-11 17:18:12 -07:00
2020-03-23 10:44:02 -07:00
// Function to create the Edit Keyboard Window
void createEditKeyboardWindow ( HINSTANCE hInst , KeyboardManagerState & keyboardManagerState )
2020-03-05 15:52:59 -08:00
{
2020-03-23 10:44:02 -07:00
// Window Registration
2020-03-05 15:52:59 -08:00
const wchar_t szWindowClass [ ] = L " EditKeyboardWindow " ;
2020-03-23 10:44:02 -07:00
if ( ! isEditKeyboardWindowRegistrationCompleted )
2020-03-05 15:52:59 -08:00
{
2020-03-23 10:44:02 -07:00
WNDCLASSEX windowClass = { } ;
windowClass . cbSize = sizeof ( WNDCLASSEX ) ;
windowClass . lpfnWndProc = EditKeyboardWindowProc ;
windowClass . hInstance = hInst ;
windowClass . lpszClassName = szWindowClass ;
windowClass . hbrBackground = ( HBRUSH ) ( COLOR_WINDOW ) ;
2020-05-12 15:58:11 -07:00
windowClass . hIcon = ( HICON ) LoadImageW (
windowClass . hInstance ,
MAKEINTRESOURCE ( IDS_KEYBOARDMANAGER_ICON ) ,
IMAGE_ICON ,
48 ,
48 ,
2020-05-11 20:13:07 -07:00
LR_DEFAULTCOLOR ) ;
2020-03-23 10:44:02 -07:00
if ( RegisterClassEx ( & windowClass ) = = NULL )
{
MessageBox ( NULL , L " Windows registration failed! " , L " Error " , NULL ) ;
return ;
}
isEditKeyboardWindowRegistrationCompleted = true ;
2020-03-05 15:52:59 -08:00
}
2020-05-08 17:34:24 -07:00
// Find center screen coordinates
RECT desktopRect ;
GetClientRect ( GetDesktopWindow ( ) , & desktopRect ) ;
2020-05-12 10:17:27 -07:00
// Calculate DPI dependent window size
int windowWidth = KeyboardManagerConstants : : DefaultEditKeyboardWindowWidth ;
int windowHeight = KeyboardManagerConstants : : DefaultEditKeyboardWindowHeight ;
DPIAware : : Convert ( nullptr , windowWidth , windowHeight ) ;
2020-05-08 17:34:24 -07:00
2020-03-23 10:44:02 -07:00
// Window Creation
2020-03-05 15:52:59 -08:00
HWND _hWndEditKeyboardWindow = CreateWindow (
szWindowClass ,
2020-05-29 21:01:29 +02:00
L " Remap keys " ,
2020-05-12 15:58:11 -07:00
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MAXIMIZEBOX ,
2020-05-08 17:34:24 -07:00
( desktopRect . right / 2 ) - ( windowWidth / 2 ) ,
( desktopRect . bottom / 2 ) - ( windowHeight / 2 ) ,
windowWidth ,
windowHeight ,
2020-03-05 15:52:59 -08:00
NULL ,
NULL ,
hInst ,
NULL ) ;
if ( _hWndEditKeyboardWindow = = NULL )
{
MessageBox ( NULL , L " Call to CreateWindow failed! " , L " Error " , NULL ) ;
return ;
}
2020-05-08 17:34:24 -07:00
// Ensures the window is in foreground on first startup. If this is not done, the window appears behind because the thread is not on the foreground.
if ( _hWndEditKeyboardWindow )
{
SetForegroundWindow ( _hWndEditKeyboardWindow ) ;
}
2020-03-05 15:52:59 -08:00
2020-04-14 09:24:11 -07:00
// Store the newly created Edit Keyboard window's handle.
std : : unique_lock < std : : mutex > hwndLock ( editKeyboardWindowMutex ) ;
hwndEditKeyboardNativeWindow = _hWndEditKeyboardWindow ;
hwndLock . unlock ( ) ;
2020-04-29 17:58:31 -07:00
// 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 ;
// Create the desktop window xaml source object and set its content
hWndXamlIslandEditKeyboardWindow = xamlBridge . InitDesktopWindowsXamlSource ( desktopSource ) ;
2020-03-05 15:52:59 -08:00
2020-04-29 17:58:31 -07:00
// Set the pointer to the xaml bridge object
xamlBridgePtr = & xamlBridge ;
2020-03-05 15:52:59 -08:00
2020-03-27 08:38:58 -07:00
// Header for the window
2020-04-23 09:14:16 -07:00
Windows : : UI : : Xaml : : Controls : : RelativePanel header ;
2020-03-27 08:38:58 -07:00
header . Margin ( { 10 , 10 , 10 , 30 } ) ;
// Header text
TextBlock headerText ;
2020-05-29 21:01:29 +02:00
headerText . Text ( L " Remap keys " ) ;
2020-03-27 08:38:58 -07:00
headerText . FontSize ( 30 ) ;
2020-04-23 09:14:16 -07:00
headerText . Margin ( { 0 , 0 , 0 , 0 } ) ;
header . SetAlignLeftWithPanel ( headerText , true ) ;
2020-03-27 08:38:58 -07:00
// Header Cancel button
Button cancelButton ;
2020-04-21 14:14:50 -07:00
cancelButton . Content ( winrt : : box_value ( L " Cancel " ) ) ;
2020-05-11 12:45:55 -07:00
cancelButton . Margin ( { 10 , 0 , 0 , 0 } ) ;
2020-04-20 08:22:36 -07:00
cancelButton . Click ( [ & ] ( winrt : : Windows : : Foundation : : IInspectable const & sender , RoutedEventArgs const & ) {
2020-03-27 08:38:58 -07:00
// Close the window since settings do not need to be saved
PostMessage ( _hWndEditKeyboardWindow , WM_CLOSE , 0 , 0 ) ;
} ) ;
// Text block for information about remap key section.
TextBlock keyRemapInfoHeader ;
2020-07-23 16:43:49 -07:00
keyRemapInfoHeader . Text ( L " Select the key you want to change (Key) and then the key or shortcut you want it to become (Mapped To). " ) ;
2020-04-18 16:12:26 -07:00
keyRemapInfoHeader . Margin ( { 10 , 0 , 0 , 10 } ) ;
2020-05-06 08:34:26 -07:00
keyRemapInfoHeader . FontWeight ( Text : : FontWeights : : SemiBold ( ) ) ;
2020-05-08 17:34:24 -07:00
keyRemapInfoHeader . TextWrapping ( TextWrapping : : Wrap ) ;
2020-05-06 08:34:26 -07:00
TextBlock keyRemapInfoExample ;
2020-07-23 16:43:49 -07:00
keyRemapInfoExample . Text ( L " For example, if you want to press A and get \" Ctrl+C \" , key \" A \" would be your \" Key \" column and the shortcut \" Ctrl+C \" would be your \" Mapped To \" column. " ) ;
2020-05-06 08:34:26 -07:00
keyRemapInfoExample . Margin ( { 10 , 0 , 0 , 20 } ) ;
keyRemapInfoExample . FontStyle ( Text : : FontStyle : : Italic ) ;
2020-05-08 17:34:24 -07:00
keyRemapInfoExample . TextWrapping ( TextWrapping : : Wrap ) ;
2020-03-27 08:38:58 -07:00
// Table to display the key remaps
2020-04-23 09:14:16 -07:00
Grid keyRemapTable ;
2020-05-08 17:34:24 -07:00
ColumnDefinition originalColumn ;
originalColumn . MinWidth ( KeyboardManagerConstants : : RemapTableDropDownWidth ) ;
originalColumn . MaxWidth ( KeyboardManagerConstants : : RemapTableDropDownWidth ) ;
ColumnDefinition arrowColumn ;
arrowColumn . MinWidth ( KeyboardManagerConstants : : TableArrowColWidth ) ;
ColumnDefinition newColumn ;
2020-07-23 16:43:49 -07:00
newColumn . MinWidth ( 3 * KeyboardManagerConstants : : ShortcutTableDropDownWidth + 2 * KeyboardManagerConstants : : ShortcutTableDropDownSpacing ) ;
newColumn . MaxWidth ( 3 * KeyboardManagerConstants : : ShortcutTableDropDownWidth + 2 * KeyboardManagerConstants : : ShortcutTableDropDownSpacing ) ;
2020-05-08 17:34:24 -07:00
ColumnDefinition removeColumn ;
removeColumn . MinWidth ( KeyboardManagerConstants : : TableRemoveColWidth ) ;
2020-03-27 08:38:58 -07:00
keyRemapTable . Margin ( { 10 , 10 , 10 , 20 } ) ;
2020-04-23 09:14:16 -07:00
keyRemapTable . HorizontalAlignment ( HorizontalAlignment : : Stretch ) ;
2020-05-08 17:34:24 -07:00
keyRemapTable . ColumnDefinitions ( ) . Append ( originalColumn ) ;
keyRemapTable . ColumnDefinitions ( ) . Append ( arrowColumn ) ;
keyRemapTable . ColumnDefinitions ( ) . Append ( newColumn ) ;
keyRemapTable . ColumnDefinitions ( ) . Append ( removeColumn ) ;
2020-04-23 09:14:16 -07:00
keyRemapTable . RowDefinitions ( ) . Append ( RowDefinition ( ) ) ;
2020-03-27 08:38:58 -07:00
// First header textblock in the header row of the keys remap table
TextBlock originalKeyRemapHeader ;
2020-05-20 17:52:10 -04:00
originalKeyRemapHeader . Text ( L " Key: " ) ;
2020-03-27 08:38:58 -07:00
originalKeyRemapHeader . FontWeight ( Text : : FontWeights : : Bold ( ) ) ;
originalKeyRemapHeader . Margin ( { 0 , 0 , 0 , 10 } ) ;
// Second header textblock in the header row of the keys remap table
TextBlock newKeyRemapHeader ;
2020-05-20 17:52:10 -04:00
newKeyRemapHeader . Text ( L " Mapped To: " ) ;
2020-03-27 08:38:58 -07:00
newKeyRemapHeader . FontWeight ( Text : : FontWeights : : Bold ( ) ) ;
newKeyRemapHeader . Margin ( { 0 , 0 , 0 , 10 } ) ;
2020-05-08 17:34:24 -07:00
keyRemapTable . SetColumn ( originalKeyRemapHeader , KeyboardManagerConstants : : RemapTableOriginalColIndex ) ;
2020-04-23 09:14:16 -07:00
keyRemapTable . SetRow ( originalKeyRemapHeader , 0 ) ;
2020-05-08 17:34:24 -07:00
keyRemapTable . SetColumn ( newKeyRemapHeader , KeyboardManagerConstants : : RemapTableNewColIndex ) ;
2020-04-23 09:14:16 -07:00
keyRemapTable . SetRow ( newKeyRemapHeader , 0 ) ;
keyRemapTable . Children ( ) . Append ( originalKeyRemapHeader ) ;
keyRemapTable . Children ( ) . Append ( newKeyRemapHeader ) ;
2020-03-27 08:38:58 -07:00
2020-04-09 09:20:19 -07:00
// Store handle of edit keyboard window
SingleKeyRemapControl : : EditKeyboardWindowHandle = _hWndEditKeyboardWindow ;
// Store keyboard manager state
SingleKeyRemapControl : : keyboardManagerState = & keyboardManagerState ;
2020-04-18 16:12:26 -07:00
KeyDropDownControl : : keyboardManagerState = & keyboardManagerState ;
2020-04-09 09:20:19 -07:00
// Clear the single key remap buffer
SingleKeyRemapControl : : singleKeyRemapBuffer . clear ( ) ;
2020-04-18 16:12:26 -07:00
// Vector to store dynamically allocated control objects to avoid early destruction
std : : vector < std : : vector < std : : unique_ptr < SingleKeyRemapControl > > > keyboardRemapControlObjects ;
2020-04-09 09:20:19 -07:00
2020-05-04 15:49:37 -07:00
// Set keyboard manager UI state so that remaps are not applied while on this window
keyboardManagerState . SetUIState ( KeyboardManagerUIState : : EditKeyboardWindowActivated , _hWndEditKeyboardWindow ) ;
2020-04-09 09:20:19 -07:00
// Load existing remaps into UI
std : : unique_lock < std : : mutex > lock ( keyboardManagerState . singleKeyReMap_mutex ) ;
2020-07-23 16:43:49 -07:00
std : : unordered_map < DWORD , std : : variant < DWORD , Shortcut > > singleKeyRemapCopy = keyboardManagerState . singleKeyReMap ;
2020-04-21 13:40:31 -07:00
lock . unlock ( ) ;
2020-08-13 16:32:15 -07:00
LoadingAndSavingRemappingHelper : : PreProcessRemapTable ( singleKeyRemapCopy ) ;
2020-04-21 13:40:31 -07:00
for ( const auto & it : singleKeyRemapCopy )
2020-04-09 09:20:19 -07:00
{
2020-04-18 16:12:26 -07:00
SingleKeyRemapControl : : AddNewControlKeyRemapRow ( keyRemapTable , keyboardRemapControlObjects , it . first , it . second ) ;
2020-04-09 09:20:19 -07:00
}
2020-03-27 08:38:58 -07:00
// Main Header Apply button
Button applyButton ;
2020-05-11 12:45:55 -07:00
applyButton . Content ( winrt : : box_value ( L " OK " ) ) ;
applyButton . Style ( AccentButtonStyle ( ) ) ;
applyButton . MinWidth ( KeyboardManagerConstants : : HeaderButtonWidth ) ;
cancelButton . MinWidth ( KeyboardManagerConstants : : HeaderButtonWidth ) ;
header . SetAlignRightWithPanel ( cancelButton , true ) ;
header . SetLeftOf ( applyButton , cancelButton ) ;
auto ApplyRemappings = [ & keyboardManagerState , _hWndEditKeyboardWindow ] ( ) {
2020-08-13 16:32:15 -07:00
LoadingAndSavingRemappingHelper : : ApplySingleKeyRemappings ( keyboardManagerState , SingleKeyRemapControl : : singleKeyRemapBuffer , true ) ;
2020-04-20 08:22:36 -07:00
// Save the updated shortcuts remaps to file.
2020-04-26 15:09:40 -07:00
bool saveResult = keyboardManagerState . SaveConfigToFile ( ) ;
2020-05-11 12:45:55 -07:00
PostMessage ( _hWndEditKeyboardWindow , WM_CLOSE , 0 , 0 ) ;
} ;
applyButton . Click ( [ & keyboardManagerState , ApplyRemappings , applyButton ] ( winrt : : Windows : : Foundation : : IInspectable const & sender , RoutedEventArgs const & ) {
OnClickAccept ( keyboardManagerState , applyButton . XamlRoot ( ) , ApplyRemappings ) ;
2020-03-27 08:38:58 -07:00
} ) ;
header . Children ( ) . Append ( headerText ) ;
header . Children ( ) . Append ( applyButton ) ;
2020-05-13 10:13:44 -07:00
header . Children ( ) . Append ( cancelButton ) ;
2020-03-27 08:38:58 -07:00
2020-05-14 09:24:50 -07:00
ScrollViewer scrollViewer ;
2020-03-27 08:38:58 -07:00
// Add remap key button
Windows : : UI : : Xaml : : Controls : : Button addRemapKey ;
FontIcon plusSymbol ;
2020-07-13 11:49:09 -07:00
plusSymbol . FontFamily ( Media : : FontFamily ( L " Segoe MDL2 Assets " ) ) ;
2020-03-27 08:38:58 -07:00
plusSymbol . Glyph ( L " \xE109 " ) ;
addRemapKey . Content ( plusSymbol ) ;
2020-04-26 21:57:51 -07:00
addRemapKey . Margin ( { 10 , 0 , 0 , 25 } ) ;
2020-04-20 08:22:36 -07:00
addRemapKey . Click ( [ & ] ( winrt : : Windows : : Foundation : : IInspectable const & sender , RoutedEventArgs const & ) {
2020-04-18 16:12:26 -07:00
SingleKeyRemapControl : : AddNewControlKeyRemapRow ( keyRemapTable , keyboardRemapControlObjects ) ;
2020-05-14 09:24:50 -07:00
// Whenever a remap is added move to the bottom of the screen
scrollViewer . ChangeView ( nullptr , scrollViewer . ScrollableHeight ( ) , nullptr ) ;
2020-03-27 08:38:58 -07:00
} ) ;
2020-04-26 21:57:51 -07:00
StackPanel mappingsPanel ;
mappingsPanel . Children ( ) . Append ( keyRemapInfoHeader ) ;
2020-05-06 08:34:26 -07:00
mappingsPanel . Children ( ) . Append ( keyRemapInfoExample ) ;
2020-04-26 21:57:51 -07:00
mappingsPanel . Children ( ) . Append ( keyRemapTable ) ;
mappingsPanel . Children ( ) . Append ( addRemapKey ) ;
scrollViewer . Content ( mappingsPanel ) ;
// Creating the Xaml content. xamlContainer is the parent UI element
RelativePanel xamlContainer ;
xamlContainer . SetBelow ( scrollViewer , header ) ;
xamlContainer . SetAlignLeftWithPanel ( header , true ) ;
xamlContainer . SetAlignRightWithPanel ( header , true ) ;
xamlContainer . SetAlignLeftWithPanel ( scrollViewer , true ) ;
xamlContainer . SetAlignRightWithPanel ( scrollViewer , true ) ;
2020-03-27 08:38:58 -07:00
xamlContainer . Children ( ) . Append ( header ) ;
2020-04-26 21:57:51 -07:00
xamlContainer . Children ( ) . Append ( scrollViewer ) ;
2020-03-05 15:52:59 -08:00
xamlContainer . UpdateLayout ( ) ;
2020-03-27 08:38:58 -07:00
2020-04-29 17:58:31 -07:00
desktopSource . Content ( xamlContainer ) ;
2020-03-05 15:52:59 -08:00
////End XAML Island section
if ( _hWndEditKeyboardWindow )
{
ShowWindow ( _hWndEditKeyboardWindow , SW_SHOW ) ;
UpdateWindow ( _hWndEditKeyboardWindow ) ;
}
// Message loop:
2020-04-29 17:58:31 -07:00
xamlBridge . MessageLoop ( ) ;
2020-04-14 09:24:11 -07:00
2020-04-29 17:58:31 -07:00
// Reset pointers to nullptr
xamlBridgePtr = nullptr ;
2020-04-14 09:24:11 -07:00
hWndXamlIslandEditKeyboardWindow = nullptr ;
hwndLock . lock ( ) ;
hwndEditKeyboardNativeWindow = nullptr ;
2020-05-04 15:49:37 -07:00
keyboardManagerState . ResetUIState ( ) ;
2020-04-29 17:58:31 -07:00
// Cannot be done in WM_DESTROY because that causes crashes due to fatal app exit
xamlBridge . ClearXamlIslands ( ) ;
2020-03-05 15:52:59 -08:00
}
LRESULT CALLBACK EditKeyboardWindowProc ( HWND hWnd , UINT messageCode , WPARAM wParam , LPARAM lParam )
{
RECT rcClient ;
switch ( messageCode )
{
2020-04-23 09:14:16 -07:00
// Resize the XAML window whenever the parent window is painted or resized
2020-03-05 15:52:59 -08:00
case WM_PAINT :
2020-04-23 09:14:16 -07:00
case WM_SIZE :
2020-03-05 15:52:59 -08:00
GetClientRect ( hWnd , & rcClient ) ;
SetWindowPos ( hWndXamlIslandEditKeyboardWindow , 0 , rcClient . left , rcClient . top , rcClient . right , rcClient . bottom , SWP_SHOWWINDOW ) ;
break ;
default :
2020-04-29 17:58:31 -07:00
// If the Xaml Bridge object exists, then use it's message handler to handle keyboard focus operations
if ( xamlBridgePtr ! = nullptr )
{
return xamlBridgePtr - > MessageHandler ( messageCode , wParam , lParam ) ;
}
2020-05-01 17:34:42 -07:00
else if ( messageCode = = WM_NCDESTROY )
2020-04-29 17:58:31 -07:00
{
PostQuitMessage ( 0 ) ;
break ;
}
2020-03-05 15:52:59 -08:00
return DefWindowProc ( hWnd , messageCode , wParam , lParam ) ;
break ;
}
return 0 ;
}
2020-04-14 09:24:11 -07:00
2020-04-29 17:58:31 -07:00
// Function to check if there is already a window active if yes bring to foreground
2020-04-14 09:24:11 -07:00
bool CheckEditKeyboardWindowActive ( )
{
bool result = false ;
std : : unique_lock < std : : mutex > hwndLock ( editKeyboardWindowMutex ) ;
if ( hwndEditKeyboardNativeWindow ! = nullptr )
{
// Check if the window is minimized if yes then restore the window.
if ( IsIconic ( hwndEditKeyboardNativeWindow ) )
{
ShowWindow ( hwndEditKeyboardNativeWindow , SW_RESTORE ) ;
}
// If there is an already existing window no need to create a new open bring it on foreground.
SetForegroundWindow ( hwndEditKeyboardNativeWindow ) ;
result = true ;
}
return result ;
}
2020-05-12 15:58:11 -07:00
// Function to close any active Edit Keyboard window
void CloseActiveEditKeyboardWindow ( )
{
std : : unique_lock < std : : mutex > hwndLock ( editKeyboardWindowMutex ) ;
if ( hwndEditKeyboardNativeWindow ! = nullptr )
{
PostMessage ( hwndEditKeyboardNativeWindow , WM_CLOSE , 0 , 0 ) ;
}
}