Index: content/browser/renderer_host/render_widget_host_view_mac_unittest.mm |
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm |
index 8a898772b66b83b2bfeed69ebdbe344bcc0ee47c..6f140ba0f6557b726e1bab7709b0faaaeff9a816 100644 |
--- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm |
+++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm |
@@ -5,6 +5,7 @@ |
#include "content/browser/renderer_host/render_widget_host_view_mac.h" |
#include "base/mac/scoped_nsautorelease_pool.h" |
+#include "base/utf_string_conversions.h" |
#include "content/browser/browser_thread_impl.h" |
#include "content/browser/renderer_host/test_render_view_host.h" |
#include "content/common/gpu/gpu_messages.h" |
@@ -15,6 +16,51 @@ |
namespace content { |
+namespace { |
+ |
+// Generates the |length| of composition rectangle vector and save them to |
+// |output|. It starts from |origin| and each rectangle contains |unit_size|. |
+void GenerateCompositionRectArray(const gfx::Point& origin, |
+ const gfx::Size& unit_size, |
+ size_t length, |
+ const std::vector<size_t>& break_points, |
+ std::vector<gfx::Rect>* output) { |
+ DCHECK(output); |
+ output->clear(); |
+ |
+ std::queue<int> break_point_queue; |
+ for (size_t i = 0; i < break_points.size(); ++i) |
+ break_point_queue.push(break_points[i]); |
+ break_point_queue.push(length); |
+ size_t next_break_point = break_point_queue.front(); |
+ break_point_queue.pop(); |
+ |
+ gfx::Rect current_rect(origin, unit_size); |
+ for (size_t i = 0; i < length; ++i) { |
+ if (i == next_break_point) { |
+ current_rect.set_x(origin.x()); |
+ current_rect.set_y(current_rect.y() + current_rect.height()); |
+ next_break_point = break_point_queue.front(); |
+ break_point_queue.pop(); |
+ } |
+ output->push_back(current_rect); |
+ current_rect.set_x(current_rect.right()); |
+ } |
+} |
+ |
+gfx::Rect GetExpectedRect(const gfx::Point& origin, |
+ const gfx::Size& size, |
+ const ui::Range& range, |
+ int line_no) { |
+ return gfx::Rect( |
+ origin.x() + range.start() * size.width(), |
+ origin.y() + line_no * size.height(), |
+ range.length() * size.width(), |
+ size.height()); |
+} |
+ |
+} // namespace |
+ |
class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness { |
public: |
RenderWidgetHostViewMacTest() : old_rwhv_(NULL), rwhv_mac_(NULL) {} |
@@ -205,4 +251,301 @@ TEST_F(RenderWidgetHostViewMacTest, Fullscreen) { |
EXPECT_TRUE(rwhv_mac_->pepper_fullscreen_window()); |
} |
+TEST_F(RenderWidgetHostViewMacTest, GetFirstRectForCharaacterRangeCaretCase) { |
+ const string16 kDummyString = UTF8ToUTF16("hogehoge"); |
+ const size_t kDummyOffset = 0; |
+ |
+ gfx::Rect caret_rect(10, 11, 0, 10); |
+ ui::Range caret_range(0, 0); |
+ |
+ NSRect rect; |
+ NSRange actual_range; |
+ rwhv_mac_->SelectionChanged(kDummyString, kDummyOffset, caret_range); |
+ rwhv_mac_->SelectionBoundsChanged(caret_rect, caret_rect); |
+ EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ caret_range.ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_EQ(caret_rect, gfx::Rect(NSRectToCGRect(rect))); |
+ EXPECT_EQ(caret_range, ui::Range(actual_range)); |
+ |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(0, 1).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(1, 1).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(2, 3).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ |
+ // Caret moved. |
+ caret_rect = gfx::Rect(20, 11, 0, 10); |
+ caret_range = ui::Range(1, 1); |
+ rwhv_mac_->SelectionChanged(kDummyString, kDummyOffset, caret_range); |
+ rwhv_mac_->SelectionBoundsChanged(caret_rect, caret_rect); |
+ EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ caret_range.ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_EQ(caret_rect, gfx::Rect(NSRectToCGRect(rect))); |
+ EXPECT_EQ(caret_range, ui::Range(actual_range)); |
+ |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(0, 0).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(1, 2).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(2, 3).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ |
+ // No caret. |
+ caret_range = ui::Range(1, 2); |
+ rwhv_mac_->SelectionChanged(kDummyString, kDummyOffset, caret_range); |
+ rwhv_mac_->SelectionBoundsChanged(caret_rect, gfx::Rect(30, 11, 0, 10)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(0, 0).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(0, 1).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(1, 1).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(1, 2).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(2, 2).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+} |
+ |
+TEST_F(RenderWidgetHostViewMacTest, UpdateCompositionSinglelineCase) { |
+ const gfx::Point kOrigin(10, 11); |
+ const gfx::Size kBoundsUnit(10, 20); |
+ |
+ // If there are no update from renderer, always returned caret position. |
+ NSRect rect; |
+ NSRange actual_range; |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(0, 0).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(0, 1).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(1, 0).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(1, 1).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(1, 2).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ |
+ const int kCompositionLength = 10; |
+ std::vector<gfx::Rect> composition_bounds; |
+ const int kCompositionStart = 3; |
+ const ui::Range kCompositionRange(kCompositionStart, |
+ kCompositionStart + kCompositionLength); |
+ GenerateCompositionRectArray(kOrigin, |
+ kBoundsUnit, |
+ kCompositionLength, |
+ std::vector<size_t>(), |
+ &composition_bounds); |
+ rwhv_mac_->ImeCompositionRangeChanged(kCompositionRange, composition_bounds); |
+ |
+ // Out of range requests will return caret position. |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(0, 0).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(1, 1).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(1, 2).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(2, 2).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(13, 14).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_FALSE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ ui::Range(14, 15).ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ |
+ for (int i = 0; i <= kCompositionLength; ++i) { |
+ for (int j = 0; j <= kCompositionLength - i; ++j) { |
+ const ui::Range range(i, i + j); |
+ const gfx::Rect expected_rect = GetExpectedRect(kOrigin, |
+ kBoundsUnit, |
+ range, |
+ 0); |
+ const NSRange request_range = ui::Range( |
+ kCompositionStart + range.start(), |
+ kCompositionStart + range.end()).ToNSRange(); |
+ EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange( |
+ request_range, |
+ &rect, |
+ &actual_range)); |
+ EXPECT_EQ(ui::Range(request_range), ui::Range(actual_range)); |
+ EXPECT_EQ(expected_rect, gfx::Rect(NSRectToCGRect(rect))); |
+ } |
+ } |
+} |
+ |
+TEST_F(RenderWidgetHostViewMacTest, UpdateCompositionMultilineCase) { |
+ const gfx::Point kOrigin(10, 11); |
+ const gfx::Size kBoundsUnit(10, 20); |
+ NSRect rect; |
+ |
+ const int kCompositionLength = 30; |
+ std::vector<gfx::Rect> composition_bounds; |
+ const ui::Range kCompositionRange(0, kCompositionLength); |
+ // Set breaking point at 10 and 20. |
+ std::vector<size_t> break_points; |
+ break_points.push_back(10); |
+ break_points.push_back(20); |
+ GenerateCompositionRectArray(kOrigin, |
+ kBoundsUnit, |
+ kCompositionLength, |
+ break_points, |
+ &composition_bounds); |
+ rwhv_mac_->ImeCompositionRangeChanged(kCompositionRange, composition_bounds); |
+ |
+ // Range doesn't contain line breaking point. |
+ ui::Range range; |
+ range = ui::Range(5, 8); |
+ NSRange actual_range; |
+ EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_EQ(range, ui::Range(actual_range)); |
+ EXPECT_EQ( |
+ GetExpectedRect(kOrigin, kBoundsUnit, range, 0), |
+ gfx::Rect(NSRectToCGRect(rect))); |
+ range = ui::Range(15, 18); |
+ EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_EQ(range, ui::Range(actual_range)); |
+ EXPECT_EQ( |
+ GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(5, 8), 1), |
+ gfx::Rect(NSRectToCGRect(rect))); |
+ range = ui::Range(25, 28); |
+ EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_EQ(range, ui::Range(actual_range)); |
+ EXPECT_EQ( |
+ GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(5, 8), 2), |
+ gfx::Rect(NSRectToCGRect(rect))); |
+ |
+ // Range contains line breaking point. |
+ range = ui::Range(8, 12); |
+ EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_EQ(ui::Range(8, 10), ui::Range(actual_range)); |
+ EXPECT_EQ( |
+ GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(8, 10), 0), |
+ gfx::Rect(NSRectToCGRect(rect))); |
+ range = ui::Range(18, 22); |
+ EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_EQ(ui::Range(18, 20), ui::Range(actual_range)); |
+ EXPECT_EQ( |
+ GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(8, 10), 1), |
+ gfx::Rect(NSRectToCGRect(rect))); |
+ |
+ // Start point is line breaking point. |
+ range = ui::Range(10, 12); |
+ EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_EQ(ui::Range(10, 12), ui::Range(actual_range)); |
+ EXPECT_EQ( |
+ GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 2), 1), |
+ gfx::Rect(NSRectToCGRect(rect))); |
+ range = ui::Range(20, 22); |
+ EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_EQ(ui::Range(20, 22), ui::Range(actual_range)); |
+ EXPECT_EQ( |
+ GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 2), 2), |
+ gfx::Rect(NSRectToCGRect(rect))); |
+ |
+ // End point is line breaking point. |
+ range = ui::Range(5, 10); |
+ EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_EQ(ui::Range(5, 10), ui::Range(actual_range)); |
+ EXPECT_EQ( |
+ GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(5, 10), 0), |
+ gfx::Rect(NSRectToCGRect(rect))); |
+ range = ui::Range(15, 20); |
+ EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_EQ(ui::Range(15, 20), ui::Range(actual_range)); |
+ EXPECT_EQ( |
+ GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(5, 10), 1), |
+ gfx::Rect(NSRectToCGRect(rect))); |
+ |
+ // Start and end point are same line breaking point. |
+ range = ui::Range(10, 10); |
+ EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_EQ(ui::Range(10, 10), ui::Range(actual_range)); |
+ EXPECT_EQ( |
+ GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 0), 1), |
+ gfx::Rect(NSRectToCGRect(rect))); |
+ range = ui::Range(20, 20); |
+ EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_EQ(ui::Range(20, 20), ui::Range(actual_range)); |
+ EXPECT_EQ( |
+ GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 0), 2), |
+ gfx::Rect(NSRectToCGRect(rect))); |
+ |
+ // Start and end point are different line breaking point. |
+ range = ui::Range(10, 20); |
+ EXPECT_TRUE(rwhv_mac_->GetCachedFirstRectForCharacterRange(range.ToNSRange(), |
+ &rect, |
+ &actual_range)); |
+ EXPECT_EQ(ui::Range(10, 20), ui::Range(actual_range)); |
+ EXPECT_EQ( |
+ GetExpectedRect(kOrigin, kBoundsUnit, ui::Range(0, 10), 1), |
+ gfx::Rect(NSRectToCGRect(rect))); |
+} |
} // namespace content |