| Index: chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
|
| diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
|
| index ea8475bf19ac70d4550bab24556f267ced20a16a..112dfe90f7ae96e36577cd50808cf57ccc343e8d 100644
|
| --- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
|
| +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
|
| @@ -4,383 +4,122 @@
|
|
|
| #include "chrome/browser/ui/views/frame/immersive_mode_controller_ash.h"
|
|
|
| -#include <set>
|
| -#include <vector>
|
| -
|
| #include "ash/shell.h"
|
| #include "ash/wm/window_state.h"
|
| #include "chrome/browser/chrome_notification_types.h"
|
| #include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
|
| -#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
|
| +#include "chrome/browser/ui/views/frame/browser_view.h"
|
| #include "chrome/browser/ui/views/frame/top_container_view.h"
|
| +#include "chrome/browser/ui/views/tabs/tab_strip.h"
|
| #include "content/public/browser/notification_service.h"
|
| #include "content/public/browser/web_contents.h"
|
| #include "content/public/browser/web_contents_view.h"
|
| -#include "ui/aura/client/activation_client.h"
|
| #include "ui/aura/client/aura_constants.h"
|
| -#include "ui/aura/client/capture_client.h"
|
| -#include "ui/aura/client/cursor_client.h"
|
| -#include "ui/aura/client/screen_position_client.h"
|
| -#include "ui/aura/env.h"
|
| -#include "ui/aura/root_window.h"
|
| #include "ui/aura/window.h"
|
| -#include "ui/gfx/animation/slide_animation.h"
|
| -#include "ui/views/bubble/bubble_delegate.h"
|
| #include "ui/views/view.h"
|
| #include "ui/views/widget/widget.h"
|
| #include "ui/views/window/non_client_view.h"
|
|
|
| -using views::View;
|
| -
|
| namespace {
|
|
|
| -// The slide open/closed animation looks better if it starts and ends just a
|
| -// few pixels before the view goes completely off the screen, which reduces
|
| -// the visual "pop" as the 2-pixel tall immersive-style tabs become visible.
|
| +// Revealing the TopContainerView looks better if the animation starts and ends
|
| +// just a few pixels before the view goes offscreen, which reduces the visual
|
| +// "pop" as the 3-pixel tall "light bar" style tab strip becomes visible.
|
| const int kAnimationOffsetY = 3;
|
|
|
| -// Duration for the reveal show/hide slide animation. The slower duration is
|
| -// used for the initial slide out to give the user more change to see what
|
| -// happened.
|
| -const int kRevealSlowAnimationDurationMs = 400;
|
| -const int kRevealFastAnimationDurationMs = 200;
|
| -
|
| -// The delay in milliseconds between the mouse stopping at the top edge of the
|
| -// screen and the top-of-window views revealing.
|
| -const int kMouseRevealDelayMs = 200;
|
| -
|
| -// The maximum amount of pixels that the cursor can move for the cursor to be
|
| -// considered "stopped". This allows the user to reveal the top-of-window views
|
| -// without holding the cursor completely still.
|
| -const int kMouseRevealXThresholdPixels = 3;
|
| -
|
| -// How many pixels a gesture can start away from |top_container_| when in
|
| -// closed state and still be considered near it. This is needed to overcome
|
| -// issues with poor location values near the edge of the display.
|
| -const int kNearTopContainerDistance = 8;
|
| -
|
| -// Used to multiply x value of an update in check to determine if gesture is
|
| -// vertical. This is used to make sure that gesture is close to vertical instead
|
| -// of just more vertical then horizontal.
|
| -const int kSwipeVerticalThresholdMultiplier = 3;
|
| -
|
| -// The height in pixels of the region above the top edge of the display which
|
| -// hosts the immersive fullscreen window in which mouse events are ignored
|
| -// (cannot reveal or unreveal the top-of-window views).
|
| -// See ShouldIgnoreMouseEventAtLocation() for more details.
|
| -const int kHeightOfDeadRegionAboveTopContainer = 10;
|
| -
|
| -// The height in pixels of the region below the top edge of the display in which
|
| -// the mouse can trigger revealing the top-of-window views. The height must be
|
| -// greater than 1px because the top pixel is used to trigger moving the cursor
|
| -// between displays if the user has a vertical display layout (primary display
|
| -// above/below secondary display).
|
| -const int kMouseRevealBoundsHeight = 3;
|
| -
|
| -// Returns the BubbleDelegateView corresponding to |maybe_bubble| if
|
| -// |maybe_bubble| is a bubble.
|
| -views::BubbleDelegateView* AsBubbleDelegate(aura::Window* maybe_bubble) {
|
| - if (!maybe_bubble)
|
| - return NULL;
|
| - views::Widget* widget = views::Widget::GetWidgetForNativeView(maybe_bubble);
|
| - if (!widget)
|
| - return NULL;
|
| - return widget->widget_delegate()->AsBubbleDelegate();
|
| -}
|
| -
|
| -// Returns true if |maybe_transient| is a transient child of |toplevel|.
|
| -bool IsWindowTransientChildOf(aura::Window* maybe_transient,
|
| - aura::Window* toplevel) {
|
| - if (!maybe_transient || !toplevel)
|
| - return false;
|
| -
|
| - for (aura::Window* window = maybe_transient; window;
|
| - window = window->transient_parent()) {
|
| - if (window == toplevel)
|
| - return true;
|
| +// The height of the region in pixels at the top edge of the screen in which to
|
| +// steal touch events targetted at the web contents while in immersive
|
| +// fullscreen. This region is used to allow us to get edge gestures even if the
|
| +// web contents consumes all touch events.
|
| +const int kStealTouchEventsFromWebContentsRegionHeightPx = 8;
|
| +
|
| +// Converts from ImmersiveModeController::AnimateReveal to
|
| +// ash::ImmersiveFullscreenController::AnimateReveal.
|
| +ash::ImmersiveFullscreenController::AnimateReveal
|
| +ToImmersiveFullscreenControllerAnimateReveal(
|
| + ImmersiveModeController::AnimateReveal animate_reveal) {
|
| + switch (animate_reveal) {
|
| + case ImmersiveModeController::ANIMATE_REVEAL_YES:
|
| + return ash::ImmersiveFullscreenController::ANIMATE_REVEAL_YES;
|
| + case ImmersiveModeController::ANIMATE_REVEAL_NO:
|
| + return ash::ImmersiveFullscreenController::ANIMATE_REVEAL_NO;
|
| }
|
| - return false;
|
| -}
|
| -
|
| -// Returns the location of |event| in screen coordinates.
|
| -gfx::Point GetEventLocationInScreen(const ui::LocatedEvent& event) {
|
| - gfx::Point location_in_screen = event.location();
|
| - aura::Window* target = static_cast<aura::Window*>(event.target());
|
| - aura::client::ScreenPositionClient* screen_position_client =
|
| - aura::client::GetScreenPositionClient(target->GetRootWindow());
|
| - screen_position_client->ConvertPointToScreen(target, &location_in_screen);
|
| - return location_in_screen;
|
| + NOTREACHED();
|
| + return ash::ImmersiveFullscreenController::ANIMATE_REVEAL_NO;
|
| }
|
|
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -class RevealedLockAsh : public ImmersiveRevealedLock {
|
| - public:
|
| - RevealedLockAsh(const base::WeakPtr<ImmersiveModeControllerAsh>& controller,
|
| - ImmersiveModeController::AnimateReveal animate_reveal)
|
| - : controller_(controller) {
|
| - DCHECK(controller_);
|
| - controller_->LockRevealedState(animate_reveal);
|
| - }
|
| -
|
| - virtual ~RevealedLockAsh() {
|
| - if (controller_)
|
| - controller_->UnlockRevealedState();
|
| - }
|
| -
|
| - private:
|
| - base::WeakPtr<ImmersiveModeControllerAsh> controller_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(RevealedLockAsh);
|
| -};
|
| -
|
| } // namespace
|
|
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -// Class which keeps the top-of-window views revealed as long as one of the
|
| -// bubbles it is observing is visible. The logic to keep the top-of-window
|
| -// views revealed based on the visibility of bubbles anchored to
|
| -// children of |ImmersiveModeController::top_container_| is separate from
|
| -// the logic related to |ImmersiveModeControllerAsh::focus_revealed_lock_|
|
| -// so that bubbles which are not activatable and bubbles which do not close
|
| -// upon deactivation also keep the top-of-window views revealed for the
|
| -// duration of their visibility.
|
| -class ImmersiveModeControllerAsh::BubbleManager : public aura::WindowObserver {
|
| - public:
|
| - explicit BubbleManager(ImmersiveModeControllerAsh* controller);
|
| - virtual ~BubbleManager();
|
| -
|
| - // Start / stop observing changes to |bubble|'s visibility.
|
| - void StartObserving(aura::Window* bubble);
|
| - void StopObserving(aura::Window* bubble);
|
| -
|
| - private:
|
| - // Updates |revealed_lock_| based on whether any of |bubbles_| is visible.
|
| - void UpdateRevealedLock();
|
| -
|
| - // aura::WindowObserver overrides:
|
| - virtual void OnWindowVisibilityChanged(aura::Window* window,
|
| - bool visible) OVERRIDE;
|
| - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
|
| -
|
| - ImmersiveModeControllerAsh* controller_;
|
| -
|
| - std::set<aura::Window*> bubbles_;
|
| -
|
| - // Lock which keeps the top-of-window views revealed based on whether any of
|
| - // |bubbles_| is visible.
|
| - scoped_ptr<ImmersiveRevealedLock> revealed_lock_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(BubbleManager);
|
| -};
|
| -
|
| -ImmersiveModeControllerAsh::BubbleManager::BubbleManager(
|
| - ImmersiveModeControllerAsh* controller)
|
| - : controller_(controller) {
|
| -}
|
| -
|
| -ImmersiveModeControllerAsh::BubbleManager::~BubbleManager() {
|
| - for (std::set<aura::Window*>::const_iterator it = bubbles_.begin();
|
| - it != bubbles_.end(); ++it) {
|
| - (*it)->RemoveObserver(this);
|
| - }
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::BubbleManager::StartObserving(
|
| - aura::Window* bubble) {
|
| - if (bubbles_.insert(bubble).second) {
|
| - bubble->AddObserver(this);
|
| - UpdateRevealedLock();
|
| - }
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::BubbleManager::StopObserving(
|
| - aura::Window* bubble) {
|
| - if (bubbles_.erase(bubble)) {
|
| - bubble->RemoveObserver(this);
|
| - UpdateRevealedLock();
|
| - }
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::BubbleManager::UpdateRevealedLock() {
|
| - bool has_visible_bubble = false;
|
| - for (std::set<aura::Window*>::const_iterator it = bubbles_.begin();
|
| - it != bubbles_.end(); ++it) {
|
| - if ((*it)->IsVisible()) {
|
| - has_visible_bubble = true;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - bool was_revealed = controller_->IsRevealed();
|
| - if (has_visible_bubble) {
|
| - if (!revealed_lock_.get()) {
|
| - // Reveal the top-of-window views without animating because it looks
|
| - // weird for the top-of-window views to animate and the bubble not to
|
| - // animate along with the top-of-window views.
|
| - revealed_lock_.reset(controller_->GetRevealedLock(
|
| - ImmersiveModeController::ANIMATE_REVEAL_NO));
|
| - }
|
| - } else {
|
| - revealed_lock_.reset();
|
| - }
|
| -
|
| - if (!was_revealed && revealed_lock_.get()) {
|
| - // Currently, there is no nice way for bubbles to reposition themselves
|
| - // whenever the anchor view moves. Tell the bubbles to reposition themselves
|
| - // explicitly instead. The hidden bubbles are also repositioned because
|
| - // BubbleDelegateView does not reposition its widget as a result of a
|
| - // visibility change.
|
| - for (std::set<aura::Window*>::const_iterator it = bubbles_.begin();
|
| - it != bubbles_.end(); ++it) {
|
| - AsBubbleDelegate(*it)->OnAnchorViewBoundsChanged();
|
| - }
|
| - }
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::BubbleManager::OnWindowVisibilityChanged(
|
| - aura::Window*,
|
| - bool visible) {
|
| - UpdateRevealedLock();
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::BubbleManager::OnWindowDestroying(
|
| - aura::Window* window) {
|
| - StopObserving(window);
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -
|
| ImmersiveModeControllerAsh::ImmersiveModeControllerAsh()
|
| - : delegate_(NULL),
|
| - widget_(NULL),
|
| - top_container_(NULL),
|
| - observers_enabled_(false),
|
| - enabled_(false),
|
| - reveal_state_(CLOSED),
|
| - revealed_lock_count_(0),
|
| - tab_indicator_visibility_(TAB_INDICATORS_HIDE),
|
| - mouse_x_when_hit_top_in_screen_(-1),
|
| - gesture_begun_(false),
|
| + : controller_(new ash::ImmersiveFullscreenController),
|
| + browser_view_(NULL),
|
| native_window_(NULL),
|
| - animation_(new gfx::SlideAnimation(this)),
|
| - animations_disabled_for_test_(false),
|
| - weak_ptr_factory_(this) {
|
| + use_tab_indicators_(false),
|
| + visible_fraction_(1),
|
| + observers_enabled_(false) {
|
| }
|
|
|
| ImmersiveModeControllerAsh::~ImmersiveModeControllerAsh() {
|
| - // The browser view is being destroyed so there's no need to update its
|
| - // layout or layers, even if the top views are revealed. But the window
|
| - // observers still need to be removed.
|
| EnableWindowObservers(false);
|
| }
|
|
|
| -void ImmersiveModeControllerAsh::LockRevealedState(
|
| - AnimateReveal animate_reveal) {
|
| - ++revealed_lock_count_;
|
| - Animate animate = (animate_reveal == ANIMATE_REVEAL_YES) ?
|
| - ANIMATE_FAST : ANIMATE_NO;
|
| - MaybeStartReveal(animate);
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::UnlockRevealedState() {
|
| - --revealed_lock_count_;
|
| - DCHECK_GE(revealed_lock_count_, 0);
|
| - if (revealed_lock_count_ == 0) {
|
| - // Always animate ending the reveal fast.
|
| - MaybeEndReveal(ANIMATE_FAST);
|
| - }
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::Init(
|
| - Delegate* delegate,
|
| - views::Widget* widget,
|
| - views::View* top_container) {
|
| - delegate_ = delegate;
|
| - widget_ = widget;
|
| - // Browser view is detached from its widget during destruction. Cache the
|
| - // window pointer so |this| can stop observing during destruction.
|
| - native_window_ = widget_->GetNativeWindow();
|
| - top_container_ = top_container;
|
| +void ImmersiveModeControllerAsh::Init(BrowserView* browser_view) {
|
| + browser_view_ = browser_view;
|
| + native_window_ = browser_view_->GetNativeWindow();
|
| + controller_->Init(this, browser_view_->frame(),
|
| + browser_view_->top_container());
|
| }
|
|
|
| void ImmersiveModeControllerAsh::SetEnabled(bool enabled) {
|
| - DCHECK(native_window_) << "Must initialize before enabling";
|
| - if (enabled_ == enabled)
|
| + if (controller_->IsEnabled() == enabled)
|
| return;
|
| - enabled_ = enabled;
|
|
|
| - EnableWindowObservers(enabled_);
|
| + EnableWindowObservers(enabled);
|
|
|
| - UpdateUseMinimalChrome(LAYOUT_NO);
|
| + // A short "light bar" version of the tab strip is painted when the
|
| + // top-of-window views are closed. If the user additionally enters into
|
| + // tab fullscreen, the tab indicators will be hidden.
|
| + use_tab_indicators_ = enabled;
|
|
|
| - if (enabled_) {
|
| - // Animate enabling immersive mode by sliding out the top-of-window views.
|
| - // No animation occurs if a lock is holding the top-of-window views open.
|
| -
|
| - // Do a reveal to set the initial state for the animation. (And any
|
| - // required state in case the animation cannot run because of a lock holding
|
| - // the top-of-window views open.) This call has the side effect of relaying
|
| - // out |browser_view_|'s root view.
|
| - MaybeStartReveal(ANIMATE_NO);
|
| -
|
| - // Reset the located event and the focus revealed locks so that they do not
|
| - // affect whether the top-of-window views are hidden.
|
| - located_event_revealed_lock_.reset();
|
| - focus_revealed_lock_.reset();
|
| -
|
| - // Try doing the animation.
|
| - MaybeEndReveal(ANIMATE_SLOW);
|
| -
|
| - if (reveal_state_ == REVEALED) {
|
| - // Reveal was unsuccessful. Reacquire the revealed locks if appropriate.
|
| - UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_NO);
|
| - UpdateFocusRevealedLock();
|
| - }
|
| - } else {
|
| - // Stop cursor-at-top tracking.
|
| - top_edge_hover_timer_.Stop();
|
| - // Snap immediately to the closed state.
|
| - reveal_state_ = CLOSED;
|
| - top_container_->SetPaintToLayer(false);
|
| - delegate_->SetImmersiveStyle(false);
|
| - SetRenderWindowTopInsetsForTouch(0);
|
| -
|
| - // Layout the root view so that incognito avatar icon, if any, gets laid
|
| - // out.
|
| - LayoutBrowserRootView();
|
| - }
|
| + controller_->SetEnabled(enabled);
|
| }
|
|
|
| bool ImmersiveModeControllerAsh::IsEnabled() const {
|
| - return enabled_;
|
| + return controller_->IsEnabled();
|
| }
|
|
|
| bool ImmersiveModeControllerAsh::ShouldHideTabIndicators() const {
|
| - return tab_indicator_visibility_ != TAB_INDICATORS_SHOW;
|
| + return !use_tab_indicators_;
|
| }
|
|
|
| bool ImmersiveModeControllerAsh::ShouldHideTopViews() const {
|
| - return enabled_ && reveal_state_ == CLOSED;
|
| + return controller_->IsEnabled() && !controller_->IsRevealed();
|
| }
|
|
|
| bool ImmersiveModeControllerAsh::IsRevealed() const {
|
| - return enabled_ && reveal_state_ != CLOSED;
|
| + return controller_->IsRevealed();
|
| }
|
|
|
| int ImmersiveModeControllerAsh::GetTopContainerVerticalOffset(
|
| const gfx::Size& top_container_size) const {
|
| - if (!enabled_ || reveal_state_ == REVEALED || reveal_state_ == CLOSED)
|
| + if (!IsEnabled())
|
| + return 0;
|
| +
|
| + // The TopContainerView is flush with the top of |browser_view_| when the
|
| + // top-of-window views are fully closed so that when the tab indicators are
|
| + // used, the "light bar" style tab strip is flush with the top of
|
| + // |browser_view_|.
|
| + if (!IsRevealed())
|
| return 0;
|
|
|
| - return animation_->CurrentValueBetween(
|
| - -top_container_size.height() + kAnimationOffsetY, 0);
|
| + int height = top_container_size.height() - kAnimationOffsetY;
|
| + return static_cast<int>(height * (visible_fraction_ - 1));
|
| }
|
|
|
| ImmersiveRevealedLock* ImmersiveModeControllerAsh::GetRevealedLock(
|
| AnimateReveal animate_reveal) {
|
| - return new RevealedLockAsh(weak_ptr_factory_.GetWeakPtr(), animate_reveal);
|
| + return controller_->GetRevealedLock(
|
| + ToImmersiveFullscreenControllerAnimateReveal(animate_reveal));
|
| }
|
|
|
| void ImmersiveModeControllerAsh::OnFindBarVisibleBoundsChanged(
|
| @@ -389,713 +128,144 @@ void ImmersiveModeControllerAsh::OnFindBarVisibleBoundsChanged(
|
| }
|
|
|
| void ImmersiveModeControllerAsh::SetupForTest() {
|
| - DCHECK(!enabled_);
|
| - animations_disabled_for_test_ = true;
|
| -
|
| - // Move the mouse off of the top-of-window views so that it does not keep
|
| - // the top-of-window views revealed.
|
| - gfx::Point cursor_pos(0, top_container_->bounds().bottom() + 100);
|
| - views::View::ConvertPointToScreen(top_container_, &cursor_pos);
|
| - aura::Env::GetInstance()->set_last_mouse_location(cursor_pos);
|
| - UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_NO);
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// Observers:
|
| -
|
| -void ImmersiveModeControllerAsh::Observe(
|
| - int type,
|
| - const content::NotificationSource& source,
|
| - const content::NotificationDetails& details) {
|
| - DCHECK_EQ(chrome::NOTIFICATION_FULLSCREEN_CHANGED, type);
|
| - if (enabled_)
|
| - UpdateUseMinimalChrome(LAYOUT_YES);
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::OnMouseEvent(ui::MouseEvent* event) {
|
| - if (!enabled_)
|
| - return;
|
| -
|
| - if (event->type() != ui::ET_MOUSE_MOVED &&
|
| - event->type() != ui::ET_MOUSE_PRESSED &&
|
| - event->type() != ui::ET_MOUSE_RELEASED &&
|
| - event->type() != ui::ET_MOUSE_CAPTURE_CHANGED) {
|
| - return;
|
| - }
|
| -
|
| - // Mouse hover should not initiate revealing the top-of-window views while
|
| - // |native_window_| is inactive.
|
| - if (!views::Widget::GetWidgetForNativeWindow(native_window_)->IsActive())
|
| - return;
|
| -
|
| - // Mouse hover should not initiate revealing the top-of-window views while
|
| - // a window has mouse capture.
|
| - if (aura::client::GetCaptureWindow(native_window_))
|
| - return;
|
| -
|
| - if (IsRevealed())
|
| - UpdateLocatedEventRevealedLock(event, ALLOW_REVEAL_WHILE_CLOSING_NO);
|
| -
|
| - // Trigger a reveal if the cursor pauses at the top of the screen for a
|
| - // while.
|
| - if (event->type() != ui::ET_MOUSE_CAPTURE_CHANGED)
|
| - UpdateTopEdgeHoverTimer(event);
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::OnTouchEvent(ui::TouchEvent* event) {
|
| - if (!enabled_ || event->type() != ui::ET_TOUCH_PRESSED)
|
| - return;
|
| -
|
| - UpdateLocatedEventRevealedLock(event, ALLOW_REVEAL_WHILE_CLOSING_NO);
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::OnGestureEvent(ui::GestureEvent* event) {
|
| - if (!enabled_)
|
| - return;
|
| -
|
| - // Touch gestures should not initiate revealing the top-of-window views while
|
| - // |native_window_| is inactive.
|
| - if (!views::Widget::GetWidgetForNativeWindow(native_window_)->IsActive())
|
| - return;
|
| -
|
| - switch (event->type()) {
|
| - case ui::ET_GESTURE_SCROLL_BEGIN:
|
| - if (ShouldHandleGestureEvent(GetEventLocationInScreen(*event))) {
|
| - gesture_begun_ = true;
|
| - event->SetHandled();
|
| - }
|
| - break;
|
| - case ui::ET_GESTURE_SCROLL_UPDATE:
|
| - if (gesture_begun_) {
|
| - if (UpdateRevealedLocksForSwipe(GetSwipeType(event)))
|
| - event->SetHandled();
|
| - gesture_begun_ = false;
|
| - }
|
| - break;
|
| - case ui::ET_GESTURE_SCROLL_END:
|
| - case ui::ET_SCROLL_FLING_START:
|
| - gesture_begun_ = false;
|
| - break;
|
| - default:
|
| - break;
|
| - }
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::OnWillChangeFocus(views::View* focused_before,
|
| - views::View* focused_now) {
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::OnDidChangeFocus(views::View* focused_before,
|
| - views::View* focused_now) {
|
| - UpdateFocusRevealedLock();
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::OnWidgetDestroying(views::Widget* widget) {
|
| - EnableWindowObservers(false);
|
| - native_window_ = NULL;
|
| -
|
| - // Set |enabled_| to false such that any calls to MaybeStartReveal() and
|
| - // MaybeEndReveal() have no effect.
|
| - enabled_ = false;
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::OnWidgetActivationChanged(
|
| - views::Widget* widget,
|
| - bool active) {
|
| - // Mouse hover should not initiate revealing the top-of-window views while
|
| - // |native_window_| is inactive.
|
| - top_edge_hover_timer_.Stop();
|
| -
|
| - UpdateFocusRevealedLock();
|
| -
|
| - // Allow the top-of-window views to stay revealed if all of the revealed locks
|
| - // were released in the process of activating |widget| but the mouse is still
|
| - // hovered above the top-of-window views. For instance, if the bubble which
|
| - // has been keeping the top-of-window views revealed is hidden but the mouse
|
| - // is hovered above the top-of-window views, the top-of-window views should
|
| - // stay revealed. We cannot call UpdateLocatedEventRevealedLock() from
|
| - // BubbleManager::UpdateRevealedLock() because |widget| is not yet active
|
| - // at that time.
|
| - UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_YES);
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// Animation delegate:
|
| -
|
| -void ImmersiveModeControllerAsh::AnimationEnded(
|
| - const gfx::Animation* animation) {
|
| - if (reveal_state_ == SLIDING_OPEN) {
|
| - // AnimationProgressed() is called immediately before AnimationEnded()
|
| - // and does a layout.
|
| - OnSlideOpenAnimationCompleted(LAYOUT_NO);
|
| - } else if (reveal_state_ == SLIDING_CLOSED) {
|
| - OnSlideClosedAnimationCompleted();
|
| - }
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::AnimationProgressed(
|
| - const gfx::Animation* animation) {
|
| - // Relayout. This will also move any views whose position depends on the
|
| - // top container position such as the find bar.
|
| - // We do not call LayoutBrowserRootView() here because we are not toggling
|
| - // the tab strip's immersive style so relaying out the non client view is not
|
| - // necessary.
|
| - top_container_->parent()->Layout();
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// aura::WindowObserver overrides:
|
| -
|
| -void ImmersiveModeControllerAsh::OnWindowPropertyChanged(aura::Window* window,
|
| - const void* key,
|
| - intptr_t old) {
|
| - if (!enabled_)
|
| - return;
|
| -
|
| - if (key == aura::client::kShowStateKey) {
|
| - // Disable immersive mode when the user exits fullscreen without going
|
| - // through FullscreenController::ToggleFullscreenMode(). This is the case
|
| - // if the user exits fullscreen via the restore button.
|
| - ui::WindowShowState show_state = static_cast<ui::WindowShowState>(
|
| - native_window_->GetProperty(aura::client::kShowStateKey));
|
| - if (show_state != ui::SHOW_STATE_FULLSCREEN &&
|
| - show_state != ui::SHOW_STATE_MINIMIZED) {
|
| - delegate_->FullscreenStateChanged();
|
| - }
|
| - }
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::OnAddTransientChild(aura::Window* window,
|
| - aura::Window* transient) {
|
| - views::BubbleDelegateView* bubble_delegate = AsBubbleDelegate(transient);
|
| - if (bubble_delegate &&
|
| - bubble_delegate->GetAnchorView() &&
|
| - top_container_->Contains(bubble_delegate->GetAnchorView())) {
|
| - // Observe the aura::Window because the BubbleDelegateView may not be
|
| - // parented to the widget's root view yet so |bubble_delegate->GetWidget()|
|
| - // may still return NULL.
|
| - bubble_manager_->StartObserving(transient);
|
| - }
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::OnRemoveTransientChild(
|
| - aura::Window* window,
|
| - aura::Window* transient) {
|
| - bubble_manager_->StopObserving(transient);
|
| + controller_->SetupForTest();
|
| }
|
|
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// private:
|
| -
|
| void ImmersiveModeControllerAsh::EnableWindowObservers(bool enable) {
|
| if (observers_enabled_ == enable)
|
| return;
|
| observers_enabled_ = enable;
|
|
|
| - if (!native_window_) {
|
| - NOTREACHED() << "ImmersiveModeControllerAsh not initialized";
|
| - return;
|
| - }
|
| -
|
| - views::Widget* widget =
|
| - views::Widget::GetWidgetForNativeWindow(native_window_);
|
| - views::FocusManager* focus_manager = widget->GetFocusManager();
|
| - if (enable) {
|
| - widget->AddObserver(this);
|
| - focus_manager->AddFocusChangeListener(this);
|
| - } else {
|
| - widget->RemoveObserver(this);
|
| - focus_manager->RemoveFocusChangeListener(this);
|
| - }
|
| -
|
| - if (enable)
|
| - ash::Shell::GetInstance()->AddPreTargetHandler(this);
|
| - else
|
| - ash::Shell::GetInstance()->RemovePreTargetHandler(this);
|
| -
|
| + content::Source<FullscreenController> source(
|
| + browser_view_->browser()->fullscreen_controller());
|
| if (enable) {
|
| - native_window_->AddObserver(this);
|
| + ash::wm::GetWindowState(native_window_)->AddObserver(this);
|
| + registrar_.Add(this, chrome::NOTIFICATION_FULLSCREEN_CHANGED, source);
|
| } else {
|
| - native_window_->RemoveObserver(this);
|
| + ash::wm::GetWindowState(native_window_)->RemoveObserver(this);
|
| + registrar_.Remove(this, chrome::NOTIFICATION_FULLSCREEN_CHANGED, source);
|
| }
|
| -
|
| - if (enable) {
|
| - RecreateBubbleManager();
|
| - } else {
|
| - // We have stopped observing whether transient children are added or removed
|
| - // to |native_window_|. The set of bubbles that BubbleManager is observing
|
| - // will become stale really quickly. Destroy BubbleManager and recreate it
|
| - // when we start observing |native_window_| again.
|
| - bubble_manager_.reset();
|
| - }
|
| -
|
| - if (enable) {
|
| - registrar_.Add(
|
| - this,
|
| - chrome::NOTIFICATION_FULLSCREEN_CHANGED,
|
| - content::Source<FullscreenController>(
|
| - delegate_->GetFullscreenController()));
|
| - } else {
|
| - registrar_.Remove(
|
| - this,
|
| - chrome::NOTIFICATION_FULLSCREEN_CHANGED,
|
| - content::Source<FullscreenController>(
|
| - delegate_->GetFullscreenController()));
|
| - }
|
| -
|
| - if (!enable)
|
| - animation_->Stop();
|
| }
|
|
|
| -void ImmersiveModeControllerAsh::UpdateTopEdgeHoverTimer(
|
| - ui::MouseEvent* event) {
|
| - DCHECK(enabled_);
|
| - // Stop the timer if the top-of-window views are already revealed.
|
| - if (reveal_state_ == SLIDING_OPEN || reveal_state_ == REVEALED) {
|
| - top_edge_hover_timer_.Stop();
|
| - return;
|
| - }
|
| -
|
| - gfx::Point location_in_screen = GetEventLocationInScreen(*event);
|
| - if (ShouldIgnoreMouseEventAtLocation(location_in_screen))
|
| - return;
|
| -
|
| - // Stop the timer if the cursor left the top edge or is on a different
|
| - // display. The bounds of |top_container_|'s parent are used to infer the hit
|
| - // bounds because |top_container_| will be partially offscreen if it is
|
| - // animating closed.
|
| - gfx::Rect hit_bounds_in_screen =
|
| - top_container_->parent()->GetBoundsInScreen();
|
| - hit_bounds_in_screen.set_height(kMouseRevealBoundsHeight);
|
| - if (!hit_bounds_in_screen.Contains(location_in_screen)) {
|
| - top_edge_hover_timer_.Stop();
|
| - return;
|
| - }
|
| -
|
| - // The cursor is now at the top of the screen. Consider the cursor "not
|
| - // moving" even if it moves a little bit because users don't have perfect
|
| - // pointing precision. (The y position is not tested because
|
| - // |hit_bounds_in_screen| is short.)
|
| - if (top_edge_hover_timer_.IsRunning() &&
|
| - abs(location_in_screen.x() - mouse_x_when_hit_top_in_screen_) <=
|
| - kMouseRevealXThresholdPixels)
|
| - return;
|
| -
|
| - // Start the reveal if the cursor doesn't move for some amount of time.
|
| - mouse_x_when_hit_top_in_screen_ = location_in_screen.x();
|
| - top_edge_hover_timer_.Stop();
|
| - // Timer is stopped when |this| is destroyed, hence Unretained() is safe.
|
| - top_edge_hover_timer_.Start(
|
| - FROM_HERE,
|
| - base::TimeDelta::FromMilliseconds(kMouseRevealDelayMs),
|
| - base::Bind(&ImmersiveModeControllerAsh::AcquireLocatedEventRevealedLock,
|
| - base::Unretained(this)));
|
| +void ImmersiveModeControllerAsh::LayoutBrowserRootView() {
|
| + views::Widget* widget = browser_view_->frame();
|
| + // Update the window caption buttons.
|
| + widget->non_client_view()->frame_view()->ResetWindowControls();
|
| + // Layout all views, including BrowserView.
|
| + widget->GetRootView()->Layout();
|
| }
|
|
|
| -void ImmersiveModeControllerAsh::UpdateLocatedEventRevealedLock(
|
| - ui::LocatedEvent* event,
|
| - AllowRevealWhileClosing allow_reveal_while_closing) {
|
| - if (!enabled_)
|
| - return;
|
| - DCHECK(!event || event->IsMouseEvent() || event->IsTouchEvent());
|
| -
|
| - // Neither the mouse nor touch can initiate a reveal when the top-of-window
|
| - // views are sliding closed or are closed with the following exceptions:
|
| - // - Hovering at y = 0 which is handled in OnMouseEvent().
|
| - // - Doing a SWIPE_OPEN edge gesture which is handled in OnGestureEvent().
|
| - if (reveal_state_ == CLOSED ||
|
| - (reveal_state_ == SLIDING_CLOSED &&
|
| - allow_reveal_while_closing == ALLOW_REVEAL_WHILE_CLOSING_NO)) {
|
| - return;
|
| - }
|
| -
|
| - // Neither the mouse nor touch should keep the top-of-window views revealed if
|
| - // |native_window_| is not active.
|
| - if (!views::Widget::GetWidgetForNativeWindow(native_window_)->IsActive()) {
|
| - located_event_revealed_lock_.reset();
|
| - return;
|
| - }
|
| -
|
| - // Ignore all events while a window has capture. This keeps the top-of-window
|
| - // views revealed during a drag.
|
| - if (aura::client::GetCaptureWindow(native_window_))
|
| - return;
|
| -
|
| - gfx::Point location_in_screen;
|
| - if (event && event->type() != ui::ET_MOUSE_CAPTURE_CHANGED) {
|
| - location_in_screen = GetEventLocationInScreen(*event);
|
| - } else {
|
| - aura::client::CursorClient* cursor_client = aura::client::GetCursorClient(
|
| - native_window_->GetRootWindow());
|
| - if (!cursor_client->IsMouseEventsEnabled()) {
|
| - // If mouse events are disabled, the user's last interaction was probably
|
| - // via touch. Do no do further processing in this case as there is no easy
|
| - // way of retrieving the position of the user's last touch.
|
| - return;
|
| +void ImmersiveModeControllerAsh::SetRenderWindowTopInsetsForTouch(
|
| + int top_inset) {
|
| + content::WebContents* contents = browser_view_->GetActiveWebContents();
|
| + if (contents) {
|
| + aura::Window* window = contents->GetView()->GetContentNativeView();
|
| + // |window| is NULL if the renderer crashed.
|
| + if (window) {
|
| + gfx::Insets inset(top_inset, 0, 0, 0);
|
| + window->SetHitTestBoundsOverrideOuter(
|
| + window->hit_test_bounds_override_outer_mouse(),
|
| + inset);
|
| }
|
| - location_in_screen = aura::Env::GetInstance()->last_mouse_location();
|
| - }
|
| -
|
| - if ((!event || event->IsMouseEvent()) &&
|
| - ShouldIgnoreMouseEventAtLocation(location_in_screen)) {
|
| - return;
|
| - }
|
| -
|
| - gfx::Rect hit_bounds_in_top_container = top_container_->GetVisibleBounds();
|
| - // TODO(tdanderson): Implement View::ConvertRectToScreen();
|
| - gfx::Point hit_bounds_in_screen_origin = hit_bounds_in_top_container.origin();
|
| - views::View::ConvertPointToScreen(top_container_,
|
| - &hit_bounds_in_screen_origin);
|
| - gfx::Rect hit_bounds_in_screen(hit_bounds_in_screen_origin,
|
| - hit_bounds_in_top_container.size());
|
| -
|
| - gfx::Rect find_bar_hit_bounds_in_screen = find_bar_visible_bounds_in_screen_;
|
| -
|
| - // Allow the cursor to move slightly off the top-of-window views before
|
| - // sliding closed. This helps when the user is attempting to click on the
|
| - // bookmark bar and overshoots slightly.
|
| - if (event && event->type() == ui::ET_MOUSE_MOVED) {
|
| - const int kBoundsOffsetY = 8;
|
| - hit_bounds_in_screen.Inset(0, 0, 0, -kBoundsOffsetY);
|
| - find_bar_hit_bounds_in_screen.Inset(0, 0, 0, -kBoundsOffsetY);
|
| }
|
| -
|
| - if (hit_bounds_in_screen.Contains(location_in_screen) ||
|
| - find_bar_hit_bounds_in_screen.Contains(location_in_screen)) {
|
| - AcquireLocatedEventRevealedLock();
|
| - } else {
|
| - located_event_revealed_lock_.reset();
|
| - }
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::AcquireLocatedEventRevealedLock() {
|
| - // CAUTION: Acquiring the lock results in a reentrant call to
|
| - // AcquireLocatedEventRevealedLock() when
|
| - // |ImmersiveModeControllerAsh::animations_disabled_for_test_| is true.
|
| - if (!located_event_revealed_lock_.get())
|
| - located_event_revealed_lock_.reset(GetRevealedLock(ANIMATE_REVEAL_YES));
|
| }
|
|
|
| -void ImmersiveModeControllerAsh::UpdateFocusRevealedLock() {
|
| - if (!enabled_)
|
| - return;
|
| -
|
| - bool hold_lock = false;
|
| - views::Widget* widget =
|
| - views::Widget::GetWidgetForNativeWindow(native_window_);
|
| - if (widget->IsActive()) {
|
| - views::View* focused_view = widget->GetFocusManager()->GetFocusedView();
|
| - if (top_container_->Contains(focused_view))
|
| - hold_lock = true;
|
| - } else {
|
| - aura::Window* active_window = aura::client::GetActivationClient(
|
| - native_window_->GetRootWindow())->GetActiveWindow();
|
| - views::BubbleDelegateView* bubble_delegate =
|
| - AsBubbleDelegate(active_window);
|
| - if (bubble_delegate && bubble_delegate->anchor_widget()) {
|
| - // BubbleManager will already have locked the top-of-window views if the
|
| - // bubble is anchored to a child of |top_container_|. Don't acquire
|
| - // |focus_revealed_lock_| here for the sake of simplicity.
|
| - // Note: Instead of checking for the existence of the |anchor_view|,
|
| - // the existence of the |anchor_widget| is performed to avoid the case
|
| - // where the view is already gone (and the widget is still running).
|
| - } else {
|
| - // The currently active window is not |native_window_| and it is not a
|
| - // bubble with an anchor view. The top-of-window views should be revealed
|
| - // if:
|
| - // 1) The active window is a transient child of |native_window_|.
|
| - // 2) The top-of-window views are already revealed. This restriction
|
| - // prevents a transient window opened by the web contents while the
|
| - // top-of-window views are hidden from from initiating a reveal.
|
| - // The top-of-window views will stay revealed till |native_window_| is
|
| - // reactivated.
|
| - if (IsRevealed() &&
|
| - IsWindowTransientChildOf(active_window, native_window_)) {
|
| - hold_lock = true;
|
| - }
|
| - }
|
| - }
|
| -
|
| - if (hold_lock) {
|
| - if (!focus_revealed_lock_.get())
|
| - focus_revealed_lock_.reset(GetRevealedLock(ANIMATE_REVEAL_YES));
|
| - } else {
|
| - focus_revealed_lock_.reset();
|
| - }
|
| +void ImmersiveModeControllerAsh::SetTabIndicatorsVisible(bool visible) {
|
| + DCHECK(!visible || use_tab_indicators_);
|
| + if (browser_view_->tabstrip())
|
| + browser_view_->tabstrip()->SetImmersiveStyle(visible);
|
| }
|
|
|
| -bool ImmersiveModeControllerAsh::UpdateRevealedLocksForSwipe(
|
| - SwipeType swipe_type) {
|
| - if (!enabled_ || swipe_type == SWIPE_NONE)
|
| - return false;
|
| -
|
| - // Swipes while |native_window_| is inactive should have been filtered out in
|
| - // OnGestureEvent().
|
| - DCHECK(views::Widget::GetWidgetForNativeWindow(native_window_)->IsActive());
|
| -
|
| - if (reveal_state_ == SLIDING_CLOSED || reveal_state_ == CLOSED) {
|
| - if (swipe_type == SWIPE_OPEN && !located_event_revealed_lock_.get()) {
|
| - located_event_revealed_lock_.reset(GetRevealedLock(ANIMATE_REVEAL_YES));
|
| - return true;
|
| - }
|
| - } else {
|
| - if (swipe_type == SWIPE_CLOSE) {
|
| - // Attempt to end the reveal. If other code is holding onto a lock, the
|
| - // attempt will be unsuccessful.
|
| - located_event_revealed_lock_.reset();
|
| - focus_revealed_lock_.reset();
|
| -
|
| - if (reveal_state_ == SLIDING_CLOSED || reveal_state_ == CLOSED)
|
| - return true;
|
| -
|
| - // Ending the reveal was unsuccessful. Reaquire the locks if appropriate.
|
| - UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_NO);
|
| - UpdateFocusRevealedLock();
|
| - }
|
| - }
|
| - return false;
|
| +void ImmersiveModeControllerAsh::OnImmersiveRevealStarted() {
|
| + visible_fraction_ = 0;
|
| + browser_view_->top_container()->SetPaintToLayer(true);
|
| + SetTabIndicatorsVisible(false);
|
| + SetRenderWindowTopInsetsForTouch(0);
|
| + LayoutBrowserRootView();
|
| + FOR_EACH_OBSERVER(Observer, observers_, OnImmersiveRevealStarted());
|
| }
|
|
|
| -void ImmersiveModeControllerAsh::UpdateUseMinimalChrome(Layout layout) {
|
| - // May be NULL in tests.
|
| - FullscreenController* fullscreen_controller =
|
| - delegate_->GetFullscreenController();
|
| - bool in_tab_fullscreen = fullscreen_controller ?
|
| - fullscreen_controller->IsFullscreenForTabOrPending() : false;
|
| - bool use_minimal_chrome = !in_tab_fullscreen && enabled_;
|
| -
|
| - // When using minimal chrome, the shelf is auto-hidden. The auto-hidden shelf
|
| - // displays a 3px 'light bar' when it is closed. Otherwise, the shelf is
|
| - // hidden completely and cannot be revealed.
|
| - ash::wm::GetWindowState(native_window_)->set_hide_shelf_when_fullscreen(
|
| - !use_minimal_chrome);
|
| -
|
| - TabIndicatorVisibility previous_tab_indicator_visibility =
|
| - tab_indicator_visibility_;
|
| - if (tab_indicator_visibility_ != TAB_INDICATORS_FORCE_HIDE) {
|
| - tab_indicator_visibility_ = use_minimal_chrome ?
|
| - TAB_INDICATORS_SHOW : TAB_INDICATORS_HIDE;
|
| - }
|
| -
|
| - ash::Shell::GetInstance()->UpdateShelfVisibility();
|
| -
|
| - if (tab_indicator_visibility_ != previous_tab_indicator_visibility) {
|
| - // If the top-of-window views are revealed or animating, the change will
|
| - // take effect with the layout once the top-of-window views are closed.
|
| - if (layout == LAYOUT_YES && reveal_state_ == CLOSED)
|
| - LayoutBrowserRootView();
|
| - }
|
| +void ImmersiveModeControllerAsh::OnImmersiveRevealEnded() {
|
| + visible_fraction_ = 0;
|
| + browser_view_->top_container()->SetPaintToLayer(false);
|
| + SetTabIndicatorsVisible(use_tab_indicators_);
|
| + SetRenderWindowTopInsetsForTouch(
|
| + kStealTouchEventsFromWebContentsRegionHeightPx);
|
| + LayoutBrowserRootView();
|
| }
|
|
|
| -int ImmersiveModeControllerAsh::GetAnimationDuration(Animate animate) const {
|
| - switch (animate) {
|
| - case ANIMATE_NO:
|
| - return 0;
|
| - case ANIMATE_SLOW:
|
| - return kRevealSlowAnimationDurationMs;
|
| - case ANIMATE_FAST:
|
| - return kRevealFastAnimationDurationMs;
|
| - }
|
| - NOTREACHED();
|
| - return 0;
|
| +void ImmersiveModeControllerAsh::OnImmersiveFullscreenExited() {
|
| + browser_view_->top_container()->SetPaintToLayer(false);
|
| + SetTabIndicatorsVisible(false);
|
| + SetRenderWindowTopInsetsForTouch(0);
|
| + LayoutBrowserRootView();
|
| }
|
|
|
| -void ImmersiveModeControllerAsh::MaybeStartReveal(Animate animate) {
|
| - if (!enabled_)
|
| - return;
|
| -
|
| - if (animations_disabled_for_test_)
|
| - animate = ANIMATE_NO;
|
| -
|
| - // Callers with ANIMATE_NO expect this function to synchronously reveal the
|
| - // top-of-window views.
|
| - if (reveal_state_ == REVEALED ||
|
| - (reveal_state_ == SLIDING_OPEN && animate != ANIMATE_NO)) {
|
| - return;
|
| - }
|
| -
|
| - RevealState previous_reveal_state = reveal_state_;
|
| - reveal_state_ = SLIDING_OPEN;
|
| - if (previous_reveal_state == CLOSED) {
|
| - // Turn on layer painting so that we can overlap the web contents.
|
| - top_container_->SetPaintToLayer(true);
|
| -
|
| - // Ensure window caption buttons are updated and the view bounds are
|
| - // computed at normal (non-immersive-style) size. The layout call moves the
|
| - // top-of-window views to their initial offscreen position for the
|
| - // animation.
|
| - delegate_->SetImmersiveStyle(false);
|
| - SetRenderWindowTopInsetsForTouch(0);
|
| - LayoutBrowserRootView();
|
| -
|
| - // Do not do any more processing if LayoutBrowserView() changed
|
| - // |reveal_state_|.
|
| - if (reveal_state_ != SLIDING_OPEN) {
|
| - if (reveal_state_ == REVEALED)
|
| - FOR_EACH_OBSERVER(Observer, observers_, OnImmersiveRevealStarted());
|
| - return;
|
| - }
|
| +void ImmersiveModeControllerAsh::SetVisibility(double visible_fraction) {
|
| + if (visible_fraction_ != visible_fraction) {
|
| + visible_fraction_ = visible_fraction;
|
| + browser_view_->Layout();
|
| }
|
| - // Slide in the reveal view.
|
| - if (animate == ANIMATE_NO) {
|
| - animation_->Reset(1);
|
| - OnSlideOpenAnimationCompleted(LAYOUT_YES);
|
| - } else {
|
| - animation_->SetSlideDuration(GetAnimationDuration(animate));
|
| - animation_->Show();
|
| - }
|
| -
|
| - if (previous_reveal_state == CLOSED)
|
| - FOR_EACH_OBSERVER(Observer, observers_, OnImmersiveRevealStarted());
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::LayoutBrowserRootView() {
|
| - // Update the window caption buttons.
|
| - widget_->non_client_view()->frame_view()->ResetWindowControls();
|
| - // Layout all views, including BrowserView.
|
| - widget_->GetRootView()->Layout();
|
| }
|
|
|
| -void ImmersiveModeControllerAsh::OnSlideOpenAnimationCompleted(Layout layout) {
|
| - DCHECK_EQ(SLIDING_OPEN, reveal_state_);
|
| - reveal_state_ = REVEALED;
|
| -
|
| - if (layout == LAYOUT_YES)
|
| - top_container_->parent()->Layout();
|
| +std::vector<gfx::Rect>
|
| +ImmersiveModeControllerAsh::GetVisibleBoundsInScreen() {
|
| + views::View* top_container_view = browser_view_->top_container();
|
| + gfx::Rect top_container_view_bounds = top_container_view->GetVisibleBounds();
|
| + // TODO(tdanderson): Implement View::ConvertRectToScreen().
|
| + gfx::Point top_container_view_bounds_in_screen_origin(
|
| + top_container_view_bounds.origin());
|
| + views::View::ConvertPointToScreen(top_container_view,
|
| + &top_container_view_bounds_in_screen_origin);
|
| + gfx::Rect top_container_view_bounds_in_screen(
|
| + top_container_view_bounds_in_screen_origin,
|
| + top_container_view_bounds.size());
|
|
|
| - // The user may not have moved the mouse since the reveal was initiated.
|
| - // Update the revealed lock to reflect the mouse's current state.
|
| - UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_NO);
|
| + std::vector<gfx::Rect> bounds_in_screen;
|
| + bounds_in_screen.push_back(top_container_view_bounds_in_screen);
|
| + bounds_in_screen.push_back(find_bar_visible_bounds_in_screen_);
|
| + return bounds_in_screen;
|
| }
|
|
|
| -void ImmersiveModeControllerAsh::MaybeEndReveal(Animate animate) {
|
| - if (!enabled_ || revealed_lock_count_ != 0)
|
| - return;
|
| -
|
| - if (animations_disabled_for_test_)
|
| - animate = ANIMATE_NO;
|
| -
|
| - // Callers with ANIMATE_NO expect this function to synchronously close the
|
| - // top-of-window views.
|
| - if (reveal_state_ == CLOSED ||
|
| - (reveal_state_ == SLIDING_CLOSED && animate != ANIMATE_NO)) {
|
| - return;
|
| +void ImmersiveModeControllerAsh::OnWindowShowTypeChanged(
|
| + ash::wm::WindowState* window_state,
|
| + ash::wm::WindowShowType old_type) {
|
| + // Disable immersive fullscreen when the user exits fullscreen without going
|
| + // through FullscreenController::ToggleFullscreenMode(). This is the case if
|
| + // the user exits fullscreen via the restore button.
|
| + if (controller_->IsEnabled() &&
|
| + !window_state->IsFullscreen() &&
|
| + !window_state->IsMinimized()) {
|
| + browser_view_->FullscreenStateChanged();
|
| }
|
| -
|
| - reveal_state_ = SLIDING_CLOSED;
|
| - int duration_ms = GetAnimationDuration(animate);
|
| - if (duration_ms > 0) {
|
| - animation_->SetSlideDuration(duration_ms);
|
| - animation_->Hide();
|
| - } else {
|
| - animation_->Reset(0);
|
| - OnSlideClosedAnimationCompleted();
|
| - }
|
| -}
|
| -
|
| -void ImmersiveModeControllerAsh::OnSlideClosedAnimationCompleted() {
|
| - DCHECK_EQ(SLIDING_CLOSED, reveal_state_);
|
| - reveal_state_ = CLOSED;
|
| - // Layers aren't needed after animation completes.
|
| - top_container_->SetPaintToLayer(false);
|
| - // Update tabstrip for closed state.
|
| - delegate_->SetImmersiveStyle(true);
|
| - SetRenderWindowTopInsetsForTouch(kNearTopContainerDistance);
|
| - LayoutBrowserRootView();
|
| -}
|
| -
|
| -ImmersiveModeControllerAsh::SwipeType ImmersiveModeControllerAsh::GetSwipeType(
|
| - ui::GestureEvent* event) const {
|
| - if (event->type() != ui::ET_GESTURE_SCROLL_UPDATE)
|
| - return SWIPE_NONE;
|
| - // Make sure that it is a clear vertical gesture.
|
| - if (abs(event->details().scroll_y()) <=
|
| - kSwipeVerticalThresholdMultiplier * abs(event->details().scroll_x()))
|
| - return SWIPE_NONE;
|
| - if (event->details().scroll_y() < 0)
|
| - return SWIPE_CLOSE;
|
| - else if (event->details().scroll_y() > 0)
|
| - return SWIPE_OPEN;
|
| - return SWIPE_NONE;
|
| -}
|
| -
|
| -bool ImmersiveModeControllerAsh::ShouldIgnoreMouseEventAtLocation(
|
| - const gfx::Point& location) const {
|
| - // Ignore mouse events in the region immediately above the top edge of the
|
| - // display. This is to handle the case of a user with a vertical display
|
| - // layout (primary display above/below secondary display) and the immersive
|
| - // fullscreen window on the bottom display. It is really hard to trigger a
|
| - // reveal in this case because:
|
| - // - It is hard to stop the cursor in the top |kMouseRevealBoundsHeight|
|
| - // pixels of the bottom display.
|
| - // - The cursor is warped to the top display if the cursor gets to the top
|
| - // edge of the bottom display.
|
| - // Mouse events are ignored in the bottom few pixels of the top display
|
| - // (Mouse events in this region cannot start or end a reveal). This allows a
|
| - // user to overshoot the top of the bottom display and still reveal the
|
| - // top-of-window views.
|
| - gfx::Rect dead_region = top_container_->parent()->GetBoundsInScreen();
|
| - dead_region.set_y(dead_region.y() - kHeightOfDeadRegionAboveTopContainer);
|
| - dead_region.set_height(kHeightOfDeadRegionAboveTopContainer);
|
| - return dead_region.Contains(location);
|
| }
|
|
|
| -bool ImmersiveModeControllerAsh::ShouldHandleGestureEvent(
|
| - const gfx::Point& location) const {
|
| - gfx::Rect top_container_bounds_in_screen =
|
| - top_container_->GetBoundsInScreen();
|
| +void ImmersiveModeControllerAsh::Observe(
|
| + int type,
|
| + const content::NotificationSource& source,
|
| + const content::NotificationDetails& details) {
|
| + DCHECK_EQ(chrome::NOTIFICATION_FULLSCREEN_CHANGED, type);
|
| + if (!controller_->IsEnabled())
|
| + return;
|
|
|
| - // All of the gestures that are of interest start in a region with left &
|
| - // right edges agreeing with |top_container_|. When CLOSED it is difficult to
|
| - // hit the bounds due to small size of the tab strip, so the hit target needs
|
| - // to be extended on the bottom, thus the inset call.
|
| - gfx::Rect near_bounds = top_container_bounds_in_screen;
|
| - if (reveal_state_ == CLOSED)
|
| - near_bounds.Inset(gfx::Insets(0, 0, -kNearTopContainerDistance, 0));
|
| - if (near_bounds.Contains(location))
|
| - return true;
|
| + bool in_tab_fullscreen = content::Source<FullscreenController>(source)->
|
| + IsFullscreenForTabOrPending();
|
|
|
| - // There may be a bezel sensor off screen logically above |top_container_|
|
| - // thus the test needs to include gestures starting above, but this needs to
|
| - // be distinguished from events originating on another screen from
|
| - // (potentially) an extended desktop. The check for the event not contained by
|
| - // the closest screen ensures that the event is from a valid bezel and can be
|
| - // interpreted as such.
|
| - gfx::Rect screen_bounds =
|
| - ash::Shell::GetScreen()->GetDisplayNearestPoint(location).bounds();
|
| - return (!screen_bounds.Contains(location) &&
|
| - location.y() < top_container_bounds_in_screen.y() &&
|
| - location.x() >= top_container_bounds_in_screen.x() &&
|
| - location.x() < top_container_bounds_in_screen.right());
|
| -}
|
| + bool used_tab_indicators = use_tab_indicators_;
|
| + use_tab_indicators_ = !in_tab_fullscreen;
|
|
|
| -void ImmersiveModeControllerAsh::SetRenderWindowTopInsetsForTouch(
|
| - int top_inset) {
|
| - content::WebContents* contents = delegate_->GetWebContents();
|
| - if (contents) {
|
| - aura::Window* window = contents->GetView()->GetContentNativeView();
|
| - // |window| is NULL if the renderer crashed.
|
| - if (window) {
|
| - gfx::Insets inset(top_inset, 0, 0, 0);
|
| - window->SetHitTestBoundsOverrideOuter(
|
| - window->hit_test_bounds_override_outer_mouse(),
|
| - inset);
|
| - }
|
| - }
|
| -}
|
| + // Auto hide the shelf in immersive browser fullscren. When auto hidden, the
|
| + // shelf displays a 3px 'light bar'. When in immersive browser fullscreen and
|
| + // tab fullscreen, hide the shelf completely and prevent it from being
|
| + // revealed.
|
| + ash::wm::GetWindowState(native_window_)->set_hide_shelf_when_fullscreen(
|
| + in_tab_fullscreen);
|
| + ash::Shell::GetInstance()->UpdateShelfVisibility();
|
|
|
| -void ImmersiveModeControllerAsh::RecreateBubbleManager() {
|
| - bubble_manager_.reset(new BubbleManager(this));
|
| - const std::vector<aura::Window*> transient_children =
|
| - native_window_->transient_children();
|
| - for (size_t i = 0; i < transient_children.size(); ++i) {
|
| - aura::Window* transient_child = transient_children[i];
|
| - views::BubbleDelegateView* bubble_delegate =
|
| - AsBubbleDelegate(transient_child);
|
| - if (bubble_delegate &&
|
| - bubble_delegate->GetAnchorView() &&
|
| - top_container_->Contains(bubble_delegate->GetAnchorView())) {
|
| - bubble_manager_->StartObserving(transient_child);
|
| - }
|
| + if (use_tab_indicators_ != used_tab_indicators) {
|
| + // If the top-of-window views are revealed or are animating, the change will
|
| + // take effect with the layout once the top-of-window views are closed.
|
| + if (!controller_->IsRevealed())
|
| + LayoutBrowserRootView();
|
| }
|
| }
|
|
|