From c3f5e6463c8341f5effeb18dc381221853b952d9 Mon Sep 17 00:00:00 2001 From: Mike Wiedenbauer Date: Mon, 9 Apr 2018 13:48:23 -0400 Subject: [PATCH] Add OSR text selection changed handler and remove hard-coded test bounds (issue #2383) --- include/capi/cef_render_handler_capi.h | 13 +- include/cef_render_handler.h | 10 + .../osr/render_widget_host_view_osr.cc | 26 ++ .../browser/osr/render_widget_host_view_osr.h | 4 + libcef_dll/cpptoc/render_handler_cpptoc.cc | 29 ++- libcef_dll/ctocpp/render_handler_ctocpp.cc | 24 +- libcef_dll/ctocpp/render_handler_ctocpp.h | 5 +- tests/ceftests/os_rendering_unittest.cc | 241 ++++++++++-------- tests/shared/resources/osr_test.html | 53 +++- 9 files changed, 294 insertions(+), 111 deletions(-) diff --git a/include/capi/cef_render_handler_capi.h b/include/capi/cef_render_handler_capi.h index 5acbf2915..b499aa49b 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=3fb1034cb02cfeddcaf02d8fde0dec5b8a18f416$ +// $hash=f2f3acb1df9815e4ac9bf34010ce260a2496ae5a$ // #ifndef CEF_INCLUDE_CAPI_CEF_RENDER_HANDLER_CAPI_H_ @@ -202,6 +202,17 @@ typedef struct _cef_render_handler_t { const cef_range_t* selected_range, size_t character_boundsCount, cef_rect_t const* character_bounds); + + /// + // Called when text selection has changed for the specified |browser|. + // |selected_text| is the currently selected text and |selected_range| is the + // character range. + /// + void(CEF_CALLBACK* on_text_selection_changed)( + struct _cef_render_handler_t* self, + struct _cef_browser_t* browser, + const cef_string_t* selected_text, + const cef_range_t* selected_range); } cef_render_handler_t; #ifdef __cplusplus diff --git a/include/cef_render_handler.h b/include/cef_render_handler.h index a9ea8cc1f..38cb74a1b 100644 --- a/include/cef_render_handler.h +++ b/include/cef_render_handler.h @@ -204,6 +204,16 @@ class CefRenderHandler : public virtual CefBaseRefCounted { virtual void OnImeCompositionRangeChanged(CefRefPtr browser, const CefRange& selected_range, const RectList& character_bounds) {} + + /// + // Called when text selection has changed for the specified |browser|. + // |selected_text| is the currently selected text and |selected_range| is + // the character range. + /// + /*--cef(optional_param=selected_text,optional_param=selected_range)--*/ + virtual void OnTextSelectionChanged(CefRefPtr browser, + const CefString& selected_text, + const CefRange& selected_range) {} }; #endif // CEF_INCLUDE_CEF_RENDER_HANDLER_H_ diff --git a/libcef/browser/osr/render_widget_host_view_osr.cc b/libcef/browser/osr/render_widget_host_view_osr.cc index 9f0447478..05db829bb 100644 --- a/libcef/browser/osr/render_widget_host_view_osr.cc +++ b/libcef/browser/osr/render_widget_host_view_osr.cc @@ -17,6 +17,7 @@ #include "base/callback_helpers.h" #include "base/command_line.h" #include "base/memory/ptr_util.h" +#include "base/strings/utf_string_conversions.h" #include "cc/base/switches.h" #include "components/viz/common/features.h" #include "components/viz/common/frame_sinks/copy_output_request.h" @@ -814,6 +815,31 @@ void CefRenderWidgetHostViewOSR::ImeCancelComposition() { RequestImeCompositionUpdate(false); } +void CefRenderWidgetHostViewOSR::SelectionChanged(const base::string16& text, + size_t offset, + const gfx::Range& range) { + RenderWidgetHostViewBase::SelectionChanged(text, offset, range); + + if (!browser_impl_.get()) + return; + + CefString selected_text; + if (!range.is_empty() && !text.empty()) { + size_t pos = range.GetMin() - offset; + size_t n = range.length(); + if (pos + n <= text.length()) + selected_text = text.substr(pos, n); + } + + CefRefPtr handler = + browser_impl_->GetClient()->GetRenderHandler(); + if (handler.get()) { + CefRange cef_range(range.start(), range.end()); + handler->OnTextSelectionChanged(browser_impl_.get(), selected_text, + cef_range); + } +} + void CefRenderWidgetHostViewOSR::SetNeedsBeginFrames(bool enabled) { SetFrameRate(); diff --git a/libcef/browser/osr/render_widget_host_view_osr.h b/libcef/browser/osr/render_widget_host_view_osr.h index f63d2726e..eb91fd12c 100644 --- a/libcef/browser/osr/render_widget_host_view_osr.h +++ b/libcef/browser/osr/render_widget_host_view_osr.h @@ -184,6 +184,10 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase, gfx::PointF* transformed_point) override; void DidNavigate() override; + void SelectionChanged(const base::string16& text, + size_t offset, + const gfx::Range& range) override; + // ui::CompositorDelegate implementation. std::unique_ptr CreateSoftwareOutputDevice( ui::Compositor* compositor) override; diff --git a/libcef_dll/cpptoc/render_handler_cpptoc.cc b/libcef_dll/cpptoc/render_handler_cpptoc.cc index 880efd990..a064ab8b5 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=7dba22b79d2e50ab27ccf93a393f5220965a08ce$ +// $hash=98625368df8daaeca9df1791f1867828a6271a89$ // #include "libcef_dll/cpptoc/render_handler_cpptoc.h" @@ -408,6 +408,31 @@ void CEF_CALLBACK render_handler_on_ime_composition_range_changed( CefBrowserCToCpp::Wrap(browser), selected_rangeVal, character_boundsList); } +void CEF_CALLBACK +render_handler_on_text_selection_changed(struct _cef_render_handler_t* self, + cef_browser_t* browser, + const cef_string_t* selected_text, + const cef_range_t* selected_range) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Unverified params: selected_text, selected_range + + // Translate param: selected_range; type: simple_byref_const + CefRange selected_rangeVal = selected_range ? *selected_range : CefRange(); + + // Execute + CefRenderHandlerCppToC::Get(self)->OnTextSelectionChanged( + CefBrowserCToCpp::Wrap(browser), CefString(selected_text), + selected_rangeVal); +} + } // namespace // CONSTRUCTOR - Do not edit by hand. @@ -429,6 +454,8 @@ CefRenderHandlerCppToC::CefRenderHandlerCppToC() { render_handler_on_scroll_offset_changed; GetStruct()->on_ime_composition_range_changed = render_handler_on_ime_composition_range_changed; + GetStruct()->on_text_selection_changed = + render_handler_on_text_selection_changed; } template <> diff --git a/libcef_dll/ctocpp/render_handler_ctocpp.cc b/libcef_dll/ctocpp/render_handler_ctocpp.cc index ed9bac12c..7ef48811d 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=f76ba6a84dade0b75d2018c4aee6b681a2a1505b$ +// $hash=98ed2d6d147cc82b00f766b45e1b0e15e0f84393$ // #include "libcef_dll/ctocpp/render_handler_ctocpp.h" @@ -326,6 +326,28 @@ void CefRenderHandlerCToCpp::OnImeCompositionRangeChanged( delete[] character_boundsList; } +void CefRenderHandlerCToCpp::OnTextSelectionChanged( + CefRefPtr browser, + const CefString& selected_text, + const CefRange& selected_range) { + cef_render_handler_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, on_text_selection_changed)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Unverified params: selected_text, selected_range + + // Execute + _struct->on_text_selection_changed(_struct, CefBrowserCppToC::Wrap(browser), + selected_text.GetStruct(), + &selected_range); +} + // 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 f76fbc946..1a3bc1532 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=980eeb6c12f70a23b985c8f3bb897b69ee9b73ef$ +// $hash=9e2bcb61512095fba2fca928f4696fbb39d9d3b1$ // #ifndef CEF_LIBCEF_DLL_CTOCPP_RENDER_HANDLER_CTOCPP_H_ @@ -69,6 +69,9 @@ class CefRenderHandlerCToCpp void OnImeCompositionRangeChanged(CefRefPtr browser, const CefRange& selected_range, const RectList& character_bounds) override; + void OnTextSelectionChanged(CefRefPtr browser, + const CefString& selected_text, + const CefRange& selected_range) 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 9885d0e60..3c5e8ef2d 100644 --- a/tests/ceftests/os_rendering_unittest.cc +++ b/tests/ceftests/os_rendering_unittest.cc @@ -4,6 +4,7 @@ #include "include/base/cef_bind.h" #include "include/base/cef_logging.h" +#include "include/cef_parser.h" #include "include/cef_v8.h" #include "include/wrapper/cef_closure_task.h" #include "include/wrapper/cef_stream_resource_handler.h" @@ -33,65 +34,13 @@ const char kTestUrl[] = "http://tests/osrtest"; const int kOsrWidth = 600; const int kOsrHeight = 400; -// precomputed bounding client rects for html elements (h1 and li). -#if defined(OS_WIN) || defined(OS_LINUX) -const CefRect kExpectedRectLI[] = { - CefRect(8, 8, 567, 74), // LI00 - CefRect(27, 103, 548, 20), // LI01 - CefRect(27, 123, 548, 20), // LI02 - CefRect(27, 143, 548, 20), // LI03 - CefRect(27, 163, 548, 20), // LI04 - CefRect(27, 183, 548, 20), // LI05 - CefRect(27, 203, 548, 20), // LI06 - CefRect(27, 223, 548, 20), // LI07 - CefRect(27, 243, 548, 26), // LI08 - CefRect(27, 269, 548, 26), // LI09 - CefRect(27, 295, 548, 20), // LI10 -}; -#elif defined(OS_MACOSX) -const CefRect kExpectedRectLI[] = { - CefRect(8, 8, 584, 74), // LI00 - CefRect(28, 103, 564, 18), // LI01 - CefRect(28, 121, 564, 18), // LI02 - CefRect(28, 139, 564, 18), // LI03 - CefRect(28, 157, 564, 18), // LI04 - CefRect(28, 175, 564, 18), // LI05 - CefRect(28, 193, 564, 18), // LI06 - CefRect(28, 211, 564, 18), // LI07 - CefRect(28, 229, 564, 23), // LI08 - CefRect(28, 252, 564, 26), // LI09 - CefRect(18, 291, 360, 21), // LI10 -}; -#else -#error "Unsupported platform" -#endif // defined(OS_WIN) - // bounding client rects for edit box and navigate button #if defined(OS_WIN) -const CefRect kEditBoxRect(412, 245, 60, 22); -const CefRect kNavigateButtonRect(360, 271, 140, 22); -const CefRect kSelectRect(467, 22, 75, 20); const CefRect kExpandedSelectRect(463, 42, 81, 334); -const CefRect kDropDivRect(8, 332, 52, 52); -const CefRect kDragDivRect(71, 342, 30, 30); -const int kDefaultVerticalScrollbarWidth = 17; -const int kVerticalScrollbarWidth = GetSystemMetrics(SM_CXVSCROLL); #elif defined(OS_MACOSX) -const CefRect kEditBoxRect(442, 251, 46, 16); -const CefRect kNavigateButtonRect(375, 275, 130, 20); -const CefRect kSelectRect(461, 21, 87, 26); const CefRect kExpandedSelectRect(463, 42, 75, 286); -const CefRect kDropDivRect(9, 330, 52, 52); -const CefRect kDragDivRect(60, 330, 30, 30); #elif defined(OS_LINUX) -const CefRect kEditBoxRect(434, 246, 60, 20); -const CefRect kNavigateButtonRect(380, 271, 140, 22); -const CefRect kSelectRect(467, 22, 75, 20); const CefRect kExpandedSelectRect(463, 42, 79, 334); -const CefRect kDropDivRect(8, 332, 52, 52); -const CefRect kDragDivRect(71, 342, 30, 30); -const int kDefaultVerticalScrollbarWidth = 14; -const int kVerticalScrollbarWidth = 14; #else #error "Unsupported platform" #endif // defined(OS_WIN) @@ -207,6 +156,8 @@ enum OSRTestType { OSR_TEST_IME_FINISH_COMPOSITION, // IMECancelComposition will update the composition range OSR_TEST_IME_CANCEL_COMPOSITION, + // text selection range changed + OSR_TEST_TEXT_SELECTION_CHANGE, // Define the range for popup tests. OSR_TEST_POPUP_FIRST = OSR_TEST_POPUP_PAINT, @@ -286,8 +237,10 @@ class OSRTestHandler : public RoutingTestHandler, CefRefPtr callback) override { EXPECT_TRUE(browser.get()); - if (!started()) - return false; + if (!started()) { + return handleBoundsQuery(browser, frame, query_id, request, persistent, + callback); + } const std::string& messageStr = request; switch (test_type_) { @@ -316,6 +269,33 @@ class OSRTestHandler : public RoutingTestHandler, return true; } + bool handleBoundsQuery(CefRefPtr browser, + CefRefPtr frame, + int64 query_id, + const CefString& request, + bool persistent, + CefRefPtr callback) { + CefRefPtr jsonObj = CefParseJSON(request, JSON_PARSER_RFC); + if (jsonObj.get()) { + CefRefPtr dict = jsonObj->GetDictionary(); + const std::string& type = dict->GetString("type"); + if (type == "ElementBounds") { + CefRefPtr elems = dict->GetList("elems"); + + for (size_t i = 0; i < elems->GetSize(); i++) { + CefRefPtr elem = elems->GetDictionary(i); + std::string elementId = elem->GetString("id"); + CefRect bounds(elem->GetInt("x"), elem->GetInt("y"), + elem->GetInt("width"), elem->GetInt("height")); + element_bounds_.insert(std::make_pair(elementId, bounds)); + } + return true; + } + } + + return false; + } + // CefClient methods, providing handlers CefRefPtr GetFocusHandler() override { return this; } @@ -359,7 +339,7 @@ class OSRTestHandler : public RoutingTestHandler, int& screenX, int& screenY) override { if (test_type_ == OSR_TEST_SCREEN_POINT && started()) { - const CefRect& expected_rect = GetExpectedRect(4); + const CefRect& expected_rect = GetElementBounds("LI04"); EXPECT_EQ(viewX, MiddleX(expected_rect)); EXPECT_EQ(viewY, MiddleY(expected_rect)); DestroySucceededTestSoon(); @@ -527,7 +507,7 @@ class OSRTestHandler : public RoutingTestHandler, mouse_event.modifiers = 0; browser->GetHost()->SendMouseMoveEvent(mouse_event, true); // enter mouse in the LI2 element having hand cursor - const CefRect& expected_rect = GetExpectedRect(2); + const CefRect& expected_rect = GetElementBounds("LI02"); mouse_event.x = MiddleX(expected_rect); mouse_event.y = MiddleY(expected_rect); browser->GetHost()->SendMouseMoveEvent(mouse_event, false); @@ -536,7 +516,7 @@ class OSRTestHandler : public RoutingTestHandler, case OSR_TEST_MOUSE_MOVE: if (StartTest()) { CefMouseEvent mouse_event; - const CefRect& expected_rect = GetExpectedRect(3); + const CefRect& expected_rect = GetElementBounds("LI03"); mouse_event.x = MiddleX(expected_rect); mouse_event.y = MiddleY(expected_rect); mouse_event.modifiers = 0; @@ -548,7 +528,7 @@ class OSRTestHandler : public RoutingTestHandler, case OSR_TEST_CONTEXT_MENU: if (StartTest()) { CefMouseEvent mouse_event; - const CefRect& expected_rect = GetExpectedRect(4); + const CefRect& expected_rect = GetElementBounds("LI04"); mouse_event.x = MiddleX(expected_rect); mouse_event.y = MiddleY(expected_rect); mouse_event.modifiers = 0; @@ -561,7 +541,7 @@ class OSRTestHandler : public RoutingTestHandler, case OSR_TEST_CLICK_LEFT: if (StartTest()) { CefMouseEvent mouse_event; - const CefRect& expected_rect = GetExpectedRect(0); + const CefRect& expected_rect = GetElementBounds("LI00"); mouse_event.x = MiddleX(expected_rect); mouse_event.y = MiddleY(expected_rect); @@ -598,8 +578,9 @@ class OSRTestHandler : public RoutingTestHandler, if (StartTest()) { // click inside edit box CefMouseEvent mouse_event; - mouse_event.x = MiddleX(kEditBoxRect); - mouse_event.y = MiddleY(kEditBoxRect); + const CefRect& editbox = GetElementBounds("editbox"); + mouse_event.x = MiddleX(editbox); + mouse_event.y = MiddleY(editbox); mouse_event.modifiers = 0; browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1); @@ -621,9 +602,11 @@ class OSRTestHandler : public RoutingTestHandler, #error "Unsupported platform" #endif } + // click button to navigate - mouse_event.x = MiddleX(kNavigateButtonRect); - mouse_event.y = MiddleY(kNavigateButtonRect); + const CefRect& btnnavigate = GetElementBounds("btnnavigate"); + mouse_event.x = MiddleX(btnnavigate); + mouse_event.y = MiddleY(btnnavigate); browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1); browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true, @@ -633,7 +616,7 @@ class OSRTestHandler : public RoutingTestHandler, case OSR_TEST_TOOLTIP: if (StartTest()) { CefMouseEvent mouse_event; - const CefRect& expected_rect = GetExpectedRect(10); + const CefRect& expected_rect = GetElementBounds("LI10"); mouse_event.x = MiddleX(expected_rect); mouse_event.y = MiddleY(expected_rect); mouse_event.modifiers = 0; @@ -645,7 +628,7 @@ class OSRTestHandler : public RoutingTestHandler, if (StartTest()) { // scroll down once CefMouseEvent mouse_event; - const CefRect& expected_rect = GetExpectedRect(0); + const CefRect& expected_rect = GetElementBounds("LI00"); mouse_event.x = MiddleX(expected_rect); mouse_event.y = MiddleY(expected_rect); mouse_event.modifiers = 0; @@ -787,8 +770,9 @@ class OSRTestHandler : public RoutingTestHandler, if (StartTest()) { // move the mouse over the element to drag CefMouseEvent mouse_event; - mouse_event.x = MiddleX(kDragDivRect); - mouse_event.y = MiddleY(kDragDivRect); + const CefRect& dragdiv = GetElementBounds("dragdiv"); + mouse_event.x = MiddleX(dragdiv); + mouse_event.y = MiddleY(dragdiv); mouse_event.modifiers = 0; browser->GetHost()->SendMouseMoveEvent(mouse_event, false); // click on the element to drag @@ -806,8 +790,9 @@ class OSRTestHandler : public RoutingTestHandler, if (StartTest()) { // click inside edit box so that text could be entered CefMouseEvent mouse_event; - mouse_event.x = MiddleX(kEditBoxRect); - mouse_event.y = MiddleY(kEditBoxRect); + const CefRect& editbox = GetElementBounds("editbox"); + mouse_event.x = MiddleX(editbox); + mouse_event.y = MiddleY(editbox); mouse_event.modifiers = 0; browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1); @@ -832,8 +817,9 @@ class OSRTestHandler : public RoutingTestHandler, browser->GetHost()->ImeCommitText(markedText, range, 0); // click button to navigate - mouse_event.x = MiddleX(kNavigateButtonRect); - mouse_event.y = MiddleY(kNavigateButtonRect); + const CefRect& btnnavigate = GetElementBounds("btnnavigate"); + mouse_event.x = MiddleX(btnnavigate); + mouse_event.y = MiddleY(btnnavigate); browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1); browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true, @@ -845,8 +831,9 @@ class OSRTestHandler : public RoutingTestHandler, if (StartTest()) { // click inside edit box so that text could be entered CefMouseEvent mouse_event; - mouse_event.x = MiddleX(kEditBoxRect); - mouse_event.y = MiddleY(kEditBoxRect); + const CefRect& editbox = GetElementBounds("editbox"); + mouse_event.x = MiddleX(editbox); + mouse_event.y = MiddleY(editbox); mouse_event.modifiers = 0; browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1); @@ -869,8 +856,9 @@ class OSRTestHandler : public RoutingTestHandler, browser->GetHost()->ImeFinishComposingText(true); // click button to navigate - mouse_event.x = MiddleX(kNavigateButtonRect); - mouse_event.y = MiddleY(kNavigateButtonRect); + const CefRect& btnnavigate = GetElementBounds("btnnavigate"); + mouse_event.x = MiddleX(btnnavigate); + mouse_event.y = MiddleY(btnnavigate); browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1); browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true, @@ -882,8 +870,9 @@ class OSRTestHandler : public RoutingTestHandler, if (StartTest()) { // click inside edit box so that text could be entered CefMouseEvent mouse_event; - mouse_event.x = MiddleX(kEditBoxRect); - mouse_event.y = MiddleY(kEditBoxRect); + const CefRect& editbox = GetElementBounds("editbox"); + mouse_event.x = MiddleX(editbox); + mouse_event.y = MiddleY(editbox); mouse_event.modifiers = 0; browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1); @@ -909,8 +898,9 @@ class OSRTestHandler : public RoutingTestHandler, browser->GetHost()->ImeCancelComposition(); // click button to navigate and verify - mouse_event.x = MiddleX(kNavigateButtonRect); - mouse_event.y = MiddleY(kNavigateButtonRect); + const CefRect& btnnavigate = GetElementBounds("btnnavigate"); + mouse_event.x = MiddleX(btnnavigate); + mouse_event.y = MiddleY(btnnavigate); browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1); browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true, @@ -922,8 +912,9 @@ class OSRTestHandler : public RoutingTestHandler, if (StartTest()) { // click inside edit box so that text could be entered CefMouseEvent mouse_event; - mouse_event.x = MiddleX(kEditBoxRect); - mouse_event.y = MiddleY(kEditBoxRect); + const CefRect& editbox = GetElementBounds("editbox"); + mouse_event.x = MiddleX(editbox); + mouse_event.y = MiddleY(editbox); mouse_event.modifiers = 0; browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1); @@ -948,6 +939,21 @@ class OSRTestHandler : public RoutingTestHandler, markedText, underlines, replacement_range, selection_range); } } break; + case OSR_TEST_TEXT_SELECTION_CHANGE: { + // trigger the text selection changed event + if (StartTest()) { + // click inside list element so text range will be selected. + CefMouseEvent mouse_event; + const CefRect& expected_rect = GetElementBounds("LI11"); + mouse_event.x = MiddleX(expected_rect); + mouse_event.y = MiddleY(expected_rect); + 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; } @@ -1013,24 +1019,24 @@ class OSRTestHandler : public RoutingTestHandler, int y) override { if (test_type_ == OSR_TEST_DRAG_DROP_START_DRAGGING && started()) { // Verify the drag image representation. + const CefRect& dragdiv = GetElementBounds("dragdiv"); EXPECT_TRUE(drag_data->HasImage()); CefRefPtr image = drag_data->GetImage(); EXPECT_TRUE(image.get() != NULL); if (image.get()) { // Drag image height seems to always be + 1px greater than the drag rect // on Linux. Therefore allow it to be +/- 1px. - EXPECT_NEAR(static_cast(image->GetWidth()), kDragDivRect.width, 1); - EXPECT_NEAR(static_cast(image->GetHeight()), kDragDivRect.height, - 1); + EXPECT_NEAR(static_cast(image->GetWidth()), dragdiv.width, 1); + EXPECT_NEAR(static_cast(image->GetHeight()), dragdiv.height, 1); } // During testing hotspot (x, y) was (15, 23) at 1x scale and (15, 18) at // 2x scale. Since the mechanism for determining this position is unclear // test only that it falls within the rect boundaries. CefPoint hotspot = drag_data->GetImageHotspot(); EXPECT_GT(hotspot.x, 0); - EXPECT_LT(hotspot.x, GetScaledInt(kDragDivRect.width)); + EXPECT_LT(hotspot.x, GetScaledInt(dragdiv.width)); EXPECT_GT(hotspot.y, 0); - EXPECT_LT(hotspot.y, GetScaledInt(kDragDivRect.height)); + EXPECT_LT(hotspot.y, GetScaledInt(dragdiv.height)); DestroySucceededTestSoon(); return false; @@ -1041,13 +1047,15 @@ class OSRTestHandler : public RoutingTestHandler, CefRefPtr data = drag_data->Clone(); data->ResetFileContents(); CefMouseEvent ev; - ev.x = MiddleX(kDragDivRect) - 5; - ev.y = MiddleY(kDragDivRect) - 5; + const CefRect& dragdiv = GetElementBounds("dragdiv"); + ev.x = MiddleX(dragdiv) - 5; + ev.y = MiddleY(dragdiv) - 5; ev.modifiers = EVENTFLAG_LEFT_MOUSE_BUTTON; browser->GetHost()->DragTargetDragEnter(data, ev, allowed_ops); - ev.x = MiddleX(kDropDivRect); - ev.y = MiddleY(kDropDivRect); + const CefRect& dropdiv = GetElementBounds("dropdiv"); + ev.x = MiddleX(dropdiv); + ev.y = MiddleY(dropdiv); browser->GetHost()->SendMouseMoveEvent(ev, false); browser->GetHost()->DragTargetDragOver(ev, allowed_ops); @@ -1064,8 +1072,9 @@ class OSRTestHandler : public RoutingTestHandler, DragOperation operation) override { if (test_type_ == OSR_TEST_DRAG_DROP_UPDATE_CURSOR && started()) { if (operation != DRAG_OPERATION_NONE) { + const CefRect& dropdiv = GetElementBounds("dropdiv"); browser->GetHost()->DragSourceEndedAt( - MiddleX(kDropDivRect), MiddleY(kDropDivRect), DRAG_OPERATION_NONE); + MiddleX(dropdiv), MiddleY(dropdiv), DRAG_OPERATION_NONE); browser->GetHost()->DragSourceSystemDragEnded(); DestroySucceededTestSoon(); } @@ -1076,8 +1085,9 @@ class OSRTestHandler : public RoutingTestHandler, got_update_cursor_.yes(); CefMouseEvent ev; - ev.x = MiddleX(kDropDivRect); - ev.y = MiddleY(kDropDivRect); + const CefRect& dropdiv = GetElementBounds("dropdiv"); + ev.x = MiddleX(dropdiv); + ev.y = MiddleY(dropdiv); ev.modifiers = 0; browser->GetHost()->SendMouseClickEvent(ev, MBT_LEFT, true, 1); browser->GetHost()->DragTargetDrop(ev); @@ -1086,6 +1096,19 @@ class OSRTestHandler : public RoutingTestHandler, } } + void OnTextSelectionChanged(CefRefPtr browser, + const CefString& selected_text, + const CefRange& selected_range) override { + if (test_type_ == OSR_TEST_TEXT_SELECTION_CHANGE && started()) { + if (!got_initial_text_selection_event_) { + got_initial_text_selection_event_.yes(); + } else { + EXPECT_STREQ("SELECTED_TEXT_RANGE", selected_text.ToString().c_str()); + DestroySucceededTestSoon(); + } + } + } + bool OnTooltip(CefRefPtr browser, CefString& text) override { if (test_type_ == OSR_TEST_TOOLTIP && started()) { EXPECT_STREQ("EXPECTED_TOOLTIP", text.ToString().c_str()); @@ -1101,7 +1124,7 @@ class OSRTestHandler : public RoutingTestHandler, if (!started()) return; if (test_type_ == OSR_TEST_CLICK_RIGHT) { - const CefRect& expected_rect = GetExpectedRect(4); + const CefRect& expected_rect = GetElementBounds("LI04"); EXPECT_EQ(params->GetXCoord(), MiddleX(expected_rect)); EXPECT_EQ(params->GetYCoord(), MiddleY(expected_rect)); DestroySucceededTestSoon(); @@ -1146,16 +1169,12 @@ class OSRTestHandler : public RoutingTestHandler, return client::LogicalToDevice(value, scale_factor_); } - CefRect GetExpectedRect(int index) { - CefRect rect = kExpectedRectLI[index]; -#if defined(OS_WIN) || defined(OS_LINUX) - // Adjust the rect to include system vertical scrollbar width. - rect.width += kDefaultVerticalScrollbarWidth - kVerticalScrollbarWidth; -#elif !defined(OS_MACOSX) -#error "Unsupported platform" -#endif - - return rect; + CefRect GetElementBounds(const std::string& id) { + ElementBoundsMap::const_iterator it = element_bounds_.find(id); + if (it != element_bounds_.end()) { + return it->second; + } + return CefRect(); } static bool IsFullRepaint(const CefRect& rc, int width, int height) { @@ -1212,6 +1231,8 @@ class OSRTestHandler : public RoutingTestHandler, // SetFocus is called by the system when we explicitly set the focus and // when popups are dismissed. EXPECT_TRUE(got_system_focus_event_); + } else if (test_type_ == OSR_TEST_TEXT_SELECTION_CHANGE) { + EXPECT_TRUE(got_initial_text_selection_event_); } else { EXPECT_FALSE(got_system_focus_event_); } @@ -1222,8 +1243,10 @@ class OSRTestHandler : public RoutingTestHandler, void ExpandDropDown() { GetBrowser()->GetHost()->SendFocusEvent(true); CefMouseEvent mouse_event; - mouse_event.x = MiddleX(kSelectRect); - mouse_event.y = MiddleY(kSelectRect); + + const CefRect& LI11select = GetElementBounds("LI11select"); + mouse_event.x = MiddleX(LI11select); + mouse_event.y = MiddleY(LI11select); mouse_event.modifiers = 0; GetBrowser()->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1); @@ -1301,6 +1324,10 @@ class OSRTestHandler : public RoutingTestHandler, TrackCallback got_update_cursor_; TrackCallback got_navigation_focus_event_; TrackCallback got_system_focus_event_; + TrackCallback got_initial_text_selection_event_; + + typedef std::map ElementBoundsMap; + ElementBoundsMap element_bounds_; IMPLEMENT_REFCOUNTING(OSRTestHandler); }; @@ -1382,3 +1409,5 @@ OSR_TEST(IMEFinishComposition, OSR_TEST_IME_FINISH_COMPOSITION, 1.0f); OSR_TEST(IMEFinishComposition2x, OSR_TEST_IME_FINISH_COMPOSITION, 2.0f); 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); diff --git a/tests/shared/resources/osr_test.html b/tests/shared/resources/osr_test.html index a12223de9..4a3944897 100644 --- a/tests/shared/resources/osr_test.html +++ b/tests/shared/resources/osr_test.html @@ -31,11 +31,52 @@ function makeH1Red() { getElement('LI00').style.color='red'; } function makeH1Black() { getElement('LI00').style.color='black'; } function navigate() { location.href='?k='+getElement('editbox').value; } - function load() { var select = document.getElementById('LI11select'); + function load() { + var elems = []; + var param = { type: 'ElementBounds', elems: elems }; + + elems.push(getElementBounds('LI00')); + elems.push(getElementBounds('LI01')); + elems.push(getElementBounds('LI02')); + elems.push(getElementBounds('LI03')); + elems.push(getElementBounds('LI04')); + elems.push(getElementBounds('LI05')); + elems.push(getElementBounds('LI06')); + elems.push(getElementBounds('LI07')); + elems.push(getElementBounds('LI08')); + elems.push(getElementBounds('LI09')); + elems.push(getElementBounds('LI10')); + elems.push(getElementBounds('LI11')); + elems.push(getElementBounds('LI11select')); + elems.push(getElementBounds('editbox')); + elems.push(getElementBounds('btnnavigate')); + elems.push(getElementBounds('dropdiv')); + elems.push(getElementBounds('dragdiv')); + + if (window.testQuery) + window.testQuery({request: JSON.stringify(param)}); + + fillDropDown(); + } + + function fillDropDown() { + var select = document.getElementById('LI11select'); for (var i = 1; i < 21; i++) select.options.add(new Option('Option ' + i, i)); } + function getElementBounds(id) { + var element = document.getElementById(id); + var bounds = element.getBoundingClientRect(); + return { + id: id, + x: Math.floor(bounds.x), + y: Math.floor(bounds.y), + width: Math.floor(bounds.width), + height: Math.floor(bounds.height) + }; + } + function onEventTest(event) { var param = 'osr' + event.type; @@ -64,6 +105,15 @@ if (window.testQuery) window.testQuery({request: "osrdrop"}); } + + function selectText(ev) { + var element = ev.target; + var selection = window.getSelection(); + var range = document.createRange(); + range.selectNodeContents(element); + selection.removeAllRanges(); + selection.addRange(range); + }

@@ -92,6 +142,7 @@ value='Click here to navigate' id='editbox' />
  • Mouse over this element will trigger show a tooltip
  • +
  • SELECTED_TEXT_RANGE
  • Drag here