| Index: chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm
|
| diff --git a/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm b/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm
|
| index c8c0e22e09bb0136af95bf6d17a17d190c4060db..a01111c7c9acd3a21e316da16911f4ef89b067fb 100644
|
| --- a/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm
|
| +++ b/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm
|
| @@ -68,6 +68,96 @@ enum ViewID {
|
| VIEW_ID_COUNT,
|
| };
|
|
|
| +// Checks that no views draw on top of the supposedly exposed view.
|
| +class ViewExposedChecker {
|
| + public:
|
| + ViewExposedChecker() : below_exposed_view_(YES) {}
|
| + ~ViewExposedChecker() {}
|
| +
|
| + void SetExceptions(NSArray* exceptions) {
|
| + exceptions_.reset([exceptions retain]);
|
| + }
|
| +
|
| + // Checks that no views draw in front of |view|, with the exception of
|
| + // |exceptions|.
|
| + void CheckViewExposed(NSView* view) {
|
| + below_exposed_view_ = YES;
|
| + exposed_view_.reset([view retain]);
|
| + CheckViewsDoNotObscure([[[view window] contentView] superview]);
|
| + }
|
| +
|
| + private:
|
| + // Checks that |view| does not draw on top of |exposed_view_|.
|
| + void CheckViewDoesNotObscure(NSView* view) {
|
| + NSRect viewWindowFrame = [view convertRect:[view bounds] toView:nil];
|
| + NSRect viewBeingVerifiedWindowFrame =
|
| + [exposed_view_ convertRect:[exposed_view_ bounds] toView:nil];
|
| +
|
| + // The views do not intersect.
|
| + if (!NSIntersectsRect(viewBeingVerifiedWindowFrame, viewWindowFrame))
|
| + return;
|
| +
|
| + // No view can be above the view being checked.
|
| + EXPECT_TRUE(below_exposed_view_);
|
| +
|
| + // If |view| is a parent of |exposed_view_|, then there's nothing else
|
| + // to check.
|
| + NSView* parent = exposed_view_;
|
| + while (parent != nil) {
|
| + parent = [parent superview];
|
| + if (parent == view)
|
| + return;
|
| + }
|
| +
|
| + if ([exposed_view_ layer])
|
| + return;
|
| +
|
| + // If the view being verified doesn't have a layer, then no views that
|
| + // intersect it can have a layer.
|
| + if ([exceptions_ containsObject:view]) {
|
| + EXPECT_FALSE([view isOpaque]);
|
| + return;
|
| + }
|
| +
|
| + EXPECT_TRUE(![view layer]) << [[view description] UTF8String] << " " <<
|
| + [NSStringFromRect(viewWindowFrame) UTF8String];
|
| + }
|
| +
|
| + // Recursively checks that |view| and its subviews do not draw on top of
|
| + // |exposed_view_|. The recursion passes through all views in order of
|
| + // back-most in Z-order to front-most in Z-order.
|
| + void CheckViewsDoNotObscure(NSView* view) {
|
| + // If this is the view being checked, don't recurse into its subviews. All
|
| + // future views encountered in the recursion are in front of the view being
|
| + // checked.
|
| + if (view == exposed_view_) {
|
| + below_exposed_view_ = NO;
|
| + return;
|
| + }
|
| +
|
| + CheckViewDoesNotObscure(view);
|
| +
|
| + // Perform the recursion.
|
| + for (NSView* subview in [view subviews])
|
| + CheckViewsDoNotObscure(subview);
|
| + }
|
| +
|
| + // The method CheckViewExposed() recurses through the views in the view
|
| + // hierarchy and checks that none of the views obscure |exposed_view_|.
|
| + base::scoped_nsobject<NSView> exposed_view_;
|
| +
|
| + // While this flag is true, the views being recursed through are below
|
| + // |exposed_view_| in Z-order. After the recursion passes |exposed_view_|,
|
| + // this flag is set to false.
|
| + BOOL below_exposed_view_;
|
| +
|
| + // Exceptions are allowed to overlap |exposed_view_|. Exceptions must still
|
| + // be Z-order behind |exposed_view_|.
|
| + base::scoped_nsobject<NSArray> exceptions_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ViewExposedChecker);
|
| +};
|
| +
|
| } // namespace
|
|
|
| @interface InfoBarContainerController(TestingAPI)
|
| @@ -223,22 +313,29 @@ class BrowserWindowControllerTest : public InProcessBrowserTest {
|
| return icon_bottom.y - info_bar_top.y;
|
| }
|
|
|
| - // The traffic lights should always be in front of the content view and the
|
| - // tab strip view. Since the traffic lights change across OSX versions, this
|
| - // test verifies that the contentView is in the back, and if the tab strip
|
| - // view is a sibling, it is directly in front of the content view.
|
| - void VerifyTrafficLightZOrder() const {
|
| - NSView* contentView = [[controller() window] contentView];
|
| - NSView* rootView = [contentView superview];
|
| - NSArray* subviews = [rootView subviews];
|
| -
|
| - EXPECT_EQ([controller() tabStripBackgroundView],
|
| - [subviews objectAtIndex:0]);
|
| - EXPECT_EQ(contentView, [subviews objectAtIndex:1]);
|
| -
|
| - NSView* tabStripView = [controller() tabStripView];
|
| - if ([subviews containsObject:tabStripView])
|
| - EXPECT_EQ(tabStripView, [subviews objectAtIndex:2]);
|
| + // Nothing should draw on top of the window controls.
|
| + void VerifyWindowControlsZOrder() {
|
| + NSWindow* window = [controller() window];
|
| + ViewExposedChecker checker;
|
| +
|
| + // The exceptions are the contentView, chromeContentView and tabStripView,
|
| + // which are layer backed but transparent.
|
| + NSArray* exceptions = @[
|
| + [window contentView],
|
| + controller().chromeContentView,
|
| + controller().tabStripView
|
| + ];
|
| + checker.SetExceptions(exceptions);
|
| +
|
| + checker.CheckViewExposed([window standardWindowButton:NSWindowCloseButton]);
|
| + checker.CheckViewExposed(
|
| + [window standardWindowButton:NSWindowMiniaturizeButton]);
|
| + checker.CheckViewExposed([window standardWindowButton:NSWindowZoomButton]);
|
| +
|
| + // There is no fullscreen button on OSX 10.6 or OSX 10.10+.
|
| + NSView* view = [window standardWindowButton:NSWindowFullScreenButton];
|
| + if (view)
|
| + checker.CheckViewExposed(view);
|
| }
|
|
|
| private:
|
| @@ -500,15 +597,17 @@ IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest,
|
|
|
| IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, TrafficLightZOrder) {
|
| // Verify z order immediately after creation.
|
| - VerifyTrafficLightZOrder();
|
| + VerifyWindowControlsZOrder();
|
|
|
| - // Toggle overlay, then verify z order.
|
| + // Verify z order in and out of overlay.
|
| [controller() showOverlay];
|
| + VerifyWindowControlsZOrder();
|
| [controller() removeOverlay];
|
| - VerifyTrafficLightZOrder();
|
| + VerifyWindowControlsZOrder();
|
|
|
| - // Toggle immersive fullscreen, then verify z order.
|
| + // Toggle immersive fullscreen, then verify z order. In immersive fullscreen,
|
| + // there are no window controls.
|
| [controller() enterImmersiveFullscreen];
|
| [controller() exitImmersiveFullscreen];
|
| - VerifyTrafficLightZOrder();
|
| + VerifyWindowControlsZOrder();
|
| }
|
|
|