OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/wm/shelf_layout_manager.h" | 5 #include "ash/wm/shelf_layout_manager.h" |
6 | 6 |
7 #include "ash/launcher/launcher.h" | 7 #include "ash/launcher/launcher.h" |
8 #include "ash/screen_ash.h" | 8 #include "ash/screen_ash.h" |
9 #include "ash/shell.h" | 9 #include "ash/shell.h" |
10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
11 #include "ui/aura/root_window.h" | 11 #include "ui/aura/root_window.h" |
12 #include "ui/gfx/compositor/layer.h" | 12 #include "ui/gfx/compositor/layer.h" |
13 #include "ui/gfx/compositor/layer_animation_observer.h" | 13 #include "ui/gfx/compositor/layer_animation_observer.h" |
14 #include "ui/gfx/compositor/layer_animator.h" | 14 #include "ui/gfx/compositor/layer_animator.h" |
15 #include "ui/gfx/compositor/scoped_layer_animation_settings.h" | 15 #include "ui/gfx/compositor/scoped_layer_animation_settings.h" |
16 #include "ui/views/widget/widget.h" | 16 #include "ui/views/widget/widget.h" |
17 | 17 |
18 namespace ash { | 18 namespace ash { |
19 namespace internal { | 19 namespace internal { |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
| 23 // Height of the shelf when auto-hidden. |
| 24 const int kAutoHideHeight = 2; |
| 25 |
23 ui::Layer* GetLayer(views::Widget* widget) { | 26 ui::Layer* GetLayer(views::Widget* widget) { |
24 return widget->GetNativeView()->layer(); | 27 return widget->GetNativeView()->layer(); |
25 } | 28 } |
26 | 29 |
27 } // namespace | 30 } // namespace |
28 | 31 |
29 // static | 32 // static |
30 const int ShelfLayoutManager::kWorkspaceAreaBottomInset = 2; | 33 const int ShelfLayoutManager::kWorkspaceAreaBottomInset = 2; |
31 | 34 |
32 //////////////////////////////////////////////////////////////////////////////// | 35 //////////////////////////////////////////////////////////////////////////////// |
33 // ShelfLayoutManager, public: | 36 // ShelfLayoutManager, public: |
34 | 37 |
35 ShelfLayoutManager::ShelfLayoutManager(views::Widget* launcher, | 38 ShelfLayoutManager::ShelfLayoutManager(views::Widget* status) |
36 views::Widget* status) | |
37 : in_layout_(false), | 39 : in_layout_(false), |
38 visible_(true), | 40 shelf_height_(-1), |
39 max_height_(-1), | 41 launcher_(NULL), |
40 launcher_(launcher), | 42 status_(status), |
41 status_(status) { | 43 window_overlaps_shelf_(false), |
42 gfx::Rect launcher_bounds = launcher->GetWindowScreenBounds(); | 44 root_window_(NULL) { |
43 gfx::Rect status_bounds = status->GetWindowScreenBounds(); | 45 gfx::Rect status_bounds = status->GetWindowScreenBounds(); |
44 max_height_ = std::max(launcher_bounds.height(), status_bounds.height()); | 46 shelf_height_ = status_bounds.height(); |
45 root_window_ = launcher->GetNativeView()->GetRootWindow(); | 47 root_window_ = status->GetNativeView()->GetRootWindow(); |
46 } | 48 } |
47 | 49 |
48 ShelfLayoutManager::~ShelfLayoutManager() { | 50 ShelfLayoutManager::~ShelfLayoutManager() { |
49 } | 51 } |
50 | 52 |
| 53 gfx::Rect ShelfLayoutManager::GetMaximizedWindowBounds( |
| 54 aura::Window* window) const { |
| 55 // TODO: needs to be multi-mon aware. |
| 56 gfx::Rect bounds(gfx::Screen::GetMonitorAreaNearestWindow(window)); |
| 57 bounds.set_height(bounds.height() - kAutoHideHeight); |
| 58 return bounds; |
| 59 } |
| 60 |
| 61 gfx::Rect ShelfLayoutManager::GetUnmaximizedWorkAreaBounds( |
| 62 aura::Window* window) const { |
| 63 // TODO: needs to be multi-mon aware. |
| 64 gfx::Rect bounds(gfx::Screen::GetMonitorAreaNearestWindow(window)); |
| 65 bounds.set_height(bounds.height() - shelf_height_ - |
| 66 kWorkspaceAreaBottomInset); |
| 67 return bounds; |
| 68 } |
| 69 |
51 void ShelfLayoutManager::LayoutShelf() { | 70 void ShelfLayoutManager::LayoutShelf() { |
52 AutoReset<bool> auto_reset_in_layout(&in_layout_, true); | 71 AutoReset<bool> auto_reset_in_layout(&in_layout_, true); |
53 StopAnimating(); | 72 StopAnimating(); |
54 TargetBounds target_bounds; | 73 TargetBounds target_bounds; |
55 float target_opacity = visible_ ? 1.0f : 0.0f; | 74 CalculateTargetBounds(state_, &target_bounds); |
56 CalculateTargetBounds(visible_, &target_bounds); | 75 if (launcher()) { |
57 GetLayer(launcher_)->SetOpacity(target_opacity); | 76 GetLayer(launcher())->SetOpacity(target_bounds.opacity); |
58 GetLayer(status_)->SetOpacity(target_opacity); | 77 launcher()->SetBounds(target_bounds.launcher_bounds); |
59 launcher_->SetBounds(target_bounds.launcher_bounds); | 78 launcher_->SetStatusWidth( |
| 79 target_bounds.status_bounds.width()); |
| 80 } |
| 81 GetLayer(status_)->SetOpacity(target_bounds.opacity); |
60 status_->SetBounds(target_bounds.status_bounds); | 82 status_->SetBounds(target_bounds.status_bounds); |
61 Shell::GetInstance()->launcher()->SetStatusWidth( | |
62 target_bounds.status_bounds.width()); | |
63 Shell::GetInstance()->SetMonitorWorkAreaInsets( | 83 Shell::GetInstance()->SetMonitorWorkAreaInsets( |
64 Shell::GetRootWindow(), | 84 Shell::GetRootWindow(), |
65 target_bounds.work_area_insets); | 85 target_bounds.work_area_insets); |
66 } | 86 } |
67 | 87 |
68 void ShelfLayoutManager::SetVisible(bool visible) { | 88 void ShelfLayoutManager::SetState(VisibilityState visibility_state, |
69 ui::Layer* launcher_layer = GetLayer(launcher_); | 89 AutoHideState auto_hide_state) { |
70 ui::Layer* status_layer = GetLayer(status_); | 90 State state; |
| 91 state.visibility_state = visibility_state; |
| 92 state.auto_hide_state = auto_hide_state; |
71 | 93 |
72 // TODO(vollick): once visibility is animatable, use GetTargetVisibility. | 94 if (state_.Equals(state)) |
73 bool current_visibility = visible_ && | |
74 launcher_layer->GetTargetOpacity() > 0.0f && | |
75 status_layer->GetTargetOpacity() > 0.0f; | |
76 | |
77 if (visible == current_visibility) | |
78 return; // Nothing changed. | 95 return; // Nothing changed. |
79 | 96 |
| 97 // Animating the background when transitioning from auto-hide & hidden to |
| 98 // visibile is janking. Update the background immediately in this case. |
| 99 Launcher::BackgroundChangeSpeed speed = |
| 100 (state_.visibility_state == AUTO_HIDE && |
| 101 state_.auto_hide_state == AUTO_HIDE_HIDDEN && |
| 102 state.visibility_state == VISIBLE) ? |
| 103 Launcher::CHANGE_IMMEDIATE : Launcher::CHANGE_ANIMATE; |
80 StopAnimating(); | 104 StopAnimating(); |
| 105 state_ = state; |
| 106 TargetBounds target_bounds; |
| 107 CalculateTargetBounds(state_, &target_bounds); |
| 108 if (launcher()) { |
| 109 ui::ScopedLayerAnimationSettings launcher_animation_setter( |
| 110 GetLayer(launcher())->GetAnimator()); |
| 111 launcher_animation_setter.SetTransitionDuration( |
| 112 base::TimeDelta::FromMilliseconds(130)); |
| 113 launcher_animation_setter.SetTweenType(ui::Tween::EASE_OUT); |
| 114 GetLayer(launcher())->SetBounds(target_bounds.launcher_bounds); |
| 115 GetLayer(launcher())->SetOpacity(target_bounds.opacity); |
| 116 } |
| 117 ui::ScopedLayerAnimationSettings status_animation_setter( |
| 118 GetLayer(status_)->GetAnimator()); |
| 119 status_animation_setter.SetTransitionDuration( |
| 120 base::TimeDelta::FromMilliseconds(130)); |
| 121 status_animation_setter.SetTweenType(ui::Tween::EASE_OUT); |
| 122 GetLayer(status_)->SetBounds(target_bounds.status_bounds); |
| 123 GetLayer(status_)->SetOpacity(target_bounds.opacity); |
| 124 Shell::GetInstance()->SetMonitorWorkAreaInsets( |
| 125 Shell::GetRootWindow(), |
| 126 target_bounds.work_area_insets); |
| 127 launcher_->SetRendersBackground(GetShelfRendersBackground(), speed); |
| 128 } |
81 | 129 |
82 visible_ = visible; | 130 void ShelfLayoutManager::SetWindowOverlapsShelf(bool value) { |
83 TargetBounds target_bounds; | 131 window_overlaps_shelf_ = value; |
84 float target_opacity = visible ? 1.0f : 0.0f; | 132 launcher_->SetRendersBackground(GetShelfRendersBackground(), |
85 CalculateTargetBounds(visible, &target_bounds); | 133 Launcher::CHANGE_ANIMATE); |
| 134 } |
86 | 135 |
87 ui::ScopedLayerAnimationSettings launcher_animation_setter( | 136 void ShelfLayoutManager::SetLauncher(Launcher* launcher) { |
88 launcher_layer->GetAnimator()); | 137 launcher_ = launcher; |
89 ui::ScopedLayerAnimationSettings status_animation_setter( | 138 gfx::Rect launcher_bounds = launcher_->widget()->GetWindowScreenBounds(); |
90 status_layer->GetAnimator()); | 139 gfx::Rect status_bounds = status_->GetWindowScreenBounds(); |
91 | 140 shelf_height_ = std::max(launcher_bounds.height(), status_bounds.height()); |
92 launcher_animation_setter.AddObserver(this); | |
93 status_animation_setter.AddObserver(this); | |
94 | |
95 launcher_layer->SetBounds(target_bounds.launcher_bounds); | |
96 launcher_layer->SetOpacity(target_opacity); | |
97 status_layer->SetBounds(target_bounds.status_bounds); | |
98 status_layer->SetOpacity(target_opacity); | |
99 } | 141 } |
100 | 142 |
101 //////////////////////////////////////////////////////////////////////////////// | 143 //////////////////////////////////////////////////////////////////////////////// |
102 // ShelfLayoutManager, aura::LayoutManager implementation: | 144 // ShelfLayoutManager, aura::LayoutManager implementation: |
103 | 145 |
104 void ShelfLayoutManager::OnWindowResized() { | 146 void ShelfLayoutManager::OnWindowResized() { |
105 LayoutShelf(); | 147 LayoutShelf(); |
106 } | 148 } |
107 | 149 |
108 void ShelfLayoutManager::OnWindowAddedToLayout(aura::Window* child) { | 150 void ShelfLayoutManager::OnWindowAddedToLayout(aura::Window* child) { |
(...skipping 10 matching lines...) Expand all Loading... |
119 const gfx::Rect& requested_bounds) { | 161 const gfx::Rect& requested_bounds) { |
120 SetChildBoundsDirect(child, requested_bounds); | 162 SetChildBoundsDirect(child, requested_bounds); |
121 if (!in_layout_) | 163 if (!in_layout_) |
122 LayoutShelf(); | 164 LayoutShelf(); |
123 } | 165 } |
124 | 166 |
125 //////////////////////////////////////////////////////////////////////////////// | 167 //////////////////////////////////////////////////////////////////////////////// |
126 // ShelfLayoutManager, private: | 168 // ShelfLayoutManager, private: |
127 | 169 |
128 void ShelfLayoutManager::StopAnimating() { | 170 void ShelfLayoutManager::StopAnimating() { |
129 StopObservingImplicitAnimations(); | 171 if (launcher()) |
130 GetLayer(launcher_)->GetAnimator()->StopAnimating(); | 172 GetLayer(launcher())->GetAnimator()->StopAnimating(); |
131 GetLayer(status_)->GetAnimator()->StopAnimating(); | 173 GetLayer(status_)->GetAnimator()->StopAnimating(); |
132 } | 174 } |
133 | 175 |
134 void ShelfLayoutManager::CalculateTargetBounds(bool visible, | 176 void ShelfLayoutManager::CalculateTargetBounds( |
135 TargetBounds* target_bounds) { | 177 const State& state, |
| 178 TargetBounds* target_bounds) const { |
136 const gfx::Rect& available_bounds(root_window_->bounds()); | 179 const gfx::Rect& available_bounds(root_window_->bounds()); |
137 int y = available_bounds.bottom() - (visible ? max_height_ : 0); | 180 int y = available_bounds.bottom(); |
| 181 int shelf_height = 0; |
| 182 int work_area_delta = 0; |
| 183 if (state.visibility_state == VISIBLE || |
| 184 (state.visibility_state == AUTO_HIDE && |
| 185 state.auto_hide_state == AUTO_HIDE_SHOWN)) { |
| 186 shelf_height = shelf_height_; |
| 187 work_area_delta = kWorkspaceAreaBottomInset; |
| 188 } else if (state.visibility_state == AUTO_HIDE && |
| 189 state.auto_hide_state == AUTO_HIDE_HIDDEN) { |
| 190 shelf_height = kAutoHideHeight; |
| 191 } |
| 192 y -= shelf_height; |
138 gfx::Rect status_bounds(status_->GetWindowScreenBounds()); | 193 gfx::Rect status_bounds(status_->GetWindowScreenBounds()); |
139 // The status widget should extend to the bottom and right edges. | 194 // The status widget should extend to the bottom and right edges. |
140 target_bounds->status_bounds = gfx::Rect( | 195 target_bounds->status_bounds = gfx::Rect( |
141 available_bounds.right() - status_bounds.width(), | 196 available_bounds.right() - status_bounds.width(), |
142 y + max_height_ - status_bounds.height(), | 197 y + shelf_height_ - status_bounds.height(), |
143 status_bounds.width(), status_bounds.height()); | 198 status_bounds.width(), status_bounds.height()); |
144 gfx::Rect launcher_bounds(launcher_->GetWindowScreenBounds()); | 199 if (launcher()) { |
145 target_bounds->launcher_bounds = gfx::Rect( | 200 gfx::Rect launcher_bounds(launcher()->GetWindowScreenBounds()); |
146 available_bounds.x(), y + (max_height_ - launcher_bounds.height()) / 2, | 201 target_bounds->launcher_bounds = gfx::Rect( |
147 available_bounds.width(), | 202 available_bounds.x(), |
148 launcher_bounds.height()); | 203 y + (shelf_height_ - launcher_bounds.height()) / 2, |
149 if (visible) | 204 available_bounds.width(), |
150 target_bounds->work_area_insets = gfx::Insets( | 205 launcher_bounds.height()); |
151 0, 0, max_height_ + kWorkspaceAreaBottomInset, 0); | 206 } |
| 207 target_bounds->opacity = |
| 208 (state.visibility_state == VISIBLE || |
| 209 state.visibility_state == AUTO_HIDE) ? 1.0f : 0.0f; |
| 210 target_bounds->work_area_insets = |
| 211 gfx::Insets(0, 0, shelf_height + work_area_delta, 0); |
152 } | 212 } |
153 | 213 |
154 void ShelfLayoutManager::OnImplicitAnimationsCompleted() { | 214 bool ShelfLayoutManager::GetShelfRendersBackground() const { |
155 TargetBounds target_bounds; | 215 return window_overlaps_shelf_ || state_.visibility_state == AUTO_HIDE; |
156 CalculateTargetBounds(visible_, &target_bounds); | |
157 Shell::GetInstance()->SetMonitorWorkAreaInsets( | |
158 Shell::GetRootWindow(), | |
159 target_bounds.work_area_insets); | |
160 } | 216 } |
161 | 217 |
162 } // namespace internal | 218 } // namespace internal |
163 } // namespace ash | 219 } // namespace ash |
OLD | NEW |