| Index: ash/wm/shelf_layout_manager.cc
|
| diff --git a/ash/wm/shelf_layout_manager.cc b/ash/wm/shelf_layout_manager.cc
|
| index dabe35b8780827b0622ae4a8a8cf9fd3fee7de78..fb16d3ec4cb55333d347cdceb3641df43be2da35 100644
|
| --- a/ash/wm/shelf_layout_manager.cc
|
| +++ b/ash/wm/shelf_layout_manager.cc
|
| @@ -9,6 +9,8 @@
|
| #include "ash/shell.h"
|
| #include "ash/system/tray/system_tray.h"
|
| #include "base/auto_reset.h"
|
| +#include "ui/aura/event.h"
|
| +#include "ui/aura/event_filter.h"
|
| #include "ui/aura/root_window.h"
|
| #include "ui/gfx/compositor/layer.h"
|
| #include "ui/gfx/compositor/layer_animation_observer.h"
|
| @@ -21,8 +23,8 @@ namespace internal {
|
|
|
| namespace {
|
|
|
| -// Height of the shelf when auto-hidden.
|
| -const int kAutoHideHeight = 2;
|
| +// Delay before showing/hiding the launcher after the mouse enters the launcher.
|
| +const int kAutoHideDelayMS = 300;
|
|
|
| ui::Layer* GetLayer(views::Widget* widget) {
|
| return widget->GetNativeView()->layer();
|
| @@ -33,6 +35,69 @@ ui::Layer* GetLayer(views::Widget* widget) {
|
| // static
|
| const int ShelfLayoutManager::kWorkspaceAreaBottomInset = 2;
|
|
|
| +// static
|
| +const int ShelfLayoutManager::kAutoHideHeight = 2;
|
| +
|
| +// Notifies ShelfLayoutManager any time the mouse moves.
|
| +class ShelfLayoutManager::AutoHideEventFilter : public aura::EventFilter {
|
| + public:
|
| + explicit AutoHideEventFilter(ShelfLayoutManager* shelf);
|
| + virtual ~AutoHideEventFilter();
|
| +
|
| + // Overridden from aura::EventFilter:
|
| + virtual bool PreHandleKeyEvent(aura::Window* target,
|
| + aura::KeyEvent* event) OVERRIDE;
|
| + virtual bool PreHandleMouseEvent(aura::Window* target,
|
| + aura::MouseEvent* event) OVERRIDE;
|
| + virtual ui::TouchStatus PreHandleTouchEvent(aura::Window* target,
|
| + aura::TouchEvent* event) OVERRIDE;
|
| + virtual ui::GestureStatus PreHandleGestureEvent(
|
| + aura::Window* target,
|
| + aura::GestureEvent* event) OVERRIDE;
|
| +
|
| + private:
|
| + ShelfLayoutManager* shelf_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(AutoHideEventFilter);
|
| +};
|
| +
|
| +ShelfLayoutManager::AutoHideEventFilter::AutoHideEventFilter(
|
| + ShelfLayoutManager* shelf)
|
| + : shelf_(shelf) {
|
| + Shell::GetInstance()->AddRootWindowEventFilter(this);
|
| +}
|
| +
|
| +ShelfLayoutManager::AutoHideEventFilter::~AutoHideEventFilter() {
|
| + Shell::GetInstance()->RemoveRootWindowEventFilter(this);
|
| +}
|
| +
|
| +bool ShelfLayoutManager::AutoHideEventFilter::PreHandleKeyEvent(
|
| + aura::Window* target,
|
| + aura::KeyEvent* event) {
|
| + return false; // Always let the event propagate.
|
| +}
|
| +
|
| +bool ShelfLayoutManager::AutoHideEventFilter::PreHandleMouseEvent(
|
| + aura::Window* target,
|
| + aura::MouseEvent* event) {
|
| + if (event->type() == ui::ET_MOUSE_MOVED)
|
| + shelf_->UpdateAutoHideState();
|
| + return false; // Not handled.
|
| +}
|
| +
|
| +ui::TouchStatus ShelfLayoutManager::AutoHideEventFilter::PreHandleTouchEvent(
|
| + aura::Window* target,
|
| + aura::TouchEvent* event) {
|
| + return ui::TOUCH_STATUS_UNKNOWN; // Not handled.
|
| +}
|
| +
|
| +ui::GestureStatus
|
| +ShelfLayoutManager::AutoHideEventFilter::PreHandleGestureEvent(
|
| + aura::Window* target,
|
| + aura::GestureEvent* event) {
|
| + return ui::GESTURE_STATUS_UNKNOWN; // Not handled.
|
| +}
|
| +
|
| ////////////////////////////////////////////////////////////////////////////////
|
| // ShelfLayoutManager, public:
|
|
|
| @@ -41,9 +106,7 @@ ShelfLayoutManager::ShelfLayoutManager(views::Widget* status)
|
| shelf_height_(status->GetWindowScreenBounds().height()),
|
| launcher_(NULL),
|
| status_(status),
|
| - window_overlaps_shelf_(false),
|
| - root_window_(NULL) {
|
| - root_window_ = status->GetNativeView()->GetRootWindow();
|
| + window_overlaps_shelf_(false) {
|
| }
|
|
|
| ShelfLayoutManager::~ShelfLayoutManager() {
|
| @@ -95,15 +158,25 @@ void ShelfLayoutManager::LayoutShelf() {
|
| target_bounds.work_area_insets);
|
| }
|
|
|
| -void ShelfLayoutManager::SetState(VisibilityState visibility_state,
|
| - AutoHideState auto_hide_state) {
|
| +void ShelfLayoutManager::SetState(VisibilityState visibility_state) {
|
| State state;
|
| state.visibility_state = visibility_state;
|
| - state.auto_hide_state = auto_hide_state;
|
| + state.auto_hide_state = CalculateAutoHideState(visibility_state);
|
|
|
| if (state_.Equals(state))
|
| return; // Nothing changed.
|
|
|
| + if (state.visibility_state == AUTO_HIDE) {
|
| + // When state is AUTO_HIDE we need to track when the mouse is over the
|
| + // launcher to unhide the shelf. AutoHideEventFilter does that for us.
|
| + if (!event_filter_.get())
|
| + event_filter_.reset(new AutoHideEventFilter(this));
|
| + } else {
|
| + event_filter_.reset(NULL);
|
| + }
|
| +
|
| + auto_hide_timer_.Stop();
|
| +
|
| // Animating the background when transitioning from auto-hide & hidden to
|
| // visibile is janking. Update the background immediately in this case.
|
| internal::BackgroundAnimator::ChangeType change_type =
|
| @@ -138,6 +211,21 @@ void ShelfLayoutManager::SetState(VisibilityState visibility_state,
|
| UpdateShelfBackground(change_type);
|
| }
|
|
|
| +void ShelfLayoutManager::UpdateAutoHideState() {
|
| + if (CalculateAutoHideState(state_.visibility_state) !=
|
| + state_.auto_hide_state) {
|
| + // Don't change state immediately. Instead delay for a bit.
|
| + if (!auto_hide_timer_.IsRunning()) {
|
| + auto_hide_timer_.Start(
|
| + FROM_HERE,
|
| + base::TimeDelta::FromMilliseconds(kAutoHideDelayMS),
|
| + this, &ShelfLayoutManager::UpdateAutoHideStateNow);
|
| + }
|
| + } else {
|
| + auto_hide_timer_.Stop();
|
| + }
|
| +}
|
| +
|
| void ShelfLayoutManager::SetWindowOverlapsShelf(bool value) {
|
| window_overlaps_shelf_ = value;
|
| UpdateShelfBackground(internal::BackgroundAnimator::CHANGE_ANIMATE);
|
| @@ -179,7 +267,8 @@ void ShelfLayoutManager::StopAnimating() {
|
| void ShelfLayoutManager::CalculateTargetBounds(
|
| const State& state,
|
| TargetBounds* target_bounds) const {
|
| - const gfx::Rect& available_bounds(root_window_->bounds());
|
| + const gfx::Rect& available_bounds(
|
| + status_->GetNativeView()->GetRootWindow()->bounds());
|
| int y = available_bounds.bottom();
|
| int shelf_height = 0;
|
| int work_area_delta = 0;
|
| @@ -228,5 +317,25 @@ bool ShelfLayoutManager::GetLauncherPaintsBackground() const {
|
| return window_overlaps_shelf_ || state_.visibility_state == AUTO_HIDE;
|
| }
|
|
|
| +void ShelfLayoutManager::UpdateAutoHideStateNow() {
|
| + SetState(state_.visibility_state);
|
| +}
|
| +
|
| +ShelfLayoutManager::AutoHideState ShelfLayoutManager::CalculateAutoHideState(
|
| + VisibilityState visibility_state) const {
|
| + if (visibility_state != AUTO_HIDE || !launcher_widget())
|
| + return AUTO_HIDE_HIDDEN;
|
| +
|
| + Shell* shell = Shell::GetInstance();
|
| + if (shell->tray()->showing_bubble())
|
| + return AUTO_HIDE_SHOWN; // Always show if a bubble is open from the shelf.
|
| +
|
| + aura::RootWindow* root = launcher_widget()->GetNativeView()->GetRootWindow();
|
| + bool mouse_over_launcher =
|
| + launcher_widget()->GetWindowScreenBounds().Contains(
|
| + root->last_mouse_location());
|
| + return mouse_over_launcher ? AUTO_HIDE_SHOWN : AUTO_HIDE_HIDDEN;
|
| +}
|
| +
|
| } // namespace internal
|
| } // namespace ash
|
|
|