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 #import "base/mac/foundation_util.h" | 9 #import "base/mac/foundation_util.h" |
| 10 #import "base/mac/mac_util.h" | 10 #import "base/mac/mac_util.h" |
| 11 #import "base/mac/sdk_forward_declarations.h" | 11 #import "base/mac/sdk_forward_declarations.h" |
| 12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 13 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
| 14 #include "base/strings/sys_string_conversions.h" | 14 #include "base/strings/sys_string_conversions.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 16 #import "testing/gtest_mac.h" | 16 #import "testing/gtest_mac.h" |
| 17 #import "ui/base/cocoa/window_size_constants.h" | 17 #import "ui/base/cocoa/window_size_constants.h" |
| 18 #include "ui/base/ime/input_method.h" | 18 #include "ui/base/ime/input_method.h" |
| 19 #import "ui/gfx/test/ui_cocoa_test_helper.h" | 19 #import "ui/gfx/test/ui_cocoa_test_helper.h" |
| 20 #include "ui/gfx/mac/coordinate_conversion.h" | |
| 20 #import "ui/views/cocoa/bridged_content_view.h" | 21 #import "ui/views/cocoa/bridged_content_view.h" |
| 21 #import "ui/views/cocoa/native_widget_mac_nswindow.h" | 22 #import "ui/views/cocoa/native_widget_mac_nswindow.h" |
| 22 #import "ui/views/cocoa/views_nswindow_delegate.h" | 23 #import "ui/views/cocoa/views_nswindow_delegate.h" |
| 23 #include "ui/views/controls/textfield/textfield.h" | 24 #include "ui/views/controls/textfield/textfield.h" |
| 24 #include "ui/views/view.h" | 25 #include "ui/views/view.h" |
| 25 #include "ui/views/widget/native_widget_mac.h" | 26 #include "ui/views/widget/native_widget_mac.h" |
| 26 #include "ui/views/widget/root_view.h" | 27 #include "ui/views/widget/root_view.h" |
| 27 #include "ui/views/widget/widget.h" | 28 #include "ui/views/widget/widget.h" |
| 28 #include "ui/views/widget/widget_observer.h" | 29 #include "ui/views/widget/widget_observer.h" |
| 29 | 30 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 121 // before the tests covering the Init() flow are ready to do that. | 122 // before the tests covering the Init() flow are ready to do that. |
| 122 init_params_.type = Widget::InitParams::TYPE_WINDOW_FRAMELESS; | 123 init_params_.type = Widget::InitParams::TYPE_WINDOW_FRAMELESS; |
| 123 | 124 |
| 124 // To control the lifetime without an actual window that must be closed, | 125 // To control the lifetime without an actual window that must be closed, |
| 125 // tests in this file need to use WIDGET_OWNS_NATIVE_WIDGET. | 126 // tests in this file need to use WIDGET_OWNS_NATIVE_WIDGET. |
| 126 init_params_.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 127 init_params_.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 127 | 128 |
| 128 // Opacity defaults to "infer" which is usually updated by ViewsDelegate. | 129 // Opacity defaults to "infer" which is usually updated by ViewsDelegate. |
| 129 init_params_.opacity = Widget::InitParams::OPAQUE_WINDOW; | 130 init_params_.opacity = Widget::InitParams::OPAQUE_WINDOW; |
| 130 | 131 |
| 132 init_params_.bounds = gfx::Rect(100, 100, 100, 100); | |
| 133 | |
| 131 native_widget_mac_->GetWidget()->Init(init_params_); | 134 native_widget_mac_->GetWidget()->Init(init_params_); |
| 132 } | 135 } |
| 133 | 136 |
| 134 protected: | 137 protected: |
| 135 scoped_ptr<Widget> widget_; | 138 scoped_ptr<Widget> widget_; |
| 136 MockNativeWidgetMac* native_widget_mac_; // Weak. Owned by |widget_|. | 139 MockNativeWidgetMac* native_widget_mac_; // Weak. Owned by |widget_|. |
| 137 | 140 |
| 138 // Make the InitParams available to tests to cover initialization codepaths. | 141 // Make the InitParams available to tests to cover initialization codepaths. |
| 139 Widget::InitParams init_params_; | 142 Widget::InitParams init_params_; |
| 140 }; | 143 }; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 167 | 170 |
| 168 BridgedNativeWidgetTest::BridgedNativeWidgetTest() { | 171 BridgedNativeWidgetTest::BridgedNativeWidgetTest() { |
| 169 } | 172 } |
| 170 | 173 |
| 171 BridgedNativeWidgetTest::~BridgedNativeWidgetTest() { | 174 BridgedNativeWidgetTest::~BridgedNativeWidgetTest() { |
| 172 } | 175 } |
| 173 | 176 |
| 174 void BridgedNativeWidgetTest::InstallTextField(const std::string& text) { | 177 void BridgedNativeWidgetTest::InstallTextField(const std::string& text) { |
| 175 Textfield* textfield = new Textfield(); | 178 Textfield* textfield = new Textfield(); |
| 176 textfield->SetText(ASCIIToUTF16(text)); | 179 textfield->SetText(ASCIIToUTF16(text)); |
| 180 textfield->SetBoundsRect(init_params_.bounds); | |
| 177 view_->AddChildView(textfield); | 181 view_->AddChildView(textfield); |
| 178 | 182 |
| 179 // Request focus so the InputMethod can dispatch events to the RootView, and | 183 // Request focus so the InputMethod can dispatch events to the RootView, and |
| 180 // have them delivered to the textfield. Note that focusing a textfield | 184 // have them delivered to the textfield. Note that focusing a textfield |
| 181 // schedules a task to flash the cursor, so this requires |message_loop_|. | 185 // schedules a task to flash the cursor, so this requires |message_loop_|. |
| 182 textfield->RequestFocus(); | 186 textfield->RequestFocus(); |
| 183 | 187 |
| 184 [ns_view_ setTextInputClient:textfield]; | 188 [ns_view_ setTextInputClient:textfield]; |
| 185 } | 189 } |
| 186 | 190 |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 498 EXPECT_EQ("a", GetText()); | 502 EXPECT_EQ("a", GetText()); |
| 499 EXPECT_EQ_RANGE(NSMakeRange(1, 0), [ns_view_ selectedRange]); | 503 EXPECT_EQ_RANGE(NSMakeRange(1, 0), [ns_view_ selectedRange]); |
| 500 | 504 |
| 501 // Should succeed after moving left first. | 505 // Should succeed after moving left first. |
| 502 [ns_view_ doCommandBySelector:@selector(moveLeft:)]; | 506 [ns_view_ doCommandBySelector:@selector(moveLeft:)]; |
| 503 [ns_view_ doCommandBySelector:@selector(deleteForward:)]; | 507 [ns_view_ doCommandBySelector:@selector(deleteForward:)]; |
| 504 EXPECT_EQ("", GetText()); | 508 EXPECT_EQ("", GetText()); |
| 505 EXPECT_EQ_RANGE(NSMakeRange(0, 0), [ns_view_ selectedRange]); | 509 EXPECT_EQ_RANGE(NSMakeRange(0, 0), [ns_view_ selectedRange]); |
| 506 } | 510 } |
| 507 | 511 |
| 512 TEST_F(BridgedNativeWidgetTest, TextInput_FirstRectForCharacterRange) { | |
|
tapted
2015/12/22 02:33:58
nit: brief comment summarising what's being tested
karandeepb
2015/12/29 07:21:16
Done.
| |
| 513 InstallTextField(""); | |
| 514 ui::TextInputClient* client = [ns_view_ textInputClient]; | |
| 515 NSRange range; | |
|
tapted
2015/12/22 02:33:58
move declarations closer to first use. Typically i
karandeepb
2015/12/29 07:21:15
Done.
| |
| 516 NSRange actual_range = NSMakeRange(-1, -1); | |
|
tapted
2015/12/22 02:33:58
NSMakeRange takes unsigned integers. An invalid ra
karandeepb
2015/12/29 07:21:16
Done.
| |
| 517 NSRect rect; | |
| 518 gfx::Rect bounds; | |
| 519 | |
| 520 // Empty composition. | |
| 521 rect = [ns_view_ firstRectForCharacterRange:NSMakeRange(0, 0) | |
| 522 actualRange:&actual_range]; | |
| 523 bounds = client->GetCaretBounds(); | |
|
tapted
2015/12/22 02:33:58
Can this be a constant in the test? (if it depends
karandeepb
2015/12/29 07:21:16
Not quite sure how to make this a constant, since
| |
| 524 bounds.set_width(0); | |
| 525 EXPECT_TRUE(gfx::ScreenRectFromNSRect(rect) == bounds); | |
|
tapted
2015/12/22 02:33:58
EXPECT_EQ should work for gfx::Bounds, and give be
karandeepb
2015/12/29 07:21:16
Done.
| |
| 526 EXPECT_TRUE(NSEqualRanges(NSMakeRange(0, 0), actual_range)); | |
|
tapted
2015/12/22 02:33:58
EXPECT_EQ_RANGE. More below
karandeepb
2015/12/29 07:21:15
Done.
| |
| 527 | |
| 528 rect = [ns_view_ firstRectForCharacterRange:NSMakeRange(1, 1) | |
| 529 actualRange:&actual_range]; | |
| 530 EXPECT_TRUE(gfx::ScreenRectFromNSRect(rect) == bounds); | |
| 531 EXPECT_TRUE(NSEqualRanges(NSMakeRange(1, 0), actual_range)); | |
| 532 | |
|
tapted
2015/12/22 02:33:58
It might be good to split up the test here into se
karandeepb
2015/12/29 07:21:15
Done.
| |
| 533 // Set composition with caret before second character('e'). | |
|
tapted
2015/12/22 02:33:58
nit: space before open paren
karandeepb
2015/12/29 07:21:16
Done.
| |
| 534 ui::CompositionText composition; | |
| 535 composition.selection = gfx::Range(1); | |
| 536 composition.text = base::UTF8ToUTF16("test_str"); | |
|
tapted
2015/12/22 02:33:58
nit: ASCIIToUTF16 is what usually gets used for st
karandeepb
2015/12/29 07:21:16
Done.
| |
| 537 size_t count = composition.text.length(); | |
|
tapted
2015/12/22 02:33:58
`count` is pretty vague here. It also breaks the l
karandeepb
2015/12/29 07:21:15
Done.
| |
| 538 client->SetCompositionText(composition); | |
| 539 bounds = client->GetCaretBounds(); | |
| 540 bounds.set_width(0); | |
| 541 | |
| 542 range = NSMakeRange(1, 0); | |
| 543 rect = [ns_view_ firstRectForCharacterRange:range actualRange:&actual_range]; | |
| 544 EXPECT_TRUE(gfx::ScreenRectFromNSRect(rect) == bounds); | |
| 545 EXPECT_TRUE(NSEqualRanges(range, actual_range)); | |
| 546 | |
| 547 range = NSMakeRange(2, 0); | |
| 548 rect = [ns_view_ firstRectForCharacterRange:range actualRange:&actual_range]; | |
| 549 EXPECT_FALSE(gfx::ScreenRectFromNSRect(rect) == bounds); | |
|
tapted
2015/12/22 02:33:58
comment about this? (what's it testing, and why is
karandeepb
2015/12/29 07:21:16
Done.
| |
| 550 EXPECT_TRUE(NSEqualRanges(range, actual_range)); | |
| 551 | |
| 552 // Query outside composition range. | |
| 553 range = NSMakeRange(count + 1, 0); | |
| 554 rect = [ns_view_ firstRectForCharacterRange:range actualRange:&actual_range]; | |
| 555 EXPECT_TRUE(gfx::ScreenRectFromNSRect(rect) == bounds); | |
| 556 EXPECT_TRUE(NSEqualRanges(range, actual_range)); | |
| 557 | |
| 558 // Set composition with caret after last character. | |
| 559 composition.selection = gfx::Range(count); | |
| 560 client->SetCompositionText(composition); | |
| 561 bounds = client->GetCaretBounds(); | |
| 562 bounds.set_width(0); | |
| 563 | |
| 564 range = NSMakeRange(count, 0); | |
| 565 rect = [ns_view_ firstRectForCharacterRange:range actualRange:&actual_range]; | |
| 566 EXPECT_TRUE(gfx::ScreenRectFromNSRect(rect) == bounds); | |
| 567 EXPECT_TRUE(NSEqualRanges(range, actual_range)); | |
| 568 | |
| 569 range = NSMakeRange(count - 1, 1); | |
| 570 rect = [ns_view_ firstRectForCharacterRange:range actualRange:&actual_range]; | |
| 571 EXPECT_FALSE(gfx::ScreenRectFromNSRect(rect) == bounds); | |
| 572 EXPECT_TRUE(NSEqualRanges(range, actual_range)); | |
| 573 | |
| 574 // Query outside composition range. | |
|
tapted
2015/12/22 02:33:58
These all need a bit more commentary. I.e. say why
karandeepb
2015/12/29 07:21:15
Done.
| |
| 575 range = NSMakeRange(count - 1, 2); | |
| 576 rect = [ns_view_ firstRectForCharacterRange:range actualRange:&actual_range]; | |
| 577 EXPECT_TRUE(gfx::ScreenRectFromNSRect(rect) == bounds); | |
| 578 EXPECT_TRUE(NSEqualRanges(NSMakeRange(count - 1, 0), actual_range)); | |
| 579 | |
| 580 std::vector<gfx::Rect> char_bounds(count); | |
|
tapted
2015/12/22 02:33:58
It's unusual to see exhaustive testing like this:
karandeepb
2015/12/29 07:21:15
That would turn out to be a bit messy, since we wi
| |
| 581 std::vector<gfx::Rect> caret_bounds(count + 1); | |
| 582 | |
| 583 // Generate caret_bounds between different characters. | |
| 584 for (size_t i = 0; i <= count; i++) { | |
| 585 composition.selection = gfx::Range(i); | |
| 586 client->SetCompositionText(composition); | |
| 587 caret_bounds[i] = client->GetCaretBounds(); | |
| 588 } | |
| 589 | |
| 590 // Generate individual character bounds from caret positions. | |
| 591 for (size_t i = 0; i < count; i++) { | |
| 592 char_bounds[i].set_origin(caret_bounds[i].origin()); | |
| 593 char_bounds[i].set_width(caret_bounds[i + 1].x() - caret_bounds[i].x()); | |
| 594 char_bounds[i].set_height( | |
| 595 std::max(caret_bounds[i].height(), caret_bounds[i + 1].height())); | |
| 596 } | |
| 597 | |
| 598 // Verify bounds for all valid ranges. | |
| 599 for (size_t i = 0; i < count; i++) { | |
| 600 for (size_t j = i + 1; j <= count; j++) { | |
| 601 range = NSMakeRange(i, j - i); | |
| 602 rect = | |
| 603 [ns_view_ firstRectForCharacterRange:range actualRange:&actual_range]; | |
| 604 | |
| 605 bounds = gfx::Rect(); | |
| 606 for (size_t k = i; k < j; k++) | |
| 607 bounds.Union(char_bounds[k]); | |
| 608 | |
| 609 EXPECT_TRUE(gfx::ScreenRectFromNSRect(rect) == bounds); | |
| 610 EXPECT_TRUE(NSEqualRanges(range, actual_range)); | |
| 611 } | |
| 612 } | |
| 613 } | |
| 614 | |
| 508 typedef BridgedNativeWidgetTestBase BridgedNativeWidgetSimulateFullscreenTest; | 615 typedef BridgedNativeWidgetTestBase BridgedNativeWidgetSimulateFullscreenTest; |
| 509 | 616 |
| 510 // Simulate the notifications that AppKit would send out if a fullscreen | 617 // Simulate the notifications that AppKit would send out if a fullscreen |
| 511 // operation begins, and then fails and must abort. This notification sequence | 618 // operation begins, and then fails and must abort. This notification sequence |
| 512 // was determined by posting delayed tasks to toggle fullscreen state and then | 619 // was determined by posting delayed tasks to toggle fullscreen state and then |
| 513 // mashing Ctrl+Left/Right to keep OSX in a transition between Spaces to cause | 620 // mashing Ctrl+Left/Right to keep OSX in a transition between Spaces to cause |
| 514 // the fullscreen transition to fail. | 621 // the fullscreen transition to fail. |
| 515 TEST_F(BridgedNativeWidgetSimulateFullscreenTest, FailToEnterAndExit) { | 622 TEST_F(BridgedNativeWidgetSimulateFullscreenTest, FailToEnterAndExit) { |
| 516 if (base::mac::IsOSSnowLeopard()) | 623 if (base::mac::IsOSSnowLeopard()) |
| 517 return; | 624 return; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 576 [center postNotificationName:NSWindowDidExitFullScreenNotification | 683 [center postNotificationName:NSWindowDidExitFullScreenNotification |
| 577 object:window]; | 684 object:window]; |
| 578 EXPECT_EQ(1, [window ignoredToggleFullScreenCount]); // No change. | 685 EXPECT_EQ(1, [window ignoredToggleFullScreenCount]); // No change. |
| 579 EXPECT_FALSE(bridge()->target_fullscreen_state()); | 686 EXPECT_FALSE(bridge()->target_fullscreen_state()); |
| 580 | 687 |
| 581 widget_->CloseNow(); | 688 widget_->CloseNow(); |
| 582 } | 689 } |
| 583 | 690 |
| 584 } // namespace test | 691 } // namespace test |
| 585 } // namespace views | 692 } // namespace views |
| OLD | NEW |