summaryrefslogtreecommitdiffstats
path: root/ash
diff options
context:
space:
mode:
authorpkotwicz@chromium.org <pkotwicz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-20 17:28:53 +0000
committerpkotwicz@chromium.org <pkotwicz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-20 17:28:53 +0000
commit63458430dba41ed11c5fde816d8fd852cb1f75f6 (patch)
treef99327be2a62992edbf08eb6af132cadf3404e1e /ash
parent74de2d9cff8bc3803b7b47794b0f02ac364fa0d1 (diff)
downloadchromium_src-63458430dba41ed11c5fde816d8fd852cb1f75f6.zip
chromium_src-63458430dba41ed11c5fde816d8fd852cb1f75f6.tar.gz
chromium_src-63458430dba41ed11c5fde816d8fd852cb1f75f6.tar.bz2
Add ash-enable-immersive-all-windows command line flag to enable immersive fullscreen for non-frameless v2 apps. (The goal is to add support for immersive fullscreen for v1 apps and miscellaneous windows such as the task manager shortly) When the flag is set, <F4> will put the app into immersive fullscreen.
In immersive fullscreen, the window header (the title bar and window controls) slide out as an overlay over the web contents when the mouse is hovered at the top of the display. chrome.app.window.current().isFullscreen() returns false for immersive fullscreen windows Entering fullscreen via the app.window api or webkitRequestFullScreen() quits immersive fullscreen. BUG=307622 R=oshima TBR=benwells (Because this is relanding https://codereview.chromium.org/59043013/), sky (For adding VIEWS_EXPORT to ui/views/widget/widget_observer.h) TEST=Manual, see steps below: 1) Install: https://chrome.google.com/webstore/detail/window-state-sample/hcbhfbnaaancmblfhdknlnojpafjohbi 2) Enable "Enable immersive fullscreen for non browser windows" in chrome://flags 3) Hit <F4> 4) Ensure that the "isFullscreen" checkbox in the app is checked 5) Ensure that the shelf light bar is visible (The shelf is not completely hidden) 6) Hover the mouse at the top of the screen. Ensure that the window header (maximize and close button slide down and overlay the web contents) 7) Move the mouse off of the header. Ensure that the window header slides off screen 8) Press the Fullscreen button in the app (It may be useful to set the "chrome.app.window actions delay" to zero seconds) 9) Ensure that the shelf is completely hidden. 10) Hover the mouse at the top of the screen. Ensure that the header slides out again. 11) Press <F4> 12) Ensure that the "isFullscreen" checkbox is unchecked 13) Ensure that the window header is visible and does not slide out Review URL: https://codereview.chromium.org/76483002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@236258 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r--ash/ash.gyp1
-rw-r--r--ash/ash_switches.cc4
-rw-r--r--ash/ash_switches.h1
-rw-r--r--ash/wm/caption_buttons/frame_caption_button_container_view.cc6
-rw-r--r--ash/wm/caption_buttons/frame_caption_button_container_view.h5
-rw-r--r--ash/wm/caption_buttons/frame_maximize_button.cc16
-rw-r--r--ash/wm/caption_buttons/frame_maximize_button.h10
-rw-r--r--ash/wm/caption_buttons/frame_maximize_button_observer.h26
-rw-r--r--ash/wm/caption_buttons/maximize_bubble_controller.cc4
-rw-r--r--ash/wm/custom_frame_view_ash.cc339
-rw-r--r--ash/wm/custom_frame_view_ash.h32
-rw-r--r--ash/wm/immersive_fullscreen_controller.h2
-rw-r--r--ash/wm/immersive_fullscreen_controller_unittest.cc2
-rw-r--r--ash/wm/window_state_delegate.h9
14 files changed, 385 insertions, 72 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp
index 3331bef..c9900cb 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -428,6 +428,7 @@
'wm/caption_buttons/frame_caption_button_container_view.h',
'wm/caption_buttons/frame_maximize_button.cc',
'wm/caption_buttons/frame_maximize_button.h',
+ 'wm/caption_buttons/frame_maximize_button_observer.h',
'wm/caption_buttons/maximize_bubble_controller.cc',
'wm/caption_buttons/maximize_bubble_controller.h',
'wm/caption_buttons/maximize_bubble_frame_state.h',
diff --git a/ash/ash_switches.cc b/ash/ash_switches.cc
index 039a0a0..88f569d 100644
--- a/ash/ash_switches.cc
+++ b/ash/ash_switches.cc
@@ -99,6 +99,10 @@ const char kAshDisableDockedWindows[] = "ash-disable-docked-windows";
// Disable dragging items off the shelf to unpin them.
const char kAshDisableDragOffShelf[] = "ash-disable-drag-off-shelf";
+// Enables putting all windows into immersive fullscreen via <F4>.
+const char kAshEnableImmersiveFullscreenForAllWindows[] =
+ "ash-enable-immersive-all-windows";
+
#if defined(OS_CHROMEOS)
// Enables the "full multi profile mode" - as it was in M-31.
const char kAshEnableFullMultiProfileMode[] =
diff --git a/ash/ash_switches.h b/ash/ash_switches.h
index ed9e413..3a9cff8 100644
--- a/ash/ash_switches.h
+++ b/ash/ash_switches.h
@@ -43,6 +43,7 @@ ASH_EXPORT extern const char kAshEnableAudioDeviceMenu[];
ASH_EXPORT extern const char kAshEnableAdvancedGestures[];
ASH_EXPORT extern const char kAshEnableAlternateFrameCaptionButtonStyle[];
ASH_EXPORT extern const char kAshEnableBrightnessControl[];
+ASH_EXPORT extern const char kAshEnableImmersiveFullscreenForAllWindows[];
#if defined(OS_CHROMEOS)
ASH_EXPORT extern const char kAshEnableFullMultiProfileMode[];
#endif
diff --git a/ash/wm/caption_buttons/frame_caption_button_container_view.cc b/ash/wm/caption_buttons/frame_caption_button_container_view.cc
index d0b0b96..41f9e08 100644
--- a/ash/wm/caption_buttons/frame_caption_button_container_view.cc
+++ b/ash/wm/caption_buttons/frame_caption_button_container_view.cc
@@ -114,6 +114,12 @@ FrameCaptionButtonContainerView::FrameCaptionButtonContainerView(
FrameCaptionButtonContainerView::~FrameCaptionButtonContainerView() {
}
+FrameMaximizeButton*
+FrameCaptionButtonContainerView::GetOldStyleSizeButton() {
+ return switches::UseAlternateFrameCaptionButtonStyle() ?
+ NULL : static_cast<FrameMaximizeButton*>(size_button_);
+}
+
void FrameCaptionButtonContainerView::ResetWindowControls() {
minimize_button_->SetState(views::CustomButton::STATE_NORMAL);
size_button_->SetState(views::CustomButton::STATE_NORMAL);
diff --git a/ash/wm/caption_buttons/frame_caption_button_container_view.h b/ash/wm/caption_buttons/frame_caption_button_container_view.h
index a88ea94..6dd9521 100644
--- a/ash/wm/caption_buttons/frame_caption_button_container_view.h
+++ b/ash/wm/caption_buttons/frame_caption_button_container_view.h
@@ -16,6 +16,7 @@ class Widget;
}
namespace ash {
+class FrameMaximizeButton;
// Container view for the frame caption buttons. It performs the appropriate
// action when a caption button is clicked.
@@ -74,6 +75,10 @@ class ASH_EXPORT FrameCaptionButtonContainerView
DISALLOW_COPY_AND_ASSIGN(TestApi);
};
+ // Returns the size button if using the old caption button style, returns NULL
+ // otherwise.
+ FrameMaximizeButton* GetOldStyleSizeButton();
+
// Tell the window controls to reset themselves to the normal state.
void ResetWindowControls();
diff --git a/ash/wm/caption_buttons/frame_maximize_button.cc b/ash/wm/caption_buttons/frame_maximize_button.cc
index 81995c2..14526a0 100644
--- a/ash/wm/caption_buttons/frame_maximize_button.cc
+++ b/ash/wm/caption_buttons/frame_maximize_button.cc
@@ -10,6 +10,7 @@
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/touch/touch_uma.h"
+#include "ash/wm/caption_buttons/frame_maximize_button_observer.h"
#include "ash/wm/caption_buttons/maximize_bubble_controller.h"
#include "ash/wm/window_animations.h"
#include "ash/wm/window_state.h"
@@ -101,6 +102,15 @@ FrameMaximizeButton::~FrameMaximizeButton() {
OnWindowDestroying(frame_->GetNativeWindow());
}
+void FrameMaximizeButton::AddObserver(FrameMaximizeButtonObserver* observer) {
+ observer_list_.AddObserver(observer);
+}
+
+void FrameMaximizeButton::RemoveObserver(
+ FrameMaximizeButtonObserver* observer) {
+ observer_list_.RemoveObserver(observer);
+}
+
void FrameMaximizeButton::SnapButtonHovered(SnapType type) {
// Make sure to only show hover operations when no button is pressed and
// a similar snap operation in progress does not get re-applied.
@@ -157,6 +167,12 @@ void FrameMaximizeButton::ExecuteSnapAndCloseMenu(SnapType snap_type) {
Snap(snap_sizer.get());
}
+void FrameMaximizeButton::OnMaximizeBubbleShown(views::Widget* bubble) {
+ FOR_EACH_OBSERVER(FrameMaximizeButtonObserver,
+ observer_list_,
+ OnMaximizeBubbleShown(bubble));
+}
+
void FrameMaximizeButton::DestroyMaximizeMenu() {
Cancel(false);
}
diff --git a/ash/wm/caption_buttons/frame_maximize_button.h b/ash/wm/caption_buttons/frame_maximize_button.h
index 1539833..c60f7a5 100644
--- a/ash/wm/caption_buttons/frame_maximize_button.h
+++ b/ash/wm/caption_buttons/frame_maximize_button.h
@@ -9,6 +9,7 @@
#include "ash/wm/caption_buttons/maximize_bubble_frame_state.h"
#include "ash/wm/workspace/snap_types.h"
#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
#include "base/timer/timer.h"
#include "ui/aura/window_observer.h"
#include "ui/views/controls/button/image_button.h"
@@ -19,6 +20,7 @@ class Widget;
}
namespace ash {
+class FrameMaximizeButtonObserver;
namespace internal {
class PhantomWindowController;
@@ -36,6 +38,9 @@ class ASH_EXPORT FrameMaximizeButton : public views::ImageButton,
views::Widget* frame);
virtual ~FrameMaximizeButton();
+ void AddObserver(FrameMaximizeButtonObserver* observer);
+ void RemoveObserver(FrameMaximizeButtonObserver* observer);
+
// Updates |snap_type_| based on a a given snap type. This is used by
// external hover events from the button menu.
void SnapButtonHovered(SnapType type);
@@ -44,6 +49,9 @@ class ASH_EXPORT FrameMaximizeButton : public views::ImageButton,
// which will at the same time close the window.
void ExecuteSnapAndCloseMenu(SnapType type);
+ // Called by the MaximizeBubbleController when the maximize bubble is shown.
+ void OnMaximizeBubbleShown(views::Widget* bubble);
+
// Remove the maximize menu from the screen (and destroy it).
void DestroyMaximizeMenu();
@@ -175,6 +183,8 @@ class ASH_EXPORT FrameMaximizeButton : public views::ImageButton,
// The delay of the bubble appearance.
int bubble_appearance_delay_ms_;
+ ObserverList<FrameMaximizeButtonObserver> observer_list_;
+
DISALLOW_COPY_AND_ASSIGN(FrameMaximizeButton);
};
diff --git a/ash/wm/caption_buttons/frame_maximize_button_observer.h b/ash/wm/caption_buttons/frame_maximize_button_observer.h
new file mode 100644
index 0000000..1962f60
--- /dev/null
+++ b/ash/wm/caption_buttons/frame_maximize_button_observer.h
@@ -0,0 +1,26 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_WM_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_OBSERVER_H_
+#define ASH_WM_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_OBSERVER_H_
+
+#include "ash/ash_export.h"
+
+namespace views {
+class Widget;
+}
+
+namespace ash {
+
+class ASH_EXPORT FrameMaximizeButtonObserver {
+ public:
+ virtual ~FrameMaximizeButtonObserver() {}
+
+ // Called when the maximize button's help bubble is shown.
+ virtual void OnMaximizeBubbleShown(views::Widget* bubble) = 0;
+};
+
+} // namespace ash
+
+#endif // ASH_WM_CAPTION_BUTTONS_FRAME_MAXIMIZE_BUTTON_OBSERVER_H_
diff --git a/ash/wm/caption_buttons/maximize_bubble_controller.cc b/ash/wm/caption_buttons/maximize_bubble_controller.cc
index 413cc0e..6148e17 100644
--- a/ash/wm/caption_buttons/maximize_bubble_controller.cc
+++ b/ash/wm/caption_buttons/maximize_bubble_controller.cc
@@ -818,8 +818,10 @@ void MaximizeBubbleController::RequestDestructionThroughOwner() {
}
void MaximizeBubbleController::CreateBubble() {
- if (!bubble_)
+ if (!bubble_) {
bubble_ = new Bubble(this, appearance_delay_ms_, snap_type_for_creation_);
+ frame_maximize_button_->OnMaximizeBubbleShown(bubble_->GetWidget());
+ }
timer_->Stop();
}
diff --git a/ash/wm/custom_frame_view_ash.cc b/ash/wm/custom_frame_view_ash.cc
index f03026c..571f1c7 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,287 @@ 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() {
+ FrameMaximizeButton* frame_maximize_button =
+ caption_button_container_->GetOldStyleSizeButton();
+ if (frame_maximize_button)
+ frame_maximize_button->RemoveObserver(this);
+}
+
+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 +329,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 +338,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 +358,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 +365,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 +373,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
diff --git a/ash/wm/custom_frame_view_ash.h b/ash/wm/custom_frame_view_ash.h
index 9593abb..7c58a1e 100644
--- a/ash/wm/custom_frame_view_ash.h
+++ b/ash/wm/custom_frame_view_ash.h
@@ -12,6 +12,7 @@
namespace ash {
class FrameBorderHitTestController;
class HeaderPainter;
+class ImmersiveFullscreenController;
}
namespace gfx {
class Font;
@@ -22,10 +23,12 @@ class Widget;
namespace ash {
-class FrameCaptionButtonContainerView;
-
-// A NonClientFrameView used for dialogs and other non-browser windows.
-// See also views::CustomFrameView and BrowserNonClientFrameViewAsh.
+// A NonClientFrameView used for packaged apps, dialogs and other non-browser
+// windows. It supports immersive fullscreen. When in immersive fullscreen, the
+// client view takes up the entire widget and the window header is an overlay.
+// The window header overlay slides onscreen when the user hovers the mouse at
+// the top of the screen. See also views::CustomFrameView and
+// BrowserNonClientFrameViewAsh.
class ASH_EXPORT CustomFrameViewAsh : public views::NonClientFrameView {
public:
// Internal class name.
@@ -34,6 +37,13 @@ class ASH_EXPORT CustomFrameViewAsh : public views::NonClientFrameView {
explicit CustomFrameViewAsh(views::Widget* frame);
virtual ~CustomFrameViewAsh();
+ // Inits |immersive_fullscreen_controller| so that the controller reveals
+ // and hides |header_view_| in immersive fullscreen.
+ // CustomFrameViewAsh does not take ownership of
+ // |immersive_fullscreen_controller|.
+ void InitImmersiveFullscreenControllerForView(
+ ImmersiveFullscreenController* immersive_fullscreen_controller);
+
// views::NonClientFrameView overrides:
virtual gfx::Rect GetBoundsForClientView() const OVERRIDE;
virtual gfx::Rect GetWindowBoundsForClientBounds(
@@ -47,24 +57,24 @@ class ASH_EXPORT CustomFrameViewAsh : public views::NonClientFrameView {
// views::View overrides:
virtual gfx::Size GetPreferredSize() OVERRIDE;
- virtual void Layout() OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
- virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
virtual gfx::Size GetMinimumSize() OVERRIDE;
virtual gfx::Size GetMaximumSize() OVERRIDE;
+ virtual void SchedulePaintInRect(const gfx::Rect& r) OVERRIDE;
+ virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE;
private:
+ class OverlayView;
+
// Height from top of window to top of client area.
int NonClientTopBorderHeight() const;
// Not owned.
views::Widget* frame_;
- // View which contains the window controls.
- FrameCaptionButtonContainerView* caption_button_container_;
-
- // Helper class for painting the header.
- scoped_ptr<HeaderPainter> header_painter_;
+ // View which contains the title and window controls.
+ class HeaderView;
+ HeaderView* header_view_;
// Updates the hittest bounds overrides based on the window show type.
scoped_ptr<FrameBorderHitTestController> frame_border_hit_test_controller_;
diff --git a/ash/wm/immersive_fullscreen_controller.h b/ash/wm/immersive_fullscreen_controller.h
index 420c486..9d0f757 100644
--- a/ash/wm/immersive_fullscreen_controller.h
+++ b/ash/wm/immersive_fullscreen_controller.h
@@ -66,7 +66,7 @@ class ASH_EXPORT ImmersiveFullscreenController
// The returned list is used for hittesting when the top-of-window views
// are revealed. GetVisibleBoundsInScreen() must return a valid value when
// not in immersive fullscreen for the sake of SetupForTest().
- virtual std::vector<gfx::Rect> GetVisibleBoundsInScreen() = 0;
+ virtual std::vector<gfx::Rect> GetVisibleBoundsInScreen() const = 0;
protected:
virtual ~Delegate() {}
diff --git a/ash/wm/immersive_fullscreen_controller_unittest.cc b/ash/wm/immersive_fullscreen_controller_unittest.cc
index c25f9ee..9d0b21b 100644
--- a/ash/wm/immersive_fullscreen_controller_unittest.cc
+++ b/ash/wm/immersive_fullscreen_controller_unittest.cc
@@ -54,7 +54,7 @@ class MockImmersiveFullscreenControllerDelegate
virtual void SetVisibleFraction(double visible_fraction) OVERRIDE {
visible_fraction_ = visible_fraction;
}
- virtual std::vector<gfx::Rect> GetVisibleBoundsInScreen() OVERRIDE {
+ virtual std::vector<gfx::Rect> GetVisibleBoundsInScreen() const OVERRIDE {
std::vector<gfx::Rect> bounds_in_screen;
bounds_in_screen.push_back(top_container_view_->GetBoundsInScreen());
return bounds_in_screen;
diff --git a/ash/wm/window_state_delegate.h b/ash/wm/window_state_delegate.h
index 7b9a8ba..53badcf 100644
--- a/ash/wm/window_state_delegate.h
+++ b/ash/wm/window_state_delegate.h
@@ -17,9 +17,12 @@ class ASH_EXPORT WindowStateDelegate {
WindowStateDelegate();
virtual ~WindowStateDelegate();
- // Invoked when the user uses Shift+F4/F4 to toggle the window
- // fullscreen state. The caller (ash::wm::WindowState) falls backs
- // to the default implementation if this returns false.
+ // Invoked when the user uses Shift+F4/F4 to toggle the window fullscreen
+ // state. If the window is not fullscreen and the window supports immersive
+ // fullscreen ToggleFullscreen() should put the window into immersive
+ // fullscreen instead of the default fullscreen type. The caller
+ // (ash::wm::WindowState) falls backs to the default implementation if this
+ // returns false.
virtual bool ToggleFullscreen(WindowState* window_state);
private: