Auto merge of #27114 - paulrouget:key_events, r=jdm

[UWP] Key events

This is the initial work required for proper keyboard events.
The text controller implementation is very basic, just enough to show the virtual keyboard when it's needed, and have basic key events.
This commit is contained in:
bors-servo 2020-06-30 09:41:15 -04:00 committed by GitHub
commit db00c1f96e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 257 additions and 28 deletions

View file

@ -120,6 +120,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="Devtools\Client.h" />
<ClInclude Include="ServoControl\Keys.h" />
<ClInclude Include="strutils.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="App.h">

View file

@ -43,6 +43,9 @@
<ClInclude Include="Devtools\Client.h">
<Filter>Devtools</Filter>
</ClInclude>
<ClInclude Include="ServoControl\Keys.h">
<Filter>ServoControl</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="Assets\Wide310x150Logo.scale-200.png">

View file

@ -0,0 +1,130 @@
using namespace winrt::Windows::System;
namespace winrt {
std::optional<const char *> KeyToString(Windows::System::VirtualKey key) {
switch (key) {
case VirtualKey::F1:
return "F1";
case VirtualKey::F2:
return "F2";
case VirtualKey::F3:
return "F3";
case VirtualKey::F4:
return "F4";
case VirtualKey::F5:
return "F5";
case VirtualKey::F6:
return "F6";
case VirtualKey::F7:
return "F7";
case VirtualKey::F8:
return "F8";
case VirtualKey::F9:
return "F9";
case VirtualKey::F10:
return "F10";
case VirtualKey::F11:
return "F11";
case VirtualKey::F12:
return "F12";
case VirtualKey::Shift:
return "Shift";
case VirtualKey::LeftShift:
return "Shift";
case VirtualKey::RightShift:
return "Shift";
case VirtualKey::Control:
return "Control";
case VirtualKey::LeftControl:
return "Control";
case VirtualKey::RightControl:
return "Control";
case VirtualKey::Escape:
return "Escape";
case VirtualKey::Enter:
return "Enter";
case VirtualKey::Tab:
return "Tab";
case VirtualKey::Delete:
return "Delete";
case VirtualKey::Back:
return "Backspace";
case VirtualKey::GoForward:
return "BrowserForward";
case VirtualKey::GoBack:
return "BrowserBack";
case VirtualKey::GoHome:
return "BrowserHome";
case VirtualKey::Favorites:
return "BrowserFavorites";
case VirtualKey::Search:
return "BrowserSearch";
case VirtualKey::Stop:
return "BrowserStop";
case VirtualKey::Menu:
return "Alt";
case VirtualKey::RightMenu:
return "Alt";
case VirtualKey::LeftMenu:
return "Alt";
case VirtualKey::CapitalLock:
return "CapsLock";
case VirtualKey::LeftWindows:
return "Meta";
case VirtualKey::RightWindows:
return "Meta";
case VirtualKey::NumberKeyLock:
return "NumLock";
case VirtualKey::Scroll:
return "ScrollLock";
case VirtualKey::Down:
return "ArrowDown";
case VirtualKey::Up:
return "ArrowUp";
case VirtualKey::Left:
return "ArrowLeft";
case VirtualKey::Right:
return "ArrowRight";
case VirtualKey::End:
return "End";
case VirtualKey::Home:
return "Home";
case VirtualKey::PageDown:
return "PageHome";
case VirtualKey::PageUp:
return "PageUp";
case VirtualKey::Clear:
return "Clear";
case VirtualKey::Insert:
return "Insert";
case VirtualKey::Accept:
return "Accept";
case VirtualKey::Cancel:
return "Cancel";
case VirtualKey::Execute:
return "Execute";
case VirtualKey::Help:
return "Help";
case VirtualKey::Pause:
return "Pause";
case VirtualKey::Select:
return "Select";
case VirtualKey::Print:
return "Print";
case VirtualKey::Convert:
return "Convert";
case VirtualKey::NonConvert:
return "NonConvert";
case VirtualKey::ModeChange:
return "ModeChange";
case VirtualKey::Hangul:
return "HangulMode";
case VirtualKey::Hanja:
return "HanjaMode";
case VirtualKey::Junja:
return "JunjaMode";
default:
return {};
}
}
} // namespace winrt

View file

@ -62,6 +62,8 @@ public:
void TouchMove(float x, float y, int32_t id) { touch_move(x, y, id); }
void TouchCancel(float x, float y, int32_t id) { touch_cancel(x, y, id); }
void MouseMove(float x, float y) { mouse_move(x, y); }
void KeyDown(const char *k) { key_down(k); }
void KeyUp(const char *k) { key_up(k); }
void Reload() { reload(); }
void Stop() { stop(); }

View file

