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 |