Index: ui/views/cocoa/bridged_native_widget_unittest.mm |
diff --git a/ui/views/cocoa/bridged_native_widget_unittest.mm b/ui/views/cocoa/bridged_native_widget_unittest.mm |
index 3f0d110643b817a4b8e6aeb20a4ec666d68d768d..fab3e4aa572aadcb9ef1e81bac8e4dd23929a07c 100644 |
--- a/ui/views/cocoa/bridged_native_widget_unittest.mm |
+++ b/ui/views/cocoa/bridged_native_widget_unittest.mm |
@@ -43,6 +43,14 @@ NSRange EmptyRange() { |
return NSMakeRange(NSNotFound, 0); |
} |
+// Changes NSRect to gfx::Rect and converts it from Apple's coordinate system |
+// (origin at bottom left) to coordinate system with origin at top left. |
+gfx::Rect ConvertCoordinateSystem(NSRect rect) { |
tapted
2015/12/17 08:42:20
gfx::ScreenRectFromNSRect
karandeepb
2015/12/18 09:15:06
Done.
|
+ NSRect screen_rect = [[NSScreen mainScreen] frame]; |
+ rect.origin.y = screen_rect.size.height - NSMaxY(rect); |
+ return gfx::Rect(NSRectToCGRect(rect)); |
+} |
+ |
} // namespace |
// Class to override -[NSWindow toggleFullScreen:] to a no-op. This simulates |
@@ -128,6 +136,8 @@ class BridgedNativeWidgetTestBase : public ui::CocoaTest { |
// Opacity defaults to "infer" which is usually updated by ViewsDelegate. |
init_params_.opacity = Widget::InitParams::OPAQUE_WINDOW; |
+ init_params_.bounds = gfx::Rect(100, 100, 100, 100); |
+ |
native_widget_mac_->GetWidget()->Init(init_params_); |
} |
@@ -174,6 +184,7 @@ BridgedNativeWidgetTest::~BridgedNativeWidgetTest() { |
void BridgedNativeWidgetTest::InstallTextField(const std::string& text) { |
Textfield* textfield = new Textfield(); |
textfield->SetText(ASCIIToUTF16(text)); |
+ textfield->SetBoundsRect(init_params_.bounds); |
view_->AddChildView(textfield); |
// Request focus so the InputMethod can dispatch events to the RootView, and |
@@ -505,6 +516,95 @@ TEST_F(BridgedNativeWidgetTest, TextInput_DeleteForward) { |
EXPECT_EQ_RANGE(NSMakeRange(0, 0), [ns_view_ selectedRange]); |
} |
+TEST_F(BridgedNativeWidgetTest, TextInput_FirstRectForCharacterRange) { |
+ InstallTextField(""); |
+ ui::TextInputClient* textInputClient = [ns_view_ textInputClient]; |
tapted
2015/12/17 08:42:20
hacker_style (eg. `client` for brevity too)
karandeepb
2015/12/18 09:15:06
Done.
|
+ NSRange range; |
+ NSRange actual_range = NSMakeRange(-1, -1); |
+ NSRect rect; |
+ gfx::Rect bounds; |
+ |
+ // Empty composition. |
+ rect = [ns_view_ firstRectForCharacterRange:NSMakeRange(0, 0) |
+ actualRange:&actual_range]; |
+ bounds = textInputClient->GetCaretBounds(); |
+ bounds.set_width(0); |
+ EXPECT_TRUE(ConvertCoordinateSystem(rect) == bounds); |
+ EXPECT_TRUE(NSEqualRanges(NSMakeRange(0, 0), actual_range)); |
+ |
+ rect = [ns_view_ firstRectForCharacterRange:NSMakeRange(1, 1) |
+ actualRange:&actual_range]; |
+ EXPECT_TRUE(ConvertCoordinateSystem(rect) == bounds); |
+ EXPECT_TRUE(NSEqualRanges(NSMakeRange(1, 0), actual_range)); |
+ |
+ // Set composition with caret before second character('e'). |
+ ui::CompositionText composition; |
+ composition.selection = gfx::Range(1); |
+ composition.text = base::UTF8ToUTF16("test_str"); |
+ size_t count = composition.text.length(); |
+ textInputClient->SetCompositionText(composition); |
+ |
+ range = NSMakeRange(1, 0); |
+ rect = [ns_view_ firstRectForCharacterRange:range actualRange:&actual_range]; |
+ bounds = textInputClient->GetCaretBounds(); |
+ bounds.set_width(0); |
+ EXPECT_TRUE(ConvertCoordinateSystem(rect) == bounds); |
+ EXPECT_TRUE(NSEqualRanges(range, actual_range)); |
+ |
+ range = NSMakeRange(2, 0); |
+ rect = [ns_view_ firstRectForCharacterRange:range actualRange:&actual_range]; |
+ EXPECT_FALSE(ConvertCoordinateSystem(rect) == bounds); |
+ EXPECT_TRUE(NSEqualRanges(range, actual_range)); |
+ |
+ // Query outside composition range. |
+ range = NSMakeRange(count + 1, 0); |
+ rect = [ns_view_ firstRectForCharacterRange:range actualRange:&actual_range]; |
+ EXPECT_TRUE(ConvertCoordinateSystem(rect) == bounds); |
+ EXPECT_TRUE(NSEqualRanges(range, actual_range)); |
+ |
+ std::vector<gfx::Rect> char_bounds, caret_bounds; |
tapted
2015/12/17 08:42:20
it's uncommon to declare multiple things on a line
karandeepb
2015/12/18 09:15:06
Done.
|
+ char_bounds.resize(count); |
+ caret_bounds.resize(count + 1); |
+ |
+ // Generate caret_bounds between different characters. |
+ for (size_t i = 0; i <= count; i++) { |
+ composition.selection = gfx::Range(i); |
+ textInputClient->SetCompositionText(composition); |
+ caret_bounds[i] = textInputClient->GetCaretBounds(); |
+ } |
+ |
+ // Generate individual character bounds from caret positions. |
+ for (size_t i = 0; i < count; i++) { |
+ char_bounds[i].set_origin(caret_bounds[i].origin()); |
+ char_bounds[i].set_width(caret_bounds[i + 1].x() - caret_bounds[i].x()); |
+ char_bounds[i].set_height( |
+ std::max(caret_bounds[i].height(), caret_bounds[i + 1].height())); |
+ } |
+ |
+ // Verify bounds for all valid ranges. |
+ for (size_t i = 0; i < count; i++) { |
+ for (size_t j = i + 1; j <= count; j++) { |
+ range = NSMakeRange(i, j - i); |
+ rect = |
+ [ns_view_ firstRectForCharacterRange:range actualRange:&actual_range]; |
+ |
+ bounds = gfx::Rect(); |
+ for (size_t k = i; k < j; k++) |
+ bounds.Union(char_bounds[k]); |
+ |
+ EXPECT_TRUE(ConvertCoordinateSystem(rect) == bounds); |
+ EXPECT_TRUE(NSEqualRanges(range, actual_range)); |
+ } |
+ } |
+ |
+ // Check NSZeroRect is returned if bridged_content_view has no textInputClient |
+ // available. |
+ [ns_view_ setTextInputClient:nil]; |
+ rect = [ns_view_ firstRectForCharacterRange:NSMakeRange(0, 0) |
+ actualRange:&actual_range]; |
+ EXPECT_TRUE(NSEqualRects(rect, NSZeroRect)); |
+} |
+ |
typedef BridgedNativeWidgetTestBase BridgedNativeWidgetSimulateFullscreenTest; |
// Simulate the notifications that AppKit would send out if a fullscreen |