Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "ui/views/cocoa/bridged_native_widget.h" | 5 #import "ui/views/cocoa/bridged_native_widget.h" |
| 6 | 6 |
| 7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 200 void InstallTextField(const std::string& text, | 200 void InstallTextField(const std::string& text, |
| 201 ui::TextInputType text_input_type); | 201 ui::TextInputType text_input_type); |
| 202 | 202 |
| 203 // Install a textfield with input type ui::TEXT_INPUT_TYPE_TEXT in the view | 203 // Install a textfield with input type ui::TEXT_INPUT_TYPE_TEXT in the view |
| 204 // hierarchy and make it the text input client. | 204 // hierarchy and make it the text input client. |
| 205 void InstallTextField(const std::string& text); | 205 void InstallTextField(const std::string& text); |
| 206 | 206 |
| 207 // Returns the current text as std::string. | 207 // Returns the current text as std::string. |
| 208 std::string GetText(); | 208 std::string GetText(); |
| 209 | 209 |
| 210 // Set the selection range for the installed textfield. | |
| 211 void SetSelectionRange(const gfx::Range& range); | |
| 212 | |
| 210 // testing::Test: | 213 // testing::Test: |
| 211 void SetUp() override; | 214 void SetUp() override; |
| 212 void TearDown() override; | 215 void TearDown() override; |
| 213 | 216 |
| 214 protected: | 217 protected: |
| 218 // Test delete to beginning of line or paragraph based on |sel|. | |
| 219 void TestDeleteBeginning(SEL sel); | |
| 220 | |
| 221 // Test delete to end of line or paragraph based on |sel|. | |
| 222 void TestDeleteEnd(SEL sel); | |
| 223 | |
| 215 std::unique_ptr<views::View> view_; | 224 std::unique_ptr<views::View> view_; |
| 216 BridgedContentView* ns_view_; // Weak. Owned by bridge(). | 225 BridgedContentView* ns_view_; // Weak. Owned by bridge(). |
| 217 base::MessageLoopForUI message_loop_; | 226 base::MessageLoopForUI message_loop_; |
| 218 | 227 |
| 219 private: | 228 private: |
| 220 DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetTest); | 229 DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetTest); |
| 221 }; | 230 }; |
| 222 | 231 |
| 223 BridgedNativeWidgetTest::BridgedNativeWidgetTest() { | 232 BridgedNativeWidgetTest::BridgedNativeWidgetTest() { |
| 224 } | 233 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 248 InstallTextField(text, ui::TEXT_INPUT_TYPE_TEXT); | 257 InstallTextField(text, ui::TEXT_INPUT_TYPE_TEXT); |
| 249 } | 258 } |
| 250 | 259 |
| 251 std::string BridgedNativeWidgetTest::GetText() { | 260 std::string BridgedNativeWidgetTest::GetText() { |
| 252 NSRange range = NSMakeRange(0, NSUIntegerMax); | 261 NSRange range = NSMakeRange(0, NSUIntegerMax); |
| 253 NSAttributedString* text = | 262 NSAttributedString* text = |
| 254 [ns_view_ attributedSubstringForProposedRange:range actualRange:NULL]; | 263 [ns_view_ attributedSubstringForProposedRange:range actualRange:NULL]; |
| 255 return SysNSStringToUTF8([text string]); | 264 return SysNSStringToUTF8([text string]); |
| 256 } | 265 } |
| 257 | 266 |
| 267 void BridgedNativeWidgetTest::SetSelectionRange(const gfx::Range& range) { | |
| 268 ui::TextInputClient* client = [ns_view_ textInputClient]; | |
| 269 client->SetSelectionRange(range); | |
| 270 } | |
| 271 | |
| 258 void BridgedNativeWidgetTest::SetUp() { | 272 void BridgedNativeWidgetTest::SetUp() { |
| 259 BridgedNativeWidgetTestBase::SetUp(); | 273 BridgedNativeWidgetTestBase::SetUp(); |
| 260 | 274 |
| 261 view_.reset(new views::internal::RootView(widget_.get())); | 275 view_.reset(new views::internal::RootView(widget_.get())); |
| 262 base::scoped_nsobject<NSWindow> window([test_window() retain]); | 276 base::scoped_nsobject<NSWindow> window([test_window() retain]); |
| 263 | 277 |
| 264 // BridgedNativeWidget expects to be initialized with a hidden (deferred) | 278 // BridgedNativeWidget expects to be initialized with a hidden (deferred) |
| 265 // window. | 279 // window. |
| 266 [window orderOut:nil]; | 280 [window orderOut:nil]; |
| 267 EXPECT_FALSE([window delegate]); | 281 EXPECT_FALSE([window delegate]); |
| 268 bridge()->Init(window, init_params_); | 282 bridge()->Init(window, init_params_); |
| 269 | 283 |
| 270 // The delegate should exist before setting the root view. | 284 // The delegate should exist before setting the root view. |
| 271 EXPECT_TRUE([window delegate]); | 285 EXPECT_TRUE([window delegate]); |
| 272 bridge()->SetRootView(view_.get()); | 286 bridge()->SetRootView(view_.get()); |
| 273 ns_view_ = bridge()->ns_view(); | 287 ns_view_ = bridge()->ns_view(); |
| 274 | 288 |
| 275 // Pretend it has been shown via NativeWidgetMac::Show(). | 289 // Pretend it has been shown via NativeWidgetMac::Show(). |
| 276 [window orderFront:nil]; | 290 [window orderFront:nil]; |
| 277 [test_window() makePretendKeyWindowAndSetFirstResponder:bridge()->ns_view()]; | 291 [test_window() makePretendKeyWindowAndSetFirstResponder:bridge()->ns_view()]; |
| 278 } | 292 } |
| 279 | 293 |
| 280 void BridgedNativeWidgetTest::TearDown() { | 294 void BridgedNativeWidgetTest::TearDown() { |
| 281 if (bridge()) | 295 if (bridge()) |
| 282 bridge()->SetRootView(nullptr); | 296 bridge()->SetRootView(nullptr); |
| 283 view_.reset(); | 297 view_.reset(); |
| 284 BridgedNativeWidgetTestBase::TearDown(); | 298 BridgedNativeWidgetTestBase::TearDown(); |
| 285 } | 299 } |
| 286 | 300 |
| 301 void BridgedNativeWidgetTest::TestDeleteBeginning(SEL sel) { | |
| 302 InstallTextField("foo bar baz"); | |
| 303 EXPECT_EQ_RANGE(NSMakeRange(11, 0), [ns_view_ selectedRange]); | |
| 304 | |
| 305 // Move the caret to the beginning of the line. | |
| 306 SetSelectionRange(gfx::Range(0)); | |
| 307 // Verify no deletion takes place. | |
| 308 [ns_view_ doCommandBySelector:sel]; | |
| 309 EXPECT_EQ("foo bar baz", GetText()); | |
| 310 EXPECT_EQ_RANGE(NSMakeRange(0, 0), [ns_view_ selectedRange]); | |
| 311 | |
| 312 // Move the caret as- "foo| bar baz". | |
| 313 SetSelectionRange(gfx::Range(3, 3)); | |
| 314 [ns_view_ doCommandBySelector:sel]; | |
| 315 // Verify state is "| bar baz". | |
| 316 EXPECT_EQ(" bar baz", GetText()); | |
| 317 EXPECT_EQ_RANGE(NSMakeRange(0, 0), [ns_view_ selectedRange]); | |
| 318 | |
| 319 // Make a selection as- " bar |baz|". | |
| 320 SetSelectionRange(gfx::Range(5, 8)); | |
| 321 [ns_view_ doCommandBySelector:sel]; | |
| 322 // Verify only the selection is deleted so that the state is " bar |". | |
| 323 EXPECT_EQ(" bar ", GetText()); | |
| 324 EXPECT_EQ_RANGE(NSMakeRange(5, 0), [ns_view_ selectedRange]); | |
| 325 } | |
| 326 | |
| 327 void BridgedNativeWidgetTest::TestDeleteEnd(SEL sel) { | |
| 328 InstallTextField("foo bar baz"); | |
| 329 EXPECT_EQ_RANGE(NSMakeRange(11, 0), [ns_view_ selectedRange]); | |
| 330 | |
| 331 // Caret is at the end of the line. Verify no deletion takes place. | |
| 332 [ns_view_ doCommandBySelector:sel]; | |
| 333 EXPECT_EQ("foo bar baz", GetText()); | |
| 334 EXPECT_EQ_RANGE(NSMakeRange(11, 0), [ns_view_ selectedRange]); | |
| 335 | |
| 336 // Move the caret as- "foo bar| baz". | |
| 337 SetSelectionRange(gfx::Range(7, 7)); | |
| 338 [ns_view_ doCommandBySelector:sel]; | |
| 339 // Verify state is "foo bar|". | |
| 340 EXPECT_EQ("foo bar", GetText()); | |
| 341 EXPECT_EQ_RANGE(NSMakeRange(7, 0), [ns_view_ selectedRange]); | |
| 342 | |
| 343 // Make a selection as- "|foo |bar". | |
| 344 SetSelectionRange(gfx::Range(0, 4)); | |
| 345 [ns_view_ doCommandBySelector:sel]; | |
| 346 // Verify only the selection is deleted so that the state is "|bar". | |
| 347 EXPECT_EQ("bar", GetText()); | |
| 348 EXPECT_EQ_RANGE(NSMakeRange(0, 0), [ns_view_ selectedRange]); | |
| 349 } | |
| 350 | |
| 287 // The TEST_VIEW macro expects the view it's testing to have a superview. In | 351 // The TEST_VIEW macro expects the view it's testing to have a superview. In |
| 288 // these tests, the NSView bridge is a contentView, at the root. These mimic | 352 // these tests, the NSView bridge is a contentView, at the root. These mimic |
| 289 // what TEST_VIEW usually does. | 353 // what TEST_VIEW usually does. |
| 290 TEST_F(BridgedNativeWidgetTest, BridgedNativeWidgetTest_TestViewAddRemove) { | 354 TEST_F(BridgedNativeWidgetTest, BridgedNativeWidgetTest_TestViewAddRemove) { |
| 291 base::scoped_nsobject<BridgedContentView> view([bridge()->ns_view() retain]); | 355 base::scoped_nsobject<BridgedContentView> view([bridge()->ns_view() retain]); |
| 292 EXPECT_NSEQ([test_window() contentView], view); | 356 EXPECT_NSEQ([test_window() contentView], view); |
| 293 EXPECT_NSEQ(test_window(), [view window]); | 357 EXPECT_NSEQ(test_window(), [view window]); |
| 294 | 358 |
| 295 // The superview of a contentView is an NSNextStepFrame. | 359 // The superview of a contentView is an NSNextStepFrame. |
| 296 EXPECT_TRUE([view superview]); | 360 EXPECT_TRUE([view superview]); |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 578 EXPECT_EQ("a", GetText()); | 642 EXPECT_EQ("a", GetText()); |
| 579 EXPECT_EQ_RANGE(NSMakeRange(1, 0), [ns_view_ selectedRange]); | 643 EXPECT_EQ_RANGE(NSMakeRange(1, 0), [ns_view_ selectedRange]); |
| 580 | 644 |
| 581 // Should succeed after moving left first. | 645 // Should succeed after moving left first. |
| 582 [ns_view_ doCommandBySelector:@selector(moveLeft:)]; | 646 [ns_view_ doCommandBySelector:@selector(moveLeft:)]; |
| 583 [ns_view_ doCommandBySelector:@selector(deleteForward:)]; | 647 [ns_view_ doCommandBySelector:@selector(deleteForward:)]; |
| 584 EXPECT_EQ("", GetText()); | 648 EXPECT_EQ("", GetText()); |
| 585 EXPECT_EQ_RANGE(NSMakeRange(0, 0), [ns_view_ selectedRange]); | 649 EXPECT_EQ_RANGE(NSMakeRange(0, 0), [ns_view_ selectedRange]); |
| 586 } | 650 } |
| 587 | 651 |
| 652 TEST_F(BridgedNativeWidgetTest, TextInput_DeleteWordForward) { | |
|
tapted
2016/04/26 05:46:55
I think we should try to make these cross-platform
karandeepb
2016/04/29 01:52:48
Added a cross-platform test here-https://coderevie
tapted
2016/04/29 04:15:39
That's not really testing the beginning/end of lin
| |
| 653 InstallTextField("foo bar baz"); | |
| 654 EXPECT_EQ_RANGE(NSMakeRange(11, 0), [ns_view_ selectedRange]); | |
| 655 | |
| 656 // Caret is at the end of the line. Verify no deletion takes place. | |
| 657 [ns_view_ doCommandBySelector:@selector(deleteWordForward:)]; | |
| 658 EXPECT_EQ("foo bar baz", GetText()); | |
| 659 EXPECT_EQ_RANGE(NSMakeRange(11, 0), [ns_view_ selectedRange]); | |
| 660 | |
| 661 // Move the caret as- "foo b|ar baz". | |
| 662 SetSelectionRange(gfx::Range(5, 5)); | |
| 663 [ns_view_ doCommandBySelector:@selector(deleteWordForward:)]; | |
| 664 // Verify state is "foo b| baz" | |
| 665 EXPECT_EQ("foo b baz", GetText()); | |
| 666 EXPECT_EQ_RANGE(NSMakeRange(5, 0), [ns_view_ selectedRange]); | |
| 667 | |
| 668 // Make a selection as- "|fo|o b baz". | |
| 669 SetSelectionRange(gfx::Range(0, 2)); | |
| 670 [ns_view_ doCommandBySelector:@selector(deleteWordForward:)]; | |
| 671 // Verify only the selection is deleted and state is "|o b baz". | |
| 672 EXPECT_EQ("o b baz", GetText()); | |
| 673 EXPECT_EQ_RANGE(NSMakeRange(0, 0), [ns_view_ selectedRange]); | |
| 674 } | |
| 675 | |
| 676 TEST_F(BridgedNativeWidgetTest, TextInput_DeleteWordBackward) { | |
| 677 InstallTextField("foo bar baz"); | |
| 678 EXPECT_EQ_RANGE(NSMakeRange(11, 0), [ns_view_ selectedRange]); | |
| 679 | |
| 680 // Move the caret to the beginning of the line. | |
| 681 SetSelectionRange(gfx::Range(0)); | |
| 682 // Verify no deletion takes place. | |
| 683 [ns_view_ doCommandBySelector:@selector(deleteWordBackward:)]; | |
| 684 EXPECT_EQ("foo bar baz", GetText()); | |
| 685 EXPECT_EQ_RANGE(NSMakeRange(0, 0), [ns_view_ selectedRange]); | |
| 686 | |
| 687 // Move the caret as- "foo ba|r baz". | |
| 688 SetSelectionRange(gfx::Range(6, 6)); | |
| 689 [ns_view_ doCommandBySelector:@selector(deleteWordBackward:)]; | |
| 690 // Verify state is "foo |r baz". | |
| 691 EXPECT_EQ("foo r baz", GetText()); | |
| 692 EXPECT_EQ_RANGE(NSMakeRange(4, 0), [ns_view_ selectedRange]); | |
| 693 | |
| 694 // Make a selection as- "f|oo r b|az". | |
| 695 SetSelectionRange(gfx::Range(1, 7)); | |
| 696 [ns_view_ doCommandBySelector:@selector(deleteWordBackward:)]; | |
| 697 // Verify only the selection is deleted and state is "f|az" | |
| 698 EXPECT_EQ("faz", GetText()); | |
| 699 EXPECT_EQ_RANGE(NSMakeRange(1, 0), [ns_view_ selectedRange]); | |
| 700 } | |
| 701 | |
| 702 TEST_F(BridgedNativeWidgetTest, TextInput_DeleteToBeginningOfLine) { | |
| 703 TestDeleteBeginning(@selector(deleteToBeginningOfLine:)); | |
| 704 } | |
| 705 | |
| 706 TEST_F(BridgedNativeWidgetTest, TextInput_DeleteToEndOfLine) { | |
| 707 TestDeleteEnd(@selector(deleteToEndOfLine:)); | |
| 708 } | |
| 709 | |
| 710 TEST_F(BridgedNativeWidgetTest, TextInput_DeleteToBeginningOfParagraph) { | |
| 711 TestDeleteBeginning(@selector(deleteToBeginningOfParagraph:)); | |
| 712 } | |
| 713 | |
| 714 TEST_F(BridgedNativeWidgetTest, TextInput_DeleteToEndOfParagraph) { | |
| 715 TestDeleteEnd(@selector(deleteToEndOfParagraph:)); | |
| 716 } | |
| 717 | |
| 588 // Test firstRectForCharacterRange:actualRange for cases where query range is | 718 // Test firstRectForCharacterRange:actualRange for cases where query range is |
| 589 // empty or outside composition range. | 719 // empty or outside composition range. |
| 590 TEST_F(BridgedNativeWidgetTest, TextInput_FirstRectForCharacterRange_Caret) { | 720 TEST_F(BridgedNativeWidgetTest, TextInput_FirstRectForCharacterRange_Caret) { |
| 591 InstallTextField(""); | 721 InstallTextField(""); |
| 592 ui::TextInputClient* client = [ns_view_ textInputClient]; | 722 ui::TextInputClient* client = [ns_view_ textInputClient]; |
| 593 | 723 |
| 594 // No composition. Ensure bounds and range corresponding to the current caret | 724 // No composition. Ensure bounds and range corresponding to the current caret |
| 595 // position are returned. | 725 // position are returned. |
| 596 // Initially selection range will be [0, 0]. | 726 // Initially selection range will be [0, 0]. |
| 597 NSRange caret_range = NSMakeRange(0, 0); | 727 NSRange caret_range = NSMakeRange(0, 0); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 743 [center postNotificationName:NSWindowDidExitFullScreenNotification | 873 [center postNotificationName:NSWindowDidExitFullScreenNotification |
| 744 object:window]; | 874 object:window]; |
| 745 EXPECT_EQ(1, [window ignoredToggleFullScreenCount]); // No change. | 875 EXPECT_EQ(1, [window ignoredToggleFullScreenCount]); // No change. |
| 746 EXPECT_FALSE(bridge()->target_fullscreen_state()); | 876 EXPECT_FALSE(bridge()->target_fullscreen_state()); |
| 747 | 877 |
| 748 widget_->CloseNow(); | 878 widget_->CloseNow(); |
| 749 } | 879 } |
| 750 | 880 |
| 751 } // namespace test | 881 } // namespace test |
| 752 } // namespace views | 882 } // namespace views |
| OLD | NEW |