diff options
author | erikchen <erikchen@chromium.org> | 2014-10-10 12:56:44 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-10 19:56:54 +0000 |
commit | 9fa914507cbcce4fb7f05501106d0a5183d3dff9 (patch) | |
tree | 733a7c20de8c5138ac0d103c92456ed2c3176137 /chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm | |
parent | 22c781e61a21d95a102e0e72c76f05c2bbe58093 (diff) | |
download | chromium_src-9fa914507cbcce4fb7f05501106d0a5183d3dff9.zip chromium_src-9fa914507cbcce4fb7f05501106d0a5183d3dff9.tar.gz chromium_src-9fa914507cbcce4fb7f05501106d0a5183d3dff9.tar.bz2 |
mac: Use a full-size content view (reland 1).
The original attempt to land the CL incorrectly interacted with another
recently landed CL that added the tabStripBackgroundView
(https://codereview.chromium.org/611453004). This CL was causing that view to
become layer backed, which caused it to draw on top of non-layer backed window
content, including the window controls.
This reland reworks the logic so that the tabStripBackgroundView is added to
the root view and does not become layer backed. This reland also updates
browser_tests to catch similar such errors in the future.
--------------Original CL Description---------------
Make the window's contentView have the same size as the window itself. Adjust
the view hierarchy so that Chrome does not add subviews directly to the root
view.
By default, the contentView does not occupy the full size of a framed window.
Chrome still wants to draw in the title bar. Historically, Chrome has done this
by adding subviews directly to the root view. This causes several problems. The
most egregious is related to layer ordering when the root view does not have a
layer. By making the window's contentView full-sized, there is no longer any
need to add subviews to the root view.
I deleted the tests in presentation_mode_controller_unittest.mm since they were
layout tests for the browser_window_controller, but the tests in
browser_window_layout_unittest.mm are both more robust and more comprehensive.
I fixed a bug in moveViewsForImmersiveFullscreen:... where the tabStripView was
being added to the source window rather than the destination window.
This CL is mostly a reland of https://codereview.chromium.org/399803002/.
Original CL Committed: https://crrev.com/746dbb9cfefaac243704956db431ff9bb9b0485b
Original CL Cr-Commit-Position: refs/heads/master@{#298584}
BUG=417923
Review URL: https://codereview.chromium.org/646703002
Cr-Commit-Position: refs/heads/master@{#299168}
Diffstat (limited to 'chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm')
-rw-r--r-- | chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm | 141 |
1 files changed, 120 insertions, 21 deletions
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm b/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm index c8c0e22..a01111c 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(); } |