@ -4,6 +4,7 @@
#include "ServoControl.g.cpp"
#include "Pref.g.cpp"
#include <stdlib.h>
#include "Keys.h"
using namespace std::placeholders;
using namespace winrt::Windows::ApplicationModel::Resources;
@ -11,6 +12,7 @@ using namespace winrt::Windows::Graphics::Display;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Popups;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::UI::Text::Core;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::System;
using namespace winrt::Windows::Devices::Input;
@ -66,21 +68,19 @@ void ServoControl::OnLoaded(IInspectable const &, RoutedEventArgs const &) {
std::bind(&ServoControl::OnSurfacePointerMoved, this, _1, _2));
panel.PointerWheelChanged(
std::bind(&ServoControl::OnSurfaceWheelChanged, this, _1, _2));
panel.ManipulationStarted(
[=](IInspectable const &,
Input::ManipulationStartedRoutedEventArgs const &e) {
mOnCaptureGesturesStartedEvent();
e.Handled(true);
});
panel.ManipulationCompleted(
[=](IInspectable const &,
Input::ManipulationCompletedRoutedEventArgs const &e) {
mOnCaptureGesturesEndedEvent();
e.Handled(true);
});
panel.ManipulationStarted([=](const auto &, const auto &e) {
mOnCaptureGesturesStartedEvent();
e.Handled(true);
});
panel.ManipulationCompleted([=](const auto &, const auto &e) {
mOnCaptureGesturesEndedEvent();
e.Handled(true);
});
panel.ManipulationDelta(
std::bind(&ServoControl::OnSurfaceManipulationDelta, this, _1, _2));
Panel().SizeChanged(std::bind(&ServoControl::OnSurfaceResized, this, _1, _2));
panel.SizeChanged(std::bind(&ServoControl::OnSurfaceResized, this, _1, _2));
InitializeTextController();
InitializeConditionVariable(&mGLCondVar);
InitializeCriticalSection(&mGLLock);
InitializeConditionVariable(&mDialogCondVar);
@ -89,6 +89,54 @@ void ServoControl::OnLoaded(IInspectable const &, RoutedEventArgs const &) {
StartRenderLoop();
}
void ServoControl::InitializeTextController() {
mInputPane = Windows::UI::ViewManagement::InputPane::GetForCurrentView();
auto manager = CoreTextServicesManager::GetForCurrentView();
mEditContext = manager.CreateEditContext();
mEditContext->InputPaneDisplayPolicy(CoreTextInputPaneDisplayPolicy::Manual);
mEditContext->InputScope(CoreTextInputScope::Text);
mEditContext->TextRequested([=](const auto &, const auto &e) {
e.Request().Text(L"");
CoreTextRange sel;
sel.StartCaretPosition = 0;
sel.EndCaretPosition = 0;
e.Request().Range() = sel;
});
mEditContext->TextUpdating([=](const auto &, const auto &e) {
RunOnGLThread([=] {
auto keystr = *hstring2char((e.Text()));
mServo->KeyDown(keystr);
});
});
mEditContext->SelectionRequested([](const auto &, const auto &) {});
GotFocus(
[=](const auto &, const auto &) { mEditContext->NotifyFocusEnter(); });
LostFocus(
[=](const auto &, const auto &) { mEditContext->NotifyFocusLeave(); });
PreviewKeyDown([=](const auto &, const auto &e) {
auto keystr = KeyToString(e.Key());
if (keystr.has_value()) {
RunOnGLThread([=] {
auto keyname = *keystr;
mServo->KeyDown(keyname);
});
}
});
PreviewKeyUp([=](const auto &, const auto &e) {
auto keystr = KeyToString(e.Key());
if (keystr.has_value()) {
RunOnGLThread([=] {
auto keyname = *keystr;
mServo->KeyUp(keyname);
});
}
});
}
Controls::SwapChainPanel ServoControl::Panel() {
return GetTemplateChild(L"swapChainPanel").as<Controls::SwapChainPanel>();
}
@ -128,6 +176,7 @@ void ServoControl::OnSurfaceManipulationDelta(
void ServoControl::OnSurfaceTapped(IInspectable const &,
Input::TappedRoutedEventArgs const &e) {
Focus(FocusState::Programmatic);
if (e.PointerDeviceType() == PointerDeviceType::Mouse) {
auto coords = e.GetPosition(Panel());
auto x = coords.X * mDPI;
@ -440,9 +489,14 @@ void ServoControl::OnServoAnimatingChanged(bool animating) {
WakeConditionVariable(&mGLCondVar);
}
void ServoControl::OnServoIMEStateChanged(bool) {
// FIXME:
// https://docs.microsoft.com/en-us/windows/win32/winauto/uiauto-implementingtextandtextrange
void ServoControl::OnServoIMEStateChanged(bool focused) {
RunOnUIThread([=] {
if (focused) {
mInputPane->TryShow();
} else {
mInputPane->TryHide();
}
});
}
void ServoControl::OnServoMediaSessionMetadata(hstring title, hstring artist,

View file

@ -264,6 +264,7 @@ private:
void RunOnGLThread(std::function<void()>);
void TryLoadUri(hstring);
void InitializeTextController();
std::unique_ptr<servo::Servo> mServo;
PropertySet mNativeWindowProperties;
@ -277,6 +278,9 @@ private:
hstring mArgs;
std::optional<servo::Servo::MouseButton> mPressedMouseButton = {};
std::unique_ptr<L10NStrings> mL10NStrings = nullptr;
std::optional<Windows::UI::Text::Core::CoreTextEditContext> mEditContext;
std::optional<Windows::UI::ViewManagement::InputPane> mInputPane;
};
} // namespace winrt::ServoApp::implementation

View file

@ -60,6 +60,7 @@
#include <winrt/Windows.UI.Xaml.Shapes.h>
#include <winrt/Windows.UI.Notifications.h>
#include <winrt/Windows.UI.Text.h>
#include <winrt/Windows.UI.Text.Core.h>
#include <winrt/Windows.Data.Xml.Dom.h>
#include <winrt/Windows.Storage.Streams.h>
#include <winrt/Windows.Data.Json.h>