Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/ui/cocoa/browser_window_controller.h" | 5 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
| 6 | 6 |
| 7 #import "base/mac/mac_util.h" | 7 #import "base/mac/mac_util.h" |
| 8 #include "base/mac/sdk_forward_declarations.h" | 8 #include "base/mac/sdk_forward_declarations.h" |
| 9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 61 VIEW_ID_TOOLBAR, | 61 VIEW_ID_TOOLBAR, |
| 62 VIEW_ID_BOOKMARK_BAR, | 62 VIEW_ID_BOOKMARK_BAR, |
| 63 VIEW_ID_INFO_BAR, | 63 VIEW_ID_INFO_BAR, |
| 64 VIEW_ID_FIND_BAR, | 64 VIEW_ID_FIND_BAR, |
| 65 VIEW_ID_DOWNLOAD_SHELF, | 65 VIEW_ID_DOWNLOAD_SHELF, |
| 66 VIEW_ID_TAB_CONTENT_AREA, | 66 VIEW_ID_TAB_CONTENT_AREA, |
| 67 VIEW_ID_FULLSCREEN_FLOATING_BAR, | 67 VIEW_ID_FULLSCREEN_FLOATING_BAR, |
| 68 VIEW_ID_COUNT, | 68 VIEW_ID_COUNT, |
| 69 }; | 69 }; |
| 70 | 70 |
| 71 // Checks that no views draw on top of the supposedly exposed view. | |
| 72 class ViewExposedChecker { | |
| 73 public: | |
| 74 ViewExposedChecker() : below_exposed_view_(YES) {} | |
| 75 ~ViewExposedChecker() {} | |
| 76 | |
| 77 void SetExceptions(NSArray* exceptions) { | |
| 78 exceptions_.reset([exceptions retain]); | |
| 79 } | |
| 80 | |
| 81 // Checks that no views draw in front of |view|, with the exception of | |
| 82 // |exceptions|. | |
| 83 void CheckViewExposed(NSView* view) { | |
| 84 below_exposed_view_ = YES; | |
| 85 exposed_view_.reset([view retain]); | |
| 86 CheckViewsDoNotObscure([[[view window] contentView] superview]); | |
| 87 } | |
| 88 | |
| 89 private: | |
| 90 // Checks that |view| does not draw on top of |exposed_view_|. | |
| 91 void CheckViewDoesNotObscure(NSView* view) { | |
| 92 NSRect viewWindowFrame = [view convertRect:[view bounds] toView:nil]; | |
| 93 NSRect viewBeingVerifiedWindowFrame = | |
| 94 [exposed_view_ convertRect:[exposed_view_ bounds] toView:nil]; | |
| 95 | |
| 96 // The views do not intersect. | |
| 97 if (!NSIntersectsRect(viewBeingVerifiedWindowFrame, viewWindowFrame)) | |
| 98 return; | |
| 99 | |
| 100 // No view can be above the view being checked. | |
| 101 EXPECT_TRUE(below_exposed_view_); | |
| 102 | |
| 103 // If |view| is a parent of |exposed_view_|, then there's nothing else | |
| 104 // to check. | |
| 105 NSView* parent = exposed_view_; | |
| 106 while (parent != nil) { | |
| 107 parent = [parent superview]; | |
| 108 if (parent == view) | |
| 109 return; | |
| 110 } | |
| 111 | |
| 112 if ([exposed_view_ layer]) | |
| 113 return; | |
| 114 | |
| 115 // If the view being verified doesn't have a layer, then no views that | |
| 116 // intersect it can have a layer. | |
| 117 if ([exceptions_ containsObject:view]) { | |
| 118 EXPECT_FALSE([view isOpaque]); | |
| 119 return; | |
| 120 } | |
| 121 | |
| 122 EXPECT_TRUE(![view layer]) << [[view description] UTF8String] << " " << | |
| 123 [NSStringFromRect(viewWindowFrame) UTF8String]; | |
| 124 } | |
| 125 | |
| 126 // Recursively checks that |view| and its subviews do not draw on top of | |
| 127 // |exposed_view_|. The recursion passes through all views in order of | |
| 128 // back-most in Z-order to front-most in Z-order. | |
| 129 void CheckViewsDoNotObscure(NSView* view) { | |
| 130 // If this is the view being checked, don't recurse into its subviews. All | |
| 131 // future views encountered in the recursion are in front of the view being | |
| 132 // checked. | |
| 133 if (view == exposed_view_) { | |
| 134 below_exposed_view_ = NO; | |
| 135 return; | |
| 136 } | |
| 137 | |
| 138 CheckViewDoesNotObscure(view); | |
| 139 | |
| 140 // Perform the recursion. | |
| 141 for (NSView* subview in [view subviews]) | |
| 142 CheckViewsDoNotObscure(subview); | |
| 143 } | |
| 144 | |
| 145 // The method CheckViewExposed() recurses through the views in the view | |
| 146 // hierarchy and checks that none of the views obscure |exposed_view_|. | |
| 147 base::scoped_nsobject<NSView> exposed_view_; | |
| 148 | |
| 149 // While this flag is true, the views being recursed through are below | |
| 150 // |exposed_view_| in Z-order. After the recursion passes |exposed_view_|, | |
| 151 // this | |
| 152 // flag is set to false. | |
|
Avi (use Gerrit)
2014/10/10 18:30:29
Weird wrapping.
erikchen
2014/10/10 18:33:15
Fixed
| |
| 153 BOOL below_exposed_view_; | |
| 154 | |
| 155 // Exceptions are allowed to overlap |exposed_view_|. Exceptions must still | |
| 156 // be Z-order behind |exposed_view_|. | |
| 157 base::scoped_nsobject<NSArray> exceptions_; | |
| 158 | |
| 159 DISALLOW_COPY_AND_ASSIGN(ViewExposedChecker); | |
| 160 }; | |
| 161 | |
| 71 } // namespace | 162 } // namespace |
| 72 | 163 |
| 73 @interface InfoBarContainerController(TestingAPI) | 164 @interface InfoBarContainerController(TestingAPI) |
| 74 - (BOOL)isTopInfoBarAnimationRunning; | 165 - (BOOL)isTopInfoBarAnimationRunning; |
| 75 @end | 166 @end |
| 76 | 167 |
| 77 @implementation InfoBarContainerController(TestingAPI) | 168 @implementation InfoBarContainerController(TestingAPI) |
| 78 - (BOOL)isTopInfoBarAnimationRunning { | 169 - (BOOL)isTopInfoBarAnimationRunning { |
| 79 InfoBarController* infoBarController = [infobarControllers_ objectAtIndex:0]; | 170 InfoBarController* infoBarController = [infobarControllers_ objectAtIndex:0]; |
| 80 if (infoBarController) { | 171 if (infoBarController) { |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 216 NSPoint icon_bottom = location_bar_view->GetPageInfoBubblePoint(); | 307 NSPoint icon_bottom = location_bar_view->GetPageInfoBubblePoint(); |
| 217 | 308 |
| 218 NSPoint info_bar_top = NSMakePoint(0, | 309 NSPoint info_bar_top = NSMakePoint(0, |
| 219 NSHeight([info_bar_container_controller view].frame) - | 310 NSHeight([info_bar_container_controller view].frame) - |
| 220 overlapping_tip_height); | 311 overlapping_tip_height); |
| 221 info_bar_top = [[info_bar_container_controller view] | 312 info_bar_top = [[info_bar_container_controller view] |
| 222 convertPoint:info_bar_top toView:nil]; | 313 convertPoint:info_bar_top toView:nil]; |
| 223 return icon_bottom.y - info_bar_top.y; | 314 return icon_bottom.y - info_bar_top.y; |
| 224 } | 315 } |
| 225 | 316 |
| 226 // The traffic lights should always be in front of the content view and the | 317 // Nothing should draw on top of the window controls. |
| 227 // tab strip view. Since the traffic lights change across OSX versions, this | 318 void VerifyWindowControlsZOrder() { |
| 228 // test verifies that the contentView is in the back, and if the tab strip | 319 NSWindow* window = [controller() window]; |
| 229 // view is a sibling, it is directly in front of the content view. | 320 ViewExposedChecker checker; |
| 230 void VerifyTrafficLightZOrder() const { | |
| 231 NSView* contentView = [[controller() window] contentView]; | |
| 232 NSView* rootView = [contentView superview]; | |
| 233 NSArray* subviews = [rootView subviews]; | |
| 234 | 321 |
| 235 EXPECT_EQ([controller() tabStripBackgroundView], | 322 // The exceptions are the contentView, chromeContentView and tabStripView, |
| 236 [subviews objectAtIndex:0]); | 323 // which are layer backed but transparent. |
| 237 EXPECT_EQ(contentView, [subviews objectAtIndex:1]); | 324 NSArray* exceptions = @[ |
| 325 [window contentView], | |
| 326 controller().chromeContentView, | |
| 327 controller().tabStripView | |
| 328 ]; | |
| 329 checker.SetExceptions(exceptions); | |
| 238 | 330 |
| 239 NSView* tabStripView = [controller() tabStripView]; | 331 checker.CheckViewExposed([window standardWindowButton:NSWindowCloseButton]); |
| 240 if ([subviews containsObject:tabStripView]) | 332 checker.CheckViewExposed( |
| 241 EXPECT_EQ(tabStripView, [subviews objectAtIndex:2]); | 333 [window standardWindowButton:NSWindowMiniaturizeButton]); |
| 334 checker.CheckViewExposed([window standardWindowButton:NSWindowZoomButton]); | |
| 335 | |
| 336 // There is no fullscreen button on OSX 10.6 or OSX 10.10+. | |
| 337 NSView* view = [window standardWindowButton:NSWindowFullScreenButton]; | |
| 338 if (view) | |
| 339 checker.CheckViewExposed(view); | |
| 242 } | 340 } |
| 243 | 341 |
| 244 private: | 342 private: |
| 245 DISALLOW_COPY_AND_ASSIGN(BrowserWindowControllerTest); | 343 DISALLOW_COPY_AND_ASSIGN(BrowserWindowControllerTest); |
| 246 }; | 344 }; |
| 247 | 345 |
| 248 // Tests that adding the first profile moves the Lion fullscreen button over | 346 // Tests that adding the first profile moves the Lion fullscreen button over |
| 249 // correctly. | 347 // correctly. |
| 250 // DISABLED_ because it regularly times out: http://crbug.com/159002. | 348 // DISABLED_ because it regularly times out: http://crbug.com/159002. |
| 251 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, | 349 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 493 | 591 |
| 494 chrome::ExecuteCommand(browser(), IDC_SHOW_BOOKMARK_BAR); | 592 chrome::ExecuteCommand(browser(), IDC_SHOW_BOOKMARK_BAR); |
| 495 WaitForBookmarkBarAnimationToFinish(); | 593 WaitForBookmarkBarAnimationToFinish(); |
| 496 EXPECT_FALSE([controller() isBookmarkBarVisible]); | 594 EXPECT_FALSE([controller() isBookmarkBarVisible]); |
| 497 EXPECT_EQ(std::min(GetExpectedTopInfoBarTipHeight(), max_tip_height), | 595 EXPECT_EQ(std::min(GetExpectedTopInfoBarTipHeight(), max_tip_height), |
| 498 [[controller() infoBarContainerController] overlappingTipHeight]); | 596 [[controller() infoBarContainerController] overlappingTipHeight]); |
| 499 } | 597 } |
| 500 | 598 |
| 501 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, TrafficLightZOrder) { | 599 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, TrafficLightZOrder) { |
| 502 // Verify z order immediately after creation. | 600 // Verify z order immediately after creation. |
| 503 VerifyTrafficLightZOrder(); | 601 VerifyWindowControlsZOrder(); |
| 504 | 602 |
| 505 // Toggle overlay, then verify z order. | 603 // Verify z order in and out of overlay. |
| 506 [controller() showOverlay]; | 604 [controller() showOverlay]; |
| 605 VerifyWindowControlsZOrder(); | |
| 507 [controller() removeOverlay]; | 606 [controller() removeOverlay]; |
| 508 VerifyTrafficLightZOrder(); | 607 VerifyWindowControlsZOrder(); |
| 509 | 608 |
| 510 // Toggle immersive fullscreen, then verify z order. | 609 // Toggle immersive fullscreen, then verify z order. In immersive fullscreen, |
| 610 // there are no window controls. | |
| 511 [controller() enterImmersiveFullscreen]; | 611 [controller() enterImmersiveFullscreen]; |
| 512 [controller() exitImmersiveFullscreen]; | 612 [controller() exitImmersiveFullscreen]; |
| 513 VerifyTrafficLightZOrder(); | 613 VerifyWindowControlsZOrder(); |
| 514 } | 614 } |
| OLD | NEW |