From 379fb8d39e264e085389af760963098e92e9c326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Riku=20Palom=C3=A4ki?= Date: Tue, 26 Feb 2019 16:49:41 +0000 Subject: [PATCH] Add CefRenderHandler::OnVirtualKeyboardRequested (issue #2607) --- include/capi/cef_render_handler_capi.h | 13 ++++++- include/cef_render_handler.h | 11 ++++++ include/internal/cef_types.h | 19 +++++++++ .../osr/render_widget_host_view_osr.cc | 31 +++++++++++++++ .../browser/osr/render_widget_host_view_osr.h | 10 ++++- libcef_dll/cpptoc/render_handler_cpptoc.cc | 25 +++++++++++- libcef_dll/ctocpp/render_handler_ctocpp.cc | 24 +++++++++++- libcef_dll/ctocpp/render_handler_ctocpp.h | 4 +- tests/ceftests/os_rendering_unittest.cc | 39 +++++++++++++++++++ tests/shared/resources/osr_test.html | 2 + 10 files changed, 173 insertions(+), 5 deletions(-) diff --git a/include/capi/cef_render_handler_capi.h b/include/capi/cef_render_handler_capi.h index 1ae4266a1..26b70081e 100644 --- a/include/capi/cef_render_handler_capi.h +++ b/include/capi/cef_render_handler_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=cf5dc6f6d2c64d5dc706edd5adc5cf6c7c752750$ +// $hash=0640490eead86e5631e8db67f3a0de8b43c10640$ // #ifndef CEF_INCLUDE_CAPI_CEF_RENDER_HANDLER_CAPI_H_ @@ -231,6 +231,17 @@ typedef struct _cef_render_handler_t { struct _cef_browser_t* browser, const cef_string_t* selected_text, const cef_range_t* selected_range); + + /// + // Called when an on-screen keyboard should be shown or hidden for the + // specified |browser|. |input_mode| specifies what kind of keyboard should be + // opened. If |input_mode| is CEF_TEXT_INPUT_MODE_NONE, any existing keyboard + // for this browser should be hidden. + /// + void(CEF_CALLBACK* on_virtual_keyboard_requested)( + struct _cef_render_handler_t* self, + struct _cef_browser_t* browser, + cef_text_input_mode_t input_mode); } cef_render_handler_t; #ifdef __cplusplus diff --git a/include/cef_render_handler.h b/include/cef_render_handler.h index 4d94e941b..ed60bf997 100644 --- a/include/cef_render_handler.h +++ b/include/cef_render_handler.h @@ -57,6 +57,7 @@ class CefRenderHandler : public virtual CefBaseRefCounted { typedef cef_drag_operations_mask_t DragOperationsMask; typedef cef_paint_element_type_t PaintElementType; typedef std::vector RectList; + typedef cef_text_input_mode_t TextInputMode; /// // Return the handler for accessibility notifications. If no handler is @@ -231,6 +232,16 @@ class CefRenderHandler : public virtual CefBaseRefCounted { virtual void OnTextSelectionChanged(CefRefPtr browser, const CefString& selected_text, const CefRange& selected_range) {} + + /// + // Called when an on-screen keyboard should be shown or hidden for the + // specified |browser|. |input_mode| specifies what kind of keyboard + // should be opened. If |input_mode| is CEF_TEXT_INPUT_MODE_NONE, any + // existing keyboard for this browser should be hidden. + /// + /*--cef()--*/ + virtual void OnVirtualKeyboardRequested(CefRefPtr browser, + TextInputMode input_mode) {} }; #endif // CEF_INCLUDE_CEF_RENDER_HANDLER_H_ diff --git a/include/internal/cef_types.h b/include/internal/cef_types.h index 4aef4ed30..09db7a311 100644 --- a/include/internal/cef_types.h +++ b/include/internal/cef_types.h @@ -994,6 +994,25 @@ typedef enum { DRAG_OPERATION_EVERY = UINT_MAX } cef_drag_operations_mask_t; +/// +// Input mode of a virtual keyboard. These constants match their equivalents +// in Chromium's text_input_mode.h and should not be renumbered. +// See https://html.spec.whatwg.org/#input-modalities:-the-inputmode-attribute +/// +typedef enum { + CEF_TEXT_INPUT_MODE_DEFAULT, + CEF_TEXT_INPUT_MODE_NONE, + CEF_TEXT_INPUT_MODE_TEXT, + CEF_TEXT_INPUT_MODE_TEL, + CEF_TEXT_INPUT_MODE_URL, + CEF_TEXT_INPUT_MODE_EMAIL, + CEF_TEXT_INPUT_MODE_NUMERIC, + CEF_TEXT_INPUT_MODE_DECIMAL, + CEF_TEXT_INPUT_MODE_SEARCH, + + CEF_TEXT_INPUT_MODE_MAX = CEF_TEXT_INPUT_MODE_SEARCH, +} cef_text_input_mode_t; + /// // V8 access control values. /// diff --git a/libcef/browser/osr/render_widget_host_view_osr.cc b/libcef/browser/osr/render_widget_host_view_osr.cc index 0d58fca47..96818021c 100644 --- a/libcef/browser/osr/render_widget_host_view_osr.cc +++ b/libcef/browser/osr/render_widget_host_view_osr.cc @@ -396,6 +396,9 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR( // Do this last because it may result in a call to SetNeedsBeginFrames. render_widget_host_->SetView(this); + + if (GetTextInputManager()) + GetTextInputManager()->AddObserver(this); } CefRenderWidgetHostViewOSR::~CefRenderWidgetHostViewOSR() { @@ -425,6 +428,9 @@ CefRenderWidgetHostViewOSR::~CefRenderWidgetHostViewOSR() { DCHECK(popup_host_view_ == NULL); DCHECK(child_host_view_ == NULL); DCHECK(guest_host_views_.empty()); + + if (text_input_manager_) + text_input_manager_->RemoveObserver(this); } // Called for full-screen widgets. @@ -1424,6 +1430,31 @@ void CefRenderWidgetHostViewOSR::SendFocusEvent(bool focus) { } } +void CefRenderWidgetHostViewOSR::OnUpdateTextInputStateCalled( + content::TextInputManager* text_input_manager, + content::RenderWidgetHostViewBase* updated_view, + bool did_update_state) { + const content::TextInputState* state = + text_input_manager->GetTextInputState(); + if (state && !state->show_ime_if_needed) + return; + + CefRenderHandler::TextInputMode mode = CEF_TEXT_INPUT_MODE_NONE; + if (state && state->type != ui::TEXT_INPUT_TYPE_NONE) { + static_assert( + static_cast(CEF_TEXT_INPUT_MODE_MAX) == + static_cast(ui::TEXT_INPUT_MODE_MAX), + "Enum values in cef_text_input_mode_t must match ui::TextInputMode"); + mode = static_cast(state->mode); + } + + CefRefPtr handler = + browser_impl_->GetClient()->GetRenderHandler(); + CHECK(handler); + + handler->OnVirtualKeyboardRequested(browser_impl_->GetBrowser(), mode); +} + void CefRenderWidgetHostViewOSR::UpdateFrameRate() { frame_rate_threshold_us_ = 0; SetFrameRate(); diff --git a/libcef/browser/osr/render_widget_host_view_osr.h b/libcef/browser/osr/render_widget_host_view_osr.h index c65c0fd8d..a4ba65c3b 100644 --- a/libcef/browser/osr/render_widget_host_view_osr.h +++ b/libcef/browser/osr/render_widget_host_view_osr.h @@ -20,6 +20,7 @@ #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" +#include "content/browser/renderer_host/text_input_manager.h" #include "content/public/common/widget_type.h" #include "ui/compositor/compositor.h" #include "ui/compositor/external_begin_frame_client.h" @@ -96,7 +97,8 @@ class MacHelper; class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase, public ui::ExternalBeginFrameClient, - public ui::CompositorDelegate { + public ui::CompositorDelegate, + public content::TextInputManager::Observer { public: CefRenderWidgetHostViewOSR(SkColor background_color, bool use_shared_texture, @@ -205,6 +207,12 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase, std::unique_ptr CreateSoftwareOutputDevice( ui::Compositor* compositor) override; + // TextInputManager::Observer implementation. + void OnUpdateTextInputStateCalled( + content::TextInputManager* text_input_manager, + RenderWidgetHostViewBase* updated_view, + bool did_update_state) override; + bool InstallTransparency(); void SynchronizeVisualProperties(); diff --git a/libcef_dll/cpptoc/render_handler_cpptoc.cc b/libcef_dll/cpptoc/render_handler_cpptoc.cc index 24f24957c..42c0246cf 100644 --- a/libcef_dll/cpptoc/render_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/render_handler_cpptoc.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=7af995d59f8f171a08ea92b3b0c3428fb26f93ad$ +// $hash=94f5afecaaa5c9c534438a1c97a4af27a97d148c$ // #include "libcef_dll/cpptoc/render_handler_cpptoc.h" @@ -500,6 +500,27 @@ render_handler_on_text_selection_changed(struct _cef_render_handler_t* self, selected_rangeVal); } +void CEF_CALLBACK +render_handler_on_virtual_keyboard_requested(struct _cef_render_handler_t* self, + cef_browser_t* browser, + cef_text_input_mode_t input_mode) { + shutdown_checker::AssertNotShutdown(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + + // Execute + CefRenderHandlerCppToC::Get(self)->OnVirtualKeyboardRequested( + CefBrowserCToCpp::Wrap(browser), input_mode); +} + } // namespace // CONSTRUCTOR - Do not edit by hand. @@ -524,6 +545,8 @@ CefRenderHandlerCppToC::CefRenderHandlerCppToC() { render_handler_on_ime_composition_range_changed; GetStruct()->on_text_selection_changed = render_handler_on_text_selection_changed; + GetStruct()->on_virtual_keyboard_requested = + render_handler_on_virtual_keyboard_requested; } // DESTRUCTOR - Do not edit by hand. diff --git a/libcef_dll/ctocpp/render_handler_ctocpp.cc b/libcef_dll/ctocpp/render_handler_ctocpp.cc index cb65d7f48..56a137adb 100644 --- a/libcef_dll/ctocpp/render_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/render_handler_ctocpp.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=bb77b018f638f1bc43208d48a84b02696b9c055c$ +// $hash=9a7d89bc978623c025c82f438eec0da543aaa7a6$ // #include "libcef_dll/ctocpp/render_handler_ctocpp.h" @@ -431,6 +431,28 @@ void CefRenderHandlerCToCpp::OnTextSelectionChanged( &selected_range); } +NO_SANITIZE("cfi-icall") +void CefRenderHandlerCToCpp::OnVirtualKeyboardRequested( + CefRefPtr browser, + TextInputMode input_mode) { + shutdown_checker::AssertNotShutdown(); + + cef_render_handler_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, on_virtual_keyboard_requested)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + _struct->on_virtual_keyboard_requested( + _struct, CefBrowserCppToC::Wrap(browser), input_mode); +} + // CONSTRUCTOR - Do not edit by hand. CefRenderHandlerCToCpp::CefRenderHandlerCToCpp() {} diff --git a/libcef_dll/ctocpp/render_handler_ctocpp.h b/libcef_dll/ctocpp/render_handler_ctocpp.h index f6cf58155..2f550e714 100644 --- a/libcef_dll/ctocpp/render_handler_ctocpp.h +++ b/libcef_dll/ctocpp/render_handler_ctocpp.h @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=f76bdd2d055df74b08fe6c77b40b68d908f20dc9$ +// $hash=b4922b3f59c932edf64692772b300f231e588388$ // #ifndef CEF_LIBCEF_DLL_CTOCPP_RENDER_HANDLER_CTOCPP_H_ @@ -77,6 +77,8 @@ class CefRenderHandlerCToCpp void OnTextSelectionChanged(CefRefPtr browser, const CefString& selected_text, const CefRange& selected_range) override; + void OnVirtualKeyboardRequested(CefRefPtr browser, + TextInputMode input_mode) override; }; #endif // CEF_LIBCEF_DLL_CTOCPP_RENDER_HANDLER_CTOCPP_H_ diff --git a/tests/ceftests/os_rendering_unittest.cc b/tests/ceftests/os_rendering_unittest.cc index 8ee693c66..a74771bf6 100644 --- a/tests/ceftests/os_rendering_unittest.cc +++ b/tests/ceftests/os_rendering_unittest.cc @@ -158,6 +158,8 @@ enum OSRTestType { OSR_TEST_IME_CANCEL_COMPOSITION, // text selection range changed OSR_TEST_TEXT_SELECTION_CHANGE, + // clicking on text input will call OnVirtualKeyboardRequested + OSR_TEST_VIRTUAL_KEYBOARD, // Define the range for popup tests. OSR_TEST_POPUP_FIRST = OSR_TEST_POPUP_PAINT, @@ -948,6 +950,19 @@ class OSRTestHandler : public RoutingTestHandler, 1); } } break; + case OSR_TEST_VIRTUAL_KEYBOARD: { + if (StartTest()) { + CefMouseEvent mouse_event; + const CefRect& input = GetElementBounds("email"); + mouse_event.x = MiddleX(input); + mouse_event.y = MiddleY(input); + mouse_event.modifiers = 0; + browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false, + 1); + browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true, + 1); + } + } break; default: break; } @@ -1103,6 +1118,28 @@ class OSRTestHandler : public RoutingTestHandler, } } + void OnVirtualKeyboardRequested(CefRefPtr browser, + TextInputMode input_mode) override { + if (test_type_ == OSR_TEST_VIRTUAL_KEYBOARD && started()) { + if (!got_virtual_keyboard_event_.isSet()) { + got_virtual_keyboard_event_.yes(); + EXPECT_EQ(CEF_TEXT_INPUT_MODE_EMAIL, input_mode); + + CefMouseEvent mouse_event; + const CefRect& input = GetElementBounds("LI01"); + mouse_event.x = MiddleX(input); + mouse_event.y = MiddleY(input); + mouse_event.modifiers = 0; + browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false, + 1); + browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true, 1); + } else { + EXPECT_EQ(CEF_TEXT_INPUT_MODE_NONE, input_mode); + DestroySucceededTestSoon(); + } + } + } + bool OnTooltip(CefRefPtr browser, CefString& text) override { if (test_type_ == OSR_TEST_TOOLTIP && started()) { EXPECT_STREQ("EXPECTED_TOOLTIP", text.ToString().c_str()); @@ -1319,6 +1356,7 @@ class OSRTestHandler : public RoutingTestHandler, TrackCallback got_navigation_focus_event_; TrackCallback got_system_focus_event_; TrackCallback got_initial_text_selection_event_; + TrackCallback got_virtual_keyboard_event_; typedef std::map ElementBoundsMap; ElementBoundsMap element_bounds_; @@ -1405,3 +1443,4 @@ OSR_TEST(IMECancelComposition, OSR_TEST_IME_CANCEL_COMPOSITION, 1.0f); OSR_TEST(IMECancelComposition2x, OSR_TEST_IME_CANCEL_COMPOSITION, 2.0f); OSR_TEST(TextSelectionChanged, OSR_TEST_TEXT_SELECTION_CHANGE, 1.0f); OSR_TEST(TextSelectionChanged2x, OSR_TEST_TEXT_SELECTION_CHANGE, 2.0f); +OSR_TEST(VirtualKeyboard, OSR_TEST_VIRTUAL_KEYBOARD, 1.0f); diff --git a/tests/shared/resources/osr_test.html b/tests/shared/resources/osr_test.html index 0f776a4c4..5b6d704d2 100644 --- a/tests/shared/resources/osr_test.html +++ b/tests/shared/resources/osr_test.html @@ -48,6 +48,7 @@ elems.push(getElementBounds('LI10')); elems.push(getElementBounds('LI11')); elems.push(getElementBounds('LI11select')); + elems.push(getElementBounds('email')); elems.push(getElementBounds('editbox')); elems.push(getElementBounds('btnnavigate')); elems.push(getElementBounds('dropdiv')); @@ -143,6 +144,7 @@
  • Mouse over this element will trigger show a tooltip
  • SELECTED_TEXT_RANGE
  • +
  • Drag here