Index: ash/common/shelf/shelf_layout_manager.cc |
diff --git a/ash/common/shelf/shelf_layout_manager.cc b/ash/common/shelf/shelf_layout_manager.cc |
deleted file mode 100644 |
index 5849bb7f85a8327a9c5e36fa3b561d118bab387c..0000000000000000000000000000000000000000 |
--- a/ash/common/shelf/shelf_layout_manager.cc |
+++ /dev/null |
@@ -1,1143 +0,0 @@ |
-// Copyright (c) 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. |
- |
-#include "ash/common/shelf/shelf_layout_manager.h" |
- |
-#include <algorithm> |
-#include <cmath> |
-#include <vector> |
- |
-#include "ash/animation/animation_change_type.h" |
-#include "ash/common/session/session_controller.h" |
-#include "ash/common/session/session_state_delegate.h" |
-#include "ash/common/shelf/shelf_constants.h" |
-#include "ash/common/shelf/shelf_layout_manager_observer.h" |
-#include "ash/common/shelf/shelf_widget.h" |
-#include "ash/common/shelf/wm_shelf.h" |
-#include "ash/common/wm/fullscreen_window_finder.h" |
-#include "ash/common/wm/mru_window_tracker.h" |
-#include "ash/common/wm/window_state.h" |
-#include "ash/common/wm/wm_screen_util.h" |
-#include "ash/common/wm_shell.h" |
-#include "ash/common/wm_window.h" |
-#include "ash/public/cpp/shell_window_ids.h" |
-#include "ash/root_window_controller.h" |
-#include "ash/system/status_area_widget.h" |
-#include "base/auto_reset.h" |
-#include "base/command_line.h" |
-#include "base/i18n/rtl.h" |
-#include "ui/base/ui_base_switches.h" |
-#include "ui/compositor/layer.h" |
-#include "ui/compositor/layer_animation_observer.h" |
-#include "ui/compositor/layer_animator.h" |
-#include "ui/compositor/scoped_layer_animation_settings.h" |
-#include "ui/display/display.h" |
-#include "ui/display/screen.h" |
-#include "ui/events/event.h" |
-#include "ui/events/event_handler.h" |
-#include "ui/keyboard/keyboard_controller.h" |
-#include "ui/keyboard/keyboard_util.h" |
-#include "ui/views/border.h" |
-#include "ui/views/widget/widget.h" |
- |
-namespace ash { |
-namespace { |
- |
-// Delay before showing the shelf. This is after the mouse stops moving. |
-const int kAutoHideDelayMS = 200; |
- |
-// Duration of the animation to show or hide the shelf. |
-const int kAnimationDurationMS = 200; |
- |
-// To avoid hiding the shelf when the mouse transitions from a message bubble |
-// into the shelf, the hit test area is enlarged by this amount of pixels to |
-// keep the shelf from hiding. |
-const int kNotificationBubbleGapHeight = 6; |
- |
-// The maximum size of the region on the display opposing the shelf managed by |
-// this ShelfLayoutManager which can trigger showing the shelf. |
-// For instance: |
-// - Primary display is left of secondary display. |
-// - Shelf is left aligned |
-// - This ShelfLayoutManager manages the shelf for the secondary display. |
-// |kMaxAutoHideShowShelfRegionSize| refers to the maximum size of the region |
-// from the right edge of the primary display which can trigger showing the |
-// auto hidden shelf. The region is used to make it easier to trigger showing |
-// the auto hidden shelf when the shelf is on the boundary between displays. |
-const int kMaxAutoHideShowShelfRegionSize = 10; |
- |
-ui::Layer* GetLayer(views::Widget* widget) { |
- return widget->GetNativeView()->layer(); |
-} |
- |
-// Returns true if the window is in the app list window container. |
-bool IsAppListWindow(WmWindow* window) { |
- return window->GetParent() && |
- window->GetParent()->GetShellWindowId() == |
- kShellWindowId_AppListContainer; |
-} |
- |
-} // namespace |
- |
-// ShelfLayoutManager::UpdateShelfObserver ------------------------------------- |
- |
-// UpdateShelfObserver is used to delay updating the background until the |
-// animation completes. |
-class ShelfLayoutManager::UpdateShelfObserver |
- : public ui::ImplicitAnimationObserver { |
- public: |
- explicit UpdateShelfObserver(ShelfLayoutManager* shelf) : shelf_(shelf) { |
- shelf_->update_shelf_observer_ = this; |
- } |
- |
- void Detach() { shelf_ = NULL; } |
- |
- void OnImplicitAnimationsCompleted() override { |
- if (shelf_) |
- shelf_->MaybeUpdateShelfBackground(AnimationChangeType::ANIMATE); |
- delete this; |
- } |
- |
- private: |
- ~UpdateShelfObserver() override { |
- if (shelf_) |
- shelf_->update_shelf_observer_ = NULL; |
- } |
- |
- // Shelf we're in. NULL if deleted before we're deleted. |
- ShelfLayoutManager* shelf_; |
- |
- DISALLOW_COPY_AND_ASSIGN(UpdateShelfObserver); |
-}; |
- |
-ShelfLayoutManager::State::State() |
- : visibility_state(SHELF_VISIBLE), |
- auto_hide_state(SHELF_AUTO_HIDE_HIDDEN), |
- window_state(wm::WORKSPACE_WINDOW_STATE_DEFAULT), |
- pre_lock_screen_animation_active(false), |
- session_state(session_manager::SessionState::UNKNOWN) {} |
- |
-bool ShelfLayoutManager::State::IsAddingSecondaryUser() const { |
- return session_state == session_manager::SessionState::LOGIN_SECONDARY; |
-} |
- |
-bool ShelfLayoutManager::State::IsScreenLocked() const { |
- return session_state == session_manager::SessionState::LOCKED; |
-} |
- |
-bool ShelfLayoutManager::State::Equals(const State& other) const { |
- return other.visibility_state == visibility_state && |
- (visibility_state != SHELF_AUTO_HIDE || |
- other.auto_hide_state == auto_hide_state) && |
- other.window_state == window_state && |
- other.pre_lock_screen_animation_active == |
- pre_lock_screen_animation_active && |
- other.session_state == session_state; |
-} |
- |
-// ShelfLayoutManager ---------------------------------------------------------- |
- |
-ShelfLayoutManager::ShelfLayoutManager(ShelfWidget* shelf_widget, |
- WmShelf* wm_shelf) |
- : updating_bounds_(false), |
- shelf_widget_(shelf_widget), |
- wm_shelf_(wm_shelf), |
- window_overlaps_shelf_(false), |
- mouse_over_shelf_when_auto_hide_timer_started_(false), |
- gesture_drag_status_(GESTURE_DRAG_NONE), |
- gesture_drag_amount_(0.f), |
- gesture_drag_auto_hide_state_(SHELF_AUTO_HIDE_SHOWN), |
- update_shelf_observer_(NULL), |
- chromevox_panel_height_(0), |
- duration_override_in_ms_(0), |
- shelf_background_type_(SHELF_BACKGROUND_OVERLAP) { |
- DCHECK(shelf_widget_); |
- DCHECK(wm_shelf_); |
- WmShell::Get()->AddShellObserver(this); |
- WmShell::Get()->AddLockStateObserver(this); |
- WmShell::Get()->AddActivationObserver(this); |
- WmShell::Get()->session_controller()->AddSessionStateObserver(this); |
- state_.session_state = |
- WmShell::Get()->session_controller()->GetSessionState(); |
-} |
- |
-ShelfLayoutManager::~ShelfLayoutManager() { |
- if (update_shelf_observer_) |
- update_shelf_observer_->Detach(); |
- |
- for (auto& observer : observers_) |
- observer.WillDeleteShelfLayoutManager(); |
- WmShell::Get()->RemoveShellObserver(this); |
- WmShell::Get()->RemoveLockStateObserver(this); |
- WmShell::Get()->session_controller()->RemoveSessionStateObserver(this); |
-} |
- |
-void ShelfLayoutManager::PrepareForShutdown() { |
- in_shutdown_ = true; |
- // Stop observing changes to avoid updating a partially destructed shelf. |
- WmShell::Get()->RemoveActivationObserver(this); |
-} |
- |
-bool ShelfLayoutManager::IsVisible() const { |
- // status_area_widget() may be NULL during the shutdown. |
- return shelf_widget_->status_area_widget() && |
- shelf_widget_->status_area_widget()->IsVisible() && |
- (state_.visibility_state == SHELF_VISIBLE || |
- (state_.visibility_state == SHELF_AUTO_HIDE && |
- state_.auto_hide_state == SHELF_AUTO_HIDE_SHOWN)); |
-} |
- |
-gfx::Rect ShelfLayoutManager::GetIdealBounds() { |
- const int shelf_size = GetShelfConstant(SHELF_SIZE); |
- WmWindow* shelf_window = WmWindow::Get(shelf_widget_->GetNativeWindow()); |
- gfx::Rect rect(wm::GetDisplayBoundsInParent(shelf_window)); |
- return SelectValueForShelfAlignment( |
- gfx::Rect(rect.x(), rect.bottom() - shelf_size, rect.width(), shelf_size), |
- gfx::Rect(rect.x(), rect.y(), shelf_size, rect.height()), |
- gfx::Rect(rect.right() - shelf_size, rect.y(), shelf_size, |
- rect.height())); |
-} |
- |
-gfx::Size ShelfLayoutManager::GetPreferredSize() { |
- TargetBounds target_bounds; |
- CalculateTargetBounds(state_, &target_bounds); |
- return target_bounds.shelf_bounds_in_root.size(); |
-} |
- |
-void ShelfLayoutManager::LayoutShelfAndUpdateBounds(bool change_work_area) { |
- TargetBounds target_bounds; |
- CalculateTargetBounds(state_, &target_bounds); |
- UpdateBoundsAndOpacity(target_bounds, false, change_work_area, NULL); |
- |
- // Update insets in ShelfWindowTargeter when shelf bounds change. |
- for (auto& observer : observers_) |
- observer.WillChangeVisibilityState(visibility_state()); |
-} |
- |
-void ShelfLayoutManager::LayoutShelf() { |
- LayoutShelfAndUpdateBounds(true); |
-} |
- |
-ShelfVisibilityState ShelfLayoutManager::CalculateShelfVisibility() { |
- switch (wm_shelf_->auto_hide_behavior()) { |
- case SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS: |
- return SHELF_AUTO_HIDE; |
- case SHELF_AUTO_HIDE_BEHAVIOR_NEVER: |
- return SHELF_VISIBLE; |
- case SHELF_AUTO_HIDE_ALWAYS_HIDDEN: |
- return SHELF_HIDDEN; |
- } |
- return SHELF_VISIBLE; |
-} |
- |
-void ShelfLayoutManager::UpdateVisibilityState() { |
- // Bail out early before the shelf is initialized or after it is destroyed. |
- WmWindow* shelf_window = WmWindow::Get(shelf_widget_->GetNativeWindow()); |
- if (in_shutdown_ || !wm_shelf_->IsShelfInitialized() || !shelf_window) |
- return; |
- if (state_.IsScreenLocked() || state_.IsAddingSecondaryUser()) { |
- SetState(SHELF_VISIBLE); |
- } else if (WmShell::Get()->IsPinned()) { |
- SetState(SHELF_HIDDEN); |
- } else { |
- // TODO(zelidrag): Verify shelf drag animation still shows on the device |
- // when we are in SHELF_AUTO_HIDE_ALWAYS_HIDDEN. |
- wm::WorkspaceWindowState window_state( |
- shelf_window->GetRootWindowController()->GetWorkspaceWindowState()); |
- switch (window_state) { |
- case wm::WORKSPACE_WINDOW_STATE_FULL_SCREEN: { |
- if (IsShelfHiddenForFullscreen()) { |
- SetState(SHELF_HIDDEN); |
- } else { |
- // The shelf is sometimes not hidden when in immersive fullscreen. |
- // Force the shelf to be auto hidden in this case. |
- SetState(SHELF_AUTO_HIDE); |
- } |
- break; |
- } |
- case wm::WORKSPACE_WINDOW_STATE_MAXIMIZED: |
- SetState(CalculateShelfVisibility()); |
- break; |
- |
- case wm::WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF: |
- case wm::WORKSPACE_WINDOW_STATE_DEFAULT: |
- SetState(CalculateShelfVisibility()); |
- SetWindowOverlapsShelf( |
- window_state == wm::WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF); |
- break; |
- } |
- } |
-} |
- |
-void ShelfLayoutManager::UpdateAutoHideState() { |
- ShelfAutoHideState auto_hide_state = |
- CalculateAutoHideState(state_.visibility_state); |
- if (auto_hide_state != state_.auto_hide_state) { |
- if (auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) { |
- // Hides happen immediately. |
- SetState(state_.visibility_state); |
- } else { |
- if (!auto_hide_timer_.IsRunning()) { |
- mouse_over_shelf_when_auto_hide_timer_started_ = |
- shelf_widget_->GetWindowBoundsInScreen().Contains( |
- display::Screen::GetScreen()->GetCursorScreenPoint()); |
- } |
- auto_hide_timer_.Start( |
- FROM_HERE, base::TimeDelta::FromMilliseconds(kAutoHideDelayMS), this, |
- &ShelfLayoutManager::UpdateAutoHideStateNow); |
- } |
- } else { |
- StopAutoHideTimer(); |
- } |
-} |
- |
-void ShelfLayoutManager::UpdateAutoHideForMouseEvent(ui::MouseEvent* event, |
- WmWindow* target) { |
- // This also checks IsShelfWindow() to make sure we don't attempt to hide the |
- // shelf if the mouse down occurs on the shelf. |
- in_mouse_drag_ = (event->type() == ui::ET_MOUSE_DRAGGED || |
- (in_mouse_drag_ && event->type() != ui::ET_MOUSE_RELEASED && |
- event->type() != ui::ET_MOUSE_CAPTURE_CHANGED)) && |
- !IsShelfWindow(target); |
- |
- // Don't update during shutdown because synthetic mouse events (e.g. mouse |
- // exit) may be generated during status area widget teardown. |
- if (visibility_state() != SHELF_AUTO_HIDE || in_shutdown_) |
- return; |
- |
- if (event->type() == ui::ET_MOUSE_MOVED || |
- event->type() == ui::ET_MOUSE_ENTERED || |
- event->type() == ui::ET_MOUSE_EXITED) { |
- UpdateAutoHideState(); |
- } |
-} |
- |
-void ShelfLayoutManager::UpdateAutoHideForGestureEvent(ui::GestureEvent* event, |
- WmWindow* target) { |
- if (visibility_state() != SHELF_AUTO_HIDE || in_shutdown_) |
- return; |
- |
- if (IsShelfWindow(target) && ProcessGestureEvent(*event)) |
- event->StopPropagation(); |
-} |
- |
-void ShelfLayoutManager::SetWindowOverlapsShelf(bool value) { |
- window_overlaps_shelf_ = value; |
- MaybeUpdateShelfBackground(AnimationChangeType::ANIMATE); |
-} |
- |
-void ShelfLayoutManager::AddObserver(ShelfLayoutManagerObserver* observer) { |
- observers_.AddObserver(observer); |
-} |
- |
-void ShelfLayoutManager::RemoveObserver(ShelfLayoutManagerObserver* observer) { |
- observers_.RemoveObserver(observer); |
-} |
- |
-bool ShelfLayoutManager::ProcessGestureEvent(const ui::GestureEvent& event) { |
- // The gestures are disabled in the lock/login screen. |
- SessionStateDelegate* delegate = WmShell::Get()->GetSessionStateDelegate(); |
- if (!delegate->NumberOfLoggedInUsers() || delegate->IsScreenLocked()) |
- return false; |
- |
- if (IsShelfHiddenForFullscreen()) |
- return false; |
- |
- if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) { |
- StartGestureDrag(event); |
- return true; |
- } |
- |
- if (gesture_drag_status_ != GESTURE_DRAG_IN_PROGRESS) |
- return false; |
- |
- if (event.type() == ui::ET_GESTURE_SCROLL_UPDATE) { |
- UpdateGestureDrag(event); |
- return true; |
- } |
- |
- if (event.type() == ui::ET_GESTURE_SCROLL_END || |
- event.type() == ui::ET_SCROLL_FLING_START) { |
- CompleteGestureDrag(event); |
- return true; |
- } |
- |
- // Unexpected event. Reset the state and let the event fall through. |
- CancelGestureDrag(); |
- return false; |
-} |
- |
-void ShelfLayoutManager::SetAnimationDurationOverride( |
- int duration_override_in_ms) { |
- duration_override_in_ms_ = duration_override_in_ms; |
-} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// ShelfLayoutManager, wm::WmSnapToPixelLayoutManager implementation: |
- |
-void ShelfLayoutManager::OnWindowResized() { |
- LayoutShelf(); |
-} |
- |
-void ShelfLayoutManager::SetChildBounds(WmWindow* child, |
- const gfx::Rect& requested_bounds) { |
- wm::WmSnapToPixelLayoutManager::SetChildBounds(child, requested_bounds); |
- // We may contain other widgets (such as frame maximize bubble) but they don't |
- // effect the layout in anyway. |
- if (!updating_bounds_ && |
- ((WmWindow::Get(shelf_widget_->GetNativeWindow()) == child) || |
- (WmWindow::Get(shelf_widget_->status_area_widget()->GetNativeWindow()) == |
- child))) { |
- LayoutShelf(); |
- } |
-} |
- |
-void ShelfLayoutManager::OnShelfAutoHideBehaviorChanged(WmWindow* root_window) { |
- UpdateVisibilityState(); |
-} |
- |
-void ShelfLayoutManager::OnPinnedStateChanged(WmWindow* pinned_window) { |
- // Shelf needs to be hidden on entering to pinned mode, or restored |
- // on exiting from pinned mode. |
- UpdateVisibilityState(); |
-} |
- |
-void ShelfLayoutManager::OnWindowActivated(WmWindow* gained_active, |
- WmWindow* lost_active) { |
- UpdateAutoHideStateNow(); |
-} |
- |
-void ShelfLayoutManager::OnKeyboardBoundsChanging(const gfx::Rect& new_bounds) { |
- bool keyboard_is_about_to_hide = false; |
- if (new_bounds.IsEmpty() && !keyboard_bounds_.IsEmpty()) |
- keyboard_is_about_to_hide = true; |
- // If new window behavior flag enabled and in non-sticky mode, do not change |
- // the work area. |
- bool change_work_area = |
- (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
- ::switches::kUseNewVirtualKeyboardBehavior) || |
- keyboard::KeyboardController::GetInstance()->keyboard_locked()); |
- |
- keyboard_bounds_ = new_bounds; |
- LayoutShelfAndUpdateBounds(change_work_area); |
- |
- // On login screen if keyboard has been just hidden, update bounds just once |
- // but ignore target_bounds.work_area_insets since shelf overlaps with login |
- // window. |
- if (WmShell::Get()->GetSessionStateDelegate()->IsUserSessionBlocked() && |
- keyboard_is_about_to_hide) { |
- WmWindow* window = WmWindow::Get(shelf_widget_->GetNativeWindow()); |
- WmShell::Get()->SetDisplayWorkAreaInsets(window, gfx::Insets()); |
- } |
-} |
- |
-void ShelfLayoutManager::OnKeyboardClosed() {} |
- |
-ShelfBackgroundType ShelfLayoutManager::GetShelfBackgroundType() const { |
- if (state_.pre_lock_screen_animation_active) |
- return SHELF_BACKGROUND_DEFAULT; |
- |
- // Handle all non active screen states, including OOBE and pre-login. |
- if (state_.session_state != session_manager::SessionState::ACTIVE) |
- return SHELF_BACKGROUND_OVERLAP; |
- |
- if (state_.visibility_state != SHELF_AUTO_HIDE && |
- state_.window_state == wm::WORKSPACE_WINDOW_STATE_MAXIMIZED) { |
- return SHELF_BACKGROUND_MAXIMIZED; |
- } |
- |
- if (gesture_drag_status_ == GESTURE_DRAG_IN_PROGRESS || |
- window_overlaps_shelf_ || state_.visibility_state == SHELF_AUTO_HIDE) { |
- return SHELF_BACKGROUND_OVERLAP; |
- } |
- |
- return SHELF_BACKGROUND_DEFAULT; |
-} |
- |
-void ShelfLayoutManager::SetChromeVoxPanelHeight(int height) { |
- chromevox_panel_height_ = height; |
- LayoutShelf(); |
-} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// ShelfLayoutManager, private: |
- |
-ShelfLayoutManager::TargetBounds::TargetBounds() |
- : opacity(0.0f), status_opacity(0.0f) {} |
- |
-ShelfLayoutManager::TargetBounds::~TargetBounds() {} |
- |
-void ShelfLayoutManager::SetState(ShelfVisibilityState visibility_state) { |
- State state; |
- state.visibility_state = visibility_state; |
- state.auto_hide_state = CalculateAutoHideState(visibility_state); |
- |
- WmWindow* shelf_window = WmWindow::Get(shelf_widget_->GetNativeWindow()); |
- RootWindowController* controller = shelf_window->GetRootWindowController(); |
- state.window_state = controller ? controller->GetWorkspaceWindowState() |
- : wm::WORKSPACE_WINDOW_STATE_DEFAULT; |
- // Preserve the log in screen states. |
- state.session_state = state_.session_state; |
- state.pre_lock_screen_animation_active = |
- state_.pre_lock_screen_animation_active; |
- |
- // Force an update because gesture drags affect the shelf bounds and we |
- // should animate back to the normal bounds at the end of a gesture. |
- bool force_update = |
- (gesture_drag_status_ == GESTURE_DRAG_CANCEL_IN_PROGRESS || |
- gesture_drag_status_ == GESTURE_DRAG_COMPLETE_IN_PROGRESS); |
- |
- if (!force_update && state_.Equals(state)) |
- return; // Nothing changed. |
- |
- for (auto& observer : observers_) |
- observer.WillChangeVisibilityState(visibility_state); |
- |
- StopAutoHideTimer(); |
- |
- State old_state = state_; |
- state_ = state; |
- |
- AnimationChangeType change_type = AnimationChangeType::ANIMATE; |
- bool delay_background_change = false; |
- |
- // Do not animate the background when: |
- // - Going from a hidden / auto hidden shelf in fullscreen to a visible shelf |
- // in maximized mode. |
- // - Going from an auto hidden shelf in maximized mode to a visible shelf in |
- // maximized mode. |
- if (state.visibility_state == SHELF_VISIBLE && |
- state.window_state == wm::WORKSPACE_WINDOW_STATE_MAXIMIZED && |
- old_state.visibility_state != SHELF_VISIBLE) { |
- change_type = AnimationChangeType::IMMEDIATE; |
- } else { |
- // Delay the animation when the shelf was hidden, and has just been made |
- // visible (e.g. using a gesture-drag). |
- if (state.visibility_state == SHELF_VISIBLE && |
- old_state.visibility_state == SHELF_AUTO_HIDE && |
- old_state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) { |
- delay_background_change = true; |
- } |
- } |
- |
- if (delay_background_change) { |
- if (update_shelf_observer_) |
- update_shelf_observer_->Detach(); |
- // |update_shelf_observer_| deletes itself when the animation is done. |
- update_shelf_observer_ = new UpdateShelfObserver(this); |
- } else { |
- MaybeUpdateShelfBackground(change_type); |
- } |
- |
- TargetBounds target_bounds; |
- CalculateTargetBounds(state_, &target_bounds); |
- UpdateBoundsAndOpacity( |
- target_bounds, true /* animate */, true /* change_work_area */, |
- delay_background_change ? update_shelf_observer_ : NULL); |
- |
- // OnAutoHideStateChanged Should be emitted when: |
- // - firstly state changed to auto-hide from other state |
- // - or, auto_hide_state has changed |
- if ((old_state.visibility_state != state_.visibility_state && |
- state_.visibility_state == SHELF_AUTO_HIDE) || |
- old_state.auto_hide_state != state_.auto_hide_state) { |
- for (auto& observer : observers_) |
- observer.OnAutoHideStateChanged(state_.auto_hide_state); |
- } |
-} |
- |
-void ShelfLayoutManager::UpdateBoundsAndOpacity( |
- const TargetBounds& target_bounds, |
- bool animate, |
- bool change_work_area, |
- ui::ImplicitAnimationObserver* observer) { |
- base::AutoReset<bool> auto_reset_updating_bounds(&updating_bounds_, true); |
- { |
- ui::ScopedLayerAnimationSettings shelf_animation_setter( |
- GetLayer(shelf_widget_)->GetAnimator()); |
- ui::ScopedLayerAnimationSettings status_animation_setter( |
- GetLayer(shelf_widget_->status_area_widget())->GetAnimator()); |
- if (animate) { |
- int duration = duration_override_in_ms_ ? duration_override_in_ms_ |
- : kAnimationDurationMS; |
- shelf_animation_setter.SetTransitionDuration( |
- base::TimeDelta::FromMilliseconds(duration)); |
- shelf_animation_setter.SetTweenType(gfx::Tween::EASE_OUT); |
- shelf_animation_setter.SetPreemptionStrategy( |
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
- status_animation_setter.SetTransitionDuration( |
- base::TimeDelta::FromMilliseconds(duration)); |
- status_animation_setter.SetTweenType(gfx::Tween::EASE_OUT); |
- status_animation_setter.SetPreemptionStrategy( |
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
- } else { |
- StopAnimating(); |
- shelf_animation_setter.SetTransitionDuration(base::TimeDelta()); |
- status_animation_setter.SetTransitionDuration(base::TimeDelta()); |
- } |
- if (observer) |
- status_animation_setter.AddObserver(observer); |
- |
- GetLayer(shelf_widget_)->SetOpacity(target_bounds.opacity); |
- WmWindow* shelf_window = WmWindow::Get(shelf_widget_->GetNativeWindow()); |
- shelf_widget_->SetBounds(shelf_window->GetParent()->ConvertRectToScreen( |
- target_bounds.shelf_bounds_in_root)); |
- |
- GetLayer(shelf_widget_->status_area_widget()) |
- ->SetOpacity(target_bounds.status_opacity); |
- |
- // Having a window which is visible but does not have an opacity is an |
- // illegal state. We therefore hide the shelf here if required. |
- if (!target_bounds.status_opacity) |
- shelf_widget_->status_area_widget()->Hide(); |
- // Setting visibility during an animation causes the visibility property to |
- // animate. Override the animation settings to immediately set the |
- // visibility property. Opacity will still animate. |
- |
- // TODO(harrym): Once status area widget is a child view of shelf |
- // this can be simplified. |
- gfx::Rect status_bounds = target_bounds.status_bounds_in_shelf; |
- status_bounds.Offset(target_bounds.shelf_bounds_in_root.OffsetFromOrigin()); |
- WmWindow* status_window = |
- WmWindow::Get(shelf_widget_->status_area_widget()->GetNativeWindow()); |
- shelf_widget_->status_area_widget()->SetBounds( |
- status_window->GetParent()->ConvertRectToScreen(status_bounds)); |
- |
- // For crbug.com/622431, when the shelf alignment is BOTTOM_LOCKED, we |
- // don't set display work area, as it is not real user-set alignment. |
- if (!state_.IsScreenLocked() && |
- wm_shelf_->GetAlignment() != SHELF_ALIGNMENT_BOTTOM_LOCKED && |
- change_work_area) { |
- gfx::Insets insets; |
- // If user session is blocked (login to new user session or add user to |
- // the existing session - multi-profile) then give 100% of work area only |
- // if keyboard is not shown. |
- if (!state_.IsAddingSecondaryUser() || !keyboard_bounds_.IsEmpty()) |
- insets = target_bounds.work_area_insets; |
- WmShell::Get()->SetDisplayWorkAreaInsets(shelf_window, insets); |
- } |
- } |
- |
- // Set an empty border to avoid the shelf view and status area overlapping. |
- // TODO(msw): Avoid setting bounds of views within the shelf widget here. |
- gfx::Rect shelf_bounds = gfx::Rect(target_bounds.shelf_bounds_in_root.size()); |
- shelf_widget_->GetContentsView()->SetBorder(views::CreateEmptyBorder( |
- shelf_bounds.InsetsFrom(target_bounds.shelf_bounds_in_shelf))); |
- shelf_widget_->GetContentsView()->Layout(); |
- |
- // Setting visibility during an animation causes the visibility property to |
- // animate. Set the visibility property without an animation. |
- if (target_bounds.status_opacity) |
- shelf_widget_->status_area_widget()->Show(); |
-} |
- |
-void ShelfLayoutManager::StopAnimating() { |
- GetLayer(shelf_widget_)->GetAnimator()->StopAnimating(); |
- GetLayer(shelf_widget_->status_area_widget())->GetAnimator()->StopAnimating(); |
-} |
- |
-void ShelfLayoutManager::CalculateTargetBounds(const State& state, |
- TargetBounds* target_bounds) { |
- int shelf_size = GetShelfConstant(SHELF_SIZE); |
- if (state.visibility_state == SHELF_AUTO_HIDE && |
- state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) { |
- // Auto-hidden shelf always starts with the default size. If a gesture-drag |
- // is in progress, then the call to UpdateTargetBoundsForGesture() below |
- // takes care of setting the height properly. |
- shelf_size = kShelfAutoHideSize; |
- } else if (state.visibility_state == SHELF_HIDDEN || |
- (!keyboard_bounds_.IsEmpty() && |
- !keyboard::IsKeyboardOverscrollEnabled())) { |
- shelf_size = 0; |
- } |
- |
- WmWindow* shelf_window = WmWindow::Get(shelf_widget_->GetNativeWindow()); |
- gfx::Rect available_bounds = wm::GetDisplayBoundsWithShelf(shelf_window); |
- available_bounds.Inset(0, chromevox_panel_height_, 0, 0); |
- int shelf_width = PrimaryAxisValue(available_bounds.width(), shelf_size); |
- int shelf_height = PrimaryAxisValue(shelf_size, available_bounds.height()); |
- int bottom_shelf_vertical_offset = available_bounds.bottom(); |
- if (keyboard_bounds_.IsEmpty()) |
- bottom_shelf_vertical_offset -= shelf_height; |
- else |
- bottom_shelf_vertical_offset -= keyboard_bounds_.height(); |
- |
- gfx::Point shelf_origin = SelectValueForShelfAlignment( |
- gfx::Point(available_bounds.x(), bottom_shelf_vertical_offset), |
- gfx::Point(available_bounds.x(), available_bounds.y()), |
- gfx::Point(available_bounds.right() - shelf_width, available_bounds.y())); |
- target_bounds->shelf_bounds_in_root = |
- gfx::Rect(shelf_origin.x(), shelf_origin.y(), shelf_width, shelf_height); |
- |
- gfx::Size status_size( |
- shelf_widget_->status_area_widget()->GetWindowBoundsInScreen().size()); |
- if (wm_shelf_->IsHorizontalAlignment()) |
- status_size.set_height(GetShelfConstant(SHELF_SIZE)); |
- else |
- status_size.set_width(GetShelfConstant(SHELF_SIZE)); |
- |
- gfx::Point status_origin = SelectValueForShelfAlignment( |
- gfx::Point(0, 0), gfx::Point(shelf_width - status_size.width(), |
- shelf_height - status_size.height()), |
- gfx::Point(0, shelf_height - status_size.height())); |
- if (wm_shelf_->IsHorizontalAlignment() && !base::i18n::IsRTL()) |
- status_origin.set_x(shelf_width - status_size.width()); |
- target_bounds->status_bounds_in_shelf = gfx::Rect(status_origin, status_size); |
- |
- target_bounds->work_area_insets = SelectValueForShelfAlignment( |
- gfx::Insets(0, 0, GetWorkAreaInsets(state, shelf_height), 0), |
- gfx::Insets(0, GetWorkAreaInsets(state, shelf_width), 0, 0), |
- gfx::Insets(0, 0, 0, GetWorkAreaInsets(state, shelf_width))); |
- |
- // TODO(varkha): The functionality of managing insets for display areas |
- // should probably be pushed to a separate component. This would simplify or |
- // remove entirely the dependency on keyboard and dock. |
- |
- if (!keyboard_bounds_.IsEmpty() && !keyboard::IsKeyboardOverscrollEnabled()) { |
- // Also push in the work area inset for the keyboard if it is visible. |
- gfx::Insets keyboard_insets(0, 0, keyboard_bounds_.height(), 0); |
- target_bounds->work_area_insets += keyboard_insets; |
- } |
- |
- // Also push in the work area inset for the dock if it is visible. |
- if (!dock_bounds_.IsEmpty()) { |
- gfx::Insets dock_insets( |
- 0, (dock_bounds_.x() > 0 ? 0 : dock_bounds_.width()), 0, |
- (dock_bounds_.x() > 0 ? dock_bounds_.width() : 0)); |
- target_bounds->work_area_insets += dock_insets; |
- } |
- |
- // Also push in the work area insets for the ChromeVox panel if it's visible. |
- if (chromevox_panel_height_) { |
- gfx::Insets chromevox_insets(chromevox_panel_height_, 0, 0, 0); |
- target_bounds->work_area_insets += chromevox_insets; |
- } |
- |
- target_bounds->opacity = ComputeTargetOpacity(state); |
- target_bounds->status_opacity = |
- (state.visibility_state == SHELF_AUTO_HIDE && |
- state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN && |
- gesture_drag_status_ != GESTURE_DRAG_IN_PROGRESS) |
- ? 0.0f |
- : target_bounds->opacity; |
- |
- if (gesture_drag_status_ == GESTURE_DRAG_IN_PROGRESS) |
- UpdateTargetBoundsForGesture(target_bounds); |
- |
- // This needs to happen after calling UpdateTargetBoundsForGesture(), because |
- // that can change the size of the shelf. |
- target_bounds->shelf_bounds_in_shelf = SelectValueForShelfAlignment( |
- gfx::Rect(0, 0, shelf_width - status_size.width(), |
- target_bounds->shelf_bounds_in_root.height()), |
- gfx::Rect(0, 0, target_bounds->shelf_bounds_in_root.width(), |
- shelf_height - status_size.height()), |
- gfx::Rect(0, 0, target_bounds->shelf_bounds_in_root.width(), |
- shelf_height - status_size.height())); |
- |
- available_bounds.Subtract(target_bounds->shelf_bounds_in_root); |
- available_bounds.Subtract(keyboard_bounds_); |
- |
- WmWindow* root = shelf_window->GetRootWindow(); |
- user_work_area_bounds_ = root->ConvertRectToScreen(available_bounds); |
-} |
- |
-void ShelfLayoutManager::UpdateTargetBoundsForGesture( |
- TargetBounds* target_bounds) const { |
- CHECK_EQ(GESTURE_DRAG_IN_PROGRESS, gesture_drag_status_); |
- bool horizontal = wm_shelf_->IsHorizontalAlignment(); |
- WmWindow* window = WmWindow::Get(shelf_widget_->GetNativeWindow()); |
- gfx::Rect available_bounds = wm::GetDisplayBoundsWithShelf(window); |
- int resistance_free_region = 0; |
- |
- if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_HIDDEN && |
- visibility_state() == SHELF_AUTO_HIDE && |
- auto_hide_state() != SHELF_AUTO_HIDE_SHOWN) { |
- // If the shelf was hidden when the drag started (and the state hasn't |
- // changed since then, e.g. because the tray-menu was shown because of the |
- // drag), then allow the drag some resistance-free region at first to make |
- // sure the shelf sticks with the finger until the shelf is visible. |
- resistance_free_region = GetShelfConstant(SHELF_SIZE) - kShelfAutoHideSize; |
- } |
- |
- bool resist = SelectValueForShelfAlignment( |
- gesture_drag_amount_<-resistance_free_region, gesture_drag_amount_> |
- resistance_free_region, |
- gesture_drag_amount_ < -resistance_free_region); |
- |
- float translate = 0.f; |
- if (resist) { |
- float diff = fabsf(gesture_drag_amount_) - resistance_free_region; |
- diff = std::min(diff, sqrtf(diff)); |
- if (gesture_drag_amount_ < 0) |
- translate = -resistance_free_region - diff; |
- else |
- translate = resistance_free_region + diff; |
- } else { |
- translate = gesture_drag_amount_; |
- } |
- int shelf_insets = GetShelfConstant(SHELF_INSETS_FOR_AUTO_HIDE); |
- if (horizontal) { |
- // Move and size the shelf with the gesture. |
- int shelf_height = target_bounds->shelf_bounds_in_root.height() - translate; |
- shelf_height = std::max(shelf_height, shelf_insets); |
- target_bounds->shelf_bounds_in_root.set_height(shelf_height); |
- if (wm_shelf_->IsHorizontalAlignment()) { |
- target_bounds->shelf_bounds_in_root.set_y(available_bounds.bottom() - |
- shelf_height); |
- } |
- |
- target_bounds->status_bounds_in_shelf.set_y(0); |
- } else { |
- // Move and size the shelf with the gesture. |
- int shelf_width = target_bounds->shelf_bounds_in_root.width(); |
- bool right_aligned = wm_shelf_->GetAlignment() == SHELF_ALIGNMENT_RIGHT; |
- if (right_aligned) |
- shelf_width -= translate; |
- else |
- shelf_width += translate; |
- shelf_width = std::max(shelf_width, shelf_insets); |
- target_bounds->shelf_bounds_in_root.set_width(shelf_width); |
- if (right_aligned) { |
- target_bounds->shelf_bounds_in_root.set_x(available_bounds.right() - |
- shelf_width); |
- } |
- |
- if (right_aligned) { |
- target_bounds->status_bounds_in_shelf.set_x(0); |
- } else { |
- target_bounds->status_bounds_in_shelf.set_x( |
- target_bounds->shelf_bounds_in_root.width() - |
- GetShelfConstant(SHELF_SIZE)); |
- } |
- } |
-} |
- |
-void ShelfLayoutManager::MaybeUpdateShelfBackground(AnimationChangeType type) { |
- const ShelfBackgroundType new_background_type(GetShelfBackgroundType()); |
- |
- if (new_background_type == shelf_background_type_) |
- return; |
- |
- shelf_background_type_ = new_background_type; |
- for (auto& observer : observers_) |
- observer.OnBackgroundUpdated(shelf_background_type_, type); |
-} |
- |
-void ShelfLayoutManager::UpdateAutoHideStateNow() { |
- SetState(state_.visibility_state); |
- |
- // If the state did not change, the auto hide timer may still be running. |
- StopAutoHideTimer(); |
-} |
- |
-void ShelfLayoutManager::StopAutoHideTimer() { |
- auto_hide_timer_.Stop(); |
- mouse_over_shelf_when_auto_hide_timer_started_ = false; |
-} |
- |
-gfx::Rect ShelfLayoutManager::GetAutoHideShowShelfRegionInScreen() const { |
- gfx::Rect shelf_bounds_in_screen = shelf_widget_->GetWindowBoundsInScreen(); |
- gfx::Vector2d offset = SelectValueForShelfAlignment( |
- gfx::Vector2d(0, shelf_bounds_in_screen.height()), |
- gfx::Vector2d(-kMaxAutoHideShowShelfRegionSize, 0), |
- gfx::Vector2d(shelf_bounds_in_screen.width(), 0)); |
- |
- gfx::Rect show_shelf_region_in_screen = shelf_bounds_in_screen; |
- show_shelf_region_in_screen += offset; |
- if (wm_shelf_->IsHorizontalAlignment()) |
- show_shelf_region_in_screen.set_height(kMaxAutoHideShowShelfRegionSize); |
- else |
- show_shelf_region_in_screen.set_width(kMaxAutoHideShowShelfRegionSize); |
- |
- // TODO: Figure out if we need any special handling when the keyboard is |
- // visible. |
- return show_shelf_region_in_screen; |
-} |
- |
-ShelfAutoHideState ShelfLayoutManager::CalculateAutoHideState( |
- ShelfVisibilityState visibility_state) const { |
- if (visibility_state != SHELF_AUTO_HIDE || !wm_shelf_->IsShelfInitialized()) |
- return SHELF_AUTO_HIDE_HIDDEN; |
- |
- if (shelf_widget_->IsShowingAppList()) |
- return SHELF_AUTO_HIDE_SHOWN; |
- |
- if (shelf_widget_->status_area_widget() && |
- shelf_widget_->status_area_widget()->ShouldShowShelf()) |
- return SHELF_AUTO_HIDE_SHOWN; |
- |
- if (shelf_widget_->IsShowingContextMenu()) |
- return SHELF_AUTO_HIDE_SHOWN; |
- |
- if (shelf_widget_->IsShowingOverflowBubble()) |
- return SHELF_AUTO_HIDE_SHOWN; |
- |
- if (shelf_widget_->IsActive() || |
- (shelf_widget_->status_area_widget() && |
- shelf_widget_->status_area_widget()->IsActive())) |
- return SHELF_AUTO_HIDE_SHOWN; |
- |
- const int64_t shelf_display_id = |
- WmWindow::Get(shelf_widget_->GetNativeWindow()) |
- ->GetDisplayNearestWindow() |
- .id(); |
- const std::vector<WmWindow*> windows = |
- WmShell::Get()->mru_window_tracker()->BuildWindowListIgnoreModal(); |
- // Process the window list and check if there are any visible windows. |
- // Ignore app list windows that may be animating to hide after dismissal. |
- bool visible_window = false; |
- for (size_t i = 0; i < windows.size(); ++i) { |
- if (windows[i] && windows[i]->IsVisible() && !IsAppListWindow(windows[i]) && |
- !windows[i]->GetWindowState()->IsMinimized() && |
- windows[i]->GetDisplayNearestWindow().id() == shelf_display_id) { |
- visible_window = true; |
- break; |
- } |
- } |
- // If there are no visible windows do not hide the shelf. |
- if (!visible_window) |
- return SHELF_AUTO_HIDE_SHOWN; |
- |
- if (gesture_drag_status_ == GESTURE_DRAG_COMPLETE_IN_PROGRESS) |
- return gesture_drag_auto_hide_state_; |
- |
- // Don't show if the user is dragging the mouse. |
- if (in_mouse_drag_) |
- return SHELF_AUTO_HIDE_HIDDEN; |
- |
- // Ignore the mouse position if mouse events are disabled. |
- if (!shelf_widget_->IsMouseEventsEnabled()) |
- return SHELF_AUTO_HIDE_HIDDEN; |
- |
- gfx::Rect shelf_region = shelf_widget_->GetWindowBoundsInScreen(); |
- if (shelf_widget_->status_area_widget() && |
- shelf_widget_->status_area_widget()->IsMessageBubbleShown() && |
- IsVisible()) { |
- // Increase the the hit test area to prevent the shelf from disappearing |
- // when the mouse is over the bubble gap. |
- ShelfAlignment alignment = wm_shelf_->GetAlignment(); |
- shelf_region.Inset( |
- alignment == SHELF_ALIGNMENT_RIGHT ? -kNotificationBubbleGapHeight : 0, |
- wm_shelf_->IsHorizontalAlignment() ? -kNotificationBubbleGapHeight : 0, |
- alignment == SHELF_ALIGNMENT_LEFT ? -kNotificationBubbleGapHeight : 0, |
- 0); |
- } |
- |
- gfx::Point cursor_position_in_screen = |
- display::Screen::GetScreen()->GetCursorScreenPoint(); |
- if (shelf_region.Contains(cursor_position_in_screen)) |
- return SHELF_AUTO_HIDE_SHOWN; |
- |
- // When the shelf is auto hidden and the shelf is on the boundary between two |
- // displays, it is hard to trigger showing the shelf. For instance, if a |
- // user's primary display is left of their secondary display, it is hard to |
- // unautohide a left aligned shelf on the secondary display. |
- // It is hard because: |
- // - It is hard to stop the cursor in the shelf "light bar" and not overshoot. |
- // - The cursor is warped to the other display if the cursor gets to the edge |
- // of the display. |
- // Show the shelf if the cursor started on the shelf and the user overshot the |
- // shelf slightly to make it easier to show the shelf in this situation. We |
- // do not check |auto_hide_timer_|.IsRunning() because it returns false when |
- // the timer's task is running. |
- if ((state_.auto_hide_state == SHELF_AUTO_HIDE_SHOWN || |
- mouse_over_shelf_when_auto_hide_timer_started_) && |
- GetAutoHideShowShelfRegionInScreen().Contains( |
- cursor_position_in_screen)) { |
- return SHELF_AUTO_HIDE_SHOWN; |
- } |
- |
- return SHELF_AUTO_HIDE_HIDDEN; |
-} |
- |
-bool ShelfLayoutManager::IsShelfWindow(WmWindow* window) { |
- if (!window) |
- return false; |
- WmWindow* shelf_window = WmWindow::Get(shelf_widget_->GetNativeWindow()); |
- WmWindow* status_window = |
- WmWindow::Get(shelf_widget_->status_area_widget()->GetNativeWindow()); |
- return (shelf_window && shelf_window->Contains(window)) || |
- (status_window && status_window->Contains(window)); |
-} |
- |
-int ShelfLayoutManager::GetWorkAreaInsets(const State& state, int size) const { |
- if (state.visibility_state == SHELF_VISIBLE) |
- return size; |
- if (state.visibility_state == SHELF_AUTO_HIDE) |
- return GetShelfConstant(SHELF_INSETS_FOR_AUTO_HIDE); |
- return 0; |
-} |
- |
-void ShelfLayoutManager::OnDockBoundsChanging( |
- const gfx::Rect& dock_bounds, |
- DockedWindowLayoutManagerObserver::Reason reason) { |
- // Skip shelf layout in case docked notification originates from this class. |
- if (reason == DISPLAY_INSETS_CHANGED) |
- return; |
- if (dock_bounds_ != dock_bounds) { |
- dock_bounds_ = dock_bounds; |
- OnWindowResized(); |
- UpdateVisibilityState(); |
- MaybeUpdateShelfBackground(AnimationChangeType::ANIMATE); |
- } |
-} |
- |
-void ShelfLayoutManager::OnLockStateEvent(LockStateObserver::EventType event) { |
- if (event == EVENT_LOCK_ANIMATION_STARTED) { |
- // Enter the screen locked state and update the visibility to avoid an odd |
- // animation when transitioning the orientation from L/R to bottom. |
- state_.pre_lock_screen_animation_active = true; |
- UpdateShelfVisibilityAfterLoginUIChange(); |
- } else { |
- state_.pre_lock_screen_animation_active = false; |
- } |
- MaybeUpdateShelfBackground(AnimationChangeType::ANIMATE); |
-} |
- |
-void ShelfLayoutManager::SessionStateChanged( |
- session_manager::SessionState state) { |
- // Check transition changes to/from the add user to session and change the |
- // shelf alignment accordingly |
- const bool was_adding_user = state_.IsAddingSecondaryUser(); |
- const bool was_locked = state_.IsScreenLocked(); |
- state_.session_state = state; |
- MaybeUpdateShelfBackground(AnimationChangeType::ANIMATE); |
- if (was_adding_user != state_.IsAddingSecondaryUser()) { |
- UpdateShelfVisibilityAfterLoginUIChange(); |
- return; |
- } |
- |
- // Force the shelf to layout for alignment (bottom if locked, restore the |
- // previous alignment otherwise). |
- if (was_locked != state_.IsScreenLocked()) |
- UpdateShelfVisibilityAfterLoginUIChange(); |
- |
- TargetBounds target_bounds; |
- CalculateTargetBounds(state_, &target_bounds); |
- UpdateBoundsAndOpacity(target_bounds, true /* animate */, |
- true /* change_work_area */, NULL); |
- UpdateVisibilityState(); |
-} |
- |
-void ShelfLayoutManager::UpdateShelfVisibilityAfterLoginUIChange() { |
- UpdateVisibilityState(); |
- LayoutShelf(); |
-} |
- |
-float ShelfLayoutManager::ComputeTargetOpacity(const State& state) { |
- if (gesture_drag_status_ == GESTURE_DRAG_IN_PROGRESS || |
- state.visibility_state == SHELF_VISIBLE) { |
- return 1.0f; |
- } |
- // In Chrome OS Material Design, when shelf is hidden during auto hide state, |
- // target bounds are also hidden. So the window can extend to the edge of |
- // screen. |
- return (state.visibility_state == SHELF_AUTO_HIDE && |
- state.auto_hide_state == SHELF_AUTO_HIDE_SHOWN) |
- ? 1.0f |
- : 0.0f; |
-} |
- |
-bool ShelfLayoutManager::IsShelfHiddenForFullscreen() const { |
- const WmWindow* fullscreen_window = wm::GetWindowForFullscreenMode( |
- WmWindow::Get(shelf_widget_->GetNativeWindow())); |
- return fullscreen_window && |
- fullscreen_window->GetWindowState()->hide_shelf_when_fullscreen(); |
-} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
-// ShelfLayoutManager, Gesture functions: |
- |
-void ShelfLayoutManager::StartGestureDrag(const ui::GestureEvent& gesture) { |
- gesture_drag_status_ = GESTURE_DRAG_IN_PROGRESS; |
- gesture_drag_amount_ = 0.f; |
- gesture_drag_auto_hide_state_ = visibility_state() == SHELF_AUTO_HIDE |
- ? auto_hide_state() |
- : SHELF_AUTO_HIDE_SHOWN; |
- MaybeUpdateShelfBackground(AnimationChangeType::ANIMATE); |
-} |
- |
-void ShelfLayoutManager::UpdateGestureDrag(const ui::GestureEvent& gesture) { |
- gesture_drag_amount_ += PrimaryAxisValue(gesture.details().scroll_y(), |
- gesture.details().scroll_x()); |
- LayoutShelf(); |
-} |
- |
-void ShelfLayoutManager::CompleteGestureDrag(const ui::GestureEvent& gesture) { |
- bool horizontal = wm_shelf_->IsHorizontalAlignment(); |
- bool should_change = false; |
- if (gesture.type() == ui::ET_GESTURE_SCROLL_END) { |
- // The visibility of the shelf changes only if the shelf was dragged X% |
- // along the correct axis. If the shelf was already visible, then the |
- // direction of the drag does not matter. |
- const float kDragHideThreshold = 0.4f; |
- gfx::Rect bounds = GetIdealBounds(); |
- float drag_ratio = fabs(gesture_drag_amount_) / |
- (horizontal ? bounds.height() : bounds.width()); |
- if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN) { |
- should_change = drag_ratio > kDragHideThreshold; |
- } else { |
- bool correct_direction = false; |
- switch (wm_shelf_->GetAlignment()) { |
- case SHELF_ALIGNMENT_BOTTOM: |
- case SHELF_ALIGNMENT_BOTTOM_LOCKED: |
- case SHELF_ALIGNMENT_RIGHT: |
- correct_direction = gesture_drag_amount_ < 0; |
- break; |
- case SHELF_ALIGNMENT_LEFT: |
- correct_direction = gesture_drag_amount_ > 0; |
- break; |
- } |
- should_change = correct_direction && drag_ratio > kDragHideThreshold; |
- } |
- } else if (gesture.type() == ui::ET_SCROLL_FLING_START) { |
- if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN) { |
- should_change = horizontal ? fabs(gesture.details().velocity_y()) > 0 |
- : fabs(gesture.details().velocity_x()) > 0; |
- } else { |
- should_change = |
- SelectValueForShelfAlignment(gesture.details().velocity_y() < 0, |
- gesture.details().velocity_x() > 0, |
- gesture.details().velocity_x() < 0); |
- } |
- } else { |
- NOTREACHED(); |
- } |
- |
- if (!should_change) { |
- CancelGestureDrag(); |
- return; |
- } |
- |
- shelf_widget_->Deactivate(); |
- shelf_widget_->status_area_widget()->Deactivate(); |
- |
- gesture_drag_auto_hide_state_ = |
- gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN |
- ? SHELF_AUTO_HIDE_HIDDEN |
- : SHELF_AUTO_HIDE_SHOWN; |
- ShelfAutoHideBehavior new_auto_hide_behavior = |
- gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN |
- ? SHELF_AUTO_HIDE_BEHAVIOR_NEVER |
- : SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS; |
- |
- // When in fullscreen and the shelf is forced to be auto hidden, the auto hide |
- // behavior affects neither the visibility state nor the auto hide state. Set |
- // |gesture_drag_status_| to GESTURE_DRAG_COMPLETE_IN_PROGRESS to set the auto |
- // hide state to |gesture_drag_auto_hide_state_|. |
- gesture_drag_status_ = GESTURE_DRAG_COMPLETE_IN_PROGRESS; |
- if (wm_shelf_->auto_hide_behavior() != new_auto_hide_behavior) |
- wm_shelf_->SetAutoHideBehavior(new_auto_hide_behavior); |
- else |
- UpdateVisibilityState(); |
- gesture_drag_status_ = GESTURE_DRAG_NONE; |
-} |
- |
-void ShelfLayoutManager::CancelGestureDrag() { |
- gesture_drag_status_ = GESTURE_DRAG_CANCEL_IN_PROGRESS; |
- UpdateVisibilityState(); |
- gesture_drag_status_ = GESTURE_DRAG_NONE; |
-} |
- |
-} // namespace ash |