1 // Copyright (c) 2012 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/custom_frame_view_ash.h"
7 #include "ash/shell_delegate.h"
8 #include "ash/wm/frame_painter.h"
9 #include "ash/wm/workspace/frame_maximize_button.h"
10 #include "grit/ash_resources.h"
11 #include "grit/ui_strings.h" // Accessibility names
12 #include "ui/base/l10n/l10n_util.h"
13 #include "ui/base/resource/resource_bundle.h"
14 #include "ui/compositor/layer_animator.h"
15 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
16 #include "ui/gfx/canvas.h"
17 #include "ui/gfx/font.h"
18 #include "ui/gfx/image/image.h"
19 #include "ui/gfx/rect.h"
20 #include "ui/gfx/size.h"
21 #include "ui/views/controls/button/image_button.h"
22 #include "ui/views/widget/native_widget_aura.h"
23 #include "ui/views/widget/widget.h"
24 #include "ui/views/widget/widget_delegate.h"
28 const gfx::Font
& GetTitleFont() {
29 static gfx::Font
* title_font
= NULL
;
31 title_font
= new gfx::Font(views::NativeWidgetAura::GetWindowTitleFont());
40 const char CustomFrameViewAsh::kViewClassName
[] = "CustomFrameViewAsh";
42 ////////////////////////////////////////////////////////////////////////////////
43 // CustomFrameViewAsh, public:
44 CustomFrameViewAsh::CustomFrameViewAsh()
46 maximize_button_(NULL
),
49 frame_painter_(new ash::FramePainter
) {
52 CustomFrameViewAsh::~CustomFrameViewAsh() {
55 void CustomFrameViewAsh::Init(views::Widget
* frame
) {
58 maximize_button_
= new FrameMaximizeButton(this, this);
59 maximize_button_
->SetAccessibleName(
60 l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MAXIMIZE
));
61 AddChildView(maximize_button_
);
62 close_button_
= new views::ImageButton(this);
63 close_button_
->SetAccessibleName(
64 l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE
));
65 AddChildView(close_button_
);
67 maximize_button_
->SetVisible(frame_
->widget_delegate()->CanMaximize());
69 if (frame_
->widget_delegate()->ShouldShowWindowIcon()) {
70 window_icon_
= new views::ImageButton(this);
71 AddChildView(window_icon_
);
74 frame_painter_
->Init(frame_
, window_icon_
, maximize_button_
, close_button_
,
75 FramePainter::SIZE_BUTTON_MAXIMIZES
);
78 ////////////////////////////////////////////////////////////////////////////////
79 // CustomFrameViewAsh, views::NonClientFrameView overrides:
80 gfx::Rect
CustomFrameViewAsh::GetBoundsForClientView() const {
81 int top_height
= NonClientTopBorderHeight();
82 return frame_painter_
->GetBoundsForClientView(top_height
,
86 gfx::Rect
CustomFrameViewAsh::GetWindowBoundsForClientBounds(
87 const gfx::Rect
& client_bounds
) const {
88 int top_height
= NonClientTopBorderHeight();
89 return frame_painter_
->GetWindowBoundsForClientBounds(top_height
,
93 int CustomFrameViewAsh::NonClientHitTest(const gfx::Point
& point
) {
94 return frame_painter_
->NonClientHitTest(this, point
);
97 void CustomFrameViewAsh::GetWindowMask(const gfx::Size
& size
,
98 gfx::Path
* window_mask
) {
99 // No window masks in Aura.
102 void CustomFrameViewAsh::ResetWindowControls() {
103 maximize_button_
->SetState(views::CustomButton::STATE_NORMAL
);
106 void CustomFrameViewAsh::UpdateWindowIcon() {
108 window_icon_
->SchedulePaint();
111 void CustomFrameViewAsh::UpdateWindowTitle() {
112 frame_painter_
->SchedulePaintForTitle(this, GetTitleFont());
115 ////////////////////////////////////////////////////////////////////////////////
116 // CustomFrameViewAsh, views::View overrides:
118 gfx::Size
CustomFrameViewAsh::GetPreferredSize() {
119 gfx::Size pref
= frame_
->client_view()->GetPreferredSize();
120 gfx::Rect
bounds(0, 0, pref
.width(), pref
.height());
121 return frame_
->non_client_view()->GetWindowBoundsForClientBounds(
125 void CustomFrameViewAsh::Layout() {
126 // Use the shorter maximized layout headers.
127 frame_painter_
->LayoutHeader(this, true);
130 void CustomFrameViewAsh::OnPaint(gfx::Canvas
* canvas
) {
131 if (frame_
->IsFullscreen())
134 // Prevent bleeding paint onto the client area below the window frame, which
135 // may become visible when the WebContent is transparent.
137 canvas
->ClipRect(gfx::Rect(0, 0, width(), NonClientTopBorderHeight()));
139 bool paint_as_active
= ShouldPaintAsActive();
140 int theme_image_id
= 0;
141 if (frame_painter_
->ShouldUseMinimalHeaderStyle(FramePainter::THEMED_NO
))
142 theme_image_id
= IDR_AURA_WINDOW_HEADER_BASE_MINIMAL
;
143 else if (paint_as_active
)
144 theme_image_id
= IDR_AURA_WINDOW_HEADER_BASE_ACTIVE
;
146 theme_image_id
= IDR_AURA_WINDOW_HEADER_BASE_INACTIVE
;
148 frame_painter_
->PaintHeader(
151 paint_as_active
? FramePainter::ACTIVE
: FramePainter::INACTIVE
,
154 frame_painter_
->PaintTitleBar(this, canvas
, GetTitleFont());
155 frame_painter_
->PaintHeaderContentSeparator(this, canvas
);
159 const char* CustomFrameViewAsh::GetClassName() const {
160 return kViewClassName
;
163 gfx::Size
CustomFrameViewAsh::GetMinimumSize() {
164 return frame_painter_
->GetMinimumSize(this);
167 gfx::Size
CustomFrameViewAsh::GetMaximumSize() {
168 return frame_painter_
->GetMaximumSize(this);
171 ////////////////////////////////////////////////////////////////////////////////
172 // views::ButtonListener overrides:
173 void CustomFrameViewAsh::ButtonPressed(views::Button
* sender
,
174 const ui::Event
& event
) {
175 scoped_ptr
<ui::ScopedAnimationDurationScaleMode
> slow_duration_mode
;
176 if (event
.IsShiftDown()) {
177 slow_duration_mode
.reset(new ui::ScopedAnimationDurationScaleMode(
178 ui::ScopedAnimationDurationScaleMode::SLOW_DURATION
));
181 ash::UserMetricsAction action
=
182 ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MAXIMIZE
;
184 if (sender
== maximize_button_
) {
185 // The maximize button may move out from under the cursor.
186 ResetWindowControls();
187 if (frame_
->IsMaximized()) {
188 action
= ash::UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_RESTORE
;
193 // |this| may be deleted - some windows delete their frames on maximize.
194 } else if (sender
== close_button_
) {
195 action
= ash::UMA_WINDOW_CLOSE_BUTTON_CLICK
;
201 ash::Shell::GetInstance()->delegate()->RecordUserMetricsAction(action
);
204 ////////////////////////////////////////////////////////////////////////////////
205 // CustomFrameViewAsh, private:
207 int CustomFrameViewAsh::NonClientTopBorderHeight() const {
208 if (frame_
->IsFullscreen())
211 // Reserve enough space to see the buttons, including any offset from top and
212 // reserving space for the separator line.
213 return close_button_
->bounds().bottom() +
214 frame_painter_
->HeaderContentSeparatorSize();