Fix Keyboard Navigation and Xaml Island focus issues for KBM (dev/build-features) (#2429)

* Added XamlBridge code and implemented keyboard focus navigation for xaml islands

* Change global pointer to static
This commit is contained in:
Arjun Balgovind
2020-04-29 17:58:31 -07:00
committed by GitHub
parent 518da7e81d
commit 5e3da57e21
8 changed files with 433 additions and 47 deletions

View File

@@ -2,6 +2,7 @@
#include "EditShortcutsWindow.h"
#include "ShortcutControl.h"
#include "KeyDropDownControl.h"
#include "XamlBridge.h"
LRESULT CALLBACK EditShortcutsWindowProc(HWND, UINT, WPARAM, LPARAM);
@@ -12,6 +13,8 @@ bool isEditShortcutsWindowRegistrationCompleted = false;
// Holds the native window handle of EditShortcuts Window.
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;
// Function to create the Edit Shortcuts Window
void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardManagerState)
@@ -61,18 +64,15 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
hwndEditShortcutsNativeWindow = _hWndEditShortcutsWindow;
hwndLock.unlock();
// This DesktopWindowXamlSource is the object that enables a non-UWP desktop application
// to host UWP controls in any UI element that is associated with a window handle (HWND).
DesktopWindowXamlSource desktopSource;
// Get handle to corewindow
auto interop = desktopSource.as<IDesktopWindowXamlSourceNative>();
// Parent the DesktopWindowXamlSource object to current window
check_hresult(interop->AttachToWindow(_hWndEditShortcutsWindow));
// 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;
// Create the desktop window xaml source object and set its content
hWndXamlIslandEditShortcutsWindow = xamlBridge.InitDesktopWindowsXamlSource(desktopSource);
// Get the new child window's hwnd
interop->get_WindowHandle(&hWndXamlIslandEditShortcutsWindow);
// Update the xaml island window size becuase initially is 0,0
SetWindowPos(hWndXamlIslandEditShortcutsWindow, 0, 0, 0, 400, 400, SWP_SHOWWINDOW);
// Set the pointer to the xaml bridge object
xamlBridgePtr = &xamlBridge;
// Header for the window
Windows::UI::Xaml::Controls::RelativePanel header;
@@ -233,8 +233,8 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
xamlContainer.SetAlignRightWithPanel(scrollViewer, true);
xamlContainer.Children().Append(header);
xamlContainer.Children().Append(scrollViewer);
xamlContainer.UpdateLayout();
desktopSource.Content(xamlContainer);
////End XAML Island section
@@ -245,17 +245,16 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
}
// Message loop:
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
desktopSource.Close();
xamlBridge.MessageLoop();
// Reset pointers to nullptr
xamlBridgePtr = nullptr;
hWndXamlIslandEditShortcutsWindow = nullptr;
hwndLock.lock();
hwndEditShortcutsNativeWindow = nullptr;
// Cannot be done in WM_DESTROY because that causes crashes due to fatal app exit
xamlBridge.ClearXamlIslands();
}
LRESULT CALLBACK EditShortcutsWindowProc(HWND hWnd, UINT messageCode, WPARAM wParam, LPARAM lParam)
@@ -269,10 +268,17 @@ LRESULT CALLBACK EditShortcutsWindowProc(HWND hWnd, UINT messageCode, WPARAM wPa
GetClientRect(hWnd, &rcClient);
SetWindowPos(hWndXamlIslandEditShortcutsWindow, 0, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom, SWP_SHOWWINDOW);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
// 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);
}
else if (messageCode == WM_DESTROY)
{
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, messageCode, wParam, lParam);
break;
}
@@ -280,6 +286,7 @@ LRESULT CALLBACK EditShortcutsWindowProc(HWND hWnd, UINT messageCode, WPARAM wPa
return 0;
}
// Function to check if there is already a window active if yes bring to foreground
bool CheckEditShortcutsWindowActive()
{
bool result = false;