| 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 |