1 // Copyright 2013 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/opaque_browser_frame_view_layout.h" 6 7 #include "base/basictypes.h" 8 #include "base/command_line.h" 9 #include "base/strings/utf_string_conversions.h" 10 #include "chrome/browser/ui/views/profiles/avatar_label.h" 11 #include "chrome/browser/ui/views/profiles/avatar_menu_button.h" 12 #include "chrome/browser/ui/views/tab_icon_view.h" 13 #include "chrome/browser/ui/views/tabs/tab.h" 14 #include "chrome/common/chrome_switches.h" 15 #include "components/signin/core/common/profile_management_switches.h" 16 #include "ui/gfx/image/image_skia.h" 17 #include "ui/gfx/image/image_skia_rep.h" 18 #include "ui/gfx/text_constants.h" 19 #include "ui/views/controls/button/image_button.h" 20 #include "ui/views/controls/button/menu_button.h" 21 #include "ui/views/controls/label.h" 22 #include "ui/views/test/views_test_base.h" 23 24 using views::Widget; 25 26 namespace { 27 28 const int kWidth = 500; 29 30 class TestLayoutDelegate : public OpaqueBrowserFrameViewLayoutDelegate { 31 public: 32 enum WindowState { 33 STATE_NORMAL, 34 STATE_MAXIMIZED, 35 STATE_MINIMIZED, 36 STATE_FULLSCREEN 37 }; 38 39 TestLayoutDelegate() 40 : show_avatar_(false), 41 show_caption_buttons_(true), 42 window_state_(STATE_NORMAL) { 43 } 44 45 virtual ~TestLayoutDelegate() {} 46 47 void SetWindowTitle(const base::string16& title) { 48 window_title_ = title; 49 } 50 51 void SetShouldShowAvatar(bool show_avatar) { 52 show_avatar_ = show_avatar; 53 } 54 55 void SetShouldShowCaptionButtons(bool show_caption_buttons) { 56 show_caption_buttons_ = show_caption_buttons; 57 } 58 59 void SetWindowState(WindowState state) { 60 window_state_ = state; 61 } 62 63 // OpaqueBrowserFrameViewLayoutDelegate overrides: 64 65 virtual bool ShouldShowWindowIcon() const OVERRIDE { 66 return !window_title_.empty(); 67 } 68 69 virtual bool ShouldShowWindowTitle() const OVERRIDE { 70 return !window_title_.empty(); 71 } 72 73 virtual base::string16 GetWindowTitle() const OVERRIDE { 74 return window_title_; 75 } 76 77 virtual int GetIconSize() const OVERRIDE { 78 // The value on linux_aura and non-aura windows. 79 return 17; 80 } 81 82 virtual bool ShouldLeaveOffsetNearTopBorder() const OVERRIDE { 83 return !IsMaximized(); 84 } 85 86 virtual gfx::Size GetBrowserViewMinimumSize() const OVERRIDE { 87 // Taken from a calculation in BrowserViewLayout. 88 return gfx::Size(168, 64); 89 } 90 91 virtual bool ShouldShowCaptionButtons() const OVERRIDE { 92 return show_caption_buttons_; 93 } 94 95 virtual bool ShouldShowAvatar() const OVERRIDE { 96 return show_avatar_; 97 } 98 99 virtual bool IsRegularOrGuestSession() const OVERRIDE { 100 return true; 101 } 102 103 virtual gfx::ImageSkia GetOTRAvatarIcon() const OVERRIDE { 104 // The calculations depend on the size of the OTR resource, and chromeos 105 // uses a different sized image, so hard code the size of the current 106 // windows/linux one. 107 gfx::ImageSkiaRep rep(gfx::Size(40, 29), 1.0f); 108 gfx::ImageSkia image(rep); 109 return image; 110 } 111 112 virtual bool IsMaximized() const OVERRIDE { 113 return window_state_ == STATE_MAXIMIZED; 114 } 115 116 virtual bool IsMinimized() const OVERRIDE { 117 return window_state_ == STATE_MINIMIZED; 118 } 119 120 virtual bool IsFullscreen() const OVERRIDE { 121 return window_state_ == STATE_FULLSCREEN; 122 } 123 124 virtual bool IsTabStripVisible() const OVERRIDE { 125 return window_title_.empty(); 126 } 127 128 virtual int GetTabStripHeight() const OVERRIDE { 129 return IsTabStripVisible() ? Tab::GetMinimumUnselectedSize().height() : 0; 130 } 131 132 virtual gfx::Size GetTabstripPreferredSize() const OVERRIDE { 133 // Measured from Tabstrip::GetPreferredSize(). 134 return IsTabStripVisible() ? gfx::Size(78, 29) : gfx::Size(0, 0); 135 } 136 137 private: 138 base::string16 window_title_; 139 bool show_avatar_; 140 bool show_caption_buttons_; 141 WindowState window_state_; 142 143 DISALLOW_COPY_AND_ASSIGN(TestLayoutDelegate); 144 }; 145 146 } // namespace 147 148 class OpaqueBrowserFrameViewLayoutTest : public views::ViewsTestBase { 149 public: 150 OpaqueBrowserFrameViewLayoutTest() {} 151 virtual ~OpaqueBrowserFrameViewLayoutTest() {} 152 153 virtual void SetUp() OVERRIDE { 154 views::ViewsTestBase::SetUp(); 155 156 delegate_.reset(new TestLayoutDelegate); 157 layout_manager_ = new OpaqueBrowserFrameViewLayout(delegate_.get()); 158 layout_manager_->set_extra_caption_y(0); 159 layout_manager_->set_window_caption_spacing(0); 160 widget_ = new Widget; 161 widget_->Init(CreateParams(Widget::InitParams::TYPE_POPUP)); 162 root_view_ = widget_->GetRootView(); 163 root_view_->SetSize(gfx::Size(kWidth, kWidth)); 164 root_view_->SetLayoutManager(layout_manager_); 165 166 // Add the caption buttons. We use fake images because we're modeling the 167 // Windows assets here, while the linux version uses differently sized 168 // assets. 169 // 170 // TODO(erg): In a follow up patch, separate these sizes out into virtual 171 // accessors so we can test both the windows and linux behaviours once we 172 // start modifying the code. 173 minimize_button_ = InitWindowCaptionButton( 174 VIEW_ID_MINIMIZE_BUTTON, gfx::Size(26, 18)); 175 maximize_button_ = InitWindowCaptionButton( 176 VIEW_ID_MAXIMIZE_BUTTON, gfx::Size(25, 18)); 177 restore_button_ = InitWindowCaptionButton( 178 VIEW_ID_RESTORE_BUTTON, gfx::Size(25, 18)); 179 close_button_ = InitWindowCaptionButton( 180 VIEW_ID_CLOSE_BUTTON, gfx::Size(43, 18)); 181 } 182 183 virtual void TearDown() OVERRIDE { 184 widget_->CloseNow(); 185 186 views::ViewsTestBase::TearDown(); 187 } 188 189 protected: 190 views::ImageButton* InitWindowCaptionButton(ViewID view_id, 191 const gfx::Size& size) { 192 views::ImageButton* button = new views::ImageButton(NULL); 193 gfx::ImageSkiaRep rep(size, 1.0f); 194 gfx::ImageSkia image(rep); 195 button->SetImage(views::CustomButton::STATE_NORMAL, &image); 196 button->set_id(view_id); 197 root_view_->AddChildView(button); 198 return button; 199 } 200 201 void AddWindowTitleIcons() { 202 tab_icon_view_ = new TabIconView(NULL, NULL); 203 tab_icon_view_->set_is_light(true); 204 tab_icon_view_->set_id(VIEW_ID_WINDOW_ICON); 205 root_view_->AddChildView(tab_icon_view_); 206 207 window_title_ = new views::Label(delegate_->GetWindowTitle()); 208 window_title_->SetVisible(delegate_->ShouldShowWindowTitle()); 209 window_title_->SetEnabledColor(SK_ColorWHITE); 210 window_title_->SetSubpixelRenderingEnabled(false); 211 window_title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 212 window_title_->set_id(VIEW_ID_WINDOW_TITLE); 213 root_view_->AddChildView(window_title_); 214 } 215 216 void AddAvatarButton() { 217 // Disable the New Avatar Menu. 218 switches::DisableNewAvatarMenuForTesting(CommandLine::ForCurrentProcess()); 219 220 menu_button_ = new AvatarMenuButton(NULL, false); 221 menu_button_->set_id(VIEW_ID_AVATAR_BUTTON); 222 delegate_->SetShouldShowAvatar(true); 223 root_view_->AddChildView(menu_button_); 224 } 225 226 void AddAvatarLabel() { 227 avatar_label_ = new AvatarLabel(NULL); 228 avatar_label_->set_id(VIEW_ID_AVATAR_LABEL); 229 root_view_->AddChildView(avatar_label_); 230 231 // The avatar label should only be used together with the avatar button. 232 AddAvatarButton(); 233 } 234 235 void AddNewAvatarButton() { 236 // Enable the New Avatar Menu. 237 switches::EnableNewAvatarMenuForTesting(CommandLine::ForCurrentProcess()); 238 239 new_avatar_button_ = 240 new views::MenuButton(NULL, base::string16(), NULL, false); 241 new_avatar_button_->set_id(VIEW_ID_NEW_AVATAR_BUTTON); 242 root_view_->AddChildView(new_avatar_button_); 243 } 244 245 void ExpectBasicWindowBounds() { 246 EXPECT_EQ("428,1 25x18", maximize_button_->bounds().ToString()); 247 EXPECT_EQ("402,1 26x18", minimize_button_->bounds().ToString()); 248 EXPECT_EQ("0,0 0x0", restore_button_->bounds().ToString()); 249 EXPECT_EQ("453,1 43x18", close_button_->bounds().ToString()); 250 } 251 252 Widget* widget_; 253 views::View* root_view_; 254 OpaqueBrowserFrameViewLayout* layout_manager_; 255 scoped_ptr<TestLayoutDelegate> delegate_; 256 257 // Widgets: 258 views::ImageButton* minimize_button_; 259 views::ImageButton* maximize_button_; 260 views::ImageButton* restore_button_; 261 views::ImageButton* close_button_; 262 263 TabIconView* tab_icon_view_; 264 views::Label* window_title_; 265 266 AvatarLabel* avatar_label_; 267 AvatarMenuButton* menu_button_; 268 views::MenuButton* new_avatar_button_; 269 270 DISALLOW_COPY_AND_ASSIGN(OpaqueBrowserFrameViewLayoutTest); 271 }; 272 273 TEST_F(OpaqueBrowserFrameViewLayoutTest, BasicWindow) { 274 // Tests the layout of a default chrome window with no avatars, no window 275 // titles, and a tabstrip. 276 root_view_->Layout(); 277 278 ExpectBasicWindowBounds(); 279 280 // After some visual inspection, it really does look like the tabstrip is 281 // initally positioned out of our view. 282 EXPECT_EQ("-1,13 398x29", 283 layout_manager_->GetBoundsForTabStrip( 284 delegate_->GetTabstripPreferredSize(), kWidth).ToString()); 285 EXPECT_EQ("261x73", layout_manager_->GetMinimumSize(kWidth).ToString()); 286 287 // A normal window with no window icon still produces icon bounds for 288 // Windows, which has a hidden icon that a user can double click on to close 289 // the window. 290 EXPECT_EQ("6,4 17x17", layout_manager_->IconBounds().ToString()); 291 } 292 293 TEST_F(OpaqueBrowserFrameViewLayoutTest, BasicWindowMaximized) { 294 // Tests the layout of a default chrome window with no avatars, no window 295 // titles, and a tabstrip, but maximized this time. 296 delegate_->SetWindowState(TestLayoutDelegate::STATE_MAXIMIZED); 297 root_view_->Layout(); 298 299 // Note how the bounds start at the exact top of the window while maximized 300 // while they start 1 pixel below when unmaximized. 301 EXPECT_EQ("0,0 0x0", maximize_button_->bounds().ToString()); 302 EXPECT_EQ("403,0 26x18", minimize_button_->bounds().ToString()); 303 EXPECT_EQ("429,0 25x18", restore_button_->bounds().ToString()); 304 EXPECT_EQ("454,0 46x18", close_button_->bounds().ToString()); 305 306 EXPECT_EQ("-5,-3 392x29", 307 layout_manager_->GetBoundsForTabStrip( 308 delegate_->GetTabstripPreferredSize(), kWidth).ToString()); 309 EXPECT_EQ("262x61", layout_manager_->GetMinimumSize(kWidth).ToString()); 310 311 // In the maximized case, OpaqueBrowserFrameView::NonClientHitTest() uses 312 // this rect, extended to the top left corner of the window. 313 EXPECT_EQ("2,0 17x17", layout_manager_->IconBounds().ToString()); 314 } 315 316 TEST_F(OpaqueBrowserFrameViewLayoutTest, MaximizedWithYOffset) { 317 // Tests the layout of a basic chrome window with the caption buttons slightly 318 // offset from the top of the screen (as they are on Linux). 319 layout_manager_->set_extra_caption_y(2); 320 delegate_->SetWindowState(TestLayoutDelegate::STATE_MAXIMIZED); 321 root_view_->Layout(); 322 323 // Note how the bounds start at the exact top of the window, DESPITE the 324 // caption Y offset of 2. This ensures that we obey Fitts' Law (the buttons 325 // are clickable on the top edge of the screen). However, the buttons are 2 326 // pixels taller, so the images appear to be offset by 2 pixels. 327 EXPECT_EQ("0,0 0x0", maximize_button_->bounds().ToString()); 328 EXPECT_EQ("403,0 26x20", minimize_button_->bounds().ToString()); 329 EXPECT_EQ("429,0 25x20", restore_button_->bounds().ToString()); 330 EXPECT_EQ("454,0 46x20", close_button_->bounds().ToString()); 331 332 EXPECT_EQ("-5,-3 392x29", 333 layout_manager_->GetBoundsForTabStrip( 334 delegate_->GetTabstripPreferredSize(), kWidth).ToString()); 335 EXPECT_EQ("262x61", layout_manager_->GetMinimumSize(kWidth).ToString()); 336 337 // In the maximized case, OpaqueBrowserFrameView::NonClientHitTest() uses 338 // this rect, extended to the top left corner of the window. 339 EXPECT_EQ("2,0 17x17", layout_manager_->IconBounds().ToString()); 340 } 341 342 TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowButtonsOnLeft) { 343 // Tests the layout of a chrome window with caption buttons on the left. 344 std::vector<views::FrameButton> leading_buttons; 345 std::vector<views::FrameButton> trailing_buttons; 346 leading_buttons.push_back(views::FRAME_BUTTON_CLOSE); 347 leading_buttons.push_back(views::FRAME_BUTTON_MINIMIZE); 348 leading_buttons.push_back(views::FRAME_BUTTON_MAXIMIZE); 349 layout_manager_->SetButtonOrdering(leading_buttons, trailing_buttons); 350 root_view_->Layout(); 351 352 EXPECT_EQ("73,1 25x18", maximize_button_->bounds().ToString()); 353 EXPECT_EQ("47,1 26x18", minimize_button_->bounds().ToString()); 354 EXPECT_EQ("0,0 0x0", restore_button_->bounds().ToString()); 355 EXPECT_EQ("4,1 43x18", close_button_->bounds().ToString()); 356 357 EXPECT_EQ("93,13 398x29", 358 layout_manager_->GetBoundsForTabStrip( 359 delegate_->GetTabstripPreferredSize(), kWidth).ToString()); 360 EXPECT_EQ("261x73", layout_manager_->GetMinimumSize(kWidth).ToString()); 361 362 // If the buttons are on the left, there should be no hidden icon for the user 363 // to double click. 364 EXPECT_EQ("0,0 0x0", layout_manager_->IconBounds().ToString()); 365 } 366 367 TEST_F(OpaqueBrowserFrameViewLayoutTest, WithoutCaptionButtons) { 368 // Tests the layout of a default chrome window with no caption buttons (which 369 // should force the tab strip to be condensed). 370 delegate_->SetShouldShowCaptionButtons(false); 371 root_view_->Layout(); 372 373 EXPECT_EQ("0,0 0x0", maximize_button_->bounds().ToString()); 374 EXPECT_EQ("0,0 0x0", minimize_button_->bounds().ToString()); 375 EXPECT_EQ("0,0 0x0", restore_button_->bounds().ToString()); 376 EXPECT_EQ("0,0 0x0", close_button_->bounds().ToString()); 377 378 EXPECT_EQ("-5,-3 500x29", 379 layout_manager_->GetBoundsForTabStrip( 380 delegate_->GetTabstripPreferredSize(), kWidth).ToString()); 381 EXPECT_EQ("251x61", layout_manager_->GetMinimumSize(kWidth).ToString()); 382 383 // A normal window with no window icon still produces icon bounds for 384 // Windows, which has a hidden icon that a user can double click on to close 385 // the window. 386 EXPECT_EQ("2,0 17x17", layout_manager_->IconBounds().ToString()); 387 } 388 389 TEST_F(OpaqueBrowserFrameViewLayoutTest, MaximizedWithoutCaptionButtons) { 390 // Tests the layout of a maximized chrome window with no caption buttons. 391 delegate_->SetWindowState(TestLayoutDelegate::STATE_MAXIMIZED); 392 delegate_->SetShouldShowCaptionButtons(false); 393 root_view_->Layout(); 394 395 EXPECT_EQ("0,0 0x0", maximize_button_->bounds().ToString()); 396 EXPECT_EQ("0,0 0x0", minimize_button_->bounds().ToString()); 397 EXPECT_EQ("0,0 0x0", restore_button_->bounds().ToString()); 398 EXPECT_EQ("0,0 0x0", close_button_->bounds().ToString()); 399 400 EXPECT_EQ("-5,-3 500x29", 401 layout_manager_->GetBoundsForTabStrip( 402 delegate_->GetTabstripPreferredSize(), kWidth).ToString()); 403 EXPECT_EQ("251x61", layout_manager_->GetMinimumSize(kWidth).ToString()); 404 405 // In the maximized case, OpaqueBrowserFrameView::NonClientHitTest() uses 406 // this rect, extended to the top left corner of the window. 407 EXPECT_EQ("2,0 17x17", layout_manager_->IconBounds().ToString()); 408 } 409 410 TEST_F(OpaqueBrowserFrameViewLayoutTest, WithWindowTitleAndIcon) { 411 // Tests the layout of pop up windows. 412 delegate_->SetWindowTitle(base::ASCIIToUTF16("Window Title")); 413 AddWindowTitleIcons(); 414 root_view_->Layout(); 415 416 // We should have the right hand side should match the BasicWindow case. 417 ExpectBasicWindowBounds(); 418 419 // Check the location of the tab icon and window title. 420 EXPECT_EQ("6,3 17x17", tab_icon_view_->bounds().ToString()); 421 EXPECT_EQ("27,3 370x17", window_title_->bounds().ToString()); 422 } 423 424 TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowWithAvatar) { 425 // Tests a normal tabstrip window with an avatar icon. 426 AddAvatarButton(); 427 root_view_->Layout(); 428 429 ExpectBasicWindowBounds(); 430 431 // Check the location of the avatar 432 EXPECT_EQ("7,11 40x29", menu_button_->bounds().ToString()); 433 EXPECT_EQ("45,13 352x29", 434 layout_manager_->GetBoundsForTabStrip( 435 delegate_->GetTabstripPreferredSize(), kWidth).ToString()); 436 EXPECT_EQ("261x73", layout_manager_->GetMinimumSize(kWidth).ToString()); 437 } 438 439 TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowWithAvatarWithButtonsOnLeft) { 440 // Tests the layout of a chrome window with an avatar icon and caption buttons 441 // on the left. The avatar icon should therefore be on the right. 442 // AddAvatarLabel() also adds the avatar button. 443 AddAvatarLabel(); 444 std::vector<views::FrameButton> leading_buttons; 445 std::vector<views::FrameButton> trailing_buttons; 446 leading_buttons.push_back(views::FRAME_BUTTON_CLOSE); 447 leading_buttons.push_back(views::FRAME_BUTTON_MINIMIZE); 448 leading_buttons.push_back(views::FRAME_BUTTON_MAXIMIZE); 449 layout_manager_->SetButtonOrdering(leading_buttons, trailing_buttons); 450 root_view_->Layout(); 451 452 EXPECT_EQ("73,1 25x18", maximize_button_->bounds().ToString()); 453 EXPECT_EQ("47,1 26x18", minimize_button_->bounds().ToString()); 454 EXPECT_EQ("0,0 0x0", restore_button_->bounds().ToString()); 455 EXPECT_EQ("4,1 43x18", close_button_->bounds().ToString()); 456 457 // Check the location of the avatar 458 EXPECT_EQ("454,11 40x29", menu_button_->bounds().ToString()); 459 460 // Check the tab strip bounds. 461 gfx::Rect tab_strip_bounds = layout_manager_->GetBoundsForTabStrip( 462 delegate_->GetTabstripPreferredSize(), kWidth); 463 EXPECT_GT(tab_strip_bounds.x(), maximize_button_->bounds().x()); 464 EXPECT_GT(maximize_button_->bounds().right(), tab_strip_bounds.x()); 465 EXPECT_EQ(13, tab_strip_bounds.y()); 466 EXPECT_EQ(29, tab_strip_bounds.height()); 467 EXPECT_GT(avatar_label_->bounds().x(), tab_strip_bounds.right()); 468 EXPECT_EQ("261x73", layout_manager_->GetMinimumSize(kWidth).ToString()); 469 470 // Check the relative location of the avatar label to the avatar. The right 471 // end of the avatar label should be slightly to the right of the right end of 472 // the avatar icon. 473 EXPECT_GT(avatar_label_->bounds().right(), menu_button_->bounds().right()); 474 EXPECT_GT(menu_button_->bounds().x(), avatar_label_->bounds().x()); 475 EXPECT_GT(menu_button_->bounds().bottom(), 476 avatar_label_->bounds().bottom()); 477 EXPECT_GT(avatar_label_->bounds().y(), menu_button_->bounds().y()); 478 479 // This means that the menu will pop out facing the left (if it were to face 480 // the right, it would go outside the window frame and be clipped). 481 EXPECT_TRUE(menu_button_->button_on_right()); 482 483 // If the buttons are on the left, there should be no hidden icon for the user 484 // to double click. 485 EXPECT_EQ("0,0 0x0", layout_manager_->IconBounds().ToString()); 486 } 487 488 TEST_F(OpaqueBrowserFrameViewLayoutTest, 489 WindowWithAvatarWithoutCaptionButtonsOnLeft) { 490 // Tests the layout of a chrome window with an avatar icon and no caption 491 // buttons. However, the caption buttons *would* be on the left if they 492 // weren't hidden, and therefore, the avatar icon should be on the right. 493 // The lack of caption buttons should force the tab strip to be condensed. 494 AddAvatarButton(); 495 std::vector<views::FrameButton> leading_buttons; 496 std::vector<views::FrameButton> trailing_buttons; 497 leading_buttons.push_back(views::FRAME_BUTTON_CLOSE); 498 leading_buttons.push_back(views::FRAME_BUTTON_MINIMIZE); 499 leading_buttons.push_back(views::FRAME_BUTTON_MAXIMIZE); 500 layout_manager_->SetButtonOrdering(leading_buttons, trailing_buttons); 501 delegate_->SetShouldShowCaptionButtons(false); 502 root_view_->Layout(); 503 504 EXPECT_EQ("0,0 0x0", maximize_button_->bounds().ToString()); 505 EXPECT_EQ("0,0 0x0", minimize_button_->bounds().ToString()); 506 EXPECT_EQ("0,0 0x0", restore_button_->bounds().ToString()); 507 EXPECT_EQ("0,0 0x0", close_button_->bounds().ToString()); 508 509 // Check the location of the avatar 510 EXPECT_EQ("458,0 40x24", menu_button_->bounds().ToString()); 511 EXPECT_EQ("-5,-3 458x29", 512 layout_manager_->GetBoundsForTabStrip( 513 delegate_->GetTabstripPreferredSize(), kWidth).ToString()); 514 EXPECT_EQ("251x61", layout_manager_->GetMinimumSize(kWidth).ToString()); 515 516 // A normal window with no window icon still produces icon bounds for 517 // Windows, which has a hidden icon that a user can double click on to close 518 // the window. 519 EXPECT_EQ("2,0 17x17", layout_manager_->IconBounds().ToString()); 520 } 521 522 TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowWithNewAvatar) { 523 // Tests a normal tabstrip window with the new style avatar icon. 524 AddNewAvatarButton(); 525 root_view_->Layout(); 526 527 ExpectBasicWindowBounds(); 528 529 // Check the location of the avatar button. 530 EXPECT_EQ("385,1 12x18", new_avatar_button_->bounds().ToString()); 531 // The new tab button is 39px wide and slides completely under the new 532 // avatar button, thus increasing the tabstrip by that amount. 533 EXPECT_EQ("-1,13 420x29", 534 layout_manager_->GetBoundsForTabStrip( 535 delegate_->GetTabstripPreferredSize(), kWidth).ToString()); 536 EXPECT_EQ("261x73", layout_manager_->GetMinimumSize(kWidth).ToString()); 537 } 538 539 TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowWithAvatarLabelAndButtonOnLeft) { 540 AddAvatarLabel(); 541 root_view_->Layout(); 542 543 ExpectBasicWindowBounds(); 544 545 // Check the location of the avatar label relative to the avatar button if 546 // both are displayed on the left side. 547 // The label height and width depends on the font size and the text displayed. 548 // This may possibly change, so we don't test it here. 549 EXPECT_EQ(menu_button_->bounds().x() - 2, avatar_label_->bounds().x()); 550 EXPECT_EQ( 551 menu_button_->bounds().bottom() - 3 - avatar_label_->bounds().height(), 552 avatar_label_->bounds().y()); 553 } 554