blob: 8255e119e5c8b6c3cc0d94e35fbb09dfe7c8242b [file] [log] [blame]
// Copyright 2012 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 CHROME_BROWSER_UI_VIEWS_FRAME_IMMERSIVE_MODE_CONTROLLER_ASH_H_
#define CHROME_BROWSER_UI_VIEWS_FRAME_IMMERSIVE_MODE_CONTROLLER_ASH_H_
#include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
#include "base/timer/timer.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "ui/aura/window_observer.h"
#include "ui/events/event_handler.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/rect.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/widget/widget_observer.h"
class BrowserView;
class BookmarkBarView;
namespace aura {
class Window;
}
namespace gfx {
class SlideAnimation;
class Transform;
}
namespace ui {
class Layer;
class LocatedEvent;
}
namespace views {
class View;
}
class ImmersiveModeControllerAsh : public ImmersiveModeController,
public content::NotificationObserver,
public gfx::AnimationDelegate,
public ui::EventHandler,
public views::FocusChangeListener,
public views::WidgetObserver,
public aura::WindowObserver {
public:
ImmersiveModeControllerAsh();
virtual ~ImmersiveModeControllerAsh();
// These methods are used to increment and decrement |revealed_lock_count_|.
// If immersive mode is enabled, a transition from 1 to 0 in
// |revealed_lock_count_| closes the top-of-window views and a transition
// from 0 to 1 in |revealed_lock_count_| reveals the top-of-window views.
void LockRevealedState(AnimateReveal animate_reveal);
void UnlockRevealedState();
// ImmersiveModeController overrides:
virtual void Init(Delegate* delegate,
views::Widget* widget,
views::View* top_container) OVERRIDE;
virtual void SetEnabled(bool enabled) OVERRIDE;
virtual bool IsEnabled() const OVERRIDE;
virtual bool ShouldHideTabIndicators() const OVERRIDE;
virtual bool ShouldHideTopViews() const OVERRIDE;
virtual bool IsRevealed() const OVERRIDE;
virtual int GetTopContainerVerticalOffset(
const gfx::Size& top_container_size) const OVERRIDE;
virtual ImmersiveRevealedLock* GetRevealedLock(
AnimateReveal animate_reveal) OVERRIDE WARN_UNUSED_RESULT;
virtual void OnFindBarVisibleBoundsChanged(
const gfx::Rect& new_visible_bounds_in_screen) OVERRIDE;
virtual void SetupForTest() OVERRIDE;
// content::NotificationObserver override:
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
// ui::EventHandler overrides:
virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
// views::FocusChangeObserver overrides:
virtual void OnWillChangeFocus(views::View* focused_before,
views::View* focused_now) OVERRIDE;
virtual void OnDidChangeFocus(views::View* focused_before,
views::View* focused_now) OVERRIDE;
// views::WidgetObserver overrides:
virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE;
virtual void OnWidgetActivationChanged(views::Widget* widget,
bool active) OVERRIDE;
// gfx::AnimationDelegate overrides:
virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
// aura::WindowObserver overrides:
virtual void OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) OVERRIDE;
virtual void OnAddTransientChild(aura::Window* window,
aura::Window* transient) OVERRIDE;
virtual void OnRemoveTransientChild(aura::Window* window,
aura::Window* transient) OVERRIDE;
private:
friend class ImmersiveModeControllerAshTest;
enum AllowRevealWhileClosing {
ALLOW_REVEAL_WHILE_CLOSING_YES,
ALLOW_REVEAL_WHILE_CLOSING_NO
};
enum Animate {
ANIMATE_NO,
ANIMATE_SLOW,
ANIMATE_FAST,
};
enum Layout {
LAYOUT_YES,
LAYOUT_NO
};
enum RevealState {
CLOSED, // Top container only showing tabstrip, y = 0.
SLIDING_OPEN, // All views showing, y animating from -height to 0.
REVEALED, // All views showing, y = 0.
SLIDING_CLOSED, // All views showing, y animating from 0 to -height.
};
enum TabIndicatorVisibility {
TAB_INDICATORS_FORCE_HIDE,
TAB_INDICATORS_HIDE,
TAB_INDICATORS_SHOW
};
enum SwipeType {
SWIPE_OPEN,
SWIPE_CLOSE,
SWIPE_NONE
};
// Enables or disables observers for mouse move, focus, and window restore.
void EnableWindowObservers(bool enable);
// Updates |top_edge_hover_timer_| based on a mouse |event|. If the mouse is
// hovered at the top of the screen the timer is started. If the mouse moves
// away from the top edge, or moves too much in the x direction, the timer is
// stopped.
void UpdateTopEdgeHoverTimer(ui::MouseEvent* event);
// Updates |located_event_revealed_lock_| based on the current mouse state and
// the current touch state.
// |event| is NULL if the source event is not known.
// |allow_reveal_while_closing| indicates whether the mouse and touch
// are allowed to initiate a reveal while the top-of-window views are sliding
// closed.
void UpdateLocatedEventRevealedLock(
ui::LocatedEvent* event,
AllowRevealWhileClosing allow_reveal_while_closing);
// Acquires |located_event_revealed_lock_| if it is not already held.
void AcquireLocatedEventRevealedLock();
// Updates |focus_revealed_lock_| based on the currently active view and the
// currently active widget.
void UpdateFocusRevealedLock();
// Update |located_event_revealed_lock_| and |focus_revealed_lock_| as a
// result of a gesture of |swipe_type|. Returns true if any locks were
// acquired or released.
bool UpdateRevealedLocksForSwipe(SwipeType swipe_type);
// Updates whether fullscreen uses any chrome at all. When using minimal
// chrome, a 'light bar' is permanently visible for the launcher and possibly
// for the tabstrip.
void UpdateUseMinimalChrome(Layout layout);
// Returns the animation duration given |animate|.
int GetAnimationDuration(Animate animate) const;
// Temporarily reveals the top-of-window views while in immersive mode,
// hiding them when the cursor exits the area of the top views. If |animate|
// is not ANIMATE_NO, slides in the view, otherwise shows it immediately.
void MaybeStartReveal(Animate animate);
// Updates the browser root view's layout including window caption controls.
void LayoutBrowserRootView();
// Called when the animation to slide open the top-of-window views has
// completed.
void OnSlideOpenAnimationCompleted(Layout layout);
// Hides the top-of-window views if immersive mode is enabled and nothing is
// keeping them revealed. Optionally animates.
void MaybeEndReveal(Animate animate);
// Called when the animation to slide out the top-of-window views has
// completed.
void OnSlideClosedAnimationCompleted();
// Returns the type of swipe given |event|.
SwipeType GetSwipeType(ui::GestureEvent* event) const;
// Returns true if a mouse event at |location_in_screen| should be ignored.
// Ignored mouse events should not contribute to revealing or unrevealing the
// top-of-window views.
bool ShouldIgnoreMouseEventAtLocation(
const gfx::Point& location_in_screen) const;
// True when |location| is "near" to the top container. When the top container
// is not closed "near" means within the displayed bounds or above it. When
// the top container is closed "near" means either within the displayed
// bounds, above it, or within a few pixels below it. This allow the container
// to steal enough pixels to detect a swipe in and handles the case that there
// is a bezel sensor above the top container.
bool ShouldHandleGestureEvent(const gfx::Point& location) const;
// Recreate |bubble_manager_| and start observing any bubbles anchored to a
// child of |top_container_|.
void RecreateBubbleManager();
// Shrinks or expands the touch hit test by updating insets for the render
// window depending on if top_inset is positive or negative respectively.
// Used to ensure that touch events at the top of the screen go to the top
// container so a slide gesture can be generated when the content window is
// consuming all touch events sent to it.
void SetRenderWindowTopInsetsForTouch(int top_inset);
// Injected dependencies. Not owned.
Delegate* delegate_;
views::Widget* widget_;
views::View* top_container_;
// True if the window observers are enabled.
bool observers_enabled_;
// True when in immersive mode.
bool enabled_;
// State machine for the revealed/closed animations.
RevealState reveal_state_;
int revealed_lock_count_;
// The visibility of the miniature "tab indicators" in the main browser view
// when immersive mode is enabled and the top-of-window views are closed.
TabIndicatorVisibility tab_indicator_visibility_;
// Timer to track cursor being held at the top edge of the screen.
base::OneShotTimer<ImmersiveModeController> top_edge_hover_timer_;
// The cursor x position in screen coordinates when the cursor first hit the
// top edge of the screen.
int mouse_x_when_hit_top_in_screen_;
// Tracks if the controller has seen a ET_GESTURE_SCROLL_BEGIN, without the
// following events.
bool gesture_begun_;
// The current visible bounds of the find bar, in screen coordinates. This is
// an empty rect if the find bar is not visible.
gfx::Rect find_bar_visible_bounds_in_screen_;
// Lock which keeps the top-of-window views revealed based on the current
// mouse state and the current touch state. Acquiring the lock is used to
// trigger a reveal when the user moves the mouse to the top of the screen
// and when the user does a SWIPE_OPEN edge gesture.
scoped_ptr<ImmersiveRevealedLock> located_event_revealed_lock_;
// Lock which keeps the top-of-window views revealed based on the focused view
// and the active widget. Acquiring the lock never triggers a reveal because
// a view is not focusable till a reveal has made it visible.
scoped_ptr<ImmersiveRevealedLock> focus_revealed_lock_;
// Native window for the browser.
aura::Window* native_window_;
// The animation which controls sliding the top-of-window views in and out.
scoped_ptr<gfx::SlideAnimation> animation_;
// Whether the animations are disabled for testing.
bool animations_disabled_for_test_;
// Manages bubbles which are anchored to a child of |top_container_|.
class BubbleManager;
scoped_ptr<BubbleManager> bubble_manager_;
content::NotificationRegistrar registrar_;
base::WeakPtrFactory<ImmersiveModeControllerAsh> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ImmersiveModeControllerAsh);
};
#endif // CHROME_BROWSER_UI_VIEWS_FRAME_IMMERSIVE_MODE_CONTROLLER_ASH_H_