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.
5 #include "ash/wm/caption_buttons/frame_caption_button_container_view.h"
7 #include "ash/ash_switches.h"
8 #include "ash/test/ash_test_base.h"
9 #include "base/command_line.h"
10 #include "grit/ash_resources.h"
11 #include "ui/aura/root_window.h"
12 #include "ui/base/resource/resource_bundle.h"
13 #include "ui/views/border.h"
14 #include "ui/views/controls/button/custom_button.h"
15 #include "ui/views/controls/button/image_button.h"
16 #include "ui/views/widget/widget.h"
17 #include "ui/views/widget/widget_delegate.h"
23 class TestWidgetDelegate
: public views::WidgetDelegateView
{
25 TestWidgetDelegate(bool can_maximize
) : can_maximize_(can_maximize
) {
27 virtual ~TestWidgetDelegate() {
30 virtual bool CanMaximize() const OVERRIDE
{
37 DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate
);
42 class FrameCaptionButtonContainerViewTest
: public ash::test::AshTestBase
{
44 enum MaximizeAllowed
{
49 FrameCaptionButtonContainerViewTest() {
52 virtual ~FrameCaptionButtonContainerViewTest() {
55 // Creates a widget which allows maximizing based on |maximize_allowed|.
56 // The caller takes ownership of the returned widget.
57 views::Widget
* CreateTestWidget(
58 MaximizeAllowed maximize_allowed
) WARN_UNUSED_RESULT
{
59 views::Widget
* widget
= new views::Widget
;
60 views::Widget::InitParams params
;
61 params
.delegate
= new TestWidgetDelegate(
62 maximize_allowed
== MAXIMIZE_ALLOWED
);
63 params
.ownership
= views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
64 params
.context
= CurrentContext();
69 // Tests that |leftmost| and |rightmost| are at |container|'s edges.
70 bool CheckButtonsAtEdges(FrameCaptionButtonContainerView
* container
,
71 const views::CustomButton
& leftmost
,
72 const views::CustomButton
& rightmost
) {
73 gfx::Rect
expected(container
->GetPreferredSize());
74 expected
.Inset(container
->GetLeftInset(), 0, container
->GetRightInset(), 0);
76 gfx::Rect
container_size(container
->GetPreferredSize());
77 if (leftmost
.y() == rightmost
.y() &&
78 leftmost
.height() == rightmost
.height() &&
79 leftmost
.x() == expected
.x() &&
80 leftmost
.y() == expected
.y() &&
81 leftmost
.height() == expected
.height() &&
82 rightmost
.bounds().right() == expected
.right()) {
86 LOG(ERROR
) << "Buttons " << leftmost
.bounds().ToString() << " "
87 << rightmost
.bounds().ToString() << " not at edges of "
88 << expected
.ToString();
93 DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerViewTest
);
96 class FrameCaptionButtonContainerViewTestOldStyle
97 : public FrameCaptionButtonContainerViewTest
{
99 FrameCaptionButtonContainerViewTestOldStyle() {
102 virtual ~FrameCaptionButtonContainerViewTestOldStyle() {
105 // Returns true if the images for |button|'s states match the passed in ids.
106 bool ImagesMatch(views::CustomButton
* custom_button
,
108 int hovered_image_id
,
109 int pressed_image_id
) {
110 views::ImageButton
* button
=
111 static_cast<views::ImageButton
*>(custom_button
);
112 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
113 gfx::ImageSkia
* normal
= rb
.GetImageSkiaNamed(normal_image_id
);
114 gfx::ImageSkia
* hovered
= rb
.GetImageSkiaNamed(hovered_image_id
);
115 gfx::ImageSkia
* pressed
= rb
.GetImageSkiaNamed(pressed_image_id
);
117 gfx::ImageSkia actual_normal
= button
->GetImage(Button::STATE_NORMAL
);
118 gfx::ImageSkia actual_hovered
= button
->GetImage(Button::STATE_HOVERED
);
119 gfx::ImageSkia actual_pressed
= button
->GetImage(Button::STATE_PRESSED
);
120 return actual_normal
.BackedBySameObjectAs(*normal
) &&
121 actual_hovered
.BackedBySameObjectAs(*hovered
) &&
122 actual_pressed
.BackedBySameObjectAs(*pressed
);
125 virtual void SetUp() OVERRIDE
{
126 FrameCaptionButtonContainerViewTest::SetUp();
127 CommandLine::ForCurrentProcess()->AppendSwitch(
128 switches::kAshDisableAlternateFrameCaptionButtonStyle
);
132 DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerViewTestOldStyle
);
135 // Test how the allowed actions affect which caption buttons are visible.
136 TEST_F(FrameCaptionButtonContainerViewTestOldStyle
, ButtonVisibility
) {
137 // The minimize button should be hidden when both minimizing and maximizing
138 // are allowed because the size button can do both.
139 scoped_ptr
<views::Widget
> widget_can_maximize(
140 CreateTestWidget(MAXIMIZE_ALLOWED
));
141 FrameCaptionButtonContainerView
container1(widget_can_maximize
.get(),
142 FrameCaptionButtonContainerView::MINIMIZE_ALLOWED
);
144 FrameCaptionButtonContainerView::TestApi
t1(&container1
);
145 EXPECT_FALSE(t1
.minimize_button()->visible());
146 EXPECT_TRUE(t1
.size_button()->visible());
147 EXPECT_TRUE(t1
.close_button()->visible());
148 EXPECT_TRUE(CheckButtonsAtEdges(
149 &container1
, *t1
.size_button(), *t1
.close_button()));
151 // The minimize button should be visible when minimizing is allowed but
152 // maximizing is disallowed.
153 scoped_ptr
<views::Widget
> widget_cannot_maximize(
154 CreateTestWidget(MAXIMIZE_DISALLOWED
));
155 FrameCaptionButtonContainerView
container2(widget_cannot_maximize
.get(),
156 FrameCaptionButtonContainerView::MINIMIZE_ALLOWED
);
158 FrameCaptionButtonContainerView::TestApi
t2(&container2
);
159 EXPECT_TRUE(t2
.minimize_button()->visible());
160 EXPECT_FALSE(t2
.size_button()->visible());
161 EXPECT_TRUE(t2
.close_button()->visible());
162 EXPECT_TRUE(CheckButtonsAtEdges(
163 &container2
, *t2
.minimize_button(), *t2
.close_button()));
165 // Neither the minimize button nor the size button should be visible when
166 // neither minimizing nor maximizing are allowed.
167 FrameCaptionButtonContainerView
container3(widget_cannot_maximize
.get(),
168 FrameCaptionButtonContainerView::MINIMIZE_DISALLOWED
);
170 FrameCaptionButtonContainerView::TestApi
t3(&container3
);
171 EXPECT_FALSE(t3
.minimize_button()->visible());
172 EXPECT_FALSE(t3
.size_button()->visible());
173 EXPECT_TRUE(t3
.close_button()->visible());
174 EXPECT_TRUE(CheckButtonsAtEdges(
175 &container3
, *t3
.close_button(), *t3
.close_button()));
178 // Test the layout when a border is set on the container.
179 TEST_F(FrameCaptionButtonContainerViewTestOldStyle
, LayoutBorder
) {
180 const int kTopInset
= 1;
181 const int kLeftInset
= 2;
182 const int kBottomInset
= 3;
183 const int kRightInset
= 4;
185 scoped_ptr
<views::Widget
> widget(CreateTestWidget(MAXIMIZE_ALLOWED
));
186 FrameCaptionButtonContainerView
container(widget
.get(),
187 FrameCaptionButtonContainerView::MINIMIZE_ALLOWED
);
188 container
.set_border(views::Border::CreateEmptyBorder(
189 kTopInset
, kLeftInset
, kBottomInset
, kRightInset
));
191 FrameCaptionButtonContainerView::TestApi
t(&container
);
193 EXPECT_EQ(kLeftInset
, t
.size_button()->x());
194 EXPECT_EQ(kTopInset
, t
.close_button()->y());
195 EXPECT_EQ(container
.GetPreferredSize().height(),
196 t
.close_button()->bounds().bottom() + kBottomInset
);
197 EXPECT_EQ(container
.GetPreferredSize().width(),
198 t
.close_button()->bounds().right() + kRightInset
);
201 // Test how the header style affects which images are used for the buttons.
202 TEST_F(FrameCaptionButtonContainerViewTestOldStyle
, HeaderStyle
) {
203 scoped_ptr
<views::Widget
> widget(CreateTestWidget(MAXIMIZE_ALLOWED
));
204 FrameCaptionButtonContainerView
container(widget
.get(),
205 FrameCaptionButtonContainerView::MINIMIZE_ALLOWED
);
206 FrameCaptionButtonContainerView::TestApi
t(&container
);
208 // Tall header style.
209 container
.set_header_style(
210 FrameCaptionButtonContainerView::HEADER_STYLE_TALL
);
212 EXPECT_TRUE(ImagesMatch(t
.size_button(),
213 IDR_AURA_WINDOW_MAXIMIZE
,
214 IDR_AURA_WINDOW_MAXIMIZE_H
,
215 IDR_AURA_WINDOW_MAXIMIZE_P
));
216 EXPECT_TRUE(ImagesMatch(t
.close_button(),
217 IDR_AURA_WINDOW_CLOSE
,
218 IDR_AURA_WINDOW_CLOSE_H
,
219 IDR_AURA_WINDOW_CLOSE_P
));
221 // Short header style.
222 container
.set_header_style(
223 FrameCaptionButtonContainerView::HEADER_STYLE_SHORT
);
225 EXPECT_TRUE(ImagesMatch(t
.size_button(),
226 IDR_AURA_WINDOW_MAXIMIZED_RESTORE
,
227 IDR_AURA_WINDOW_MAXIMIZED_RESTORE_H
,
228 IDR_AURA_WINDOW_MAXIMIZED_RESTORE_P
));
229 EXPECT_TRUE(ImagesMatch(t
.close_button(),
230 IDR_AURA_WINDOW_MAXIMIZED_CLOSE
,
231 IDR_AURA_WINDOW_MAXIMIZED_CLOSE_H
,
232 IDR_AURA_WINDOW_MAXIMIZED_CLOSE_P
));
234 // Maximized short header style.
237 EXPECT_TRUE(ImagesMatch(t
.size_button(),
238 IDR_AURA_WINDOW_MAXIMIZED_RESTORE2
,
239 IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_H
,
240 IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_P
));
241 EXPECT_TRUE(ImagesMatch(t
.close_button(),
242 IDR_AURA_WINDOW_MAXIMIZED_CLOSE2
,
243 IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_H
,
244 IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_P
));
246 // The buttons are visible during a reveal of the top-of-window views in
247 // immersive fullscreen. They should use the same images as maximized.
248 widget
->SetFullscreen(true);
250 EXPECT_TRUE(ImagesMatch(t
.size_button(),
251 IDR_AURA_WINDOW_MAXIMIZED_RESTORE2
,
252 IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_H
,
253 IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_P
));
254 EXPECT_TRUE(ImagesMatch(t
.close_button(),
255 IDR_AURA_WINDOW_MAXIMIZED_CLOSE2
,
256 IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_H
,
257 IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_P
));
259 // AppNonClientFrameViewAsh has a dedicated set of images.
260 container
.set_header_style(
261 FrameCaptionButtonContainerView::HEADER_STYLE_MAXIMIZED_HOSTED_APP
);
263 EXPECT_TRUE(ImagesMatch(t
.size_button(),
264 IDR_AURA_WINDOW_FULLSCREEN_RESTORE
,
265 IDR_AURA_WINDOW_FULLSCREEN_RESTORE_H
,
266 IDR_AURA_WINDOW_FULLSCREEN_RESTORE_P
));
267 EXPECT_TRUE(ImagesMatch(t
.close_button(),
268 IDR_AURA_WINDOW_FULLSCREEN_CLOSE
,
269 IDR_AURA_WINDOW_FULLSCREEN_CLOSE_H
,
270 IDR_AURA_WINDOW_FULLSCREEN_CLOSE_P
));
273 class FrameCaptionButtonContainerViewTestAlternateStyle
274 : public FrameCaptionButtonContainerViewTest
{
276 FrameCaptionButtonContainerViewTestAlternateStyle() {
279 virtual ~FrameCaptionButtonContainerViewTestAlternateStyle() {
282 virtual void SetUp() OVERRIDE
{
283 FrameCaptionButtonContainerViewTest::SetUp();
284 CommandLine::ForCurrentProcess()->AppendSwitch(
285 switches::kAshEnableAlternateFrameCaptionButtonStyle
);
286 ASSERT_TRUE(switches::UseAlternateFrameCaptionButtonStyle());
290 DISALLOW_COPY_AND_ASSIGN(FrameCaptionButtonContainerViewTestAlternateStyle
);
293 // Test how the alternate button style affects which buttons are visible in the
295 TEST_F(FrameCaptionButtonContainerViewTestAlternateStyle
, ButtonVisibility
) {
296 // Both the minimize button and the maximize button should be visible when
297 // both minimizing and maximizing are allowed when using the alternate
299 scoped_ptr
<views::Widget
> widget_can_maximize(
300 CreateTestWidget(MAXIMIZE_ALLOWED
));
301 FrameCaptionButtonContainerView
container(widget_can_maximize
.get(),
302 FrameCaptionButtonContainerView::MINIMIZE_ALLOWED
);
304 FrameCaptionButtonContainerView::TestApi
t(&container
);
305 EXPECT_TRUE(t
.minimize_button()->visible());
306 EXPECT_TRUE(t
.size_button()->visible());
307 EXPECT_TRUE(t
.close_button()->visible());
308 EXPECT_TRUE(CheckButtonsAtEdges(
309 &container
, *t
.minimize_button(), *t
.close_button()));