| 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/shelf/shelf_layout_manager.h" | 5 #include "ash/shelf/shelf_layout_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 #include <cstring> | 9 #include <cstring> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 | 180 |
| 181 DISALLOW_COPY_AND_ASSIGN(UpdateShelfObserver); | 181 DISALLOW_COPY_AND_ASSIGN(UpdateShelfObserver); |
| 182 }; | 182 }; |
| 183 | 183 |
| 184 // ShelfLayoutManager ---------------------------------------------------------- | 184 // ShelfLayoutManager ---------------------------------------------------------- |
| 185 | 185 |
| 186 ShelfLayoutManager::ShelfLayoutManager(ShelfWidget* shelf) | 186 ShelfLayoutManager::ShelfLayoutManager(ShelfWidget* shelf) |
| 187 : SnapToPixelLayoutManager(shelf->GetNativeView()->parent()), | 187 : SnapToPixelLayoutManager(shelf->GetNativeView()->parent()), |
| 188 root_window_(shelf->GetNativeView()->GetRootWindow()), | 188 root_window_(shelf->GetNativeView()->GetRootWindow()), |
| 189 updating_bounds_(false), | 189 updating_bounds_(false), |
| 190 auto_hide_behavior_(SHELF_AUTO_HIDE_BEHAVIOR_NEVER), | |
| 191 alignment_(SHELF_ALIGNMENT_BOTTOM), | |
| 192 shelf_(shelf), | 190 shelf_(shelf), |
| 193 workspace_controller_(NULL), | 191 workspace_controller_(NULL), |
| 194 window_overlaps_shelf_(false), | 192 window_overlaps_shelf_(false), |
| 195 mouse_over_shelf_when_auto_hide_timer_started_(false), | 193 mouse_over_shelf_when_auto_hide_timer_started_(false), |
| 196 bezel_event_filter_(new ShelfBezelEventFilter(this)), | 194 bezel_event_filter_(new ShelfBezelEventFilter(this)), |
| 197 gesture_drag_status_(GESTURE_DRAG_NONE), | 195 gesture_drag_status_(GESTURE_DRAG_NONE), |
| 198 gesture_drag_amount_(0.f), | 196 gesture_drag_amount_(0.f), |
| 199 gesture_drag_auto_hide_state_(SHELF_AUTO_HIDE_SHOWN), | 197 gesture_drag_auto_hide_state_(SHELF_AUTO_HIDE_SHOWN), |
| 200 update_shelf_observer_(NULL), | 198 update_shelf_observer_(NULL), |
| 201 chromevox_panel_height_(0), | 199 chromevox_panel_height_(0), |
| 202 duration_override_in_ms_(0) { | 200 duration_override_in_ms_(0) { |
| 203 Shell::GetInstance()->AddShellObserver(this); | 201 Shell::GetInstance()->AddShellObserver(this); |
| 204 Shell::GetInstance()->lock_state_controller()->AddObserver(this); | 202 Shell::GetInstance()->lock_state_controller()->AddObserver(this); |
| 205 aura::client::GetActivationClient(root_window_)->AddObserver(this); | 203 aura::client::GetActivationClient(root_window_)->AddObserver(this); |
| 206 Shell::GetInstance()->session_state_delegate()->AddSessionStateObserver(this); | 204 Shell::GetInstance()->session_state_delegate()->AddSessionStateObserver(this); |
| 207 } | 205 } |
| 208 | 206 |
| 209 ShelfLayoutManager::~ShelfLayoutManager() { | 207 ShelfLayoutManager::~ShelfLayoutManager() { |
| 210 if (update_shelf_observer_) | 208 if (update_shelf_observer_) |
| 211 update_shelf_observer_->Detach(); | 209 update_shelf_observer_->Detach(); |
| 212 | 210 |
| 213 FOR_EACH_OBSERVER(ShelfLayoutManagerObserver, observers_, WillDeleteShelf()); | 211 FOR_EACH_OBSERVER(ShelfLayoutManagerObserver, observers_, WillDeleteShelf()); |
| 214 Shell::GetInstance()->RemoveShellObserver(this); | 212 Shell::GetInstance()->RemoveShellObserver(this); |
| 215 Shell::GetInstance()->lock_state_controller()->RemoveObserver(this); | 213 Shell::GetInstance()->lock_state_controller()->RemoveObserver(this); |
| 216 Shell::GetInstance()-> | 214 Shell::GetInstance()-> |
| 217 session_state_delegate()->RemoveSessionStateObserver(this); | 215 session_state_delegate()->RemoveSessionStateObserver(this); |
| 218 } | 216 } |
| 219 | 217 |
| 220 void ShelfLayoutManager::SetAutoHideBehavior(ShelfAutoHideBehavior behavior) { | |
| 221 if (auto_hide_behavior_ == behavior) | |
| 222 return; | |
| 223 auto_hide_behavior_ = behavior; | |
| 224 UpdateVisibilityState(); | |
| 225 FOR_EACH_OBSERVER(ShelfLayoutManagerObserver, observers_, | |
| 226 OnAutoHideBehaviorChanged(root_window_, | |
| 227 auto_hide_behavior_)); | |
| 228 } | |
| 229 | |
| 230 void ShelfLayoutManager::PrepareForShutdown() { | 218 void ShelfLayoutManager::PrepareForShutdown() { |
| 231 // Clear all event filters, otherwise sometimes those filters may catch | 219 // Clear all event filters, otherwise sometimes those filters may catch |
| 232 // synthesized mouse event and cause crashes during the shutdown. | 220 // synthesized mouse event and cause crashes during the shutdown. |
| 233 set_workspace_controller(NULL); | 221 set_workspace_controller(NULL); |
| 234 auto_hide_event_filter_.reset(); | 222 auto_hide_event_filter_.reset(); |
| 235 bezel_event_filter_.reset(); | 223 bezel_event_filter_.reset(); |
| 236 // Stop observing window change, otherwise we can attempt to update a | 224 // Stop observing window change, otherwise we can attempt to update a |
| 237 // partially destructed shelf. | 225 // partially destructed shelf. |
| 238 aura::client::GetActivationClient(root_window_)->RemoveObserver(this); | 226 aura::client::GetActivationClient(root_window_)->RemoveObserver(this); |
| 239 } | 227 } |
| 240 | 228 |
| 241 bool ShelfLayoutManager::IsVisible() const { | 229 bool ShelfLayoutManager::IsVisible() const { |
| 242 // status_area_widget() may be NULL during the shutdown. | 230 // status_area_widget() may be NULL during the shutdown. |
| 243 return shelf_->status_area_widget() && | 231 return shelf_->status_area_widget() && |
| 244 shelf_->status_area_widget()->IsVisible() && | 232 shelf_->status_area_widget()->IsVisible() && |
| 245 (state_.visibility_state == SHELF_VISIBLE || | 233 (state_.visibility_state == SHELF_VISIBLE || |
| 246 (state_.visibility_state == SHELF_AUTO_HIDE && | 234 (state_.visibility_state == SHELF_AUTO_HIDE && |
| 247 state_.auto_hide_state == SHELF_AUTO_HIDE_SHOWN)); | 235 state_.auto_hide_state == SHELF_AUTO_HIDE_SHOWN)); |
| 248 } | 236 } |
| 249 | 237 |
| 250 void ShelfLayoutManager::SetAlignment(ShelfAlignment alignment) { | |
| 251 if (alignment_ == alignment) | |
| 252 return; | |
| 253 | |
| 254 alignment_ = alignment; | |
| 255 // The shelf will itself move to the bottom while locked or obscured by user | |
| 256 // login. If a request is sent to move while being obscured, we postpone the | |
| 257 // move until the user session is resumed. | |
| 258 if (!IsAlignmentLocked()) { | |
| 259 shelf_->SetAlignment(alignment); | |
| 260 LayoutShelf(); | |
| 261 Shell::GetInstance()->OnShelfAlignmentChanged( | |
| 262 shelf_->GetNativeWindow()->GetRootWindow()); | |
| 263 } | |
| 264 } | |
| 265 | |
| 266 ShelfAlignment ShelfLayoutManager::GetAlignment() const { | |
| 267 // When the screen is locked or a user gets added, the shelf is forced into | |
| 268 // bottom alignment. | |
| 269 if (IsAlignmentLocked()) | |
| 270 return SHELF_ALIGNMENT_BOTTOM; | |
| 271 return alignment_; | |
| 272 } | |
| 273 | |
| 274 gfx::Rect ShelfLayoutManager::GetIdealBounds() { | 238 gfx::Rect ShelfLayoutManager::GetIdealBounds() { |
| 275 gfx::Rect rect(ScreenUtil::GetDisplayBoundsInParent(shelf_->GetNativeView())); | 239 gfx::Rect rect(ScreenUtil::GetDisplayBoundsInParent(shelf_->GetNativeView())); |
| 276 return SelectValueForShelfAlignment( | 240 return SelectValueForShelfAlignment( |
| 277 gfx::Rect(rect.x(), rect.bottom() - kShelfSize, rect.width(), kShelfSize), | 241 gfx::Rect(rect.x(), rect.bottom() - kShelfSize, rect.width(), kShelfSize), |
| 278 gfx::Rect(rect.x(), rect.y(), kShelfSize, rect.height()), | 242 gfx::Rect(rect.x(), rect.y(), kShelfSize, rect.height()), |
| 279 gfx::Rect(rect.right() - kShelfSize, rect.y(), kShelfSize, | 243 gfx::Rect(rect.right() - kShelfSize, rect.y(), kShelfSize, |
| 280 rect.height())); | 244 rect.height())); |
| 281 } | 245 } |
| 282 | 246 |
| 283 void ShelfLayoutManager::LayoutShelf() { | 247 void ShelfLayoutManager::LayoutShelf() { |
| 284 TargetBounds target_bounds; | 248 if (shelf_->shelf()) { |
| 285 CalculateTargetBounds(state_, &target_bounds); | 249 TargetBounds target_bounds; |
| 286 UpdateBoundsAndOpacity(target_bounds, false, NULL); | 250 CalculateTargetBounds(state_, &target_bounds); |
| 251 UpdateBoundsAndOpacity(target_bounds, false, NULL); |
| 287 | 252 |
| 288 if (shelf_->shelf()) { | |
| 289 // Update insets in ShelfWindowTargeter when shelf bounds change. | 253 // Update insets in ShelfWindowTargeter when shelf bounds change. |
| 290 FOR_EACH_OBSERVER(ShelfLayoutManagerObserver, observers_, | 254 FOR_EACH_OBSERVER(ShelfLayoutManagerObserver, observers_, |
| 291 WillChangeVisibilityState(visibility_state())); | 255 WillChangeVisibilityState(visibility_state())); |
| 292 } | 256 } |
| 293 } | 257 } |
| 294 | 258 |
| 295 ShelfVisibilityState ShelfLayoutManager::CalculateShelfVisibility() { | 259 ShelfVisibilityState ShelfLayoutManager::CalculateShelfVisibility() { |
| 296 switch(auto_hide_behavior_) { | 260 switch (auto_hide_behavior()) { |
| 297 case SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS: | 261 case SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS: |
| 298 return SHELF_AUTO_HIDE; | 262 return SHELF_AUTO_HIDE; |
| 299 case SHELF_AUTO_HIDE_BEHAVIOR_NEVER: | 263 case SHELF_AUTO_HIDE_BEHAVIOR_NEVER: |
| 300 return SHELF_VISIBLE; | 264 return SHELF_VISIBLE; |
| 301 case SHELF_AUTO_HIDE_ALWAYS_HIDDEN: | 265 case SHELF_AUTO_HIDE_ALWAYS_HIDDEN: |
| 302 return SHELF_HIDDEN; | 266 return SHELF_HIDDEN; |
| 303 } | 267 } |
| 304 return SHELF_VISIBLE; | 268 return SHELF_VISIBLE; |
| 305 } | 269 } |
| 306 | 270 |
| 307 void ShelfLayoutManager::UpdateVisibilityState() { | 271 void ShelfLayoutManager::UpdateVisibilityState() { |
| 308 // Bail out early when there is no |workspace_controller_|, which happens | 272 // Bail out early when there is no |workspace_controller_|, which happens |
| 309 // during shutdown after PrepareForShutdown. | 273 // during shutdown after PrepareForShutdown. Also bail before a shelf exists. |
| 310 if (!workspace_controller_) | 274 if (!workspace_controller_ || !shelf_->shelf()) |
| 311 return; | 275 return; |
| 312 | 276 |
| 313 if (state_.is_screen_locked || state_.is_adding_user_screen) { | 277 if (state_.is_screen_locked || state_.is_adding_user_screen) { |
| 314 SetState(SHELF_VISIBLE); | 278 SetState(SHELF_VISIBLE); |
| 315 } else { | 279 } else { |
| 316 // TODO(zelidrag): Verify shelf drag animation still shows on the device | 280 // TODO(zelidrag): Verify shelf drag animation still shows on the device |
| 317 // when we are in SHELF_AUTO_HIDE_ALWAYS_HIDDEN. | 281 // when we are in SHELF_AUTO_HIDE_ALWAYS_HIDDEN. |
| 318 WorkspaceWindowState window_state(workspace_controller_->GetWindowState()); | 282 WorkspaceWindowState window_state(workspace_controller_->GetWindowState()); |
| 319 switch (window_state) { | 283 switch (window_state) { |
| 320 case WORKSPACE_WINDOW_STATE_FULL_SCREEN: { | 284 case WORKSPACE_WINDOW_STATE_FULL_SCREEN: { |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 SHELF_AUTO_HIDE_HIDDEN : SHELF_AUTO_HIDE_SHOWN; | 424 SHELF_AUTO_HIDE_HIDDEN : SHELF_AUTO_HIDE_SHOWN; |
| 461 ShelfAutoHideBehavior new_auto_hide_behavior = | 425 ShelfAutoHideBehavior new_auto_hide_behavior = |
| 462 gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN ? | 426 gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN ? |
| 463 SHELF_AUTO_HIDE_BEHAVIOR_NEVER : SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS; | 427 SHELF_AUTO_HIDE_BEHAVIOR_NEVER : SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS; |
| 464 | 428 |
| 465 // When in fullscreen and the shelf is forced to be auto hidden, the auto hide | 429 // When in fullscreen and the shelf is forced to be auto hidden, the auto hide |
| 466 // behavior affects neither the visibility state nor the auto hide state. Set | 430 // behavior affects neither the visibility state nor the auto hide state. Set |
| 467 // |gesture_drag_status_| to GESTURE_DRAG_COMPLETE_IN_PROGRESS to set the auto | 431 // |gesture_drag_status_| to GESTURE_DRAG_COMPLETE_IN_PROGRESS to set the auto |
| 468 // hide state to |gesture_drag_auto_hide_state_|. | 432 // hide state to |gesture_drag_auto_hide_state_|. |
| 469 gesture_drag_status_ = GESTURE_DRAG_COMPLETE_IN_PROGRESS; | 433 gesture_drag_status_ = GESTURE_DRAG_COMPLETE_IN_PROGRESS; |
| 470 if (auto_hide_behavior_ != new_auto_hide_behavior) | 434 if (auto_hide_behavior() != new_auto_hide_behavior) |
| 471 SetAutoHideBehavior(new_auto_hide_behavior); | 435 SetAutoHideBehavior(new_auto_hide_behavior); |
| 472 else | 436 else |
| 473 UpdateVisibilityState(); | 437 UpdateVisibilityState(); |
| 474 gesture_drag_status_ = GESTURE_DRAG_NONE; | 438 gesture_drag_status_ = GESTURE_DRAG_NONE; |
| 475 } | 439 } |
| 476 | 440 |
| 477 void ShelfLayoutManager::CancelGestureDrag() { | 441 void ShelfLayoutManager::CancelGestureDrag() { |
| 478 gesture_drag_status_ = GESTURE_DRAG_CANCEL_IN_PROGRESS; | 442 gesture_drag_status_ = GESTURE_DRAG_CANCEL_IN_PROGRESS; |
| 479 UpdateVisibilityState(); | 443 UpdateVisibilityState(); |
| 480 gesture_drag_status_ = GESTURE_DRAG_NONE; | 444 gesture_drag_status_ = GESTURE_DRAG_NONE; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 504 } | 468 } |
| 505 } | 469 } |
| 506 | 470 |
| 507 void ShelfLayoutManager::OnLockStateChanged(bool locked) { | 471 void ShelfLayoutManager::OnLockStateChanged(bool locked) { |
| 508 // Force the shelf to layout for alignment (bottom if locked, restore | 472 // Force the shelf to layout for alignment (bottom if locked, restore |
| 509 // the previous alignment otherwise). | 473 // the previous alignment otherwise). |
| 510 state_.is_screen_locked = locked; | 474 state_.is_screen_locked = locked; |
| 511 UpdateShelfVisibilityAfterLoginUIChange(); | 475 UpdateShelfVisibilityAfterLoginUIChange(); |
| 512 } | 476 } |
| 513 | 477 |
| 478 void ShelfLayoutManager::OnShelfAlignmentChanged(aura::Window* root_window) { |
| 479 LayoutShelf(); |
| 480 } |
| 481 |
| 482 void ShelfLayoutManager::OnShelfAutoHideBehaviorChanged( |
| 483 aura::Window* root_window) { |
| 484 UpdateVisibilityState(); |
| 485 } |
| 486 |
| 514 void ShelfLayoutManager::OnWindowActivated( | 487 void ShelfLayoutManager::OnWindowActivated( |
| 515 aura::client::ActivationChangeObserver::ActivationReason reason, | 488 aura::client::ActivationChangeObserver::ActivationReason reason, |
| 516 aura::Window* gained_active, | 489 aura::Window* gained_active, |
| 517 aura::Window* lost_active) { | 490 aura::Window* lost_active) { |
| 518 UpdateAutoHideStateNow(); | 491 UpdateAutoHideStateNow(); |
| 519 } | 492 } |
| 520 | 493 |
| 521 bool ShelfLayoutManager::IsHorizontalAlignment() const { | 494 bool ShelfLayoutManager::IsHorizontalAlignment() const { |
| 522 return GetAlignment() == SHELF_ALIGNMENT_BOTTOM; | 495 return GetAlignment() == SHELF_ALIGNMENT_BOTTOM; |
| 523 } | 496 } |
| 524 | 497 |
| 498 bool ShelfLayoutManager::IsAlignmentLocked() const { |
| 499 if (state_.is_screen_locked) |
| 500 return true; |
| 501 // The session state becomes active at the start of transitioning to a user |
| 502 // session, however the session is considered blocked until the full UI is |
| 503 // ready. Exit early to allow for proper layout. |
| 504 SessionStateDelegate* session_state_delegate = |
| 505 Shell::GetInstance()->session_state_delegate(); |
| 506 if (session_state_delegate->GetSessionState() == |
| 507 SessionStateDelegate::SESSION_STATE_ACTIVE) { |
| 508 return false; |
| 509 } |
| 510 if (session_state_delegate->IsUserSessionBlocked() || |
| 511 state_.is_adding_user_screen) { |
| 512 return true; |
| 513 } |
| 514 return false; |
| 515 } |
| 516 |
| 525 void ShelfLayoutManager::SetChromeVoxPanelHeight(int height) { | 517 void ShelfLayoutManager::SetChromeVoxPanelHeight(int height) { |
| 526 chromevox_panel_height_ = height; | 518 chromevox_panel_height_ = height; |
| 527 LayoutShelf(); | 519 LayoutShelf(); |
| 528 } | 520 } |
| 529 | 521 |
| 530 //////////////////////////////////////////////////////////////////////////////// | 522 //////////////////////////////////////////////////////////////////////////////// |
| 531 // ShelfLayoutManager, private: | 523 // ShelfLayoutManager, private: |
| 532 | 524 |
| 533 ShelfLayoutManager::TargetBounds::TargetBounds() | 525 ShelfLayoutManager::TargetBounds::TargetBounds() |
| 534 : opacity(0.0f), status_opacity(0.0f) {} | 526 : opacity(0.0f), status_opacity(0.0f) {} |
| (...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1118 UpdateShelfVisibilityAfterLoginUIChange(); | 1110 UpdateShelfVisibilityAfterLoginUIChange(); |
| 1119 return; | 1111 return; |
| 1120 } | 1112 } |
| 1121 TargetBounds target_bounds; | 1113 TargetBounds target_bounds; |
| 1122 CalculateTargetBounds(state_, &target_bounds); | 1114 CalculateTargetBounds(state_, &target_bounds); |
| 1123 UpdateBoundsAndOpacity(target_bounds, true, NULL); | 1115 UpdateBoundsAndOpacity(target_bounds, true, NULL); |
| 1124 UpdateVisibilityState(); | 1116 UpdateVisibilityState(); |
| 1125 } | 1117 } |
| 1126 | 1118 |
| 1127 void ShelfLayoutManager::UpdateShelfVisibilityAfterLoginUIChange() { | 1119 void ShelfLayoutManager::UpdateShelfVisibilityAfterLoginUIChange() { |
| 1128 shelf_->SetAlignment(GetAlignment()); | |
| 1129 UpdateVisibilityState(); | 1120 UpdateVisibilityState(); |
| 1130 LayoutShelf(); | 1121 LayoutShelf(); |
| 1122 // The shelf alignment may have changed when it was unlocked. |
| 1131 Shell::GetInstance()->OnShelfAlignmentChanged( | 1123 Shell::GetInstance()->OnShelfAlignmentChanged( |
| 1132 shelf_->GetNativeWindow()->GetRootWindow()); | 1124 shelf_->GetNativeWindow()->GetRootWindow()); |
| 1133 } | 1125 } |
| 1134 | 1126 |
| 1135 bool ShelfLayoutManager::IsAlignmentLocked() const { | |
| 1136 if (state_.is_screen_locked) | |
| 1137 return true; | |
| 1138 // The session state becomes active at the start of transitioning to a user | |
| 1139 // session, however the session is considered blocked until the full UI is | |
| 1140 // ready. Exit early to allow for proper layout. | |
| 1141 SessionStateDelegate* session_state_delegate = | |
| 1142 Shell::GetInstance()->session_state_delegate(); | |
| 1143 if (session_state_delegate->GetSessionState() == | |
| 1144 SessionStateDelegate::SESSION_STATE_ACTIVE) { | |
| 1145 return false; | |
| 1146 } | |
| 1147 if (session_state_delegate->IsUserSessionBlocked() || | |
| 1148 state_.is_adding_user_screen) { | |
| 1149 return true; | |
| 1150 } | |
| 1151 return false; | |
| 1152 } | |
| 1153 | |
| 1154 } // namespace ash | 1127 } // namespace ash |
| OLD | NEW |