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
3 // found in the LICENSE file.
5 #import "ui/views/cocoa/bridged_native_widget.h"
7 #import <Cocoa/Cocoa.h>
9 #import "base/mac/mac_util.h"
10 #import "base/mac/sdk_forward_declarations.h"
11 #import "ui/base/test/nswindow_fullscreen_notification_waiter.h"
12 #include "ui/views/test/widget_test.h"
16 class BridgedNativeWidgetUITest : public test::WidgetTest {
18 BridgedNativeWidgetUITest() {}
21 void SetUp() override {
23 Widget::InitParams init_params =
24 CreateParams(Widget::InitParams::TYPE_WINDOW);
25 init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
26 widget_.reset(new Widget);
27 widget_->Init(init_params);
30 void TearDown() override {
31 // Ensures any compositor is removed before ViewsTestBase tears down the
34 WidgetTest::TearDown();
37 NSWindow* test_window() {
38 return widget_->GetNativeWindow();
42 scoped_ptr<Widget> widget_;
45 // Tests for correct fullscreen tracking, regardless of whether it is initiated
46 // by the Widget code or elsewhere (e.g. by the user).
47 TEST_F(BridgedNativeWidgetUITest, FullscreenSynchronousState) {
48 EXPECT_FALSE(widget_->IsFullscreen());
49 if (base::mac::IsOSSnowLeopard())
52 // Allow user-initiated fullscreen changes on the Window.
54 setCollectionBehavior:[test_window() collectionBehavior] |
55 NSWindowCollectionBehaviorFullScreenPrimary];
57 base::scoped_nsobject<NSWindowFullscreenNotificationWaiter> waiter(
58 [[NSWindowFullscreenNotificationWaiter alloc]
59 initWithWindow:test_window()]);
60 const gfx::Rect restored_bounds = widget_->GetRestoredBounds();
62 // First show the widget. A user shouldn't be able to initiate fullscreen
63 // unless the window is visible in the first place.
66 // Simulate a user-initiated fullscreen. Note trying to to this again before
67 // spinning a runloop will cause Cocoa to emit text to stdio and ignore it.
68 [test_window() toggleFullScreen:nil];
69 EXPECT_TRUE(widget_->IsFullscreen());
70 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds());
72 // Note there's now an animation running. While that's happening, toggling the
73 // state should work as expected, but do "nothing".
74 widget_->SetFullscreen(false);
75 EXPECT_FALSE(widget_->IsFullscreen());
76 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds());
77 widget_->SetFullscreen(false); // Same request - should no-op.
78 EXPECT_FALSE(widget_->IsFullscreen());
79 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds());
81 widget_->SetFullscreen(true);
82 EXPECT_TRUE(widget_->IsFullscreen());
83 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds());
85 // Always finish out of fullscreen. Otherwise there are 4 NSWindow objects
86 // that Cocoa creates which don't close themselves and will be seen by the Mac
87 // test harness on teardown. Note that the test harness will be waiting until
88 // all animations complete, since these temporary animation windows will not
89 // be removed from the window list until they do.
90 widget_->SetFullscreen(false);
91 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds());
93 // Now we must wait for the notifications. Since, if the widget is torn down,
94 // the NSWindowDelegate is removed, and the pending request to take out of
95 // fullscreen is lost. Since a message loop has not yet spun up in this test
96 // we can reliably say there will be one enter and one exit, despite all the
98 [waiter waitForEnterCount:1 exitCount:1];
99 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds());
102 // Test fullscreen without overlapping calls and without changing collection
103 // behavior on the test window.
104 TEST_F(BridgedNativeWidgetUITest, FullscreenEnterAndExit) {
105 base::scoped_nsobject<NSWindowFullscreenNotificationWaiter> waiter(
106 [[NSWindowFullscreenNotificationWaiter alloc]
107 initWithWindow:test_window()]);
109 EXPECT_FALSE(widget_->IsFullscreen());
110 const gfx::Rect restored_bounds = widget_->GetRestoredBounds();
111 EXPECT_FALSE(restored_bounds.IsEmpty());
113 // Ensure this works without having to change collection behavior as for the
114 // test above. Also check that making a hidden widget fullscreen shows it.
115 EXPECT_FALSE(widget_->IsVisible());
116 widget_->SetFullscreen(true);
117 EXPECT_TRUE(widget_->IsVisible());
118 if (base::mac::IsOSSnowLeopard()) {
119 // On Snow Leopard, SetFullscreen() isn't implemented. But shouldn't crash.
120 EXPECT_FALSE(widget_->IsFullscreen());
124 EXPECT_TRUE(widget_->IsFullscreen());
125 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds());
127 // Should be zero until the runloop spins.
128 EXPECT_EQ(0, [waiter enterCount]);
129 [waiter waitForEnterCount:1 exitCount:0];
131 // Verify it hasn't exceeded.
132 EXPECT_EQ(1, [waiter enterCount]);
133 EXPECT_EQ(0, [waiter exitCount]);
134 EXPECT_TRUE(widget_->IsFullscreen());
135 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds());
137 widget_->SetFullscreen(false);
138 EXPECT_FALSE(widget_->IsFullscreen());
139 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds());
141 [waiter waitForEnterCount:1 exitCount:1];
142 EXPECT_EQ(1, [waiter enterCount]);
143 EXPECT_EQ(1, [waiter exitCount]);
144 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds());