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/mac_util.h" | 9 #import "base/mac/mac_util.h" |
10 #import "base/mac/sdk_forward_declarations.h" | 10 #import "base/mac/sdk_forward_declarations.h" |
11 #include "base/run_loop.h" | 11 #import "ui/base/test/nswindow_fullscreen_notification_waiter.h" |
12 #include "ui/views/test/widget_test.h" | 12 #include "ui/views/test/widget_test.h" |
13 | 13 |
14 @interface NativeWidgetMacNotificationWaiter : NSObject { | |
15 @private | |
16 scoped_ptr<base::RunLoop> runLoop_; | |
17 base::scoped_nsobject<NSWindow> window_; | |
18 int enterCount_; | |
19 int exitCount_; | |
20 int targetEnterCount_; | |
21 int targetExitCount_; | |
22 } | |
23 | |
24 @property(readonly, nonatomic) int enterCount; | |
25 @property(readonly, nonatomic) int exitCount; | |
26 | |
27 // Initialize for the given window and start tracking notifications. | |
28 - (id)initWithWindow:(NSWindow*)window; | |
29 | |
30 // Keep spinning a run loop until the enter and exit counts match. | |
31 - (void)waitForEnterCount:(int)enterCount exitCount:(int)exitCount; | |
32 | |
33 // private: | |
34 // Exit the RunLoop if there is one and the counts being tracked match. | |
35 - (void)maybeQuitForChangedArg:(int*)changedArg; | |
36 | |
37 - (void)onEnter:(NSNotification*)notification; | |
38 - (void)onExit:(NSNotification*)notification; | |
39 | |
40 @end | |
41 | |
42 @implementation NativeWidgetMacNotificationWaiter | |
43 | |
44 @synthesize enterCount = enterCount_; | |
45 @synthesize exitCount = exitCount_; | |
46 | |
47 - (id)initWithWindow:(NSWindow*)window { | |
48 if ((self = [super init])) { | |
49 window_.reset([window retain]); | |
50 NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter]; | |
51 [defaultCenter addObserver:self | |
52 selector:@selector(onEnter:) | |
53 name:NSWindowDidEnterFullScreenNotification | |
54 object:window]; | |
55 [defaultCenter addObserver:self | |
56 selector:@selector(onExit:) | |
57 name:NSWindowDidExitFullScreenNotification | |
58 object:window]; | |
59 } | |
60 return self; | |
61 } | |
62 | |
63 - (void)dealloc { | |
64 DCHECK(!runLoop_); | |
65 [[NSNotificationCenter defaultCenter] removeObserver:self]; | |
66 [super dealloc]; | |
67 } | |
68 | |
69 - (void)waitForEnterCount:(int)enterCount exitCount:(int)exitCount { | |
70 if (enterCount_ >= enterCount && exitCount_ >= exitCount) | |
71 return; | |
72 | |
73 targetEnterCount_ = enterCount; | |
74 targetExitCount_ = exitCount; | |
75 runLoop_.reset(new base::RunLoop); | |
76 runLoop_->Run(); | |
77 runLoop_.reset(); | |
78 } | |
79 | |
80 - (void)maybeQuitForChangedArg:(int*)changedArg { | |
81 ++*changedArg; | |
82 if (!runLoop_) | |
83 return; | |
84 | |
85 if (enterCount_ >= targetEnterCount_ && exitCount_ >= targetExitCount_) | |
86 runLoop_->Quit(); | |
87 } | |
88 | |
89 - (void)onEnter:(NSNotification*)notification { | |
90 [self maybeQuitForChangedArg:&enterCount_]; | |
91 } | |
92 | |
93 - (void)onExit:(NSNotification*)notification { | |
94 [self maybeQuitForChangedArg:&exitCount_]; | |
95 } | |
96 | |
97 @end | |
98 | |
99 namespace views { | 14 namespace views { |
100 | 15 |
101 class BridgedNativeWidgetUITest : public test::WidgetTest { | 16 class BridgedNativeWidgetUITest : public test::WidgetTest { |
102 public: | 17 public: |
103 BridgedNativeWidgetUITest() {} | 18 BridgedNativeWidgetUITest() {} |
104 | 19 |
105 // testing::Test: | 20 // testing::Test: |
106 void SetUp() override { | 21 void SetUp() override { |
107 WidgetTest::SetUp(); | 22 WidgetTest::SetUp(); |
108 Widget::InitParams init_params = | 23 Widget::InitParams init_params = |
(...skipping 23 matching lines...) Expand all Loading... |
132 TEST_F(BridgedNativeWidgetUITest, FullscreenSynchronousState) { | 47 TEST_F(BridgedNativeWidgetUITest, FullscreenSynchronousState) { |
133 EXPECT_FALSE(widget_->IsFullscreen()); | 48 EXPECT_FALSE(widget_->IsFullscreen()); |
134 if (base::mac::IsOSSnowLeopard()) | 49 if (base::mac::IsOSSnowLeopard()) |
135 return; | 50 return; |
136 | 51 |
137 // Allow user-initiated fullscreen changes on the Window. | 52 // Allow user-initiated fullscreen changes on the Window. |
138 [test_window() | 53 [test_window() |
139 setCollectionBehavior:[test_window() collectionBehavior] | | 54 setCollectionBehavior:[test_window() collectionBehavior] | |
140 NSWindowCollectionBehaviorFullScreenPrimary]; | 55 NSWindowCollectionBehaviorFullScreenPrimary]; |
141 | 56 |
142 base::scoped_nsobject<NativeWidgetMacNotificationWaiter> waiter( | 57 base::scoped_nsobject<NSWindowFullscreenNotificationWaiter> waiter( |
143 [[NativeWidgetMacNotificationWaiter alloc] initWithWindow:test_window()]); | 58 [[NSWindowFullscreenNotificationWaiter alloc] |
| 59 initWithWindow:test_window()]); |
144 const gfx::Rect restored_bounds = widget_->GetRestoredBounds(); | 60 const gfx::Rect restored_bounds = widget_->GetRestoredBounds(); |
145 | 61 |
146 // First show the widget. A user shouldn't be able to initiate fullscreen | 62 // First show the widget. A user shouldn't be able to initiate fullscreen |
147 // unless the window is visible in the first place. | 63 // unless the window is visible in the first place. |
148 widget_->Show(); | 64 widget_->Show(); |
149 | 65 |
150 // Simulate a user-initiated fullscreen. Note trying to to this again before | 66 // Simulate a user-initiated fullscreen. Note trying to to this again before |
151 // spinning a runloop will cause Cocoa to emit text to stdio and ignore it. | 67 // spinning a runloop will cause Cocoa to emit text to stdio and ignore it. |
152 [test_window() toggleFullScreen:nil]; | 68 [test_window() toggleFullScreen:nil]; |
153 EXPECT_TRUE(widget_->IsFullscreen()); | 69 EXPECT_TRUE(widget_->IsFullscreen()); |
(...skipping 25 matching lines...) Expand all Loading... |
179 // fullscreen is lost. Since a message loop has not yet spun up in this test | 95 // fullscreen is lost. Since a message loop has not yet spun up in this test |
180 // we can reliably say there will be one enter and one exit, despite all the | 96 // we can reliably say there will be one enter and one exit, despite all the |
181 // toggling above. | 97 // toggling above. |
182 [waiter waitForEnterCount:1 exitCount:1]; | 98 [waiter waitForEnterCount:1 exitCount:1]; |
183 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds()); | 99 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds()); |
184 } | 100 } |
185 | 101 |
186 // Test fullscreen without overlapping calls and without changing collection | 102 // Test fullscreen without overlapping calls and without changing collection |
187 // behavior on the test window. | 103 // behavior on the test window. |
188 TEST_F(BridgedNativeWidgetUITest, FullscreenEnterAndExit) { | 104 TEST_F(BridgedNativeWidgetUITest, FullscreenEnterAndExit) { |
189 base::scoped_nsobject<NativeWidgetMacNotificationWaiter> waiter( | 105 base::scoped_nsobject<NSWindowFullscreenNotificationWaiter> waiter( |
190 [[NativeWidgetMacNotificationWaiter alloc] initWithWindow:test_window()]); | 106 [[NSWindowFullscreenNotificationWaiter alloc] |
| 107 initWithWindow:test_window()]); |
191 | 108 |
192 EXPECT_FALSE(widget_->IsFullscreen()); | 109 EXPECT_FALSE(widget_->IsFullscreen()); |
193 const gfx::Rect restored_bounds = widget_->GetRestoredBounds(); | 110 const gfx::Rect restored_bounds = widget_->GetRestoredBounds(); |
194 EXPECT_FALSE(restored_bounds.IsEmpty()); | 111 EXPECT_FALSE(restored_bounds.IsEmpty()); |
195 | 112 |
196 // Ensure this works without having to change collection behavior as for the | 113 // Ensure this works without having to change collection behavior as for the |
197 // test above. Also check that making a hidden widget fullscreen shows it. | 114 // test above. Also check that making a hidden widget fullscreen shows it. |
198 EXPECT_FALSE(widget_->IsVisible()); | 115 EXPECT_FALSE(widget_->IsVisible()); |
199 widget_->SetFullscreen(true); | 116 widget_->SetFullscreen(true); |
200 EXPECT_TRUE(widget_->IsVisible()); | 117 EXPECT_TRUE(widget_->IsVisible()); |
(...skipping 20 matching lines...) Expand all Loading... |
221 EXPECT_FALSE(widget_->IsFullscreen()); | 138 EXPECT_FALSE(widget_->IsFullscreen()); |
222 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds()); | 139 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds()); |
223 | 140 |
224 [waiter waitForEnterCount:1 exitCount:1]; | 141 [waiter waitForEnterCount:1 exitCount:1]; |
225 EXPECT_EQ(1, [waiter enterCount]); | 142 EXPECT_EQ(1, [waiter enterCount]); |
226 EXPECT_EQ(1, [waiter exitCount]); | 143 EXPECT_EQ(1, [waiter exitCount]); |
227 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds()); | 144 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds()); |
228 } | 145 } |
229 | 146 |
230 } // namespace views | 147 } // namespace views |
OLD | NEW |