| 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 56f911cb2bc6fb1821211455b6f3d7015f43049e..d289af521760fda2615f267ecd6be338ffe9dae0 100644
|
| --- a/ui/views/cocoa/bridged_native_widget_unittest.mm
|
| +++ b/ui/views/cocoa/bridged_native_widget_unittest.mm
|
| @@ -18,6 +18,7 @@
|
| #import "ui/base/cocoa/window_size_constants.h"
|
| #include "ui/base/ime/input_method.h"
|
| #import "ui/gfx/test/ui_cocoa_test_helper.h"
|
| +#import "ui/gfx/mac/coordinate_conversion.h"
|
| #import "ui/views/cocoa/bridged_content_view.h"
|
| #import "ui/views/cocoa/native_widget_mac_nswindow.h"
|
| #import "ui/views/cocoa/views_nswindow_delegate.h"
|
| @@ -44,6 +45,54 @@ NSRange EmptyRange() {
|
| return NSMakeRange(NSNotFound, 0);
|
| }
|
|
|
| +// Sets |composition_text| as the composition text with caret placed at
|
| +// |caret_pos| and updates |caret_range|.
|
| +void SetCompositionText(ui::TextInputClient* client,
|
| + const base::string16& composition_text,
|
| + const int caret_pos,
|
| + NSRange* caret_range) {
|
| + ui::CompositionText composition;
|
| + composition.selection = gfx::Range(caret_pos);
|
| + composition.text = composition_text;
|
| + client->SetCompositionText(composition);
|
| + if (caret_range)
|
| + *caret_range = NSMakeRange(caret_pos, 0);
|
| +}
|
| +
|
| +// Returns a zero width rectangle corresponding to current caret position.
|
| +gfx::Rect GetCaretBounds(const ui::TextInputClient* client) {
|
| + gfx::Rect caret_bounds = client->GetCaretBounds();
|
| + caret_bounds.set_width(0);
|
| + return caret_bounds;
|
| +}
|
| +
|
| +// Returns a zero width rectangle corresponding to caret bounds when it's placed
|
| +// at |caret_pos| and updates |caret_range|.
|
| +gfx::Rect GetCaretBoundsForPosition(ui::TextInputClient* client,
|
| + const base::string16& composition_text,
|
| + const int caret_pos,
|
| + NSRange* caret_range) {
|
| + SetCompositionText(client, composition_text, caret_pos, caret_range);
|
| + return GetCaretBounds(client);
|
| +}
|
| +
|
| +// Returns the expected boundary rectangle for characters of |composition_text|
|
| +// within the |query_range|.
|
| +gfx::Rect GetExpectedBoundsForRange(ui::TextInputClient* client,
|
| + const base::string16& composition_text,
|
| + NSRange query_range) {
|
| + gfx::Rect left_caret = GetCaretBoundsForPosition(
|
| + client, composition_text, query_range.location, nullptr);
|
| + gfx::Rect right_caret = GetCaretBoundsForPosition(
|
| + client, composition_text, query_range.location + query_range.length,
|
| + nullptr);
|
| +
|
| + // The expected bounds correspond to the area between the left and right caret
|
| + // positions.
|
| + return gfx::Rect(left_caret.x(), left_caret.y(),
|
| + right_caret.x() - left_caret.x(), left_caret.height());
|
| +}
|
| +
|
| } // namespace
|
|
|
| // Class to override -[NSWindow toggleFullScreen:] to a no-op. This simulates
|
| @@ -129,6 +178,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_);
|
| }
|
|
|
| @@ -185,6 +236,7 @@ void BridgedNativeWidgetTest::InstallTextField(
|
| textfield->SetTextInputType(text_input_type);
|
| view_->RemoveAllChildViews(true);
|
| view_->AddChildView(textfield);
|
| + textfield->SetBoundsRect(init_params_.bounds);
|
|
|
| // Request focus so the InputMethod can dispatch events to the RootView, and
|
| // have them delivered to the textfield. Note that focusing a textfield
|
| @@ -533,6 +585,96 @@ TEST_F(BridgedNativeWidgetTest, TextInput_DeleteForward) {
|
| EXPECT_EQ_RANGE(NSMakeRange(0, 0), [ns_view_ selectedRange]);
|
| }
|
|
|
| +// Test firstRectForCharacterRange:actualRange for cases where query range is
|
| +// empty or outside composition range.
|
| +TEST_F(BridgedNativeWidgetTest, TextInput_FirstRectForCharacterRange_Caret) {
|
| + InstallTextField("");
|
| + ui::TextInputClient* client = [ns_view_ textInputClient];
|
| +
|
| + // No composition. Ensure bounds and range corresponding to the current caret
|
| + // position are returned.
|
| + // Initially selection range will be [0, 0].
|
| + NSRange caret_range = NSMakeRange(0, 0);
|
| + NSRange query_range = NSMakeRange(1, 1);
|
| + NSRange actual_range;
|
| + NSRect rect = [ns_view_ firstRectForCharacterRange:query_range
|
| + actualRange:&actual_range];
|
| + EXPECT_EQ(GetCaretBounds(client), gfx::ScreenRectFromNSRect(rect));
|
| + EXPECT_EQ_RANGE(caret_range, actual_range);
|
| +
|
| + // Set composition with caret before second character ('e').
|
| + const base::string16 test_string = base::ASCIIToUTF16("test_str");
|
| + const size_t kTextLength = 8;
|
| + SetCompositionText(client, test_string, 1, &caret_range);
|
| +
|
| + // Test bounds returned for empty ranges within composition range. As per
|
| + // Apple's documentation for firstRectForCharacterRange:actualRange:, for an
|
| + // empty query range, the returned rectangle should coincide with the
|
| + // insertion point and have zero width. However in our implementation, if the
|
| + // empty query range lies within the composition range, we return a zero width
|
| + // rectangle corresponding to the query range location.
|
| +
|
| + // Test bounds returned for empty range before second character ('e') are same
|
| + // as caret bounds when placed before second character.
|
| + query_range = NSMakeRange(1, 0);
|
| + rect = [ns_view_ firstRectForCharacterRange:query_range
|
| + actualRange:&actual_range];
|
| + EXPECT_EQ(GetCaretBoundsForPosition(client, test_string, 1, &caret_range),
|
| + gfx::ScreenRectFromNSRect(rect));
|
| + EXPECT_EQ_RANGE(query_range, actual_range);
|
| +
|
| + // Test bounds returned for empty range after the composition text are same as
|
| + // caret bounds when placed after the composition text.
|
| + query_range = NSMakeRange(kTextLength, 0);
|
| + rect = [ns_view_ firstRectForCharacterRange:query_range
|
| + actualRange:&actual_range];
|
| + EXPECT_NE(GetCaretBoundsForPosition(client, test_string, 1, &caret_range),
|
| + gfx::ScreenRectFromNSRect(rect));
|
| + EXPECT_EQ(
|
| + GetCaretBoundsForPosition(client, test_string, kTextLength, &caret_range),
|
| + gfx::ScreenRectFromNSRect(rect));
|
| + EXPECT_EQ_RANGE(query_range, actual_range);
|
| +
|
| + // Query outside composition range. Ensure bounds and range corresponding to
|
| + // the current caret position are returned.
|
| + query_range = NSMakeRange(kTextLength + 1, 0);
|
| + rect = [ns_view_ firstRectForCharacterRange:query_range
|
| + actualRange:&actual_range];
|
| + EXPECT_EQ(GetCaretBounds(client), gfx::ScreenRectFromNSRect(rect));
|
| + EXPECT_EQ_RANGE(caret_range, actual_range);
|
| +
|
| + // Make sure not crashing by passing null pointer instead of actualRange.
|
| + rect = [ns_view_ firstRectForCharacterRange:query_range actualRange:nullptr];
|
| +}
|
| +
|
| +// Test firstRectForCharacterRange:actualRange for non-empty query ranges within
|
| +// the composition range.
|
| +TEST_F(BridgedNativeWidgetTest, TextInput_FirstRectForCharacterRange) {
|
| + InstallTextField("");
|
| + ui::TextInputClient* client = [ns_view_ textInputClient];
|
| +
|
| + const base::string16 kTestString = base::ASCIIToUTF16("test_str");
|
| + const size_t kTextLength = 8;
|
| + SetCompositionText(client, kTestString, 1, nullptr);
|
| +
|
| + // Query bounds for the whole composition string.
|
| + NSRange query_range = NSMakeRange(0, kTextLength);
|
| + NSRange actual_range;
|
| + NSRect rect = [ns_view_ firstRectForCharacterRange:query_range
|
| + actualRange:&actual_range];
|
| + EXPECT_EQ(GetExpectedBoundsForRange(client, kTestString, query_range),
|
| + gfx::ScreenRectFromNSRect(rect));
|
| + EXPECT_EQ_RANGE(query_range, actual_range);
|
| +
|
| + // Query bounds for the substring "est_".
|
| + query_range = NSMakeRange(1, 4);
|
| + rect = [ns_view_ firstRectForCharacterRange:query_range
|
| + actualRange:&actual_range];
|
| + EXPECT_EQ(GetExpectedBoundsForRange(client, kTestString, query_range),
|
| + gfx::ScreenRectFromNSRect(rect));
|
| + EXPECT_EQ_RANGE(query_range, actual_range);
|
| +}
|
| +
|
| typedef BridgedNativeWidgetTestBase BridgedNativeWidgetSimulateFullscreenTest;
|
|
|
| // Simulate the notifications that AppKit would send out if a fullscreen
|
|
|