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 "ash/system/tray/system_tray.h" | 10 #include "ash/system/tray/system_tray.h" |
11 #include "base/auto_reset.h" | 11 #include "base/auto_reset.h" |
| 12 #include "ui/aura/event.h" |
| 13 #include "ui/aura/event_filter.h" |
12 #include "ui/aura/root_window.h" | 14 #include "ui/aura/root_window.h" |
13 #include "ui/gfx/compositor/layer.h" | 15 #include "ui/gfx/compositor/layer.h" |
14 #include "ui/gfx/compositor/layer_animation_observer.h" | 16 #include "ui/gfx/compositor/layer_animation_observer.h" |
15 #include "ui/gfx/compositor/layer_animator.h" | 17 #include "ui/gfx/compositor/layer_animator.h" |
16 #include "ui/gfx/compositor/scoped_layer_animation_settings.h" | 18 #include "ui/gfx/compositor/scoped_layer_animation_settings.h" |
17 #include "ui/views/widget/widget.h" | 19 #include "ui/views/widget/widget.h" |
18 | 20 |
19 namespace ash { | 21 namespace ash { |
20 namespace internal { | 22 namespace internal { |
21 | 23 |
22 namespace { | 24 namespace { |
23 | 25 |
24 // Height of the shelf when auto-hidden. | 26 // Delay before showing/hiding the launcher after the mouse enters the launcher. |
25 const int kAutoHideHeight = 2; | 27 const int kAutoHideDelayMS = 300; |
26 | 28 |
27 ui::Layer* GetLayer(views::Widget* widget) { | 29 ui::Layer* GetLayer(views::Widget* widget) { |
28 return widget->GetNativeView()->layer(); | 30 return widget->GetNativeView()->layer(); |
29 } | 31 } |
30 | 32 |
31 } // namespace | 33 } // namespace |
32 | 34 |
33 // static | 35 // static |
34 const int ShelfLayoutManager::kWorkspaceAreaBottomInset = 2; | 36 const int ShelfLayoutManager::kWorkspaceAreaBottomInset = 2; |
35 | 37 |
| 38 // static |
| 39 const int ShelfLayoutManager::kAutoHideHeight = 2; |
| 40 |
| 41 // Notifies ShelfLayoutManager any time the mouse moves. |
| 42 class ShelfLayoutManager::AutoHideEventFilter : public aura::EventFilter { |
| 43 public: |
| 44 explicit AutoHideEventFilter(ShelfLayoutManager* shelf); |
| 45 virtual ~AutoHideEventFilter(); |
| 46 |
| 47 // Overridden from aura::EventFilter: |
| 48 virtual bool PreHandleKeyEvent(aura::Window* target, |
| 49 aura::KeyEvent* event) OVERRIDE; |
| 50 virtual bool PreHandleMouseEvent(aura::Window* target, |
| 51 aura::MouseEvent* event) OVERRIDE; |
| 52 virtual ui::TouchStatus PreHandleTouchEvent(aura::Window* target, |
| 53 aura::TouchEvent* event) OVERRIDE; |
| 54 virtual ui::GestureStatus PreHandleGestureEvent( |
| 55 aura::Window* target, |
| 56 aura::GestureEvent* event) OVERRIDE; |
| 57 |
| 58 private: |
| 59 ShelfLayoutManager* shelf_; |
| 60 |
| 61 DISALLOW_COPY_AND_ASSIGN(AutoHideEventFilter); |
| 62 }; |
| 63 |
| 64 ShelfLayoutManager::AutoHideEventFilter::AutoHideEventFilter( |
| 65 ShelfLayoutManager* shelf) |
| 66 : shelf_(shelf) { |
| 67 Shell::GetInstance()->AddRootWindowEventFilter(this); |
| 68 } |
| 69 |
| 70 ShelfLayoutManager::AutoHideEventFilter::~AutoHideEventFilter() { |
| 71 Shell::GetInstance()->RemoveRootWindowEventFilter(this); |
| 72 } |
| 73 |
| 74 bool ShelfLayoutManager::AutoHideEventFilter::PreHandleKeyEvent( |
| 75 aura::Window* target, |
| 76 aura::KeyEvent* event) { |
| 77 return false; // Always let the event propagate. |
| 78 } |
| 79 |
| 80 bool ShelfLayoutManager::AutoHideEventFilter::PreHandleMouseEvent( |
| 81 aura::Window* target, |
| 82 aura::MouseEvent* event) { |
| 83 if (event->type() == ui::ET_MOUSE_MOVED) |
| 84 shelf_->UpdateAutoHideState(); |
| 85 return false; // Not handled. |
| 86 } |
| 87 |
| 88 ui::TouchStatus ShelfLayoutManager::AutoHideEventFilter::PreHandleTouchEvent( |
| 89 aura::Window* target, |
| 90 aura::TouchEvent* event) { |
| 91 return ui::TOUCH_STATUS_UNKNOWN; // Not handled. |
| 92 } |
| 93 |
| 94 ui::GestureStatus |
| 95 ShelfLayoutManager::AutoHideEventFilter::PreHandleGestureEvent( |
| 96 aura::Window* target, |
| 97 aura::GestureEvent* event) { |
| 98 return ui::GESTURE_STATUS_UNKNOWN; // Not handled. |
| 99 } |
| 100 |
36 //////////////////////////////////////////////////////////////////////////////// | 101 //////////////////////////////////////////////////////////////////////////////// |
37 // ShelfLayoutManager, public: | 102 // ShelfLayoutManager, public: |
38 | 103 |
39 ShelfLayoutManager::ShelfLayoutManager(views::Widget* status) | 104 ShelfLayoutManager::ShelfLayoutManager(views::Widget* status) |
40 : in_layout_(false), | 105 : in_layout_(false), |
41 shelf_height_(status->GetWindowScreenBounds().height()), | 106 shelf_height_(status->GetWindowScreenBounds().height()), |
42 launcher_(NULL), | 107 launcher_(NULL), |
43 status_(status), | 108 status_(status), |
44 window_overlaps_shelf_(false), | 109 window_overlaps_shelf_(false) { |
45 root_window_(NULL) { | |
46 root_window_ = status->GetNativeView()->GetRootWindow(); | |
47 } | 110 } |
48 | 111 |
49 ShelfLayoutManager::~ShelfLayoutManager() { | 112 ShelfLayoutManager::~ShelfLayoutManager() { |
50 } | 113 } |
51 | 114 |
52 gfx::Rect ShelfLayoutManager::GetMaximizedWindowBounds( | 115 gfx::Rect ShelfLayoutManager::GetMaximizedWindowBounds( |
53 aura::Window* window) const { | 116 aura::Window* window) const { |
54 // TODO: needs to be multi-mon aware. | 117 // TODO: needs to be multi-mon aware. |
55 gfx::Rect bounds(gfx::Screen::GetMonitorAreaNearestWindow(window)); | 118 gfx::Rect bounds(gfx::Screen::GetMonitorAreaNearestWindow(window)); |
56 bounds.set_height(bounds.height() - kAutoHideHeight); | 119 bounds.set_height(bounds.height() - kAutoHideHeight); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 launcher_->SetStatusWidth( | 151 launcher_->SetStatusWidth( |
89 target_bounds.status_bounds.width()); | 152 target_bounds.status_bounds.width()); |
90 } | 153 } |
91 GetLayer(status_)->SetOpacity(target_bounds.opacity); | 154 GetLayer(status_)->SetOpacity(target_bounds.opacity); |
92 status_->SetBounds(target_bounds.status_bounds); | 155 status_->SetBounds(target_bounds.status_bounds); |
93 Shell::GetInstance()->SetMonitorWorkAreaInsets( | 156 Shell::GetInstance()->SetMonitorWorkAreaInsets( |
94 Shell::GetRootWindow(), | 157 Shell::GetRootWindow(), |
95 target_bounds.work_area_insets); | 158 target_bounds.work_area_insets); |
96 } | 159 } |
97 | 160 |
98 void ShelfLayoutManager::SetState(VisibilityState visibility_state, | 161 void ShelfLayoutManager::SetState(VisibilityState visibility_state) { |
99 AutoHideState auto_hide_state) { | |
100 State state; | 162 State state; |
101 state.visibility_state = visibility_state; | 163 state.visibility_state = visibility_state; |
102 state.auto_hide_state = auto_hide_state; | 164 state.auto_hide_state = CalculateAutoHideState(visibility_state); |
103 | 165 |
104 if (state_.Equals(state)) | 166 if (state_.Equals(state)) |
105 return; // Nothing changed. | 167 return; // Nothing changed. |
106 | 168 |
| 169 if (state.visibility_state == AUTO_HIDE) { |
| 170 // When state is AUTO_HIDE we need to track when the mouse is over the |
| 171 // launcher to unhide the shelf. AutoHideEventFilter does that for us. |
| 172 if (!event_filter_.get()) |
| 173 event_filter_.reset(new AutoHideEventFilter(this)); |
| 174 } else { |
| 175 event_filter_.reset(NULL); |
| 176 } |
| 177 |
| 178 auto_hide_timer_.Stop(); |
| 179 |
107 // Animating the background when transitioning from auto-hide & hidden to | 180 // Animating the background when transitioning from auto-hide & hidden to |
108 // visibile is janking. Update the background immediately in this case. | 181 // visibile is janking. Update the background immediately in this case. |
109 internal::BackgroundAnimator::ChangeType change_type = | 182 internal::BackgroundAnimator::ChangeType change_type = |
110 (state_.visibility_state == AUTO_HIDE && | 183 (state_.visibility_state == AUTO_HIDE && |
111 state_.auto_hide_state == AUTO_HIDE_HIDDEN && | 184 state_.auto_hide_state == AUTO_HIDE_HIDDEN && |
112 state.visibility_state == VISIBLE) ? | 185 state.visibility_state == VISIBLE) ? |
113 internal::BackgroundAnimator::CHANGE_IMMEDIATE : | 186 internal::BackgroundAnimator::CHANGE_IMMEDIATE : |
114 internal::BackgroundAnimator::CHANGE_ANIMATE; | 187 internal::BackgroundAnimator::CHANGE_ANIMATE; |
115 StopAnimating(); | 188 StopAnimating(); |
116 state_ = state; | 189 state_ = state; |
(...skipping 14 matching lines...) Expand all Loading... |
131 base::TimeDelta::FromMilliseconds(130)); | 204 base::TimeDelta::FromMilliseconds(130)); |
132 status_animation_setter.SetTweenType(ui::Tween::EASE_OUT); | 205 status_animation_setter.SetTweenType(ui::Tween::EASE_OUT); |
133 GetLayer(status_)->SetBounds(target_bounds.status_bounds); | 206 GetLayer(status_)->SetBounds(target_bounds.status_bounds); |
134 GetLayer(status_)->SetOpacity(target_bounds.opacity); | 207 GetLayer(status_)->SetOpacity(target_bounds.opacity); |
135 Shell::GetInstance()->SetMonitorWorkAreaInsets( | 208 Shell::GetInstance()->SetMonitorWorkAreaInsets( |
136 Shell::GetRootWindow(), | 209 Shell::GetRootWindow(), |
137 target_bounds.work_area_insets); | 210 target_bounds.work_area_insets); |
138 UpdateShelfBackground(change_type); | 211 UpdateShelfBackground(change_type); |
139 } | 212 } |
140 | 213 |
| 214 void ShelfLayoutManager::UpdateAutoHideState() { |
| 215 if (CalculateAutoHideState(state_.visibility_state) != |
| 216 state_.auto_hide_state) { |
| 217 // Don't change state immediately. Instead delay for a bit. |
| 218 if (!auto_hide_timer_.IsRunning()) { |
| 219 auto_hide_timer_.Start( |
| 220 FROM_HERE, |
| 221 base::TimeDelta::FromMilliseconds(kAutoHideDelayMS), |
| 222 this, &ShelfLayoutManager::UpdateAutoHideStateNow); |
| 223 } |
| 224 } else { |
| 225 auto_hide_timer_.Stop(); |
| 226 } |
| 227 } |
| 228 |
141 void ShelfLayoutManager::SetWindowOverlapsShelf(bool value) { | 229 void ShelfLayoutManager::SetWindowOverlapsShelf(bool value) { |
142 window_overlaps_shelf_ = value; | 230 window_overlaps_shelf_ = value; |
143 UpdateShelfBackground(internal::BackgroundAnimator::CHANGE_ANIMATE); | 231 UpdateShelfBackground(internal::BackgroundAnimator::CHANGE_ANIMATE); |
144 } | 232 } |
145 | 233 |
146 //////////////////////////////////////////////////////////////////////////////// | 234 //////////////////////////////////////////////////////////////////////////////// |
147 // ShelfLayoutManager, aura::LayoutManager implementation: | 235 // ShelfLayoutManager, aura::LayoutManager implementation: |
148 | 236 |
149 void ShelfLayoutManager::OnWindowResized() { | 237 void ShelfLayoutManager::OnWindowResized() { |
150 LayoutShelf(); | 238 LayoutShelf(); |
(...skipping 21 matching lines...) Expand all Loading... |
172 | 260 |
173 void ShelfLayoutManager::StopAnimating() { | 261 void ShelfLayoutManager::StopAnimating() { |
174 if (launcher_widget()) | 262 if (launcher_widget()) |
175 GetLayer(launcher_widget())->GetAnimator()->StopAnimating(); | 263 GetLayer(launcher_widget())->GetAnimator()->StopAnimating(); |
176 GetLayer(status_)->GetAnimator()->StopAnimating(); | 264 GetLayer(status_)->GetAnimator()->StopAnimating(); |
177 } | 265 } |
178 | 266 |
179 void ShelfLayoutManager::CalculateTargetBounds( | 267 void ShelfLayoutManager::CalculateTargetBounds( |
180 const State& state, | 268 const State& state, |
181 TargetBounds* target_bounds) const { | 269 TargetBounds* target_bounds) const { |
182 const gfx::Rect& available_bounds(root_window_->bounds()); | 270 const gfx::Rect& available_bounds( |
| 271 status_->GetNativeView()->GetRootWindow()->bounds()); |
183 int y = available_bounds.bottom(); | 272 int y = available_bounds.bottom(); |
184 int shelf_height = 0; | 273 int shelf_height = 0; |
185 int work_area_delta = 0; | 274 int work_area_delta = 0; |
186 if (state.visibility_state == VISIBLE || | 275 if (state.visibility_state == VISIBLE || |
187 (state.visibility_state == AUTO_HIDE && | 276 (state.visibility_state == AUTO_HIDE && |
188 state.auto_hide_state == AUTO_HIDE_SHOWN)) { | 277 state.auto_hide_state == AUTO_HIDE_SHOWN)) { |
189 shelf_height = shelf_height_; | 278 shelf_height = shelf_height_; |
190 work_area_delta = kWorkspaceAreaBottomInset; | 279 work_area_delta = kWorkspaceAreaBottomInset; |
191 } else if (state.visibility_state == AUTO_HIDE && | 280 } else if (state.visibility_state == AUTO_HIDE && |
192 state.auto_hide_state == AUTO_HIDE_HIDDEN) { | 281 state.auto_hide_state == AUTO_HIDE_HIDDEN) { |
(...skipping 28 matching lines...) Expand all Loading... |
221 launcher_->SetPaintsBackground(launcher_paints, type); | 310 launcher_->SetPaintsBackground(launcher_paints, type); |
222 // SystemTray normally draws a background, but we don't want it to draw a | 311 // SystemTray normally draws a background, but we don't want it to draw a |
223 // background when the launcher does. | 312 // background when the launcher does. |
224 Shell::GetInstance()->tray()->SetPaintsBackground(!launcher_paints, type); | 313 Shell::GetInstance()->tray()->SetPaintsBackground(!launcher_paints, type); |
225 } | 314 } |
226 | 315 |
227 bool ShelfLayoutManager::GetLauncherPaintsBackground() const { | 316 bool ShelfLayoutManager::GetLauncherPaintsBackground() const { |
228 return window_overlaps_shelf_ || state_.visibility_state == AUTO_HIDE; | 317 return window_overlaps_shelf_ || state_.visibility_state == AUTO_HIDE; |
229 } | 318 } |
230 | 319 |
| 320 void ShelfLayoutManager::UpdateAutoHideStateNow() { |
| 321 SetState(state_.visibility_state); |
| 322 } |
| 323 |
| 324 ShelfLayoutManager::AutoHideState ShelfLayoutManager::CalculateAutoHideState( |
| 325 VisibilityState visibility_state) const { |
| 326 if (visibility_state != AUTO_HIDE || !launcher_widget()) |
| 327 return AUTO_HIDE_HIDDEN; |
| 328 |
| 329 Shell* shell = Shell::GetInstance(); |
| 330 if (shell->tray()->showing_bubble()) |
| 331 return AUTO_HIDE_SHOWN; // Always show if a bubble is open from the shelf. |
| 332 |
| 333 aura::RootWindow* root = launcher_widget()->GetNativeView()->GetRootWindow(); |
| 334 bool mouse_over_launcher = |
| 335 launcher_widget()->GetWindowScreenBounds().Contains( |
| 336 root->last_mouse_location()); |
| 337 return mouse_over_launcher ? AUTO_HIDE_SHOWN : AUTO_HIDE_HIDDEN; |
| 338 } |
| 339 |
231 } // namespace internal | 340 } // namespace internal |
232 } // namespace ash | 341 } // namespace ash |
OLD | NEW |