From 2dcb78de13cbd23c12f992eddda6004f0ea443e9 Mon Sep 17 00:00:00 2001 From: Paul Rouget Date: Mon, 29 Jun 2020 10:27:34 +0200 Subject: [PATCH] UWP: Basic key events --- ports/libsimpleservo/capi/src/lib.rs | 31 +++-- support/hololens/ServoApp/ServoApp.vcxproj | 1 + .../ServoApp/ServoApp.vcxproj.filters | 3 + support/hololens/ServoApp/ServoControl/Keys.h | 130 ++++++++++++++++++ .../hololens/ServoApp/ServoControl/Servo.h | 2 + .../ServoApp/ServoControl/ServoControl.cpp | 86 +++++++++--- .../ServoApp/ServoControl/ServoControl.h | 4 + support/hololens/ServoApp/pch.h | 1 + 8 files changed, 228 insertions(+), 30 deletions(-) create mode 100644 support/hololens/ServoApp/ServoControl/Keys.h diff --git a/ports/libsimpleservo/capi/src/lib.rs b/ports/libsimpleservo/capi/src/lib.rs index ca0f0419f348..a82ab950c326 100644 --- a/ports/libsimpleservo/capi/src/lib.rs +++ b/ports/libsimpleservo/capi/src/lib.rs @@ -720,30 +720,33 @@ pub extern "C" fn click(x: f32, y: f32) { #[no_mangle] pub extern "C" fn key_down(name: *const c_char) { - catch_any_panic(|| { - debug!("key_down"); - let name = unsafe { CStr::from_ptr(name) }; - let key = Key::from_str(&name.to_str().expect("Can't read string")); - if let Ok(key) = key { - call(|s| s.key_down(key)); - } else { - warn!("Received unknown keys"); - } - }) + debug!("key_up"); + key_event(name, false); } #[no_mangle] pub extern "C" fn key_up(name: *const c_char) { + debug!("key_up"); + key_event(name, true); +} + +fn key_event(name: *const c_char, up: bool) { catch_any_panic(|| { - debug!("key_up"); let name = unsafe { CStr::from_ptr(name) }; - let key = Key::from_str(&name.to_str().expect("Can't read string")); + let name = match name.to_str() { + Ok(name) => name, + Err(..) => { + warn!("Couldn't not read str"); + return; + }, + }; + let key = Key::from_str(&name); if let Ok(key) = key { - call(|s| s.key_up(key)); + call(|s| if up { s.key_up(key) } else { s.key_down(key) }); } else { warn!("Received unknown keys"); } - }) + }); } #[no_mangle] diff --git a/support/hololens/ServoApp/ServoApp.vcxproj b/support/hololens/ServoApp/ServoApp.vcxproj index 0d819c3fffc4..8b189190a244 100644 --- a/support/hololens/ServoApp/ServoApp.vcxproj +++ b/support/hololens/ServoApp/ServoApp.vcxproj @@ -120,6 +120,7 @@ + diff --git a/support/hololens/ServoApp/ServoApp.vcxproj.filters b/support/hololens/ServoApp/ServoApp.vcxproj.filters index 4bb5ad598a78..256c28acce5c 100644 --- a/support/hololens/ServoApp/ServoApp.vcxproj.filters +++ b/support/hololens/ServoApp/ServoApp.vcxproj.filters @@ -43,6 +43,9 @@ Devtools + + ServoControl + diff --git a/support/hololens/ServoApp/ServoControl/Keys.h b/support/hololens/ServoApp/ServoControl/Keys.h new file mode 100644 index 000000000000..8f862995f424 --- /dev/null +++ b/support/hololens/ServoApp/ServoControl/Keys.h @@ -0,0 +1,130 @@ +using namespace winrt::Windows::System; + +namespace winrt { +std::optional 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 diff --git a/support/hololens/ServoApp/ServoControl/Servo.h b/support/hololens/ServoApp/ServoControl/Servo.h index d662942f1da7..d91d4daeffb4 100644 --- a/support/hololens/ServoApp/ServoControl/Servo.h +++ b/support/hololens/ServoApp/ServoControl/Servo.h @@ -63,6 +63,8 @@ class Servo { 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(); } diff --git a/support/hololens/ServoApp/ServoControl/ServoControl.cpp b/support/hololens/ServoApp/ServoControl/ServoControl.cpp index 1b9fb910d6e6..e430d713e7ec 100644 --- a/support/hololens/ServoApp/ServoControl/ServoControl.cpp +++ b/support/hololens/ServoApp/ServoControl/ServoControl.cpp @@ -4,6 +4,7 @@ #include "ServoControl.g.cpp" #include "Pref.g.cpp" #include +#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(); } @@ -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; @@ -439,9 +488,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, diff --git a/support/hololens/ServoApp/ServoControl/ServoControl.h b/support/hololens/ServoApp/ServoControl/ServoControl.h index 56d32e2a12cc..8437c7930ff4 100644 --- a/support/hololens/ServoApp/ServoControl/ServoControl.h +++ b/support/hololens/ServoApp/ServoControl/ServoControl.h @@ -265,6 +265,7 @@ struct ServoControl : ServoControlT, public servo::ServoDelegate { void RunOnGLThread(std::function); void TryLoadUri(hstring); + void InitializeTextController(); std::unique_ptr mServo; PropertySet mNativeWindowProperties; @@ -278,6 +279,9 @@ struct ServoControl : ServoControlT, public servo::ServoDelegate { hstring mArgs; std::optional mPressedMouseButton = {}; std::unique_ptr mL10NStrings = nullptr; + + std::optional mEditContext; + std::optional mInputPane; }; } // namespace winrt::ServoApp::implementation diff --git a/support/hololens/ServoApp/pch.h b/support/hololens/ServoApp/pch.h index 49cffb0f3abb..66759332c621 100644 --- a/support/hololens/ServoApp/pch.h +++ b/support/hololens/ServoApp/pch.h @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include