Chromium Code Reviews| Index: ash/shelf/shelf_layout_manager.cc |
| diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc |
| index 8210b5beaeabaedc3b0b32ad64099a165e115b12..a507da648a839e58de1b06987e4e344ea9226e16 100644 |
| --- a/ash/shelf/shelf_layout_manager.cc |
| +++ b/ash/shelf/shelf_layout_manager.cc |
| @@ -36,6 +36,7 @@ |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_util.h" |
| #include "ui/aura/client/activation_client.h" |
| +#include "ui/aura/client/cursor_client.h" |
| #include "ui/aura/root_window.h" |
| #include "ui/base/events/event.h" |
| #include "ui/base/events/event_handler.h" |
| @@ -196,7 +197,7 @@ class ShelfLayoutManager::UpdateShelfObserver |
| ShelfLayoutManager::ShelfLayoutManager(ShelfWidget* shelf) |
| : root_window_(shelf->GetNativeView()->GetRootWindow()), |
| - in_layout_(false), |
| + updating_bounds_(false), |
| auto_hide_behavior_(SHELF_AUTO_HIDE_BEHAVIOR_NEVER), |
| alignment_(SHELF_ALIGNMENT_BOTTOM), |
| shelf_(shelf), |
| @@ -271,34 +272,20 @@ gfx::Rect ShelfLayoutManager::GetIdealBounds() { |
| } |
| void ShelfLayoutManager::LayoutShelf() { |
| - base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true); |
| - StopAnimating(); |
| TargetBounds target_bounds; |
| CalculateTargetBounds(state_, &target_bounds); |
| - GetLayer(shelf_)->SetOpacity(target_bounds.opacity); |
| - shelf_->SetWidgetBounds( |
| - ScreenAsh::ConvertRectToScreen( |
| - shelf_->GetNativeView()->parent(), |
| - target_bounds.shelf_bounds_in_root)); |
| - if (shelf_->launcher()) |
| + UpdateBoundsAndOpacity(target_bounds, false, NULL); |
| + |
| + if (shelf_->launcher()) { |
| + // This is not part of UpdateBoundsAndOpacity() because |
| + // SetLauncherViewBounds() sets the bounds immediately and does not animate. |
| + // The height of the LauncherView for a horizontal shelf and the width of |
| + // the LauncherView for a vertical shelf are set when |shelf_|'s bounds |
| + // are changed via UpdateBoundsAndOpacity(). This sets the origin and the |
| + // dimension in the other direction. |
| shelf_->launcher()->SetLauncherViewBounds( |
| target_bounds.launcher_bounds_in_shelf); |
| - GetLayer(shelf_->status_area_widget())->SetOpacity( |
| - target_bounds.status_opacity); |
| - // 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.set_x(status_bounds.x() + |
| - target_bounds.shelf_bounds_in_root.x()); |
| - status_bounds.set_y(status_bounds.y() + |
| - target_bounds.shelf_bounds_in_root.y()); |
| - shelf_->status_area_widget()->SetBounds( |
| - ScreenAsh::ConvertRectToScreen( |
| - shelf_->status_area_widget()->GetNativeView()->parent(), |
| - status_bounds)); |
| - Shell::GetInstance()->SetDisplayWorkAreaInsets( |
| - root_window_, target_bounds.work_area_insets); |
| - UpdateHitTestBounds(); |
| + } |
| } |
| ShelfVisibilityState ShelfLayoutManager::CalculateShelfVisibility() { |
| @@ -480,17 +467,12 @@ void ShelfLayoutManager::CompleteGestureDrag(const ui::GestureEvent& gesture) { |
| else |
| UpdateVisibilityState(); |
| gesture_drag_status_ = GESTURE_DRAG_NONE; |
| - LayoutShelf(); |
| } |
| void ShelfLayoutManager::CancelGestureDrag() { |
| - gesture_drag_status_ = GESTURE_DRAG_NONE; |
| - ui::ScopedLayerAnimationSettings |
| - launcher_settings(GetLayer(shelf_)->GetAnimator()), |
| - status_settings(GetLayer(shelf_->status_area_widget())->GetAnimator()); |
| - LayoutShelf(); |
| + gesture_drag_status_ = GESTURE_DRAG_CANCEL_IN_PROGRESS; |
| UpdateVisibilityState(); |
| - UpdateShelfBackground(BackgroundAnimator::CHANGE_ANIMATE); |
| + gesture_drag_status_ = GESTURE_DRAG_NONE; |
| } |
| //////////////////////////////////////////////////////////////////////////////// |
| @@ -518,7 +500,7 @@ void ShelfLayoutManager::SetChildBounds(aura::Window* child, |
| SetChildBoundsDirect(child, requested_bounds); |
| // We may contain other widgets (such as frame maximize bubble) but they don't |
| // effect the layout in anyway. |
| - if (!in_layout_ && |
| + if (!updating_bounds_ && |
| ((shelf_->GetNativeView() == child) || |
| (shelf_->status_area_widget()->GetNativeView() == child))) { |
| LayoutShelf(); |
| @@ -575,7 +557,13 @@ void ShelfLayoutManager::SetState(ShelfVisibilityState visibility_state) { |
| state.window_state = workspace_controller_ ? |
| workspace_controller_->GetWindowState() : WORKSPACE_WINDOW_STATE_DEFAULT; |
| - if (state_.Equals(state)) |
| + // 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_EACH_OBSERVER(ShelfLayoutManagerObserver, observers_, |
| @@ -594,26 +582,6 @@ void ShelfLayoutManager::SetState(ShelfVisibilityState visibility_state) { |
| State old_state = state_; |
| state_ = state; |
| - TargetBounds target_bounds; |
| - CalculateTargetBounds(state_, &target_bounds); |
| - |
| - ui::ScopedLayerAnimationSettings launcher_animation_setter( |
| - GetLayer(shelf_)->GetAnimator()); |
| - launcher_animation_setter.SetTransitionDuration( |
| - base::TimeDelta::FromMilliseconds(kCrossFadeDurationMS)); |
| - launcher_animation_setter.SetTweenType(ui::Tween::EASE_OUT); |
| - launcher_animation_setter.SetPreemptionStrategy( |
| - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
| - GetLayer(shelf_)->SetBounds( |
| - target_bounds.shelf_bounds_in_root); |
| - GetLayer(shelf_)->SetOpacity(target_bounds.opacity); |
| - ui::ScopedLayerAnimationSettings status_animation_setter( |
| - GetLayer(shelf_->status_area_widget())->GetAnimator()); |
| - status_animation_setter.SetTransitionDuration( |
| - base::TimeDelta::FromMilliseconds(kCrossFadeDurationMS)); |
| - status_animation_setter.SetTweenType(ui::Tween::EASE_OUT); |
| - status_animation_setter.SetPreemptionStrategy( |
| - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
| BackgroundAnimator::ChangeType change_type = |
| BackgroundAnimator::CHANGE_ANIMATE; |
| @@ -643,7 +611,6 @@ void ShelfLayoutManager::SetState(ShelfVisibilityState visibility_state) { |
| update_shelf_observer_->Detach(); |
| // UpdateShelfBackground deletes itself when the animation is done. |
| update_shelf_observer_ = new UpdateShelfObserver(this); |
| - status_animation_setter.AddObserver(update_shelf_observer_); |
| } else { |
| UpdateShelfBackground(change_type); |
| } |
| @@ -652,18 +619,10 @@ void ShelfLayoutManager::SetState(ShelfVisibilityState visibility_state) { |
| state.visibility_state == SHELF_VISIBLE && |
| state.window_state == WORKSPACE_WINDOW_STATE_MAXIMIZED); |
| - ui::Layer* layer = GetLayer(shelf_->status_area_widget()); |
| - // TODO(harrym): Remove when status_area is view (crbug.com/180422). |
| - gfx::Rect status_bounds = target_bounds.status_bounds_in_shelf; |
| - status_bounds.set_x(status_bounds.x() + |
| - target_bounds.shelf_bounds_in_root.x()); |
| - status_bounds.set_y(status_bounds.y() + |
| - target_bounds.shelf_bounds_in_root.y()); |
| - layer->SetBounds(status_bounds); |
| - layer->SetOpacity(target_bounds.status_opacity); |
| - Shell::GetInstance()->SetDisplayWorkAreaInsets( |
| - root_window_, target_bounds.work_area_insets); |
| - UpdateHitTestBounds(); |
| + TargetBounds target_bounds; |
| + CalculateTargetBounds(state_, &target_bounds); |
| + UpdateBoundsAndOpacity(target_bounds, true, |
| + delay_background_change ? update_shelf_observer_ : NULL); |
| // OnAutoHideStateChanged Should be emitted when: |
| // - firstly state changed to auto-hide from other state |
| @@ -676,6 +635,58 @@ void ShelfLayoutManager::SetState(ShelfVisibilityState visibility_state) { |
| } |
| } |
| +void ShelfLayoutManager::UpdateBoundsAndOpacity( |
| + const TargetBounds& target_bounds, |
| + bool animate, |
| + ui::ImplicitAnimationObserver* observer) { |
| + base::AutoReset<bool> auto_reset_updating_bounds(&updating_bounds_, true); |
| + |
| + ui::ScopedLayerAnimationSettings launcher_animation_setter( |
| + GetLayer(shelf_)->GetAnimator()); |
| + ui::ScopedLayerAnimationSettings status_animation_setter( |
| + GetLayer(shelf_->status_area_widget())->GetAnimator()); |
| + if (animate) { |
| + launcher_animation_setter.SetTransitionDuration( |
| + base::TimeDelta::FromMilliseconds(kCrossFadeDurationMS)); |
| + launcher_animation_setter.SetTweenType(ui::Tween::EASE_OUT); |
| + launcher_animation_setter.SetPreemptionStrategy( |
| + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
| + status_animation_setter.SetTransitionDuration( |
| + base::TimeDelta::FromMilliseconds(kCrossFadeDurationMS)); |
| + status_animation_setter.SetTweenType(ui::Tween::EASE_OUT); |
| + status_animation_setter.SetPreemptionStrategy( |
| + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
| + } else { |
| + StopAnimating(); |
| + launcher_animation_setter.SetTransitionDuration(base::TimeDelta()); |
| + status_animation_setter.SetTransitionDuration(base::TimeDelta()); |
| + } |
| + if (observer) |
| + status_animation_setter.AddObserver(observer); |
| + |
| + GetLayer(shelf_)->SetOpacity(target_bounds.opacity); |
| + shelf_->SetBounds(ScreenAsh::ConvertRectToScreen( |
| + shelf_->GetNativeView()->parent(), |
| + target_bounds.shelf_bounds_in_root)); |
| + |
| + GetLayer(shelf_->status_area_widget())->SetOpacity( |
| + target_bounds.status_opacity); |
| + // 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.set_x(status_bounds.x() + |
| + target_bounds.shelf_bounds_in_root.x()); |
| + status_bounds.set_y(status_bounds.y() + |
| + target_bounds.shelf_bounds_in_root.y()); |
| + shelf_->status_area_widget()->SetBounds( |
| + ScreenAsh::ConvertRectToScreen( |
| + shelf_->status_area_widget()->GetNativeView()->parent(), |
| + status_bounds)); |
| + Shell::GetInstance()->SetDisplayWorkAreaInsets( |
| + root_window_, target_bounds.work_area_insets); |
| + UpdateHitTestBounds(); |
| +} |
| + |
| void ShelfLayoutManager::StopAnimating() { |
| GetLayer(shelf_)->GetAnimator()->StopAnimating(); |
| GetLayer(shelf_->status_area_widget())->GetAnimator()->StopAnimating(); |
| @@ -954,9 +965,6 @@ ShelfAutoHideState ShelfLayoutManager::CalculateAutoHideState( |
| if (visibility_state != SHELF_AUTO_HIDE || !shelf_) |
| return SHELF_AUTO_HIDE_HIDDEN; |
| - if (gesture_drag_status_ == GESTURE_DRAG_COMPLETE_IN_PROGRESS) |
| - return gesture_drag_auto_hide_state_; |
| - |
| Shell* shell = Shell::GetInstance(); |
| if (shell->GetAppListTargetVisibility()) |
| return SHELF_AUTO_HIDE_SHOWN; |
| @@ -974,10 +982,36 @@ ShelfAutoHideState ShelfLayoutManager::CalculateAutoHideState( |
| if (shelf_->IsActive() || shelf_->status_area_widget()->IsActive()) |
| return SHELF_AUTO_HIDE_SHOWN; |
| + const std::vector<aura::Window*> windows = |
| + ash::MruWindowTracker::BuildWindowList(false); |
| + |
| + // Process the window list and check if there are any visible windows. |
| + bool visible_window = false; |
| + for (size_t i = 0; i < windows.size(); ++i) { |
| + if (windows[i] && windows[i]->IsVisible() && |
| + !ash::wm::IsWindowMinimized(windows[i]) && |
| + root_window_ == windows[i]->GetRootWindow()) { |
| + 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 (auto_hide_event_filter_.get() && auto_hide_event_filter_->in_mouse_drag()) |
| return SHELF_AUTO_HIDE_HIDDEN; |
| + // Ignore the mouse position if mouse events are disabled. |
| + aura::client::CursorClient* cursor_client = aura::client::GetCursorClient( |
| + shelf_->GetNativeWindow()->GetRootWindow()); |
| + if (!cursor_client->IsMouseEventsEnabled()) |
| + return SHELF_AUTO_HIDE_HIDDEN; |
|
sadrul
2013/08/13 17:21:34
This parts are from another CL, right?
pkotwicz
2013/08/14 17:03:21
That CL has now landed, rebasing is easier :)
|
| + |
| gfx::Rect shelf_region = shelf_->GetWindowBoundsInScreen(); |
| if (shelf_->status_area_widget() && |
| shelf_->status_area_widget()->IsMessageBubbleShown() && |
| @@ -1018,19 +1052,7 @@ ShelfAutoHideState ShelfLayoutManager::CalculateAutoHideState( |
| return SHELF_AUTO_HIDE_SHOWN; |
| } |
| - const std::vector<aura::Window*> windows = |
| - ash::MruWindowTracker::BuildWindowList(false); |
| - |
| - // Process the window list and check if there are any visible windows. |
| - for (size_t i = 0; i < windows.size(); ++i) { |
| - if (windows[i] && windows[i]->IsVisible() && |
| - !ash::wm::IsWindowMinimized(windows[i]) && |
| - root_window_ == windows[i]->GetRootWindow()) |
| - return SHELF_AUTO_HIDE_HIDDEN; |
| - } |
| - |
| - // If there are no visible windows do not hide the shelf. |
| - return SHELF_AUTO_HIDE_SHOWN; |
| + return SHELF_AUTO_HIDE_HIDDEN; |
| } |
| void ShelfLayoutManager::UpdateHitTestBounds() { |