| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.h" |
| |
| #include "base/macros.h" |
| #include "chrome/browser/ui/views/nav_button_provider.h" |
| #include "chrome/browser/ui/views/tabs/tab.h" |
| #include "ui/views/background.h" |
| #include "ui/views/controls/button/image_button.h" |
| #include "ui/views/test/views_test_base.h" |
| |
| using NNBFVL = DesktopLinuxBrowserFrameViewLayout; |
| |
| namespace { |
| |
| constexpr int kWindowWidth = 500; |
| |
| constexpr gfx::Size kCloseButtonSize = gfx::Size(2, 3); |
| constexpr gfx::Size kMaximizeButtonSize = gfx::Size(5, 7); |
| constexpr gfx::Size kMinimizeButtonSize = gfx::Size(11, 13); |
| |
| constexpr gfx::Insets kCloseButtonMargin = gfx::Insets(17, 19, 23, 29); |
| constexpr gfx::Insets kMaximizeButtonMargin = gfx::Insets(31, 37, 41, 43); |
| constexpr gfx::Insets kMinimizeButtonMargin = gfx::Insets(47, 53, 59, 61); |
| |
| constexpr gfx::Insets kTopAreaSpacing = gfx::Insets(67, 71, 73, 79); |
| |
| constexpr int kInterNavButtonSpacing = 83; |
| |
| static gfx::ImageSkia GetTestImageForSize(gfx::Size size) { |
| SkBitmap bitmap; |
| bitmap.allocN32Pixels(size.width(), size.height()); |
| return gfx::ImageSkia::CreateFrom1xBitmap(bitmap); |
| } |
| |
| class TestLayoutDelegate : public OpaqueBrowserFrameViewLayoutDelegate { |
| public: |
| TestLayoutDelegate() {} |
| ~TestLayoutDelegate() override {} |
| |
| // OpaqueBrowserFrameViewLayoutDelegate: |
| bool ShouldShowWindowIcon() const override { return false; } |
| bool ShouldShowWindowTitle() const override { return false; } |
| base::string16 GetWindowTitle() const override { return base::string16(); } |
| int GetIconSize() const override { return 17; } |
| gfx::Size GetBrowserViewMinimumSize() const override { |
| return gfx::Size(168, 64); |
| } |
| bool ShouldShowCaptionButtons() const override { return true; } |
| bool IsRegularOrGuestSession() const override { return true; } |
| gfx::ImageSkia GetIncognitoAvatarIcon() const override { |
| return gfx::ImageSkia(); |
| } |
| bool IsMaximized() const override { return false; } |
| bool IsMinimized() const override { return false; } |
| bool IsFullscreen() const override { return false; } |
| bool IsTabStripVisible() const override { return true; } |
| int GetTabStripHeight() const override { |
| return Tab::GetMinimumInactiveSize().height(); |
| } |
| bool IsToolbarVisible() const override { return true; } |
| gfx::Size GetTabstripPreferredSize() const override { |
| return gfx::Size(78, 29); |
| } |
| int GetTopAreaHeight() const override { return 0; } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(TestLayoutDelegate); |
| }; |
| |
| class TestNavButtonProvider : public views::NavButtonProvider { |
| public: |
| TestNavButtonProvider() {} |
| |
| ~TestNavButtonProvider() override {} |
| |
| void RedrawImages(int top_area_height, bool maximized, bool active) override { |
| ASSERT_EQ(false, maximized); // This only tests the restored state. |
| } |
| |
| gfx::ImageSkia GetImage(chrome::FrameButtonDisplayType type, |
| views::Button::ButtonState state) const override { |
| switch (type) { |
| case chrome::FrameButtonDisplayType::kClose: |
| return GetTestImageForSize(kCloseButtonSize); |
| case chrome::FrameButtonDisplayType::kMaximize: |
| return GetTestImageForSize(kMaximizeButtonSize); |
| case chrome::FrameButtonDisplayType::kMinimize: |
| return GetTestImageForSize(kMinimizeButtonSize); |
| default: |
| NOTREACHED(); |
| return gfx::ImageSkia(); |
| } |
| } |
| |
| gfx::Insets GetNavButtonMargin( |
| chrome::FrameButtonDisplayType type) const override { |
| switch (type) { |
| case chrome::FrameButtonDisplayType::kClose: |
| return kCloseButtonMargin; |
| case chrome::FrameButtonDisplayType::kMaximize: |
| return kMaximizeButtonMargin; |
| case chrome::FrameButtonDisplayType::kMinimize: |
| return kMinimizeButtonMargin; |
| default: |
| NOTREACHED(); |
| return gfx::Insets(); |
| } |
| } |
| |
| gfx::Insets GetTopAreaSpacing() const override { return kTopAreaSpacing; } |
| |
| int GetInterNavButtonSpacing() const override { |
| return kInterNavButtonSpacing; |
| } |
| |
| std::unique_ptr<views::Background> CreateAvatarButtonBackground( |
| const views::Button* avatar_button) const override { |
| return nullptr; |
| } |
| |
| void CalculateCaptionButtonLayout( |
| const gfx::Size& content_size, |
| int top_area_height, |
| gfx::Size* caption_button_size, |
| gfx::Insets* caption_button_spacing) const override {} |
| }; |
| |
| } // namespace |
| |
| class DesktopLinuxBrowserFrameViewLayoutTest : public views::ViewsTestBase { |
| public: |
| DesktopLinuxBrowserFrameViewLayoutTest() {} |
| ~DesktopLinuxBrowserFrameViewLayoutTest() override {} |
| |
| void SetUp() override { |
| views::ViewsTestBase::SetUp(); |
| |
| delegate_.reset(new TestLayoutDelegate); |
| nav_button_provider_ = base::MakeUnique<::TestNavButtonProvider>(); |
| layout_manager_ = new NNBFVL(nav_button_provider_.get()); |
| layout_manager_->set_delegate(delegate_.get()); |
| layout_manager_->set_extra_caption_y(0); |
| layout_manager_->set_forced_window_caption_spacing_for_test(0); |
| widget_ = new views::Widget; |
| widget_->Init(CreateParams(views::Widget::InitParams::TYPE_POPUP)); |
| root_view_ = widget_->GetRootView(); |
| root_view_->SetSize(gfx::Size(kWindowWidth, kWindowWidth)); |
| root_view_->SetLayoutManager(layout_manager_); |
| |
| minimize_button_ = InitWindowCaptionButton(VIEW_ID_MINIMIZE_BUTTON); |
| maximize_button_ = InitWindowCaptionButton(VIEW_ID_MAXIMIZE_BUTTON); |
| restore_button_ = InitWindowCaptionButton(VIEW_ID_RESTORE_BUTTON); |
| close_button_ = InitWindowCaptionButton(VIEW_ID_CLOSE_BUTTON); |
| } |
| |
| void TearDown() override { |
| widget_->CloseNow(); |
| |
| views::ViewsTestBase::TearDown(); |
| } |
| |
| protected: |
| views::ImageButton* InitWindowCaptionButton(ViewID view_id) { |
| views::ImageButton* button = new views::ImageButton(nullptr); |
| button->set_id(view_id); |
| root_view_->AddChildView(button); |
| return button; |
| } |
| |
| void ResetNativeNavButtonImagesFromButtonProvider() { |
| std::vector<views::ImageButton*> buttons{close_button_, maximize_button_, |
| minimize_button_}; |
| std::vector<chrome::FrameButtonDisplayType> button_types{ |
| chrome::FrameButtonDisplayType::kClose, |
| chrome::FrameButtonDisplayType::kMaximize, |
| chrome::FrameButtonDisplayType::kMinimize}; |
| for (size_t i = 0; i < buttons.size(); i++) { |
| for (views::Button::ButtonState state : |
| {views::Button::STATE_NORMAL, views ::Button::STATE_HOVERED, |
| views::Button::STATE_PRESSED}) { |
| buttons[i]->SetImage( |
| state, nav_button_provider_->GetImage(button_types[i], state)); |
| } |
| } |
| } |
| |
| int TitlebarTopThickness() const { |
| return static_cast<OpaqueBrowserFrameViewLayout*>(layout_manager_) |
| ->TitlebarTopThickness(false); |
| } |
| |
| views::Widget* widget_ = nullptr; |
| views::View* root_view_ = nullptr; |
| NNBFVL* layout_manager_ = nullptr; |
| std::unique_ptr<TestLayoutDelegate> delegate_; |
| std::unique_ptr<views::NavButtonProvider> nav_button_provider_; |
| |
| // Widgets: |
| views::ImageButton* minimize_button_ = nullptr; |
| views::ImageButton* maximize_button_ = nullptr; |
| views::ImageButton* restore_button_ = nullptr; |
| views::ImageButton* close_button_ = nullptr; |
| |
| DISALLOW_COPY_AND_ASSIGN(DesktopLinuxBrowserFrameViewLayoutTest); |
| }; |
| |
| // Tests layout of native navigation buttons. |
| TEST_F(DesktopLinuxBrowserFrameViewLayoutTest, NativeNavButtons) { |
| std::vector<views::FrameButton> leading_buttons; |
| std::vector<views::FrameButton> trailing_buttons; |
| leading_buttons.push_back(views::FRAME_BUTTON_CLOSE); |
| leading_buttons.push_back(views::FRAME_BUTTON_MAXIMIZE); |
| leading_buttons.push_back(views::FRAME_BUTTON_MINIMIZE); |
| layout_manager_->SetButtonOrdering(leading_buttons, trailing_buttons); |
| ResetNativeNavButtonImagesFromButtonProvider(); |
| |
| root_view_->Layout(); |
| |
| const int frame_thickness = TitlebarTopThickness(); |
| int x = frame_thickness; |
| |
| // Close button. |
| EXPECT_EQ(kCloseButtonSize, close_button_->size()); |
| x += kTopAreaSpacing.left() + kCloseButtonMargin.left(); |
| EXPECT_EQ(x, close_button_->x()); |
| EXPECT_EQ(kCloseButtonMargin.top() + frame_thickness, close_button_->y()); |
| |
| // Maximize button. |
| EXPECT_EQ(kMaximizeButtonSize, maximize_button_->size()); |
| x += kCloseButtonSize.width() + kCloseButtonMargin.right() + |
| kInterNavButtonSpacing + kMaximizeButtonMargin.left(); |
| EXPECT_EQ(x, maximize_button_->x()); |
| EXPECT_EQ(kMaximizeButtonMargin.top() + frame_thickness, |
| maximize_button_->y()); |
| |
| // Minimize button. |
| EXPECT_EQ(kMinimizeButtonSize, minimize_button_->size()); |
| x += kMaximizeButtonSize.width() + kMaximizeButtonMargin.right() + |
| kInterNavButtonSpacing + kMinimizeButtonMargin.left(); |
| EXPECT_EQ(x, minimize_button_->x()); |
| EXPECT_EQ(kMinimizeButtonMargin.top() + frame_thickness, |
| minimize_button_->y()); |
| } |