1 // Copyright 2014 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 "ash/frame/custom_frame_view_ash.h" 6 7 #include "ash/frame/caption_buttons/frame_caption_button.h" 8 #include "ash/frame/caption_buttons/frame_caption_button_container_view.h" 9 #include "ash/shell.h" 10 #include "ash/test/ash_test_base.h" 11 #include "ash/test/test_session_state_delegate.h" 12 #include "ash/wm/maximize_mode/maximize_mode_controller.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "grit/ash_resources.h" 15 #include "ui/base/resource/resource_bundle.h" 16 #include "ui/gfx/image/image_skia.h" 17 #include "ui/gfx/rect.h" 18 #include "ui/views/widget/widget.h" 19 #include "ui/views/widget/widget_delegate.h" 20 21 namespace ash { 22 23 // A views::WidgetDelegate which uses a CustomFrameViewAsh. 24 class TestWidgetDelegate : public views::WidgetDelegateView { 25 public: 26 TestWidgetDelegate() {} 27 virtual ~TestWidgetDelegate() {} 28 29 virtual views::NonClientFrameView* CreateNonClientFrameView( 30 views::Widget* widget) OVERRIDE { 31 custom_frame_view_ = new CustomFrameViewAsh(widget); 32 return custom_frame_view_; 33 } 34 35 CustomFrameViewAsh* custom_frame_view() const { 36 return custom_frame_view_; 37 } 38 39 private: 40 // Not owned. 41 CustomFrameViewAsh* custom_frame_view_; 42 43 DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate); 44 }; 45 46 class TestWidgetConstraintsDelegate : public TestWidgetDelegate { 47 public: 48 TestWidgetConstraintsDelegate() {} 49 virtual ~TestWidgetConstraintsDelegate() {} 50 51 // views::View: 52 virtual gfx::Size GetMinimumSize() const OVERRIDE { 53 return minimum_size_; 54 } 55 56 virtual gfx::Size GetMaximumSize() const OVERRIDE { 57 return maximum_size_; 58 } 59 60 virtual views::View* GetContentsView() OVERRIDE { 61 // Set this instance as the contents view so that the maximum and minimum 62 // size constraints will be used. 63 return this; 64 } 65 66 // views::WidgetDelegate: 67 virtual bool CanMaximize() const OVERRIDE { 68 return true; 69 } 70 71 virtual bool CanMinimize() const OVERRIDE { 72 return true; 73 } 74 75 void set_minimum_size(const gfx::Size& min_size) { 76 minimum_size_ = min_size; 77 } 78 79 void set_maximum_size(const gfx::Size& max_size) { 80 maximum_size_ = max_size; 81 } 82 83 const gfx::Rect& GetFrameCaptionButtonContainerViewBounds() { 84 return custom_frame_view()->GetFrameCaptionButtonContainerViewForTest()-> 85 bounds(); 86 } 87 88 void EndFrameCaptionButtonContainerViewAnimations() { 89 FrameCaptionButtonContainerView::TestApi test(custom_frame_view()-> 90 GetFrameCaptionButtonContainerViewForTest()); 91 test.EndAnimations(); 92 } 93 94 int GetTitleBarHeight() const { 95 return custom_frame_view()->NonClientTopBorderHeight(); 96 } 97 98 private: 99 gfx::Size minimum_size_; 100 gfx::Size maximum_size_; 101 102 DISALLOW_COPY_AND_ASSIGN(TestWidgetConstraintsDelegate); 103 }; 104 105 class CustomFrameViewAshTest : public test::AshTestBase { 106 public: 107 CustomFrameViewAshTest() {} 108 virtual ~CustomFrameViewAshTest() {} 109 110 protected: 111 scoped_ptr<views::Widget> CreateWidget(TestWidgetDelegate* delegate) { 112 scoped_ptr<views::Widget> widget(new views::Widget); 113 views::Widget::InitParams params; 114 params.delegate = delegate; 115 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 116 params.bounds = gfx::Rect(0, 0, 100, 100); 117 params.context = CurrentContext(); 118 widget->Init(params); 119 return widget.Pass(); 120 } 121 122 test::TestSessionStateDelegate* GetTestSessionStateDelegate() { 123 return static_cast<ash::test::TestSessionStateDelegate*>( 124 Shell::GetInstance()->session_state_delegate()); 125 } 126 127 private: 128 DISALLOW_COPY_AND_ASSIGN(CustomFrameViewAshTest); 129 }; 130 131 // Test that the height of the header is correct upon initially displaying 132 // the widget. 133 TEST_F(CustomFrameViewAshTest, HeaderHeight) { 134 TestWidgetDelegate* delegate = new TestWidgetDelegate; 135 136 scoped_ptr<views::Widget> widget(CreateWidget(delegate)); 137 widget->Show(); 138 139 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 140 gfx::ImageSkia* close_button = 141 rb.GetImageSkiaNamed(IDR_AURA_WINDOW_CONTROL_BACKGROUND_H); 142 143 // The header should have enough room for the window controls. The 144 // header/content separator line overlays the window controls. 145 EXPECT_EQ(close_button->height(), 146 delegate->custom_frame_view()->GetHeaderView()->height()); 147 } 148 149 // Verify that CustomFrameViewAsh returns the correct minimum and maximum frame 150 // sizes when the client view does not specify any size constraints. 151 TEST_F(CustomFrameViewAshTest, NoSizeConstraints) { 152 TestWidgetConstraintsDelegate* delegate = new TestWidgetConstraintsDelegate; 153 scoped_ptr<views::Widget> widget(CreateWidget(delegate)); 154 155 CustomFrameViewAsh* custom_frame_view = delegate->custom_frame_view(); 156 gfx::Size min_frame_size = custom_frame_view->GetMinimumSize(); 157 gfx::Size max_frame_size = custom_frame_view->GetMaximumSize(); 158 159 EXPECT_EQ(delegate->GetTitleBarHeight(), min_frame_size.height()); 160 161 // A width and height constraint of 0 denotes unbounded. 162 EXPECT_EQ(0, max_frame_size.width()); 163 EXPECT_EQ(0, max_frame_size.height()); 164 } 165 166 // Verify that CustomFrameViewAsh returns the correct minimum and maximum frame 167 // sizes when the client view specifies size constraints. 168 TEST_F(CustomFrameViewAshTest, MinimumAndMaximumSize) { 169 gfx::Size min_client_size(500, 500); 170 gfx::Size max_client_size(800, 800); 171 TestWidgetConstraintsDelegate* delegate = new TestWidgetConstraintsDelegate; 172 delegate->set_minimum_size(min_client_size); 173 delegate->set_maximum_size(max_client_size); 174 scoped_ptr<views::Widget> widget(CreateWidget(delegate)); 175 176 CustomFrameViewAsh* custom_frame_view = delegate->custom_frame_view(); 177 gfx::Size min_frame_size = custom_frame_view->GetMinimumSize(); 178 gfx::Size max_frame_size = custom_frame_view->GetMaximumSize(); 179 180 EXPECT_EQ(min_client_size.width(), min_frame_size.width()); 181 EXPECT_EQ(max_client_size.width(), max_frame_size.width()); 182 EXPECT_EQ(min_client_size.height() + delegate->GetTitleBarHeight(), 183 min_frame_size.height()); 184 EXPECT_EQ(max_client_size.height() + delegate->GetTitleBarHeight(), 185 max_frame_size.height()); 186 } 187 188 // Verify that CustomFrameViewAsh updates the avatar icon based on the 189 // state of the SessionStateDelegate after visibility change. 190 TEST_F(CustomFrameViewAshTest, AvatarIcon) { 191 TestWidgetConstraintsDelegate* delegate = new TestWidgetConstraintsDelegate; 192 scoped_ptr<views::Widget> widget(CreateWidget(delegate)); 193 194 CustomFrameViewAsh* custom_frame_view = delegate->custom_frame_view(); 195 EXPECT_FALSE(custom_frame_view->GetAvatarIconViewForTest()); 196 197 // Avatar image becomes available. 198 const gfx::ImageSkia user_image = 199 *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 200 IDR_AURA_UBER_TRAY_GUEST_ICON); 201 GetTestSessionStateDelegate()->SetUserImage(user_image); 202 widget->Hide(); 203 widget->Show(); 204 EXPECT_TRUE(custom_frame_view->GetAvatarIconViewForTest()); 205 206 // Avatar image is gone; the ImageView for the avatar icon should be 207 // removed. 208 GetTestSessionStateDelegate()->SetUserImage(gfx::ImageSkia()); 209 widget->Hide(); 210 widget->Show(); 211 EXPECT_FALSE(custom_frame_view->GetAvatarIconViewForTest()); 212 } 213 214 // The visibility of the size button is updated when maximize mode is toggled. 215 // Verify that the layout of the HeaderView is updated for the size button's 216 // new visibility. 217 TEST_F(CustomFrameViewAshTest, HeaderViewNotifiedOfChildSizeChange) { 218 TestWidgetConstraintsDelegate* delegate = new TestWidgetConstraintsDelegate; 219 scoped_ptr<views::Widget> widget(CreateWidget(delegate)); 220 221 const gfx::Rect initial = delegate-> 222 GetFrameCaptionButtonContainerViewBounds(); 223 Shell::GetInstance()->maximize_mode_controller()-> 224 EnableMaximizeModeWindowManager(true); 225 delegate->EndFrameCaptionButtonContainerViewAnimations(); 226 const gfx::Rect maximize_mode_bounds = delegate-> 227 GetFrameCaptionButtonContainerViewBounds(); 228 EXPECT_GT(initial.width(), maximize_mode_bounds.width()); 229 Shell::GetInstance()->maximize_mode_controller()-> 230 EnableMaximizeModeWindowManager(false); 231 delegate->EndFrameCaptionButtonContainerViewAnimations(); 232 const gfx::Rect after_restore = delegate-> 233 GetFrameCaptionButtonContainerViewBounds(); 234 EXPECT_EQ(initial, after_restore); 235 } 236 237 } // namespace ash 238