| Index: ash/wm/custom_frame_view_ash.cc
|
| diff --git a/ash/wm/custom_frame_view_ash.cc b/ash/wm/custom_frame_view_ash.cc
|
| index f03026c0ecdb8bdfab6e74c2da2ea055d4c19428..d100a248a33c0445884913eca96a8929c8367e74 100644
|
| --- a/ash/wm/custom_frame_view_ash.cc
|
| +++ b/ash/wm/custom_frame_view_ash.cc
|
| @@ -5,16 +5,21 @@
|
| #include "ash/wm/custom_frame_view_ash.h"
|
|
|
| #include "ash/wm/caption_buttons/frame_caption_button_container_view.h"
|
| +#include "ash/wm/caption_buttons/frame_maximize_button.h"
|
| +#include "ash/wm/caption_buttons/frame_maximize_button_observer.h"
|
| #include "ash/wm/frame_border_hit_test_controller.h"
|
| #include "ash/wm/header_painter.h"
|
| +#include "ash/wm/immersive_fullscreen_controller.h"
|
| #include "grit/ash_resources.h"
|
| #include "ui/gfx/canvas.h"
|
| #include "ui/gfx/font.h"
|
| #include "ui/gfx/rect.h"
|
| #include "ui/gfx/size.h"
|
| +#include "ui/views/view.h"
|
| #include "ui/views/widget/native_widget_aura.h"
|
| #include "ui/views/widget/widget.h"
|
| #include "ui/views/widget/widget_delegate.h"
|
| +#include "ui/views/widget/widget_deletion_observer.h"
|
|
|
| namespace {
|
|
|
| @@ -29,35 +34,283 @@ const gfx::Font& GetTitleFont() {
|
|
|
| namespace ash {
|
|
|
| -// static
|
| -const char CustomFrameViewAsh::kViewClassName[] = "CustomFrameViewAsh";
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +// CustomFrameViewAsh::HeaderView
|
|
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// CustomFrameViewAsh, public:
|
| -CustomFrameViewAsh::CustomFrameViewAsh(views::Widget* frame)
|
| +// View which paints the header. It slides off and on screen in immersive
|
| +// fullscreen.
|
| +class CustomFrameViewAsh::HeaderView
|
| + : public views::View,
|
| + public ImmersiveFullscreenController::Delegate,
|
| + public FrameMaximizeButtonObserver {
|
| + public:
|
| + // |frame| is the widget that the caption buttons act on.
|
| + explicit HeaderView(views::Widget* frame);
|
| + virtual ~HeaderView();
|
| +
|
| + // Schedules a repaint for the entire title.
|
| + void SchedulePaintForTitle();
|
| +
|
| + // Tells the window controls to reset themselves to the normal state.
|
| + void ResetWindowControls();
|
| +
|
| + // Returns the amount of the view's pixels which should be on screen.
|
| + int GetPreferredOnScreenHeight() const;
|
| +
|
| + // Returns the view's preferred height.
|
| + int GetPreferredHeight() const;
|
| +
|
| + // Returns the view's minimum width.
|
| + int GetMinimumWidth() const;
|
| +
|
| + // views::View overrides:
|
| + virtual void Layout() OVERRIDE;
|
| + virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
|
| +
|
| + // Sets whether the header should be painted as active.
|
| + void set_paint_as_active(bool paint_as_active) {
|
| + paint_as_active_ = paint_as_active;
|
| + }
|
| +
|
| + HeaderPainter* header_painter() {
|
| + return header_painter_.get();
|
| + }
|
| +
|
| + private:
|
| + // ImmersiveFullscreenController::Delegate overrides:
|
| + virtual void OnImmersiveRevealStarted() OVERRIDE;
|
| + virtual void OnImmersiveRevealEnded() OVERRIDE;
|
| + virtual void OnImmersiveFullscreenExited() OVERRIDE;
|
| + virtual void SetVisibleFraction(double visible_fraction) OVERRIDE;
|
| + virtual std::vector<gfx::Rect> GetVisibleBoundsInScreen() const OVERRIDE;
|
| +
|
| + // FrameMaximizeButtonObserver overrides:
|
| + virtual void OnMaximizeBubbleShown(views::Widget* bubble) OVERRIDE;
|
| +
|
| + // The widget that the caption buttons act on.
|
| + views::Widget* frame_;
|
| +
|
| + // Helper for painting the header.
|
| + scoped_ptr<HeaderPainter> header_painter_;
|
| +
|
| + // View which contains the window caption buttons.
|
| + FrameCaptionButtonContainerView* caption_button_container_;
|
| +
|
| + // The maximize bubble widget. |maximize_bubble_| may be non-NULL but have
|
| + // been already destroyed.
|
| + views::Widget* maximize_bubble_;
|
| +
|
| + // Keeps track of whether |maximize_bubble_| is still alive.
|
| + scoped_ptr<views::WidgetDeletionObserver> maximize_bubble_lifetime_observer_;
|
| +
|
| + // Whether the header should be painted as active.
|
| + bool paint_as_active_;
|
| +
|
| + // The fraction of the header's height which is visible while in fullscreen.
|
| + // This value is meaningless when not in fullscreen.
|
| + double fullscreen_visible_fraction_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(HeaderView);
|
| +};
|
| +
|
| +CustomFrameViewAsh::HeaderView::HeaderView(views::Widget* frame)
|
| : frame_(frame),
|
| - caption_button_container_(NULL),
|
| header_painter_(new ash::HeaderPainter),
|
| - frame_border_hit_test_controller_(
|
| - new FrameBorderHitTestController(frame_)) {
|
| + caption_button_container_(NULL),
|
| + maximize_bubble_(NULL),
|
| + paint_as_active_(false),
|
| + fullscreen_visible_fraction_(0) {
|
| // Unfortunately, there is no views::WidgetDelegate::CanMinimize(). Assume
|
| // that the window frame can be minimized if it can be maximized.
|
| FrameCaptionButtonContainerView::MinimizeAllowed minimize_allowed =
|
| frame_->widget_delegate()->CanMaximize() ?
|
| FrameCaptionButtonContainerView::MINIMIZE_ALLOWED :
|
| FrameCaptionButtonContainerView::MINIMIZE_DISALLOWED;
|
| - caption_button_container_ = new FrameCaptionButtonContainerView(frame,
|
| + caption_button_container_ = new FrameCaptionButtonContainerView(frame_,
|
| minimize_allowed);
|
| AddChildView(caption_button_container_);
|
| + FrameMaximizeButton* frame_maximize_button =
|
| + caption_button_container_->GetOldStyleSizeButton();
|
| + if (frame_maximize_button)
|
| + frame_maximize_button->AddObserver(this);
|
|
|
| header_painter_->Init(frame_, this, NULL, caption_button_container_);
|
| }
|
|
|
| +CustomFrameViewAsh::HeaderView::~HeaderView() {
|
| +}
|
| +
|
| +void CustomFrameViewAsh::HeaderView::SchedulePaintForTitle() {
|
| + header_painter_->SchedulePaintForTitle(GetTitleFont());
|
| +}
|
| +
|
| +void CustomFrameViewAsh::HeaderView::ResetWindowControls() {
|
| + caption_button_container_->ResetWindowControls();
|
| +}
|
| +
|
| +int CustomFrameViewAsh::HeaderView::GetPreferredOnScreenHeight() const {
|
| + if (frame_->IsFullscreen()) {
|
| + return static_cast<int>(
|
| + GetPreferredHeight() * fullscreen_visible_fraction_);
|
| + }
|
| + return GetPreferredHeight();
|
| +}
|
| +
|
| +int CustomFrameViewAsh::HeaderView::GetPreferredHeight() const {
|
| + // Reserve enough space to see the buttons and the separator line.
|
| + return caption_button_container_->bounds().bottom() +
|
| + header_painter_->HeaderContentSeparatorSize();
|
| +}
|
| +
|
| +int CustomFrameViewAsh::HeaderView::GetMinimumWidth() const {
|
| + return header_painter_->GetMinimumHeaderWidth();
|
| +}
|
| +
|
| +void CustomFrameViewAsh::HeaderView::Layout() {
|
| + header_painter_->LayoutHeader(true);
|
| + header_painter_->set_header_height(GetPreferredHeight());
|
| +}
|
| +
|
| +void CustomFrameViewAsh::HeaderView::OnPaint(gfx::Canvas* canvas) {
|
| + int theme_image_id = 0;
|
| + if (header_painter_->ShouldUseMinimalHeaderStyle(HeaderPainter::THEMED_NO))
|
| + theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_MINIMAL;
|
| + else if (paint_as_active_)
|
| + theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_ACTIVE;
|
| + else
|
| + theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_INACTIVE;
|
| +
|
| + header_painter_->PaintHeader(
|
| + canvas,
|
| + paint_as_active_ ? HeaderPainter::ACTIVE : HeaderPainter::INACTIVE,
|
| + theme_image_id,
|
| + 0);
|
| + header_painter_->PaintTitleBar(canvas, GetTitleFont());
|
| + header_painter_->PaintHeaderContentSeparator(canvas);
|
| +}
|
| +
|
| +void CustomFrameViewAsh::HeaderView::OnImmersiveRevealStarted() {
|
| + fullscreen_visible_fraction_ = 0;
|
| + SetPaintToLayer(true);
|
| + parent()->Layout();
|
| +}
|
| +
|
| +void CustomFrameViewAsh::HeaderView::OnImmersiveRevealEnded() {
|
| + fullscreen_visible_fraction_ = 0;
|
| + SetPaintToLayer(false);
|
| + parent()->Layout();
|
| +}
|
| +
|
| +void CustomFrameViewAsh::HeaderView::OnImmersiveFullscreenExited() {
|
| + fullscreen_visible_fraction_ = 0;
|
| + SetPaintToLayer(false);
|
| + parent()->Layout();
|
| +}
|
| +
|
| +void CustomFrameViewAsh::HeaderView::SetVisibleFraction(
|
| + double visible_fraction) {
|
| + if (fullscreen_visible_fraction_ != visible_fraction) {
|
| + fullscreen_visible_fraction_ = visible_fraction;
|
| + parent()->Layout();
|
| + }
|
| +}
|
| +
|
| +std::vector<gfx::Rect>
|
| +CustomFrameViewAsh::HeaderView::GetVisibleBoundsInScreen() const {
|
| + // TODO(pkotwicz): Implement views::View::ConvertRectToScreen().
|
| + gfx::Rect visible_bounds(GetVisibleBounds());
|
| + gfx::Point visible_origin_in_screen(visible_bounds.origin());
|
| + views::View::ConvertPointToScreen(this, &visible_origin_in_screen);
|
| + std::vector<gfx::Rect> bounds_in_screen;
|
| + bounds_in_screen.push_back(
|
| + gfx::Rect(visible_origin_in_screen, visible_bounds.size()));
|
| + if (maximize_bubble_lifetime_observer_.get() &&
|
| + maximize_bubble_lifetime_observer_->IsWidgetAlive()) {
|
| + bounds_in_screen.push_back(maximize_bubble_->GetWindowBoundsInScreen());
|
| + }
|
| + return bounds_in_screen;
|
| +}
|
| +
|
| +void CustomFrameViewAsh::HeaderView::OnMaximizeBubbleShown(
|
| + views::Widget* bubble) {
|
| + maximize_bubble_ = bubble;
|
| + maximize_bubble_lifetime_observer_.reset(
|
| + new views::WidgetDeletionObserver(bubble));
|
| +}
|
| +
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +// CustomFrameViewAsh::OverlayView
|
| +
|
| +// View which takes up the entire widget and contains the HeaderView. HeaderView
|
| +// is a child of OverlayView to avoid creating a larger texture than necessary
|
| +// when painting the HeaderView to its own layer.
|
| +class CustomFrameViewAsh::OverlayView : public views::View {
|
| + public:
|
| + explicit OverlayView(HeaderView* header_view);
|
| + virtual ~OverlayView();
|
| +
|
| + // views::View override:
|
| + virtual void Layout() OVERRIDE;
|
| + virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE;
|
| +
|
| + private:
|
| + HeaderView* header_view_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(OverlayView);
|
| +};
|
| +
|
| +CustomFrameViewAsh::OverlayView::OverlayView(HeaderView* header_view)
|
| + : header_view_(header_view) {
|
| + AddChildView(header_view);
|
| +}
|
| +
|
| +CustomFrameViewAsh::OverlayView::~OverlayView() {
|
| +}
|
| +
|
| +void CustomFrameViewAsh::OverlayView::Layout() {
|
| + int onscreen_height = header_view_->GetPreferredOnScreenHeight();
|
| + if (onscreen_height == 0) {
|
| + header_view_->SetVisible(false);
|
| + } else {
|
| + int height = header_view_->GetPreferredHeight();
|
| + header_view_->SetBounds(0, onscreen_height - height, width(), height);
|
| + header_view_->SetVisible(true);
|
| + }
|
| +}
|
| +
|
| +bool CustomFrameViewAsh::OverlayView::HitTestRect(const gfx::Rect& rect) const {
|
| + // Grab events in the header view. Return false for other events so that they
|
| + // can be handled by the client view.
|
| + return header_view_->HitTestRect(rect);
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// CustomFrameViewAsh, public:
|
| +
|
| +// static
|
| +const char CustomFrameViewAsh::kViewClassName[] = "CustomFrameViewAsh";
|
| +
|
| +CustomFrameViewAsh::CustomFrameViewAsh(views::Widget* frame)
|
| + : frame_(frame),
|
| + header_view_(new HeaderView(frame)),
|
| + frame_border_hit_test_controller_(
|
| + new FrameBorderHitTestController(frame_)) {
|
| + // |header_view_| is set as the non client view's overlay view so that it can
|
| + // overlay the web contents in immersive fullscreen.
|
| + frame->non_client_view()->SetOverlayView(new OverlayView(header_view_));
|
| +}
|
| +
|
| CustomFrameViewAsh::~CustomFrameViewAsh() {
|
| }
|
|
|
| +void CustomFrameViewAsh::InitImmersiveFullscreenControllerForView(
|
| + ImmersiveFullscreenController* immersive_fullscreen_controller) {
|
| + immersive_fullscreen_controller->Init(header_view_, frame_, header_view_);
|
| +}
|
| +
|
| ////////////////////////////////////////////////////////////////////////////////
|
| // CustomFrameViewAsh, views::NonClientFrameView overrides:
|
| +
|
| gfx::Rect CustomFrameViewAsh::GetBoundsForClientView() const {
|
| int top_height = NonClientTopBorderHeight();
|
| return HeaderPainter::GetBoundsForClientView(top_height, bounds());
|
| @@ -72,7 +325,7 @@ gfx::Rect CustomFrameViewAsh::GetWindowBoundsForClientBounds(
|
|
|
| int CustomFrameViewAsh::NonClientHitTest(const gfx::Point& point) {
|
| return FrameBorderHitTestController::NonClientHitTest(this,
|
| - header_painter_.get(), point);
|
| + header_view_->header_painter(), point);
|
| }
|
|
|
| void CustomFrameViewAsh::GetWindowMask(const gfx::Size& size,
|
| @@ -81,14 +334,14 @@ void CustomFrameViewAsh::GetWindowMask(const gfx::Size& size,
|
| }
|
|
|
| void CustomFrameViewAsh::ResetWindowControls() {
|
| - caption_button_container_->ResetWindowControls();
|
| + header_view_->ResetWindowControls();
|
| }
|
|
|
| void CustomFrameViewAsh::UpdateWindowIcon() {
|
| }
|
|
|
| void CustomFrameViewAsh::UpdateWindowTitle() {
|
| - header_painter_->SchedulePaintForTitle(GetTitleFont());
|
| + header_view_->SchedulePaintForTitle();
|
| }
|
|
|
| ////////////////////////////////////////////////////////////////////////////////
|
| @@ -101,40 +354,6 @@ gfx::Size CustomFrameViewAsh::GetPreferredSize() {
|
| bounds).size();
|
| }
|
|
|
| -void CustomFrameViewAsh::Layout() {
|
| - // Use the shorter maximized layout headers.
|
| - header_painter_->LayoutHeader(true);
|
| - header_painter_->set_header_height(NonClientTopBorderHeight());
|
| -}
|
| -
|
| -void CustomFrameViewAsh::OnPaint(gfx::Canvas* canvas) {
|
| - if (frame_->IsFullscreen())
|
| - return;
|
| -
|
| - // Prevent bleeding paint onto the client area below the window frame, which
|
| - // may become visible when the WebContent is transparent.
|
| - canvas->Save();
|
| - canvas->ClipRect(gfx::Rect(0, 0, width(), NonClientTopBorderHeight()));
|
| -
|
| - bool paint_as_active = ShouldPaintAsActive();
|
| - int theme_image_id = 0;
|
| - if (header_painter_->ShouldUseMinimalHeaderStyle(HeaderPainter::THEMED_NO))
|
| - theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_MINIMAL;
|
| - else if (paint_as_active)
|
| - theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_ACTIVE;
|
| - else
|
| - theme_image_id = IDR_AURA_WINDOW_HEADER_BASE_INACTIVE;
|
| -
|
| - header_painter_->PaintHeader(
|
| - canvas,
|
| - paint_as_active ? HeaderPainter::ACTIVE : HeaderPainter::INACTIVE,
|
| - theme_image_id,
|
| - 0);
|
| - header_painter_->PaintTitleBar(canvas, GetTitleFont());
|
| - header_painter_->PaintHeaderContentSeparator(canvas);
|
| - canvas->Restore();
|
| -}
|
| -
|
| const char* CustomFrameViewAsh::GetClassName() const {
|
| return kViewClassName;
|
| }
|
| @@ -142,8 +361,7 @@ const char* CustomFrameViewAsh::GetClassName() const {
|
| gfx::Size CustomFrameViewAsh::GetMinimumSize() {
|
| gfx::Size min_client_view_size(frame_->client_view()->GetMinimumSize());
|
| return gfx::Size(
|
| - std::max(header_painter_->GetMinimumHeaderWidth(),
|
| - min_client_view_size.width()),
|
| + std::max(header_view_->GetMinimumWidth(), min_client_view_size.width()),
|
| NonClientTopBorderHeight() + min_client_view_size.height());
|
| }
|
|
|
| @@ -151,17 +369,24 @@ gfx::Size CustomFrameViewAsh::GetMaximumSize() {
|
| return frame_->client_view()->GetMaximumSize();
|
| }
|
|
|
| +void CustomFrameViewAsh::SchedulePaintInRect(const gfx::Rect& r) {
|
| + // The HeaderView is not a child of CustomFrameViewAsh. Redirect the paint to
|
| + // HeaderView instead.
|
| + header_view_->set_paint_as_active(ShouldPaintAsActive());
|
| + header_view_->SchedulePaint();
|
| +}
|
| +
|
| +bool CustomFrameViewAsh::HitTestRect(const gfx::Rect& rect) const {
|
| + // NonClientView hit tests the NonClientFrameView first instead of going in
|
| + // z-order. Return false so that events get to the OverlayView.
|
| + return false;
|
| +}
|
| +
|
| ////////////////////////////////////////////////////////////////////////////////
|
| // CustomFrameViewAsh, private:
|
|
|
| int CustomFrameViewAsh::NonClientTopBorderHeight() const {
|
| - if (frame_->IsFullscreen())
|
| - return 0;
|
| -
|
| - // Reserve enough space to see the buttons, including any offset from top and
|
| - // reserving space for the separator line.
|
| - return caption_button_container_->bounds().bottom() +
|
| - header_painter_->HeaderContentSeparatorSize();
|
| + return frame_->IsFullscreen() ? 0 : header_view_->GetPreferredHeight();
|
| }
|
|
|
| } // namespace ash
|
|
|