Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3226)

Unified Diff: chrome/browser/ui/views/immersive_mode_controller.cc

Issue 11411250: Immersive mode reveals the tabstrip/omnibox on top of web content (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: update comment Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/views/immersive_mode_controller.cc
diff --git a/chrome/browser/ui/views/immersive_mode_controller.cc b/chrome/browser/ui/views/immersive_mode_controller.cc
index 09773626db42533d3cf563fbb1cb4dbd04994f26..c92e9a654180882e05c10c430bf845dc836429d6 100644
--- a/chrome/browser/ui/views/immersive_mode_controller.cc
+++ b/chrome/browser/ui/views/immersive_mode_controller.cc
@@ -4,10 +4,16 @@
#include "chrome/browser/ui/views/immersive_mode_controller.h"
+#include "chrome/browser/ui/views/frame/browser_frame.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/contents_container.h"
#include "chrome/browser/ui/views/tabs/tab_strip.h"
+#include "chrome/browser/ui/views/toolbar_view.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/gfx/transform.h"
#include "ui/views/mouse_watcher_view_host.h"
+#include "ui/views/view.h"
+#include "ui/views/window/non_client_view.h"
#if defined(USE_AURA)
#include "ui/aura/window.h"
@@ -24,21 +30,125 @@ const int kHideDelayMs = 200;
} // namespace
+////////////////////////////////////////////////////////////////////////////////
+
+// View to hold the tab strip, toolbar, and sometimes the bookmark bar during
+// an immersive mode reveal. Paints on top of other layers in order to appear
+// over the web contents. Immersive mode uses this view to avoid changing the
+// BrowserView's view structure in the steady state.
+// TODO(jamescook): If immersive mode becomes non-experimental, use a permanent
+// top-of-window container view in BrowserView instead of RevealView to avoid
+// reparenting.
+// TODO(jamescook): Bookmark bar does not yet work.
+class RevealView : public views::View {
+ public:
+ explicit RevealView(BrowserView* browser_view);
+ virtual ~RevealView();
+
+ // Reparents the |browser_view_| tab strip, toolbar, and bookmark bar to
+ // this view.
+ void AcquireTopViews();
+
+ // Reparents tab strip, toolbar, and bookmark bar back to |browser_view_|.
+ void ReleaseTopViews();
+
+ // views::View overrides:
+ virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE;
+
+ private:
+ // None of these views are owned.
+ BrowserView* browser_view_;
+ TabStrip* tabstrip_;
+ ToolbarView* toolbar_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(RevealView);
+};
+
+RevealView::RevealView(BrowserView* browser_view)
+ : browser_view_(browser_view),
+ tabstrip_(NULL),
+ toolbar_view_(NULL) {
+ SetPaintToLayer(true);
+ SetFillsBoundsOpaquely(true);
+}
+
+RevealView::~RevealView() {}
+
+void RevealView::AcquireTopViews() {
+ // Reparenting causes hit tests that require a parent for |this|.
+ DCHECK(parent());
+
+ tabstrip_ = browser_view_->tabstrip();
+ toolbar_view_ = browser_view_->GetToolbarView();
+
+ // Ensure the indices are what we expect before we start moving the views.
+ DCHECK_EQ(browser_view_->GetIndexOf(tabstrip_), BrowserView::kTabstripIndex);
+ DCHECK_EQ(browser_view_->GetIndexOf(toolbar_view_),
+ BrowserView::kToolbarIndex);
+
+ AddChildView(tabstrip_);
+ AddChildView(toolbar_view_);
+
+ // Set our initial bounds, which triggers a Layout().
+ int width = parent()->width();
+ int height = toolbar_view_->bounds().bottom();
+ SetBounds(0, 0, width, height);
+}
+
+void RevealView::ReleaseTopViews() {
+ // Reparenting causes hit tests that require a parent for |this|.
+ DCHECK(parent());
+
+ browser_view_->AddChildViewAt(tabstrip_, BrowserView::kTabstripIndex);
+ browser_view_->AddChildViewAt(toolbar_view_, BrowserView::kToolbarIndex);
+
+ // Ensure the newly restored views get painted.
+ tabstrip_->SchedulePaint();
+ toolbar_view_->SchedulePaint();
+
+ tabstrip_ = NULL;
+ toolbar_view_ = NULL;
+}
+
+void RevealView::PaintChildren(gfx::Canvas* canvas) {
+ // Top-views depend on parts of the frame (themes, window buttons) being
+ // painted underneath them. Clip rect has already been set to the bounds
+ // of this view, so just paint the frame.
+ views::View* frame = browser_view_->frame()->GetFrameView();
+ frame->Paint(canvas);
+
+ views::View::PaintChildren(canvas);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
ImmersiveModeController::ImmersiveModeController(BrowserView* browser_view)
: browser_view_(browser_view),
enabled_(false),
- hide_top_views_(false) {
+ revealed_(false) {
}
-ImmersiveModeController::~ImmersiveModeController() {}
+ImmersiveModeController::~ImmersiveModeController() {
+ // Ensure views are reparented if we are deleted mid-reveal.
+ if (reveal_view_.get()) {
+ reveal_view_->ReleaseTopViews();
+ ResetRevealView();
+ }
+}
void ImmersiveModeController::SetEnabled(bool enabled) {
if (enabled_ == enabled)
return;
enabled_ = enabled;
- hide_top_views_ = enabled;
- browser_view_->tabstrip()->SetImmersiveStyle(enabled_);
- browser_view_->Layout();
+
+ if (enabled_) {
+ browser_view_->tabstrip()->SetImmersiveStyle(true);
+ browser_view_->Layout();
+ } else {
+ // Don't Layout() browser_view_ because EndReveal() does so.
+ EndReveal(false);
+ top_timer_.Stop();
+ }
#if defined(USE_AURA)
// TODO(jamescook): If we want to port this feature to non-Aura views we'll
@@ -51,38 +161,6 @@ void ImmersiveModeController::SetEnabled(bool enabled) {
else
browser_view_->GetNativeWindow()->RemovePreTargetHandler(this);
#endif // defined(USE_AURA)
-
- if (!enabled_) {
- // Stop watching the mouse on disable.
- mouse_watcher_.reset();
- top_timer_.Stop();
- }
-}
-
-void ImmersiveModeController::RevealTopViews() {
- if (!hide_top_views_)
- return;
- hide_top_views_ = false;
-
- // Recompute the bounds of the views when painted normally.
- browser_view_->tabstrip()->SetImmersiveStyle(false);
- browser_view_->Layout();
-
- // Compute the top of the content area in order to find the bottom of all
- // the top-of-window views like toolbar, bookmarks, etc.
- gfx::Point content_origin(0, 0);
- views::View::ConvertPointToTarget(
- browser_view_->contents(), browser_view_, &content_origin);
-
- // Stop the immersive reveal when the mouse leaves the top-of-window area.
- gfx::Insets insets(0, 0, content_origin.y() - browser_view_->height(), 0);
- views::MouseWatcherViewHost* host =
- new views::MouseWatcherViewHost(browser_view_, insets);
- // MouseWatcher takes ownership of |host|.
- mouse_watcher_.reset(new views::MouseWatcher(host, this));
- mouse_watcher_->set_notify_on_exit_time(
- base::TimeDelta::FromMilliseconds(kHideDelayMs));
- mouse_watcher_->Start();
}
// ui::EventHandler overrides:
@@ -91,12 +169,14 @@ ui::EventResult ImmersiveModeController::OnKeyEvent(ui::KeyEvent* event) {
}
ui::EventResult ImmersiveModeController::OnMouseEvent(ui::MouseEvent* event) {
+ if (event->type() != ui::ET_MOUSE_MOVED)
+ return ui::ER_UNHANDLED;
if (event->location().y() == 0) {
// Use a timer to detect if the cursor stays at the top past a delay.
if (!top_timer_.IsRunning()) {
top_timer_.Start(FROM_HERE,
base::TimeDelta::FromMilliseconds(kRevealDelayMs),
- this, &ImmersiveModeController::RevealTopViews);
+ this, &ImmersiveModeController::StartReveal);
}
} else {
// Cursor left the top edge.
@@ -121,10 +201,102 @@ ui::EventResult ImmersiveModeController::OnGestureEvent(
// views::MouseWatcherListener overrides:
void ImmersiveModeController::MouseMovedOutOfHost() {
- // Stop watching the mouse.
+ EndReveal(true);
+}
+
+// ui::ImplicitAnimationObserver overrides:
+void ImmersiveModeController::OnImplicitAnimationsCompleted() {
+ // Fired when the slide-out animation completes.
+ ResetRevealView();
+}
+
+// Testing interface:
+void ImmersiveModeController::StartRevealForTest() {
+ StartReveal();
+}
+
+void ImmersiveModeController::EndRevealForTest() {
+ EndReveal(false);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// private:
+
+void ImmersiveModeController::StartReveal() {
+ if (revealed_)
+ return;
+ revealed_ = true;
+
+ // Recompute the bounds of the views when painted normally.
+ browser_view_->tabstrip()->SetImmersiveStyle(false);
+ browser_view_->Layout();
+
+ // Place tabstrip, toolbar, and bookmarks bar in a new view at the end of
+ // the BrowserView hierarchy so it paints over the web contents.
+ reveal_view_.reset(new RevealView(browser_view_));
+ browser_view_->AddChildView(reveal_view_.get());
+ reveal_view_->AcquireTopViews();
+
+ // Slide in the reveal view.
+ AnimateShowRevealView();
+
+ // Stop the immersive reveal when the mouse leaves the top-of-window area.
+ StartMouseWatcher();
+}
+
+void ImmersiveModeController::AnimateShowRevealView() {
+ DCHECK(reveal_view_.get());
+ gfx::Transform transform;
+ transform.Translate(0, -reveal_view_->height());
+ reveal_view_->SetTransform(transform);
+
+ ui::ScopedLayerAnimationSettings settings(
+ reveal_view_->layer()->GetAnimator());
+ settings.SetTweenType(ui::Tween::EASE_OUT);
+ reveal_view_->SetTransform(gfx::Transform());
+}
+
+void ImmersiveModeController::StartMouseWatcher() {
+ DCHECK(reveal_view_.get());
+ views::MouseWatcherViewHost* host =
+ new views::MouseWatcherViewHost(reveal_view_.get(), gfx::Insets());
+ // MouseWatcher takes ownership of |host|.
+ mouse_watcher_.reset(new views::MouseWatcher(host, this));
+ mouse_watcher_->set_notify_on_exit_time(
+ base::TimeDelta::FromMilliseconds(kHideDelayMs));
+ mouse_watcher_->Start();
+}
+
+void ImmersiveModeController::EndReveal(bool animate) {
+ revealed_ = false;
mouse_watcher_.reset();
- // Stop showing the top views.
- hide_top_views_ = true;
- browser_view_->tabstrip()->SetImmersiveStyle(true);
+
+ if (reveal_view_.get()) {
+ reveal_view_->ReleaseTopViews();
+ if (animate) {
+ // Animation resets the reveal view when complete.
+ AnimateHideRevealView();
+ } else {
+ ResetRevealView();
+ }
+ }
+
+ browser_view_->tabstrip()->SetImmersiveStyle(enabled_);
browser_view_->Layout();
}
+
+void ImmersiveModeController::AnimateHideRevealView() {
+ ui::Layer* layer = reveal_view_->layer();
+ ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
+ settings.SetTweenType(ui::Tween::EASE_OUT);
+ settings.AddObserver(this); // Resets |reveal_view_| on completion.
+ gfx::Transform transform;
+ transform.Translate(0, -layer->bounds().height());
+ layer->SetTransform(transform);
+}
+
+void ImmersiveModeController::ResetRevealView() {
+ browser_view_->RemoveChildView(reveal_view_.get());
+ reveal_view_.reset();
+}
+
« no previous file with comments | « chrome/browser/ui/views/immersive_mode_controller.h ('k') | chrome/browser/ui/views/infobars/infobar_container_view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698