custom_frame_view_ash.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/custom_frame_view_ash.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/frame_painter.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/workspace/frame_maximize_button.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ash_resources.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_strings.h"  // Accessibility names
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer_animator.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/font.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/image_button.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/native_widget_aura.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget_delegate.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const gfx::Font& GetTitleFont() {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static gfx::Font* title_font = NULL;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!title_font)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    title_font = new gfx::Font(views::NativeWidgetAura::GetWindowTitleFont());
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *title_font;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char CustomFrameViewAsh::kViewClassName[] = "ash/wm/CustomFrameViewAsh";
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CustomFrameViewAsh, public:
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CustomFrameViewAsh::CustomFrameViewAsh()
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : frame_(NULL),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      maximize_button_(NULL),
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      close_button_(NULL),
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window_icon_(NULL),
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame_painter_(new ash::FramePainter) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CustomFrameViewAsh::~CustomFrameViewAsh() {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameViewAsh::Init(views::Widget* frame) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_ = frame;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  maximize_button_ = new FrameMaximizeButton(this, this);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  maximize_button_->SetAccessibleName(
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MAXIMIZE));
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddChildView(maximize_button_);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  close_button_ = new views::ImageButton(this);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  close_button_->SetAccessibleName(
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE));
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddChildView(close_button_);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  maximize_button_->SetVisible(frame_->widget_delegate()->CanMaximize());
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frame_->widget_delegate()->ShouldShowWindowIcon()) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_icon_ = new views::ImageButton(this);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddChildView(window_icon_);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_painter_->Init(frame_, window_icon_, maximize_button_, close_button_,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       FramePainter::SIZE_BUTTON_MAXIMIZES);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CustomFrameViewAsh, views::NonClientFrameView overrides:
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect CustomFrameViewAsh::GetBoundsForClientView() const {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int top_height = NonClientTopBorderHeight();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame_painter_->GetBoundsForClientView(top_height,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                bounds());
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect CustomFrameViewAsh::GetWindowBoundsForClientBounds(
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& client_bounds) const {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int top_height = NonClientTopBorderHeight();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame_painter_->GetWindowBoundsForClientBounds(top_height,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                        client_bounds);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomFrameViewAsh::NonClientHitTest(const gfx::Point& point) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame_painter_->NonClientHitTest(this, point);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameViewAsh::GetWindowMask(const gfx::Size& size,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       gfx::Path* window_mask) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No window masks in Aura.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameViewAsh::ResetWindowControls() {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  maximize_button_->SetState(views::CustomButton::BS_NORMAL);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameViewAsh::UpdateWindowIcon() {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window_icon_)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_icon_->SchedulePaint();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameViewAsh::UpdateWindowTitle() {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_painter_->SchedulePaintForTitle(this, GetTitleFont());
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CustomFrameViewAsh, views::View overrides:
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size CustomFrameViewAsh::GetPreferredSize() {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size pref = frame_->client_view()->GetPreferredSize();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect bounds(0, 0, pref.width(), pref.height());
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame_->non_client_view()->GetWindowBoundsForClientBounds(
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bounds).size();
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameViewAsh::Layout() {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use the shorter maximized layout headers.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_painter_->LayoutHeader(this, true);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameViewAsh::OnPaint(gfx::Canvas* canvas) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frame_->IsFullscreen())
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool paint_as_active = ShouldPaintAsActive();
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int theme_image_id = paint_as_active ? IDR_AURA_WINDOW_HEADER_BASE_ACTIVE :
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IDR_AURA_WINDOW_HEADER_BASE_INACTIVE;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_painter_->PaintHeader(
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      canvas,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      paint_as_active ? FramePainter::ACTIVE : FramePainter::INACTIVE,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      theme_image_id,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_painter_->PaintTitleBar(this, canvas, GetTitleFont());
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_painter_->PaintHeaderContentSeparator(this, canvas);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string CustomFrameViewAsh::GetClassName() const {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kViewClassName;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size CustomFrameViewAsh::GetMinimumSize() {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frame_painter_->GetMinimumSize(this);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// views::ButtonListener overrides:
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CustomFrameViewAsh::ButtonPressed(views::Button* sender,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const ui::Event& event) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event.IsShiftDown())
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::LayerAnimator::set_slow_animation_mode(true);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sender == maximize_button_) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The maximize button may move out from under the cursor.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResetWindowControls();
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (frame_->IsMaximized())
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame_->Restore();
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame_->Maximize();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |this| may be deleted - some windows delete their frames on maximize.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (sender == close_button_) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    frame_->Close();
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event.IsShiftDown())
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::LayerAnimator::set_slow_animation_mode(false);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CustomFrameViewAsh, private:
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CustomFrameViewAsh::NonClientTopBorderHeight() const {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frame_->IsFullscreen())
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reserve enough space to see the buttons, including any offset from top and
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reserving space for the separator line.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return close_button_->bounds().bottom() +
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame_painter_->HeaderContentSeparatorSize();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
187