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() {} | |
| 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: | |
|
Andre
2014/10/10 18:08:49
DISALLOW_COPY_AND_ASSIGN
erikchen
2014/10/10 18:19:11
Done. (Moved to end of class, since that's the com
| |
| 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_) { | |
|
Andre
2014/10/10 18:08:49
I think you may be able to move the code from abov
erikchen
2014/10/10 18:19:11
That doesn't sound accurate. The first view passed
Andre
2014/10/10 18:22:20
Got it.
| |
| 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. | |
| 153 BOOL below_exposed_view_; | |
|
Andre
2014/10/10 18:08:49
This should be initialized in constructor to avoid
erikchen
2014/10/10 18:19:11
Done.
| |
| 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 | |
| 71 } // namespace | 160 } // namespace |
| 72 | 161 |
| 73 @interface InfoBarContainerController(TestingAPI) | 162 @interface InfoBarContainerController(TestingAPI) |
| 74 - (BOOL)isTopInfoBarAnimationRunning; | 163 - (BOOL)isTopInfoBarAnimationRunning; |
| 75 @end | 164 @end |
| 76 | 165 |
| 77 @implementation InfoBarContainerController(TestingAPI) | 166 @implementation InfoBarContainerController(TestingAPI) |
| 78 - (BOOL)isTopInfoBarAnimationRunning { | 167 - (BOOL)isTopInfoBarAnimationRunning { |
| 79 InfoBarController* infoBarController = [infobarControllers_ objectAtIndex:0]; | 168 InfoBarController* infoBarController = [infobarControllers_ objectAtIndex:0]; |
| 80 if (infoBarController) { | 169 if (infoBarController) { |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 216 NSPoint icon_bottom = location_bar_view->GetPageInfoBubblePoint(); | 305 NSPoint icon_bottom = location_bar_view->GetPageInfoBubblePoint(); |
| 217 | 306 |
| 218 NSPoint info_bar_top = NSMakePoint(0, | 307 NSPoint info_bar_top = NSMakePoint(0, |
| 219 NSHeight([info_bar_container_controller view].frame) - | 308 NSHeight([info_bar_container_controller view].frame) - |
| 220 overlapping_tip_height); | 309 overlapping_tip_height); |
| 221 info_bar_top = [[info_bar_container_controller view] | 310 info_bar_top = [[info_bar_container_controller view] |
| 222 convertPoint:info_bar_top toView:nil]; | 311 convertPoint:info_bar_top toView:nil]; |
| 223 return icon_bottom.y - info_bar_top.y; | 312 return icon_bottom.y - info_bar_top.y; |
| 224 } | 313 } |
| 225 | 314 |
| 226 // The traffic lights should always be in front of the content view and the | 315 // Nothing should draw on top of the window controls. |
| 227 // tab strip view. Since the traffic lights change across OSX versions, this | 316 void VerifyWindowControlsZOrder() { |
| 228 // test verifies that the contentView is in the back, and if the tab strip | 317 NSWindow* window = [controller() window]; |
| 229 // view is a sibling, it is directly in front of the content view. | 318 ViewExposedChecker checker; |
| 230 void VerifyTrafficLightZOrder() const { | |
| 231 NSView* contentView = [[controller() window] contentView]; | |
| 232 NSView* rootView = [contentView superview]; | |
| 233 NSArray* subviews = [rootView subviews]; | |
| 234 | 319 |
| 235 EXPECT_EQ([controller() tabStripBackgroundView], | 320 // The exceptions are the contentView, chromeContentView and tabStripView, |
| 236 [subviews objectAtIndex:0]); | 321 // which are layer backed but transparent. |
| 237 EXPECT_EQ(contentView, [subviews objectAtIndex:1]); | 322 NSArray* exceptions = @[ |
| 323 [window contentView], | |
| 324 controller().chromeContentView, | |
| 325 controller().tabStripView | |
| 326 ]; | |
| 327 checker.SetExceptions(exceptions); | |
| 238 | 328 |
| 239 NSView* tabStripView = [controller() tabStripView]; | 329 checker.CheckViewExposed([window standardWindowButton:NSWindowCloseButton]); |
| 240 if ([subviews containsObject:tabStripView]) | 330 checker.CheckViewExposed( |
| 241 EXPECT_EQ(tabStripView, [subviews objectAtIndex:2]); | 331 [window standardWindowButton:NSWindowMiniaturizeButton]); |
| 332 checker.CheckViewExposed([window standardWindowButton:NSWindowZoomButton]); | |
| 333 | |
| 334 // There is no fullscreen button on OSX 10.6 or OSX 10.10+. | |
| 335 NSView* view = [window standardWindowButton:NSWindowFullScreenButton]; | |
| 336 if (view) | |
| 337 checker.CheckViewExposed(view); | |
| 242 } | 338 } |
| 243 | 339 |
| 244 private: | 340 private: |
| 245 DISALLOW_COPY_AND_ASSIGN(BrowserWindowControllerTest); | 341 DISALLOW_COPY_AND_ASSIGN(BrowserWindowControllerTest); |
| 246 }; | 342 }; |
| 247 | 343 |
| 248 // Tests that adding the first profile moves the Lion fullscreen button over | 344 // Tests that adding the first profile moves the Lion fullscreen button over |
| 249 // correctly. | 345 // correctly. |
| 250 // DISABLED_ because it regularly times out: http://crbug.com/159002. | 346 // DISABLED_ because it regularly times out: http://crbug.com/159002. |
| 251 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, | 347 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 493 | 589 |
| 494 chrome::ExecuteCommand(browser(), IDC_SHOW_BOOKMARK_BAR); | 590 chrome::ExecuteCommand(browser(), IDC_SHOW_BOOKMARK_BAR); |
| 495 WaitForBookmarkBarAnimationToFinish(); | 591 WaitForBookmarkBarAnimationToFinish(); |
| 496 EXPECT_FALSE([controller() isBookmarkBarVisible]); | 592 EXPECT_FALSE([controller() isBookmarkBarVisible]); |
| 497 EXPECT_EQ(std::min(GetExpectedTopInfoBarTipHeight(), max_tip_height), | 593 EXPECT_EQ(std::min(GetExpectedTopInfoBarTipHeight(), max_tip_height), |
| 498 [[controller() infoBarContainerController] overlappingTipHeight]); | 594 [[controller() infoBarContainerController] overlappingTipHeight]); |
| 499 } | 595 } |
| 500 | 596 |
| 501 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, TrafficLightZOrder) { | 597 IN_PROC_BROWSER_TEST_F(BrowserWindowControllerTest, TrafficLightZOrder) { |
| 502 // Verify z order immediately after creation. | 598 // Verify z order immediately after creation. |
| 503 VerifyTrafficLightZOrder(); | 599 VerifyWindowControlsZOrder(); |
| 504 | 600 |
| 505 // Toggle overlay, then verify z order. | 601 // Verify z order in and out of overlay. |
| 506 [controller() showOverlay]; | 602 [controller() showOverlay]; |
| 603 VerifyWindowControlsZOrder(); | |
| 507 [controller() removeOverlay]; | 604 [controller() removeOverlay]; |
| 508 VerifyTrafficLightZOrder(); | 605 VerifyWindowControlsZOrder(); |
| 509 | 606 |
| 510 // Toggle immersive fullscreen, then verify z order. | 607 // Toggle immersive fullscreen, then verify z order. In immersive fullscreen, |
| 608 // there are no window controls. | |
| 511 [controller() enterImmersiveFullscreen]; | 609 [controller() enterImmersiveFullscreen]; |
| 512 [controller() exitImmersiveFullscreen]; | 610 [controller() exitImmersiveFullscreen]; |
| 513 VerifyTrafficLightZOrder(); | 611 VerifyWindowControlsZOrder(); |
| 514 } | 612 } |
| OLD | NEW |