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 |