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 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h" 6 7#include "ash/ash_constants.h" 8#include "ash/ash_switches.h" 9#include "ash/frame/caption_buttons/frame_caption_button_container_view.h" 10#include "ash/frame/header_painter.h" 11#include "ash/shell.h" 12#include "ash/wm/maximize_mode/maximize_mode_controller.h" 13#include "base/command_line.h" 14#include "chrome/browser/ui/browser.h" 15#include "chrome/browser/ui/browser_commands.h" 16#include "chrome/browser/ui/fullscreen/fullscreen_controller.h" 17#include "chrome/browser/ui/fullscreen/fullscreen_controller_test.h" 18#include "chrome/browser/ui/views/frame/browser_view.h" 19#include "chrome/browser/ui/views/frame/immersive_mode_controller.h" 20#include "chrome/browser/ui/views/tabs/tab.h" 21#include "chrome/test/base/in_process_browser_test.h" 22#include "ui/base/hit_test.h" 23#include "ui/compositor/scoped_animation_duration_scale_mode.h" 24#include "ui/views/widget/widget.h" 25 26using views::Widget; 27 28typedef InProcessBrowserTest BrowserNonClientFrameViewAshTest; 29 30IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest, NonClientHitTest) { 31 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); 32 Widget* widget = browser_view->GetWidget(); 33 // We know we're using Ash, so static cast. 34 BrowserNonClientFrameViewAsh* frame_view = 35 static_cast<BrowserNonClientFrameViewAsh*>( 36 widget->non_client_view()->frame_view()); 37 38 // Click on the top edge of a restored window hits the top edge resize handle. 39 const int kWindowWidth = 300; 40 const int kWindowHeight = 290; 41 widget->SetBounds(gfx::Rect(10, 10, kWindowWidth, kWindowHeight)); 42 gfx::Point top_edge(kWindowWidth / 2, 0); 43 EXPECT_EQ(HTTOP, frame_view->NonClientHitTest(top_edge)); 44 45 // Click just below the resize handle hits the caption. 46 gfx::Point below_resize(kWindowWidth / 2, ash::kResizeInsideBoundsSize); 47 EXPECT_EQ(HTCAPTION, frame_view->NonClientHitTest(below_resize)); 48 49 // Click in the top edge of a maximized window now hits the client area, 50 // because we want it to fall through to the tab strip and select a tab. 51 widget->Maximize(); 52 EXPECT_EQ(HTCLIENT, frame_view->NonClientHitTest(top_edge)); 53} 54 55// Test that the frame view does not do any painting in non-immersive 56// fullscreen. 57IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest, 58 NonImmersiveFullscreen) { 59 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); 60 content::WebContents* web_contents = browser_view->GetActiveWebContents(); 61 Widget* widget = browser_view->GetWidget(); 62 // We know we're using Ash, so static cast. 63 BrowserNonClientFrameViewAsh* frame_view = 64 static_cast<BrowserNonClientFrameViewAsh*>( 65 widget->non_client_view()->frame_view()); 66 67 // Frame paints by default. 68 EXPECT_TRUE(frame_view->ShouldPaint()); 69 70 // No painting should occur in non-immersive fullscreen. (We enter into tab 71 // fullscreen here because tab fullscreen is non-immersive even on ChromeOS). 72 { 73 // NOTIFICATION_FULLSCREEN_CHANGED is sent asynchronously. 74 scoped_ptr<FullscreenNotificationObserver> waiter( 75 new FullscreenNotificationObserver()); 76 browser()->fullscreen_controller()->ToggleFullscreenModeForTab( 77 web_contents, true); 78 waiter->Wait(); 79 } 80 EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); 81 EXPECT_FALSE(frame_view->ShouldPaint()); 82 83 // The client view abuts top of the window. 84 EXPECT_EQ(0, frame_view->GetBoundsForClientView().y()); 85 86 // The frame should be painted again when fullscreen is exited and the caption 87 // buttons should be visible. 88 { 89 scoped_ptr<FullscreenNotificationObserver> waiter( 90 new FullscreenNotificationObserver()); 91 chrome::ToggleFullscreenMode(browser()); 92 waiter->Wait(); 93 } 94 EXPECT_TRUE(frame_view->ShouldPaint()); 95 EXPECT_TRUE(frame_view->caption_button_container_->visible()); 96} 97 98// TODO(zturner): Change this to USE_ASH after fixing the test on Windows. 99#if defined(OS_CHROMEOS) 100IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest, ImmersiveFullscreen) { 101 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); 102 content::WebContents* web_contents = browser_view->GetActiveWebContents(); 103 Widget* widget = browser_view->GetWidget(); 104 // We know we're using Ash, so static cast. 105 BrowserNonClientFrameViewAsh* frame_view = 106 static_cast<BrowserNonClientFrameViewAsh*>( 107 widget->non_client_view()->frame_view()); 108 109 ImmersiveModeController* immersive_mode_controller = 110 browser_view->immersive_mode_controller(); 111 immersive_mode_controller->SetupForTest(); 112 113 // Immersive fullscreen starts disabled. 114 ASSERT_FALSE(widget->IsFullscreen()); 115 EXPECT_FALSE(immersive_mode_controller->IsEnabled()); 116 117 // Frame paints by default. 118 EXPECT_TRUE(frame_view->ShouldPaint()); 119 EXPECT_LT(Tab::GetImmersiveHeight(), 120 frame_view->header_painter_->GetHeaderHeightForPainting()); 121 122 // Enter both browser fullscreen and tab fullscreen. Entering browser 123 // fullscreen should enable immersive fullscreen. 124 { 125 // NOTIFICATION_FULLSCREEN_CHANGED is sent asynchronously. 126 scoped_ptr<FullscreenNotificationObserver> waiter( 127 new FullscreenNotificationObserver()); 128 chrome::ToggleFullscreenMode(browser()); 129 waiter->Wait(); 130 } 131 { 132 scoped_ptr<FullscreenNotificationObserver> waiter( 133 new FullscreenNotificationObserver()); 134 browser()->fullscreen_controller()->ToggleFullscreenModeForTab( 135 web_contents, true); 136 waiter->Wait(); 137 } 138 EXPECT_TRUE(immersive_mode_controller->IsEnabled()); 139 140 // An immersive reveal shows the buttons and the top of the frame. 141 scoped_ptr<ImmersiveRevealedLock> revealed_lock( 142 immersive_mode_controller->GetRevealedLock( 143 ImmersiveModeController::ANIMATE_REVEAL_NO)); 144 EXPECT_TRUE(immersive_mode_controller->IsRevealed()); 145 EXPECT_TRUE(frame_view->ShouldPaint()); 146 EXPECT_TRUE(frame_view->caption_button_container_->visible()); 147 EXPECT_FALSE(frame_view->UseImmersiveLightbarHeaderStyle()); 148 149 // End the reveal. When in both immersive browser fullscreen and tab 150 // fullscreen, the tab lightbars should not be painted. 151 revealed_lock.reset(); 152 EXPECT_FALSE(immersive_mode_controller->IsRevealed()); 153 EXPECT_FALSE(frame_view->ShouldPaint()); 154 EXPECT_EQ(0, frame_view->header_painter_->GetHeaderHeightForPainting()); 155 156 // Repeat test but without tab fullscreen. The tab lightbars should now show 157 // when the top-of-window views are not revealed. 158 { 159 scoped_ptr<FullscreenNotificationObserver> waiter( 160 new FullscreenNotificationObserver()); 161 browser()->fullscreen_controller()->ToggleFullscreenModeForTab( 162 web_contents, false); 163 waiter->Wait(); 164 } 165 166 // Immersive reveal should have same behavior as before. 167 revealed_lock.reset(immersive_mode_controller->GetRevealedLock( 168 ImmersiveModeController::ANIMATE_REVEAL_NO)); 169 EXPECT_TRUE(immersive_mode_controller->IsRevealed()); 170 EXPECT_TRUE(frame_view->ShouldPaint()); 171 EXPECT_TRUE(frame_view->caption_button_container_->visible()); 172 EXPECT_FALSE(frame_view->UseImmersiveLightbarHeaderStyle()); 173 EXPECT_LT(Tab::GetImmersiveHeight(), 174 frame_view->header_painter_->GetHeaderHeightForPainting()); 175 176 // Ending the reveal should hide the caption buttons and the header should 177 // be in the lightbar style. 178 revealed_lock.reset(); 179 EXPECT_TRUE(frame_view->ShouldPaint()); 180 EXPECT_FALSE(frame_view->caption_button_container_->visible()); 181 EXPECT_TRUE(frame_view->UseImmersiveLightbarHeaderStyle()); 182 EXPECT_EQ(Tab::GetImmersiveHeight(), 183 frame_view->header_painter_->GetHeaderHeightForPainting()); 184 185 // Exiting immersive fullscreen should make the caption buttons and the frame 186 // visible again. 187 { 188 scoped_ptr<FullscreenNotificationObserver> waiter( 189 new FullscreenNotificationObserver()); 190 browser_view->ExitFullscreen(); 191 waiter->Wait(); 192 } 193 EXPECT_FALSE(immersive_mode_controller->IsEnabled()); 194 EXPECT_TRUE(frame_view->ShouldPaint()); 195 EXPECT_TRUE(frame_view->caption_button_container_->visible()); 196 EXPECT_FALSE(frame_view->UseImmersiveLightbarHeaderStyle()); 197 EXPECT_LT(Tab::GetImmersiveHeight(), 198 frame_view->header_painter_->GetHeaderHeightForPainting()); 199} 200#endif // defined(OS_CHROMEOS) 201 202// Tests that FrameCaptionButtonContainer has been relaid out in response to 203// maximize mode being toggled. 204IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest, 205 ToggleMaximizeModeRelayout) { 206 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); 207 Widget* widget = browser_view->GetWidget(); 208 // We know we're using Ash, so static cast. 209 BrowserNonClientFrameViewAsh* frame_view = 210 static_cast<BrowserNonClientFrameViewAsh*>( 211 widget->non_client_view()->frame_view()); 212 213 const gfx::Rect initial = frame_view->caption_button_container_->bounds(); 214 ash::Shell::GetInstance()->maximize_mode_controller()-> 215 EnableMaximizeModeWindowManager(true); 216 ash::FrameCaptionButtonContainerView::TestApi test(frame_view-> 217 caption_button_container_); 218 test.EndAnimations(); 219 const gfx::Rect during_maximize = frame_view->caption_button_container_-> 220 bounds(); 221 EXPECT_GT(initial.width(), during_maximize.width()); 222 ash::Shell::GetInstance()->maximize_mode_controller()-> 223 EnableMaximizeModeWindowManager(false); 224 test.EndAnimations(); 225 const gfx::Rect after_restore = frame_view->caption_button_container_-> 226 bounds(); 227 EXPECT_EQ(initial, after_restore); 228} 229