diff --git a/Cargo.lock b/Cargo.lock index fef028c035c..7f2cf27f6d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2736,9 +2736,9 @@ dependencies = [ [[package]] name = "keyboard-types" -version = "0.4.4" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b536dc22c0dabb295e85dbd0c062023885b12b8db24e1d86833f4e50ea7959" +checksum = "a989afac88279b0482f402d234b5fbd405bf1ad051308595b58de4e6de22346b" dependencies = [ "bitflags", "serde", @@ -5224,6 +5224,7 @@ dependencies = [ "backtrace", "cbindgen", "env_logger", + "keyboard-types", "lazy_static", "libc", "log", diff --git a/components/compositing/Cargo.toml b/components/compositing/Cargo.toml index 027d16233bf..0d4fc881921 100644 --- a/components/compositing/Cargo.toml +++ b/components/compositing/Cargo.toml @@ -24,7 +24,7 @@ gfx_traits = { path = "../gfx_traits" } gleam = { version = "0.11", optional = true } image = "0.23" ipc-channel = "0.14" -keyboard-types = "0.4.3" +keyboard-types = "0.5" libc = "0.2" log = "0.4" msg = { path = "../msg" } diff --git a/components/constellation/Cargo.toml b/components/constellation/Cargo.toml index d373aac8063..29fbccd66d3 100644 --- a/components/constellation/Cargo.toml +++ b/components/constellation/Cargo.toml @@ -25,7 +25,7 @@ gfx = { path = "../gfx" } gfx_traits = { path = "../gfx_traits" } http = "0.1" ipc-channel = "0.14" -keyboard-types = "0.4.3" +keyboard-types = "0.5" layout_traits = { path = "../layout_traits" } log = "0.4" media = { path = "../media" } diff --git a/components/embedder_traits/Cargo.toml b/components/embedder_traits/Cargo.toml index 8393476be98..0e85686e729 100644 --- a/components/embedder_traits/Cargo.toml +++ b/components/embedder_traits/Cargo.toml @@ -13,7 +13,7 @@ path = "lib.rs" [dependencies] crossbeam-channel = "0.4" ipc-channel = "0.14" -keyboard-types = "0.4.3" +keyboard-types = "0.5" lazy_static = "1" log = "0.4" msg = { path = "../msg" } diff --git a/components/malloc_size_of/Cargo.toml b/components/malloc_size_of/Cargo.toml index 77915f1fa67..e9b5bedd228 100644 --- a/components/malloc_size_of/Cargo.toml +++ b/components/malloc_size_of/Cargo.toml @@ -36,7 +36,7 @@ euclid = "0.20" hashglobe = { path = "../hashglobe" } hyper = { version = "0.12", optional = true } hyper_serde = { version = "0.11", optional = true } -keyboard-types = { version = "0.4.3", optional = true } +keyboard-types = { version = "0.5", optional = true } selectors = { path = "../selectors" } serde = { version = "1.0.27", optional = true } serde_bytes = { version = "0.11", optional = true } diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 8746273e9f1..225367a7090 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -64,7 +64,7 @@ ipc-channel = "0.14" itertools = "0.8" js = { package = "mozjs", git = "https://github.com/servo/rust-mozjs" } jstraceable_derive = { path = "../jstraceable_derive" } -keyboard-types = "0.4.4" +keyboard-types = "0.5" lazy_static = "1" libc = "0.2" log = "0.4" diff --git a/components/script_traits/Cargo.toml b/components/script_traits/Cargo.toml index 96f51c82707..9f9e1233c8e 100644 --- a/components/script_traits/Cargo.toml +++ b/components/script_traits/Cargo.toml @@ -24,7 +24,7 @@ http = "0.1" hyper = "0.12" hyper_serde = "0.11" ipc-channel = "0.14" -keyboard-types = "0.4.3" +keyboard-types = "0.5" libc = "0.2" log = "0.4" malloc_size_of = { path = "../malloc_size_of" } diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index 87c5e713f60..6f357927aa7 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -57,7 +57,7 @@ gfx_traits = { path = "../gfx_traits" } gleam = "0.11" gstreamer = { version = "0.15", optional = true } ipc-channel = "0.14" -keyboard-types = "0.4" +keyboard-types = "0.5" layout_thread_2013 = { path = "../layout_thread", optional = true } layout_thread_2020 = { path = "../layout_thread_2020", optional = true } log = "0.4" diff --git a/components/webdriver_server/Cargo.toml b/components/webdriver_server/Cargo.toml index 146f825c89d..b568d1cfb09 100644 --- a/components/webdriver_server/Cargo.toml +++ b/components/webdriver_server/Cargo.toml @@ -19,7 +19,7 @@ euclid = "0.20" hyper = "0.12" image = "0.23" ipc-channel = "0.14" -keyboard-types = "0.4.3" +keyboard-types = "0.5" log = "0.4" msg = { path = "../msg" } net_traits = { path = "../net_traits" } diff --git a/ports/libsimpleservo/capi/Cargo.toml b/ports/libsimpleservo/capi/Cargo.toml index 334a77f9198..a1906bb9557 100644 --- a/ports/libsimpleservo/capi/Cargo.toml +++ b/ports/libsimpleservo/capi/Cargo.toml @@ -19,6 +19,7 @@ lazy_static = "1" log = "0.4" simpleservo = { path = "../api" } surfman = "0.3" +keyboard-types = "0.5" [target.'cfg(target_os = "windows")'.dependencies] libc = "0.2" diff --git a/ports/libsimpleservo/capi/src/lib.rs b/ports/libsimpleservo/capi/src/lib.rs index 1730f1c1cf2..a82ab950c32 100644 --- a/ports/libsimpleservo/capi/src/lib.rs +++ b/ports/libsimpleservo/capi/src/lib.rs @@ -16,6 +16,7 @@ mod vslogger; use backtrace::Backtrace; #[cfg(not(target_os = "windows"))] use env_logger; +use keyboard_types::Key; use log::LevelFilter; use simpleservo::{self, gl_glue, ServoGlue, SERVO}; use simpleservo::{ @@ -717,6 +718,37 @@ pub extern "C" fn click(x: f32, y: f32) { }); } +#[no_mangle] +pub extern "C" fn key_down(name: *const c_char) { + 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(|| { + let name = unsafe { CStr::from_ptr(name) }; + 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| if up { s.key_up(key) } else { s.key_down(key) }); + } else { + warn!("Received unknown keys"); + } + }); +} + #[no_mangle] pub extern "C" fn media_session_action(action: CMediaSessionActionType) { catch_any_panic(|| { diff --git a/ports/winit/Cargo.toml b/ports/winit/Cargo.toml index 1091cdc4b17..3f3247f558e 100644 --- a/ports/winit/Cargo.toml +++ b/ports/winit/Cargo.toml @@ -50,7 +50,7 @@ backtrace = "0.3" clipboard = "0.5" euclid = "0.20" getopts = "0.2.11" -keyboard-types = "0.4.3" +keyboard-types = "0.5" lazy_static = "1" libc = "0.2" libservo = { path = "../../components/servo" } diff --git a/support/hololens/ServoApp/ServoApp.vcxproj b/support/hololens/ServoApp/ServoApp.vcxproj index 3943c35dcc2..45e44535548 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 d5a81928a8d..89ed3bff83e 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 00000000000..8f862995f42 --- /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 1cf0641bf8b..accd7ccd12f 100644 --- a/support/hololens/ServoApp/ServoControl/Servo.h +++ b/support/hololens/ServoApp/ServoControl/Servo.h @@ -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(); } diff --git a/support/hololens/ServoApp/ServoControl/ServoControl.cpp b/support/hololens/ServoApp/ServoControl/ServoControl.cpp index b567a622cb3..eadf4d52016 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; @@ -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, diff --git a/support/hololens/ServoApp/ServoControl/ServoControl.h b/support/hololens/ServoApp/ServoControl/ServoControl.h index 041f9f42f54..392c4107d52 100644 --- a/support/hololens/ServoApp/ServoControl/ServoControl.h +++ b/support/hololens/ServoApp/ServoControl/ServoControl.h @@ -264,6 +264,7 @@ private: void RunOnGLThread(std::function); void TryLoadUri(hstring); + void InitializeTextController(); std::unique_ptr mServo; PropertySet mNativeWindowProperties; @@ -277,6 +278,9 @@ private: 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 49cffb0f3ab..66759332c62 100644 --- a/support/hololens/ServoApp/pch.h +++ b/support/hololens/ServoApp/pch.h @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include diff --git a/tests/unit/script/Cargo.toml b/tests/unit/script/Cargo.toml index 3194bc35ddc..e898e9b803c 100644 --- a/tests/unit/script/Cargo.toml +++ b/tests/unit/script/Cargo.toml @@ -11,6 +11,6 @@ path = "lib.rs" [dependencies] euclid = "0.20" -keyboard-types = "0.4.3" +keyboard-types = "0.5" script = {path = "../../../components/script"} servo_url = {path = "../../../components/url"}