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 "base/command_line.h" 10 #include "chrome/browser/ui/browser.h" 11 #include "chrome/browser/ui/browser_commands.h" 12 #include "chrome/browser/ui/fullscreen/fullscreen_controller.h" 13 #include "chrome/browser/ui/fullscreen/fullscreen_controller_test.h" 14 #include "chrome/browser/ui/immersive_fullscreen_configuration.h" 15 #include "chrome/browser/ui/views/frame/browser_view.h" 16 #include "chrome/browser/ui/views/frame/immersive_mode_controller_ash.h" 17 #include "chrome/test/base/in_process_browser_test.h" 18 #include "ui/base/hit_test.h" 19 #include "ui/compositor/scoped_animation_duration_scale_mode.h" 20 #include "ui/views/controls/button/image_button.h" 21 #include "ui/views/widget/widget.h" 22 23 using views::Widget; 24 25 typedef InProcessBrowserTest BrowserNonClientFrameViewAshTest; 26 27 IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest, WindowHeader) { 28 // We know we're using Views, so static cast. 29 BrowserView* browser_view = static_cast<BrowserView*>(browser()->window()); 30 Widget* widget = browser_view->GetWidget(); 31 // We know we're using Ash, so static cast. 32 BrowserNonClientFrameViewAsh* frame_view = 33 static_cast<BrowserNonClientFrameViewAsh*>( 34 widget->non_client_view()->frame_view()); 35 36 // Restored window uses tall header. 37 const int kWindowWidth = 300; 38 const int kWindowHeight = 290; 39 widget->SetBounds(gfx::Rect(10, 10, kWindowWidth, kWindowHeight)); 40 EXPECT_FALSE(frame_view->UseShortHeader()); 41 42 // Click on the top edge of a window hits the top edge resize handle. 43 gfx::Point top_edge(kWindowWidth / 2, 0); 44 EXPECT_EQ(HTTOP, frame_view->NonClientHitTest(top_edge)); 45 46 // Click just below the resize handle hits the caption. 47 gfx::Point below_resize(kWindowWidth / 2, ash::kResizeInsideBoundsSize); 48 EXPECT_EQ(HTCAPTION, frame_view->NonClientHitTest(below_resize)); 49 50 // Window at top of screen uses normal header. 51 widget->SetBounds(gfx::Rect(10, 0, kWindowWidth, kWindowHeight)); 52 EXPECT_FALSE(frame_view->UseShortHeader()); 53 54 // Maximized window uses short header. 55 widget->Maximize(); 56 EXPECT_TRUE(frame_view->UseShortHeader()); 57 58 // Click in the top edge of a maximized window now hits the client area, 59 // because we want it to fall through to the tab strip and select a tab. 60 EXPECT_EQ(HTCLIENT, frame_view->NonClientHitTest(top_edge)); 61 62 // Popups tall header. 63 Browser* popup = CreateBrowserForPopup(browser()->profile()); 64 Widget* popup_widget = 65 static_cast<BrowserView*>(popup->window())->GetWidget(); 66 BrowserNonClientFrameViewAsh* popup_frame_view = 67 static_cast<BrowserNonClientFrameViewAsh*>( 68 popup_widget->non_client_view()->frame_view()); 69 popup_widget->SetBounds(gfx::Rect(5, 5, 200, 200)); 70 EXPECT_FALSE(popup_frame_view->UseShortHeader()); 71 72 // Apps use tall header. 73 Browser* app = CreateBrowserForApp("name", browser()->profile()); 74 Widget* app_widget = 75 static_cast<BrowserView*>(app->window())->GetWidget(); 76 BrowserNonClientFrameViewAsh* app_frame_view = 77 static_cast<BrowserNonClientFrameViewAsh*>( 78 app_widget->non_client_view()->frame_view()); 79 app_widget->SetBounds(gfx::Rect(15, 15, 250, 250)); 80 EXPECT_FALSE(app_frame_view->UseShortHeader()); 81 } 82 83 // Test that the frame view does not do any painting in non-immersive 84 // fullscreen. 85 IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest, 86 NonImmersiveFullscreen) { 87 // We know we're using Views, so static cast. 88 BrowserView* browser_view = static_cast<BrowserView*>(browser()->window()); 89 content::WebContents* web_contents = browser_view->GetActiveWebContents(); 90 Widget* widget = browser_view->GetWidget(); 91 // We know we're using Ash, so static cast. 92 BrowserNonClientFrameViewAsh* frame_view = 93 static_cast<BrowserNonClientFrameViewAsh*>( 94 widget->non_client_view()->frame_view()); 95 96 // Frame paints by default. 97 EXPECT_TRUE(frame_view->ShouldPaint()); 98 99 // No painting should occur in non-immersive fullscreen. (We enter into tab 100 // fullscreen here because tab fullscreen is non-immersive even when 101 // ImmersiveFullscreenConfiguration::UseImmersiveFullscreen()) returns 102 // true. 103 { 104 // NOTIFICATION_FULLSCREEN_CHANGED is sent asynchronously. 105 scoped_ptr<FullscreenNotificationObserver> waiter( 106 new FullscreenNotificationObserver()); 107 browser()->fullscreen_controller()->ToggleFullscreenModeForTab( 108 web_contents, true); 109 waiter->Wait(); 110 } 111 EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); 112 EXPECT_FALSE(frame_view->ShouldPaint()); 113 114 // Frame abuts top of window. 115 EXPECT_EQ(0, frame_view->NonClientTopBorderHeight(false)); 116 117 // The frame should be painted again when fullscreen is exited and the caption 118 // buttons should be visible. 119 { 120 scoped_ptr<FullscreenNotificationObserver> waiter( 121 new FullscreenNotificationObserver()); 122 chrome::ToggleFullscreenMode(browser()); 123 waiter->Wait(); 124 } 125 EXPECT_TRUE(frame_view->ShouldPaint()); 126 EXPECT_TRUE(frame_view->size_button_->visible()); 127 EXPECT_TRUE(frame_view->close_button_->visible()); 128 } 129 130 IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest, ImmersiveFullscreen) { 131 if (!ImmersiveFullscreenConfiguration::UseImmersiveFullscreen()) 132 return; 133 134 // We know we're using Views, so static cast. 135 BrowserView* browser_view = static_cast<BrowserView*>(browser()->window()); 136 Widget* widget = browser_view->GetWidget(); 137 // We know we're using Ash, so static cast. 138 BrowserNonClientFrameViewAsh* frame_view = 139 static_cast<BrowserNonClientFrameViewAsh*>( 140 widget->non_client_view()->frame_view()); 141 142 ImmersiveModeControllerAsh* immersive_mode_controller = 143 static_cast<ImmersiveModeControllerAsh*>( 144 browser_view->immersive_mode_controller()); 145 immersive_mode_controller->DisableAnimationsForTest(); 146 immersive_mode_controller->SetForceHideTabIndicatorsForTest(true); 147 148 // Immersive mode starts disabled. 149 ASSERT_FALSE(widget->IsFullscreen()); 150 EXPECT_FALSE(immersive_mode_controller->IsEnabled()); 151 152 // Frame paints by default. 153 EXPECT_TRUE(frame_view->ShouldPaint()); 154 155 // Going fullscreen enables immersive mode. 156 chrome::ToggleFullscreenMode(browser()); 157 EXPECT_TRUE(immersive_mode_controller->IsEnabled()); 158 159 // An immersive reveal shows the buttons and the top of the frame. 160 immersive_mode_controller->StartRevealForTest(true); 161 EXPECT_TRUE(immersive_mode_controller->IsRevealed()); 162 EXPECT_TRUE(frame_view->ShouldPaint()); 163 EXPECT_TRUE(frame_view->size_button_->visible()); 164 EXPECT_TRUE(frame_view->close_button_->visible()); 165 EXPECT_TRUE(frame_view->UseShortHeader()); 166 EXPECT_FALSE(frame_view->UseImmersiveLightbarHeaderStyle()); 167 168 // End the reveal. As the header does not paint a light bar when the 169 // top-of-window views are not revealed, nothing should be painted. 170 immersive_mode_controller->SetMouseHoveredForTest(false); 171 EXPECT_FALSE(immersive_mode_controller->IsRevealed()); 172 EXPECT_FALSE(frame_view->ShouldPaint()); 173 174 // Frame abuts top of window. 175 EXPECT_EQ(0, frame_view->NonClientTopBorderHeight(false)); 176 177 // Repeat test but with the tab light bar visible when the top-of-window views 178 // are not revealed. 179 immersive_mode_controller->SetForceHideTabIndicatorsForTest(false); 180 181 // Immersive reveal should have same behavior as before. 182 immersive_mode_controller->StartRevealForTest(true); 183 EXPECT_TRUE(immersive_mode_controller->IsRevealed()); 184 EXPECT_TRUE(frame_view->ShouldPaint()); 185 EXPECT_TRUE(frame_view->size_button_->visible()); 186 EXPECT_TRUE(frame_view->close_button_->visible()); 187 EXPECT_TRUE(frame_view->UseShortHeader()); 188 EXPECT_FALSE(frame_view->UseImmersiveLightbarHeaderStyle()); 189 190 // Ending the reveal should hide the caption buttons and the header should 191 // be in the lightbar style. 192 immersive_mode_controller->SetMouseHoveredForTest(false); 193 EXPECT_TRUE(frame_view->ShouldPaint()); 194 EXPECT_FALSE(frame_view->size_button_->visible()); 195 EXPECT_FALSE(frame_view->close_button_->visible()); 196 EXPECT_TRUE(frame_view->UseShortHeader()); 197 EXPECT_TRUE(frame_view->UseImmersiveLightbarHeaderStyle()); 198 199 // Exiting fullscreen exits immersive mode. 200 browser_view->ExitFullscreen(); 201 EXPECT_FALSE(immersive_mode_controller->IsEnabled()); 202 203 // Exiting immersive mode makes controls and frame visible again. 204 EXPECT_TRUE(frame_view->ShouldPaint()); 205 EXPECT_TRUE(frame_view->size_button_->visible()); 206 EXPECT_TRUE(frame_view->close_button_->visible()); 207 EXPECT_FALSE(frame_view->UseImmersiveLightbarHeaderStyle()); 208 } 209