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 "ash/wm/header_painter.h"
6
7 #include "ash/shell.h"
8 #include "ash/test/ash_test_base.h"
9 #include "ash/wm/caption_buttons/frame_caption_button_container_view.h"
10 #include "ash/wm/window_state.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "grit/ash_resources.h"
13 #include "ui/gfx/font.h"
14 #include "ui/views/widget/widget.h"
15 #include "ui/views/window/non_client_view.h"
16
17 using ash::HeaderPainter;
18 using views::NonClientFrameView;
19 using views::Widget;
20
21 namespace {
22
23 // Modifies the values of kInactiveWindowOpacity, kActiveWindowOpacity, and
24 // kSoloWindowOpacity for the lifetime of the class. This is useful so that
25 // the constants each have different values.
26 class ScopedOpacityConstantModifier {
27 public:
ScopedOpacityConstantModifier()28 ScopedOpacityConstantModifier()
29 : initial_active_window_opacity_(
30 ash::HeaderPainter::kActiveWindowOpacity),
31 initial_inactive_window_opacity_(
32 ash::HeaderPainter::kInactiveWindowOpacity),
33 initial_solo_window_opacity_(ash::HeaderPainter::kSoloWindowOpacity) {
34 ash::HeaderPainter::kActiveWindowOpacity = 100;
35 ash::HeaderPainter::kInactiveWindowOpacity = 120;
36 ash::HeaderPainter::kSoloWindowOpacity = 140;
37 }
~ScopedOpacityConstantModifier()38 ~ScopedOpacityConstantModifier() {
39 ash::HeaderPainter::kActiveWindowOpacity = initial_active_window_opacity_;
40 ash::HeaderPainter::kInactiveWindowOpacity =
41 initial_inactive_window_opacity_;
42 ash::HeaderPainter::kSoloWindowOpacity = initial_solo_window_opacity_;
43 }
44
45 private:
46 int initial_active_window_opacity_;
47 int initial_inactive_window_opacity_;
48 int initial_solo_window_opacity_;
49
50 DISALLOW_COPY_AND_ASSIGN(ScopedOpacityConstantModifier);
51 };
52
53 // Creates a new HeaderPainter with empty buttons. Caller owns the memory.
CreateTestPainter(Widget * widget)54 HeaderPainter* CreateTestPainter(Widget* widget) {
55 HeaderPainter* painter = new HeaderPainter();
56 NonClientFrameView* frame_view = widget->non_client_view()->frame_view();
57 ash::FrameCaptionButtonContainerView* container =
58 new ash::FrameCaptionButtonContainerView(
59 widget,
60 ash::FrameCaptionButtonContainerView::MINIMIZE_ALLOWED);
61 // Add the container to the widget's non-client frame view so that it will be
62 // deleted when the widget is destroyed.
63 frame_view->AddChildView(container);
64 painter->Init(widget, frame_view, NULL, container);
65 return painter;
66 }
67
68 } // namespace
69
70 namespace ash {
71
72 class HeaderPainterTest : public ash::test::AshTestBase {
73 public:
74 // Creates a test widget that owns its native widget.
CreateTestWidget()75 Widget* CreateTestWidget() {
76 Widget* widget = new Widget;
77 Widget::InitParams params;
78 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
79 params.context = CurrentContext();
80 widget->Init(params);
81 return widget;
82 }
83 };
84
TEST_F(HeaderPainterTest,GetHeaderOpacity)85 TEST_F(HeaderPainterTest, GetHeaderOpacity) {
86 // Create a widget and a painter for it.
87 scoped_ptr<Widget> w1(CreateTestWidget());
88 scoped_ptr<HeaderPainter> p1(CreateTestPainter(w1.get()));
89 w1->Show();
90
91 // Modify the values of the opacity constants so that they each have a
92 // different value.
93 ScopedOpacityConstantModifier opacity_constant_modifier;
94
95 // Solo active window has solo window opacity.
96 EXPECT_EQ(HeaderPainter::kSoloWindowOpacity,
97 p1->GetHeaderOpacity(HeaderPainter::ACTIVE,
98 IDR_AURA_WINDOW_HEADER_BASE_ACTIVE,
99 0));
100
101 // Create a second widget and painter.
102 scoped_ptr<Widget> w2(CreateTestWidget());
103 scoped_ptr<HeaderPainter> p2(CreateTestPainter(w2.get()));
104 w2->Show();
105
106 // Active window has active window opacity.
107 EXPECT_EQ(HeaderPainter::kActiveWindowOpacity,
108 p2->GetHeaderOpacity(HeaderPainter::ACTIVE,
109 IDR_AURA_WINDOW_HEADER_BASE_ACTIVE,
110 0));
111
112 // Inactive window has inactive window opacity.
113 EXPECT_EQ(HeaderPainter::kInactiveWindowOpacity,
114 p2->GetHeaderOpacity(HeaderPainter::INACTIVE,
115 IDR_AURA_WINDOW_HEADER_BASE_INACTIVE,
116 0));
117
118 // Regular maximized windows are fully opaque.
119 wm::GetWindowState(w1->GetNativeWindow())->Maximize();
120 EXPECT_EQ(255,
121 p1->GetHeaderOpacity(HeaderPainter::ACTIVE,
122 IDR_AURA_WINDOW_HEADER_BASE_ACTIVE,
123 0));
124 }
125
126 // Ensure the title text is vertically aligned with the window icon.
TEST_F(HeaderPainterTest,TitleIconAlignment)127 TEST_F(HeaderPainterTest, TitleIconAlignment) {
128 scoped_ptr<Widget> w(CreateTestWidget());
129 HeaderPainter p;
130 ash::FrameCaptionButtonContainerView container(w.get(),
131 ash::FrameCaptionButtonContainerView::MINIMIZE_ALLOWED);
132 views::View window_icon;
133 window_icon.SetBounds(0, 0, 16, 16);
134 p.Init(w.get(),
135 w->non_client_view()->frame_view(),
136 &window_icon,
137 &container);
138 w->SetBounds(gfx::Rect(0, 0, 500, 500));
139 w->Show();
140
141 // Title and icon are aligned when shorter_header is false.
142 p.LayoutHeader(false);
143 gfx::Font default_font;
144 gfx::Rect large_header_title_bounds = p.GetTitleBounds(default_font);
145 EXPECT_EQ(window_icon.bounds().CenterPoint().y(),
146 large_header_title_bounds.CenterPoint().y());
147
148 // Title and icon are aligned when shorter_header is true.
149 p.LayoutHeader(true);
150 gfx::Rect short_header_title_bounds = p.GetTitleBounds(default_font);
151 EXPECT_EQ(window_icon.bounds().CenterPoint().y(),
152 short_header_title_bounds.CenterPoint().y());
153 }
154
155 } // namespace ash
156