| 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 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 } | 199 } |
| 200 | 200 |
| 201 @end | 201 @end |
| 202 | 202 |
| 203 namespace views { | 203 namespace views { |
| 204 namespace test { | 204 namespace test { |
| 205 | 205 |
| 206 // Provides the |parent| argument to construct a BridgedNativeWidget. | 206 // Provides the |parent| argument to construct a BridgedNativeWidget. |
| 207 class MockNativeWidgetMac : public NativeWidgetMac { | 207 class MockNativeWidgetMac : public NativeWidgetMac { |
| 208 public: | 208 public: |
| 209 MockNativeWidgetMac(Widget* delegate) : NativeWidgetMac(delegate) {} | 209 explicit MockNativeWidgetMac(internal::NativeWidgetDelegate* delegate) |
| 210 : NativeWidgetMac(delegate) {} |
| 210 | 211 |
| 211 // Expose a reference, so that it can be reset() independently. | 212 // Expose a reference, so that it can be reset() independently. |
| 212 std::unique_ptr<BridgedNativeWidget>& bridge() { return bridge_; } | 213 std::unique_ptr<BridgedNativeWidget>& bridge() { return bridge_; } |
| 213 | 214 |
| 214 // internal::NativeWidgetPrivate: | 215 // internal::NativeWidgetPrivate: |
| 215 void InitNativeWidget(const Widget::InitParams& params) override { | 216 void InitNativeWidget(const Widget::InitParams& params) override { |
| 216 ownership_ = params.ownership; | 217 ownership_ = params.ownership; |
| 217 | 218 |
| 218 // Usually the bridge gets initialized here. It is skipped to run extra | 219 // Usually the bridge gets initialized here. It is skipped to run extra |
| 219 // checks in tests, and so that a second window isn't created. | 220 // checks in tests, and so that a second window isn't created. |
| 220 delegate()->OnNativeWidgetCreated(true); | 221 delegate()->OnNativeWidgetCreated(true); |
| 221 | 222 |
| 222 // To allow events to dispatch to a view, it needs a way to get focus. | 223 // To allow events to dispatch to a view, it needs a way to get focus. |
| 223 bridge_->SetFocusManager(GetWidget()->GetFocusManager()); | 224 bridge_->SetFocusManager(GetWidget()->GetFocusManager()); |
| 224 } | 225 } |
| 225 | 226 |
| 226 void ReorderNativeViews() override { | 227 void ReorderNativeViews() override { |
| 227 // Called via Widget::Init to set the content view. No-op in these tests. | 228 // Called via Widget::Init to set the content view. No-op in these tests. |
| 228 } | 229 } |
| 229 | 230 |
| 230 private: | 231 private: |
| 231 DISALLOW_COPY_AND_ASSIGN(MockNativeWidgetMac); | 232 DISALLOW_COPY_AND_ASSIGN(MockNativeWidgetMac); |
| 232 }; | 233 }; |
| 233 | 234 |
| 234 // Helper test base to construct a BridgedNativeWidget with a valid parent. | 235 // Helper test base to construct a BridgedNativeWidget with a valid parent. |
| 235 class BridgedNativeWidgetTestBase : public ui::CocoaTest { | 236 class BridgedNativeWidgetTestBase : public ui::CocoaTest { |
| 236 public: | 237 public: |
| 238 struct SkipInitialization {}; |
| 239 |
| 237 BridgedNativeWidgetTestBase() | 240 BridgedNativeWidgetTestBase() |
| 238 : widget_(new Widget), | 241 : widget_(new Widget), |
| 239 native_widget_mac_(new MockNativeWidgetMac(widget_.get())) { | 242 native_widget_mac_(new MockNativeWidgetMac(widget_.get())) {} |
| 240 } | 243 |
| 244 explicit BridgedNativeWidgetTestBase(SkipInitialization tag) |
| 245 : native_widget_mac_(nullptr) {} |
| 241 | 246 |
| 242 std::unique_ptr<BridgedNativeWidget>& bridge() { | 247 std::unique_ptr<BridgedNativeWidget>& bridge() { |
| 243 return native_widget_mac_->bridge(); | 248 return native_widget_mac_->bridge(); |
| 244 } | 249 } |
| 245 | 250 |
| 246 // Overridden from testing::Test: | 251 // Overridden from testing::Test: |
| 247 void SetUp() override { | 252 void SetUp() override { |
| 248 ui::CocoaTest::SetUp(); | 253 ui::CocoaTest::SetUp(); |
| 254 |
| 255 // MaterialDesignController leaks state across tests. See |
| 256 // http://crbug.com/656871. |
| 257 ui::test::MaterialDesignControllerTestAPI::Uninitialize(); |
| 249 ui::MaterialDesignController::Initialize(); | 258 ui::MaterialDesignController::Initialize(); |
| 250 | 259 |
| 251 init_params_.native_widget = native_widget_mac_; | 260 init_params_.native_widget = native_widget_mac_; |
| 252 | 261 |
| 253 // Use a frameless window, otherwise Widget will try to center the window | 262 // Use a frameless window, otherwise Widget will try to center the window |
| 254 // before the tests covering the Init() flow are ready to do that. | 263 // before the tests covering the Init() flow are ready to do that. |
| 255 init_params_.type = Widget::InitParams::TYPE_WINDOW_FRAMELESS; | 264 init_params_.type = Widget::InitParams::TYPE_WINDOW_FRAMELESS; |
| 256 | 265 |
| 257 // To control the lifetime without an actual window that must be closed, | 266 // To control the lifetime without an actual window that must be closed, |
| 258 // tests in this file need to use WIDGET_OWNS_NATIVE_WIDGET. | 267 // tests in this file need to use WIDGET_OWNS_NATIVE_WIDGET. |
| 259 init_params_.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 268 init_params_.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 260 | 269 |
| 261 // Opacity defaults to "infer" which is usually updated by ViewsDelegate. | 270 // Opacity defaults to "infer" which is usually updated by ViewsDelegate. |
| 262 init_params_.opacity = Widget::InitParams::OPAQUE_WINDOW; | 271 init_params_.opacity = Widget::InitParams::OPAQUE_WINDOW; |
| 263 | 272 |
| 264 init_params_.bounds = gfx::Rect(100, 100, 100, 100); | 273 init_params_.bounds = gfx::Rect(100, 100, 100, 100); |
| 265 | 274 |
| 266 native_widget_mac_->GetWidget()->Init(init_params_); | 275 if (native_widget_mac_) |
| 276 native_widget_mac_->GetWidget()->Init(init_params_); |
| 267 } | 277 } |
| 268 | 278 |
| 269 void TearDown() override { | 279 void TearDown() override { |
| 270 ui::test::MaterialDesignControllerTestAPI::Uninitialize(); | 280 ui::test::MaterialDesignControllerTestAPI::Uninitialize(); |
| 271 ui::CocoaTest::TearDown(); | 281 ui::CocoaTest::TearDown(); |
| 272 } | 282 } |
| 273 | 283 |
| 274 protected: | 284 protected: |
| 275 std::unique_ptr<Widget> widget_; | 285 std::unique_ptr<Widget> widget_; |
| 276 MockNativeWidgetMac* native_widget_mac_; // Weak. Owned by |widget_|. | 286 MockNativeWidgetMac* native_widget_mac_; // Weak. Owned by |widget_|. |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 596 EXPECT_NSEQ(test_window(), [view window]); | 606 EXPECT_NSEQ(test_window(), [view window]); |
| 597 | 607 |
| 598 // The superview of a contentView is an NSNextStepFrame. | 608 // The superview of a contentView is an NSNextStepFrame. |
| 599 EXPECT_TRUE([view superview]); | 609 EXPECT_TRUE([view superview]); |
| 600 EXPECT_TRUE([view hostedView]); | 610 EXPECT_TRUE([view hostedView]); |
| 601 | 611 |
| 602 // Ensure the tracking area to propagate mouseMoved: events to the RootView is | 612 // Ensure the tracking area to propagate mouseMoved: events to the RootView is |
| 603 // installed. | 613 // installed. |
| 604 EXPECT_EQ(1u, [[view trackingAreas] count]); | 614 EXPECT_EQ(1u, [[view trackingAreas] count]); |
| 605 | 615 |
| 606 // Destroying the C++ bridge should remove references to any C++ objects in | 616 // Closing the window should tear down the C++ bridge, remove references to |
| 607 // the ObjectiveC object, and remove it from the hierarchy. | 617 // any C++ objects in the ObjectiveC object, and remove it from the hierarchy. |
| 608 bridge().reset(); | 618 [test_window() close]; |
| 609 EXPECT_FALSE([view hostedView]); | 619 EXPECT_FALSE([view hostedView]); |
| 610 EXPECT_FALSE([view superview]); | 620 EXPECT_FALSE([view superview]); |
| 611 EXPECT_FALSE([view window]); | 621 EXPECT_FALSE([view window]); |
| 612 EXPECT_EQ(0u, [[view trackingAreas] count]); | 622 EXPECT_EQ(0u, [[view trackingAreas] count]); |
| 613 EXPECT_FALSE([test_window() contentView]); | 623 EXPECT_FALSE([test_window() contentView]); |
| 614 EXPECT_FALSE([test_window() delegate]); | 624 EXPECT_FALSE([test_window() delegate]); |
| 615 } | 625 } |
| 616 | 626 |
| 617 TEST_F(BridgedNativeWidgetTest, BridgedNativeWidgetTest_TestViewDisplay) { | 627 TEST_F(BridgedNativeWidgetTest, BridgedNativeWidgetTest_TestViewDisplay) { |
| 618 [bridge()->ns_view() display]; | 628 [bridge()->ns_view() display]; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 638 EXPECT_EQ(kTestNewHeight, view_->height()); | 648 EXPECT_EQ(kTestNewHeight, view_->height()); |
| 639 } | 649 } |
| 640 | 650 |
| 641 TEST_F(BridgedNativeWidgetTest, GetInputMethodShouldNotReturnNull) { | 651 TEST_F(BridgedNativeWidgetTest, GetInputMethodShouldNotReturnNull) { |
| 642 EXPECT_TRUE(bridge()->GetInputMethod()); | 652 EXPECT_TRUE(bridge()->GetInputMethod()); |
| 643 } | 653 } |
| 644 | 654 |
| 645 // A simpler test harness for testing initialization flows. | 655 // A simpler test harness for testing initialization flows. |
| 646 class BridgedNativeWidgetInitTest : public BridgedNativeWidgetTestBase { | 656 class BridgedNativeWidgetInitTest : public BridgedNativeWidgetTestBase { |
| 647 public: | 657 public: |
| 648 BridgedNativeWidgetInitTest() {} | 658 BridgedNativeWidgetInitTest() |
| 659 : BridgedNativeWidgetTestBase(SkipInitialization()) {} |
| 649 | 660 |
| 650 // Prepares a new |window_| and |widget_| for a call to PerformInit(). | 661 // Prepares a new |window_| and |widget_| for a call to PerformInit(). |
| 651 void CreateNewWidgetToInit(NSUInteger style_mask) { | 662 void CreateNewWidgetToInit(NSUInteger style_mask) { |
| 652 window_.reset( | 663 window_.reset( |
| 653 [[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater | 664 [[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater |
| 654 styleMask:style_mask | 665 styleMask:style_mask |
| 655 backing:NSBackingStoreBuffered | 666 backing:NSBackingStoreBuffered |
| 656 defer:NO]); | 667 defer:NO]); |
| 657 [window_ setReleasedWhenClosed:NO]; // Owned by scoped_nsobject. | 668 [window_ setReleasedWhenClosed:NO]; // Owned by scoped_nsobject. |
| 658 widget_.reset(new Widget); | 669 widget_.reset(new Widget); |
| 659 native_widget_mac_ = new MockNativeWidgetMac(widget_.get()); | 670 native_widget_mac_ = new MockNativeWidgetMac(widget_.get()); |
| 660 init_params_.native_widget = native_widget_mac_; | 671 init_params_.native_widget = native_widget_mac_; |
| 661 } | 672 } |
| 662 | 673 |
| 663 void PerformInit() { | 674 void PerformInit() { |
| 664 widget_->Init(init_params_); | 675 widget_->Init(init_params_); |
| 665 bridge()->Init(window_, init_params_); | 676 bridge()->Init(window_, init_params_); |
| 666 } | 677 } |
| 667 | 678 |
| 668 protected: | 679 protected: |
| 669 base::scoped_nsobject<NSWindow> window_; | 680 base::scoped_nsobject<NSWindow> window_; |
| 670 | 681 |
| 671 private: | 682 private: |
| 672 DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetInitTest); | 683 DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetInitTest); |
| 673 }; | 684 }; |
| 674 | 685 |
| 675 // Test that BridgedNativeWidget remains sane if Init() is never called. | 686 // Test that BridgedNativeWidget remains sane if Init() is never called. |
| 676 TEST_F(BridgedNativeWidgetInitTest, InitNotCalled) { | 687 TEST_F(BridgedNativeWidgetInitTest, InitNotCalled) { |
| 688 // Don't use a Widget* as the delegate. ~Widget() checks for Widget:: |
| 689 // |native_widget_destroyed_| being set to true. That can only happen with a |
| 690 // non-null WidgetDelegate, which is only set in Widget::Init(). Then, since |
| 691 // neither Widget nor NativeWidget take ownership, use a unique_ptr. |
| 692 std::unique_ptr<MockNativeWidgetMac> native_widget( |
| 693 new MockNativeWidgetMac(nullptr)); |
| 694 native_widget_mac_ = native_widget.get(); |
| 677 EXPECT_FALSE(bridge()->ns_view()); | 695 EXPECT_FALSE(bridge()->ns_view()); |
| 678 EXPECT_FALSE(bridge()->ns_window()); | 696 EXPECT_FALSE(bridge()->ns_window()); |
| 679 bridge().reset(); | |
| 680 } | 697 } |
| 681 | 698 |
| 682 // Tests the shadow type given in InitParams. | 699 // Tests the shadow type given in InitParams. |
| 683 TEST_F(BridgedNativeWidgetInitTest, ShadowType) { | 700 TEST_F(BridgedNativeWidgetInitTest, ShadowType) { |
| 684 // Verify Widget::InitParam defaults and arguments added from SetUp(). | 701 // Verify Widget::InitParam defaults and arguments added from SetUp(). |
| 685 EXPECT_EQ(Widget::InitParams::TYPE_WINDOW_FRAMELESS, init_params_.type); | 702 EXPECT_EQ(Widget::InitParams::TYPE_WINDOW_FRAMELESS, init_params_.type); |
| 686 EXPECT_EQ(Widget::InitParams::OPAQUE_WINDOW, init_params_.opacity); | 703 EXPECT_EQ(Widget::InitParams::OPAQUE_WINDOW, init_params_.opacity); |
| 687 EXPECT_EQ(Widget::InitParams::SHADOW_TYPE_DEFAULT, init_params_.shadow_type); | 704 EXPECT_EQ(Widget::InitParams::SHADOW_TYPE_DEFAULT, init_params_.shadow_type); |
| 688 | 705 |
| 689 CreateNewWidgetToInit(NSBorderlessWindowMask); | 706 CreateNewWidgetToInit(NSBorderlessWindowMask); |
| (...skipping 616 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1306 [center postNotificationName:NSWindowDidExitFullScreenNotification | 1323 [center postNotificationName:NSWindowDidExitFullScreenNotification |
| 1307 object:window]; | 1324 object:window]; |
| 1308 EXPECT_EQ(1, [window ignoredToggleFullScreenCount]); // No change. | 1325 EXPECT_EQ(1, [window ignoredToggleFullScreenCount]); // No change. |
| 1309 EXPECT_FALSE(bridge()->target_fullscreen_state()); | 1326 EXPECT_FALSE(bridge()->target_fullscreen_state()); |
| 1310 | 1327 |
| 1311 widget_->CloseNow(); | 1328 widget_->CloseNow(); |
| 1312 } | 1329 } |
| 1313 | 1330 |
| 1314 } // namespace test | 1331 } // namespace test |
| 1315 } // namespace views | 1332 } // namespace views |
| OLD | NEW |