| 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 <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 #include "ash/common/wm/wm_screen_util.h" | 21 #include "ash/common/wm/wm_screen_util.h" |
| 22 #include "ash/common/wm_lookup.h" | 22 #include "ash/common/wm_lookup.h" |
| 23 #include "ash/common/wm_root_window_controller.h" | 23 #include "ash/common/wm_root_window_controller.h" |
| 24 #include "ash/common/wm_root_window_controller_observer.h" | 24 #include "ash/common/wm_root_window_controller_observer.h" |
| 25 #include "ash/common/wm_shell.h" | 25 #include "ash/common/wm_shell.h" |
| 26 #include "ash/common/wm_window.h" | 26 #include "ash/common/wm_window.h" |
| 27 #include "ash/shelf/shelf.h" | 27 #include "ash/shelf/shelf.h" |
| 28 #include "ash/shelf/shelf_bezel_event_filter.h" | 28 #include "ash/shelf/shelf_bezel_event_filter.h" |
| 29 #include "ash/shelf/shelf_layout_manager_observer.h" | 29 #include "ash/shelf/shelf_layout_manager_observer.h" |
| 30 #include "ash/shell.h" | 30 #include "ash/shell.h" |
| 31 #include "ash/wm/gestures/shelf_gesture_handler.h" | |
| 32 #include "ash/wm/window_animations.h" | 31 #include "ash/wm/window_animations.h" |
| 33 #include "ash/wm/workspace_controller.h" | 32 #include "ash/wm/workspace_controller.h" |
| 34 #include "base/auto_reset.h" | 33 #include "base/auto_reset.h" |
| 35 #include "base/i18n/rtl.h" | 34 #include "base/i18n/rtl.h" |
| 36 #include "ui/compositor/layer.h" | 35 #include "ui/compositor/layer.h" |
| 37 #include "ui/compositor/layer_animation_observer.h" | 36 #include "ui/compositor/layer_animation_observer.h" |
| 38 #include "ui/compositor/layer_animator.h" | 37 #include "ui/compositor/layer_animator.h" |
| 39 #include "ui/compositor/scoped_layer_animation_settings.h" | 38 #include "ui/compositor/scoped_layer_animation_settings.h" |
| 40 #include "ui/display/display.h" | 39 #include "ui/display/display.h" |
| 41 #include "ui/display/screen.h" | 40 #include "ui/display/screen.h" |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 SetState(SHELF_VISIBLE); | 294 SetState(SHELF_VISIBLE); |
| 296 } else if (WmShell::Get()->IsPinned()) { | 295 } else if (WmShell::Get()->IsPinned()) { |
| 297 SetState(SHELF_HIDDEN); | 296 SetState(SHELF_HIDDEN); |
| 298 } else { | 297 } else { |
| 299 // TODO(zelidrag): Verify shelf drag animation still shows on the device | 298 // TODO(zelidrag): Verify shelf drag animation still shows on the device |
| 300 // when we are in SHELF_AUTO_HIDE_ALWAYS_HIDDEN. | 299 // when we are in SHELF_AUTO_HIDE_ALWAYS_HIDDEN. |
| 301 wm::WorkspaceWindowState window_state( | 300 wm::WorkspaceWindowState window_state( |
| 302 workspace_controller_->GetWindowState()); | 301 workspace_controller_->GetWindowState()); |
| 303 switch (window_state) { | 302 switch (window_state) { |
| 304 case wm::WORKSPACE_WINDOW_STATE_FULL_SCREEN: { | 303 case wm::WORKSPACE_WINDOW_STATE_FULL_SCREEN: { |
| 305 const WmWindow* fullscreen_window = wm::GetWindowForFullscreenMode( | 304 if (IsShelfHiddenForFullscreen()) { |
| 306 WmLookup::Get()->GetWindowForWidget(shelf_widget_)); | |
| 307 if (fullscreen_window && | |
| 308 fullscreen_window->GetWindowState()->hide_shelf_when_fullscreen()) { | |
| 309 SetState(SHELF_HIDDEN); | 305 SetState(SHELF_HIDDEN); |
| 310 } else { | 306 } else { |
| 311 // The shelf is sometimes not hidden when in immersive fullscreen. | 307 // The shelf is sometimes not hidden when in immersive fullscreen. |
| 312 // Force the shelf to be auto hidden in this case. | 308 // Force the shelf to be auto hidden in this case. |
| 313 SetState(SHELF_AUTO_HIDE); | 309 SetState(SHELF_AUTO_HIDE); |
| 314 } | 310 } |
| 315 break; | 311 break; |
| 316 } | 312 } |
| 317 | 313 |
| 318 case wm::WORKSPACE_WINDOW_STATE_MAXIMIZED: | 314 case wm::WORKSPACE_WINDOW_STATE_MAXIMIZED: |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 363 UpdateAutoHideState(); | 359 UpdateAutoHideState(); |
| 364 } | 360 } |
| 365 } | 361 } |
| 366 | 362 |
| 367 void ShelfLayoutManager::UpdateAutoHideForGestureEvent( | 363 void ShelfLayoutManager::UpdateAutoHideForGestureEvent( |
| 368 ui::GestureEvent* event) { | 364 ui::GestureEvent* event) { |
| 369 if (visibility_state() != SHELF_AUTO_HIDE || in_shutdown_) | 365 if (visibility_state() != SHELF_AUTO_HIDE || in_shutdown_) |
| 370 return; | 366 return; |
| 371 | 367 |
| 372 aura::Window* target_window = static_cast<aura::Window*>(event->target()); | 368 aura::Window* target_window = static_cast<aura::Window*>(event->target()); |
| 373 if (IsShelfWindow(target_window)) { | 369 if (IsShelfWindow(target_window) && ProcessGestureEvent(*event)) |
| 374 if (gesture_handler_.ProcessGestureEvent(*event, target_window)) | 370 event->StopPropagation(); |
| 375 event->StopPropagation(); | |
| 376 } | |
| 377 } | 371 } |
| 378 | 372 |
| 379 void ShelfLayoutManager::SetWindowOverlapsShelf(bool value) { | 373 void ShelfLayoutManager::SetWindowOverlapsShelf(bool value) { |
| 380 window_overlaps_shelf_ = value; | 374 window_overlaps_shelf_ = value; |
| 381 UpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE); | 375 UpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE); |
| 382 } | 376 } |
| 383 | 377 |
| 384 void ShelfLayoutManager::AddObserver(ShelfLayoutManagerObserver* observer) { | 378 void ShelfLayoutManager::AddObserver(ShelfLayoutManagerObserver* observer) { |
| 385 observers_.AddObserver(observer); | 379 observers_.AddObserver(observer); |
| 386 } | 380 } |
| 387 | 381 |
| 388 void ShelfLayoutManager::RemoveObserver(ShelfLayoutManagerObserver* observer) { | 382 void ShelfLayoutManager::RemoveObserver(ShelfLayoutManagerObserver* observer) { |
| 389 observers_.RemoveObserver(observer); | 383 observers_.RemoveObserver(observer); |
| 390 } | 384 } |
| 391 | 385 |
| 392 //////////////////////////////////////////////////////////////////////////////// | 386 bool ShelfLayoutManager::ProcessGestureEvent(const ui::GestureEvent& event) { |
| 393 // ShelfLayoutManager, Gesture functions: | 387 // The gestures are disabled in the lock/login screen. |
| 388 SessionStateDelegate* delegate = WmShell::Get()->GetSessionStateDelegate(); |
| 389 if (!delegate->NumberOfLoggedInUsers() || delegate->IsScreenLocked()) |
| 390 return false; |
| 394 | 391 |
| 395 void ShelfLayoutManager::OnGestureEdgeSwipe(const ui::GestureEvent& gesture) { | 392 if (IsShelfHiddenForFullscreen()) |
| 396 if (visibility_state() == SHELF_AUTO_HIDE) { | 393 return false; |
| 397 gesture_drag_auto_hide_state_ = SHELF_AUTO_HIDE_SHOWN; | |
| 398 gesture_drag_status_ = GESTURE_DRAG_COMPLETE_IN_PROGRESS; | |
| 399 UpdateVisibilityState(); | |
| 400 gesture_drag_status_ = GESTURE_DRAG_NONE; | |
| 401 } | |
| 402 } | |
| 403 | 394 |
| 404 void ShelfLayoutManager::StartGestureDrag(const ui::GestureEvent& gesture) { | 395 if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) { |
| 405 gesture_drag_status_ = GESTURE_DRAG_IN_PROGRESS; | 396 StartGestureDrag(event); |
| 406 gesture_drag_amount_ = 0.f; | 397 return true; |
| 407 gesture_drag_auto_hide_state_ = visibility_state() == SHELF_AUTO_HIDE | |
| 408 ? auto_hide_state() | |
| 409 : SHELF_AUTO_HIDE_SHOWN; | |
| 410 UpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE); | |
| 411 } | |
| 412 | |
| 413 void ShelfLayoutManager::UpdateGestureDrag(const ui::GestureEvent& gesture) { | |
| 414 gesture_drag_amount_ += PrimaryAxisValue(gesture.details().scroll_y(), | |
| 415 gesture.details().scroll_x()); | |
| 416 LayoutShelf(); | |
| 417 } | |
| 418 | |
| 419 void ShelfLayoutManager::CompleteGestureDrag(const ui::GestureEvent& gesture) { | |
| 420 bool horizontal = IsHorizontalAlignment(); | |
| 421 bool should_change = false; | |
| 422 if (gesture.type() == ui::ET_GESTURE_SCROLL_END) { | |
| 423 // The visibility of the shelf changes only if the shelf was dragged X% | |
| 424 // along the correct axis. If the shelf was already visible, then the | |
| 425 // direction of the drag does not matter. | |
| 426 const float kDragHideThreshold = 0.4f; | |
| 427 gfx::Rect bounds = GetIdealBounds(); | |
| 428 float drag_ratio = fabs(gesture_drag_amount_) / | |
| 429 (horizontal ? bounds.height() : bounds.width()); | |
| 430 if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN) { | |
| 431 should_change = drag_ratio > kDragHideThreshold; | |
| 432 } else { | |
| 433 bool correct_direction = false; | |
| 434 switch (GetAlignment()) { | |
| 435 case SHELF_ALIGNMENT_BOTTOM: | |
| 436 case SHELF_ALIGNMENT_BOTTOM_LOCKED: | |
| 437 case SHELF_ALIGNMENT_RIGHT: | |
| 438 correct_direction = gesture_drag_amount_ < 0; | |
| 439 break; | |
| 440 case SHELF_ALIGNMENT_LEFT: | |
| 441 correct_direction = gesture_drag_amount_ > 0; | |
| 442 break; | |
| 443 } | |
| 444 should_change = correct_direction && drag_ratio > kDragHideThreshold; | |
| 445 } | |
| 446 } else if (gesture.type() == ui::ET_SCROLL_FLING_START) { | |
| 447 if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN) { | |
| 448 should_change = horizontal ? fabs(gesture.details().velocity_y()) > 0 | |
| 449 : fabs(gesture.details().velocity_x()) > 0; | |
| 450 } else { | |
| 451 should_change = | |
| 452 SelectValueForShelfAlignment(gesture.details().velocity_y() < 0, | |
| 453 gesture.details().velocity_x() > 0, | |
| 454 gesture.details().velocity_x() < 0); | |
| 455 } | |
| 456 } else { | |
| 457 NOTREACHED(); | |
| 458 } | 398 } |
| 459 | 399 |
| 460 if (!should_change) { | 400 if (gesture_drag_status_ != GESTURE_DRAG_IN_PROGRESS) |
| 461 CancelGestureDrag(); | 401 return false; |
| 462 return; | 402 |
| 403 if (event.type() == ui::ET_GESTURE_SCROLL_UPDATE) { |
| 404 UpdateGestureDrag(event); |
| 405 return true; |
| 463 } | 406 } |
| 464 if (shelf_widget_) { | 407 |
| 465 shelf_widget_->Deactivate(); | 408 if (event.type() == ui::ET_GESTURE_SCROLL_END || |
| 466 shelf_widget_->status_area_widget()->Deactivate(); | 409 event.type() == ui::ET_SCROLL_FLING_START) { |
| 410 CompleteGestureDrag(event); |
| 411 return true; |
| 467 } | 412 } |
| 468 gesture_drag_auto_hide_state_ = | |
| 469 gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN | |
| 470 ? SHELF_AUTO_HIDE_HIDDEN | |
| 471 : SHELF_AUTO_HIDE_SHOWN; | |
| 472 ShelfAutoHideBehavior new_auto_hide_behavior = | |
| 473 gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN | |
| 474 ? SHELF_AUTO_HIDE_BEHAVIOR_NEVER | |
| 475 : SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS; | |
| 476 | 413 |
| 477 // When in fullscreen and the shelf is forced to be auto hidden, the auto hide | 414 // Unexpected event. Reset the state and let the event fall through. |
| 478 // behavior affects neither the visibility state nor the auto hide state. Set | 415 CancelGestureDrag(); |
| 479 // |gesture_drag_status_| to GESTURE_DRAG_COMPLETE_IN_PROGRESS to set the auto | 416 return false; |
| 480 // hide state to |gesture_drag_auto_hide_state_|. | |
| 481 gesture_drag_status_ = GESTURE_DRAG_COMPLETE_IN_PROGRESS; | |
| 482 Shelf* shelf = shelf_widget_->shelf(); | |
| 483 if (shelf->auto_hide_behavior() != new_auto_hide_behavior) | |
| 484 shelf->SetAutoHideBehavior(new_auto_hide_behavior); | |
| 485 else | |
| 486 UpdateVisibilityState(); | |
| 487 gesture_drag_status_ = GESTURE_DRAG_NONE; | |
| 488 } | |
| 489 | |
| 490 void ShelfLayoutManager::CancelGestureDrag() { | |
| 491 gesture_drag_status_ = GESTURE_DRAG_CANCEL_IN_PROGRESS; | |
| 492 UpdateVisibilityState(); | |
| 493 gesture_drag_status_ = GESTURE_DRAG_NONE; | |
| 494 } | 417 } |
| 495 | 418 |
| 496 void ShelfLayoutManager::SetAnimationDurationOverride( | 419 void ShelfLayoutManager::SetAnimationDurationOverride( |
| 497 int duration_override_in_ms) { | 420 int duration_override_in_ms) { |
| 498 duration_override_in_ms_ = duration_override_in_ms; | 421 duration_override_in_ms_ = duration_override_in_ms; |
| 499 } | 422 } |
| 500 | 423 |
| 501 //////////////////////////////////////////////////////////////////////////////// | 424 //////////////////////////////////////////////////////////////////////////////// |
| 502 // ShelfLayoutManager, wm::WmSnapToPixelLayoutManager implementation: | 425 // ShelfLayoutManager, wm::WmSnapToPixelLayoutManager implementation: |
| 503 | 426 |
| (...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1185 // screen. | 1108 // screen. |
| 1186 if (ash::MaterialDesignController::IsShelfMaterial()) { | 1109 if (ash::MaterialDesignController::IsShelfMaterial()) { |
| 1187 return (state.visibility_state == SHELF_AUTO_HIDE && | 1110 return (state.visibility_state == SHELF_AUTO_HIDE && |
| 1188 state.auto_hide_state == SHELF_AUTO_HIDE_SHOWN) | 1111 state.auto_hide_state == SHELF_AUTO_HIDE_SHOWN) |
| 1189 ? 1.0f | 1112 ? 1.0f |
| 1190 : 0.0f; | 1113 : 0.0f; |
| 1191 } | 1114 } |
| 1192 return (state.visibility_state == SHELF_AUTO_HIDE) ? 1.0f : 0.0f; | 1115 return (state.visibility_state == SHELF_AUTO_HIDE) ? 1.0f : 0.0f; |
| 1193 } | 1116 } |
| 1194 | 1117 |
| 1118 bool ShelfLayoutManager::IsShelfHiddenForFullscreen() const { |
| 1119 const WmWindow* fullscreen_window = wm::GetWindowForFullscreenMode( |
| 1120 WmLookup::Get()->GetWindowForWidget(shelf_widget_)); |
| 1121 return fullscreen_window && |
| 1122 fullscreen_window->GetWindowState()->hide_shelf_when_fullscreen(); |
| 1123 } |
| 1124 |
| 1125 //////////////////////////////////////////////////////////////////////////////// |
| 1126 // ShelfLayoutManager, Gesture functions: |
| 1127 |
| 1128 void ShelfLayoutManager::StartGestureDrag(const ui::GestureEvent& gesture) { |
| 1129 gesture_drag_status_ = GESTURE_DRAG_IN_PROGRESS; |
| 1130 gesture_drag_amount_ = 0.f; |
| 1131 gesture_drag_auto_hide_state_ = visibility_state() == SHELF_AUTO_HIDE |
| 1132 ? auto_hide_state() |
| 1133 : SHELF_AUTO_HIDE_SHOWN; |
| 1134 UpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE); |
| 1135 } |
| 1136 |
| 1137 void ShelfLayoutManager::UpdateGestureDrag(const ui::GestureEvent& gesture) { |
| 1138 gesture_drag_amount_ += PrimaryAxisValue(gesture.details().scroll_y(), |
| 1139 gesture.details().scroll_x()); |
| 1140 LayoutShelf(); |
| 1141 } |
| 1142 |
| 1143 void ShelfLayoutManager::CompleteGestureDrag(const ui::GestureEvent& gesture) { |
| 1144 bool horizontal = IsHorizontalAlignment(); |
| 1145 bool should_change = false; |
| 1146 if (gesture.type() == ui::ET_GESTURE_SCROLL_END) { |
| 1147 // The visibility of the shelf changes only if the shelf was dragged X% |
| 1148 // along the correct axis. If the shelf was already visible, then the |
| 1149 // direction of the drag does not matter. |
| 1150 const float kDragHideThreshold = 0.4f; |
| 1151 gfx::Rect bounds = GetIdealBounds(); |
| 1152 float drag_ratio = fabs(gesture_drag_amount_) / |
| 1153 (horizontal ? bounds.height() : bounds.width()); |
| 1154 if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN) { |
| 1155 should_change = drag_ratio > kDragHideThreshold; |
| 1156 } else { |
| 1157 bool correct_direction = false; |
| 1158 switch (GetAlignment()) { |
| 1159 case SHELF_ALIGNMENT_BOTTOM: |
| 1160 case SHELF_ALIGNMENT_BOTTOM_LOCKED: |
| 1161 case SHELF_ALIGNMENT_RIGHT: |
| 1162 correct_direction = gesture_drag_amount_ < 0; |
| 1163 break; |
| 1164 case SHELF_ALIGNMENT_LEFT: |
| 1165 correct_direction = gesture_drag_amount_ > 0; |
| 1166 break; |
| 1167 } |
| 1168 should_change = correct_direction && drag_ratio > kDragHideThreshold; |
| 1169 } |
| 1170 } else if (gesture.type() == ui::ET_SCROLL_FLING_START) { |
| 1171 if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN) { |
| 1172 should_change = horizontal ? fabs(gesture.details().velocity_y()) > 0 |
| 1173 : fabs(gesture.details().velocity_x()) > 0; |
| 1174 } else { |
| 1175 should_change = |
| 1176 SelectValueForShelfAlignment(gesture.details().velocity_y() < 0, |
| 1177 gesture.details().velocity_x() > 0, |
| 1178 gesture.details().velocity_x() < 0); |
| 1179 } |
| 1180 } else { |
| 1181 NOTREACHED(); |
| 1182 } |
| 1183 |
| 1184 if (!should_change) { |
| 1185 CancelGestureDrag(); |
| 1186 return; |
| 1187 } |
| 1188 if (shelf_widget_) { |
| 1189 shelf_widget_->Deactivate(); |
| 1190 shelf_widget_->status_area_widget()->Deactivate(); |
| 1191 } |
| 1192 gesture_drag_auto_hide_state_ = |
| 1193 gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN |
| 1194 ? SHELF_AUTO_HIDE_HIDDEN |
| 1195 : SHELF_AUTO_HIDE_SHOWN; |
| 1196 ShelfAutoHideBehavior new_auto_hide_behavior = |
| 1197 gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN |
| 1198 ? SHELF_AUTO_HIDE_BEHAVIOR_NEVER |
| 1199 : SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS; |
| 1200 |
| 1201 // When in fullscreen and the shelf is forced to be auto hidden, the auto hide |
| 1202 // behavior affects neither the visibility state nor the auto hide state. Set |
| 1203 // |gesture_drag_status_| to GESTURE_DRAG_COMPLETE_IN_PROGRESS to set the auto |
| 1204 // hide state to |gesture_drag_auto_hide_state_|. |
| 1205 gesture_drag_status_ = GESTURE_DRAG_COMPLETE_IN_PROGRESS; |
| 1206 Shelf* shelf = shelf_widget_->shelf(); |
| 1207 if (shelf->auto_hide_behavior() != new_auto_hide_behavior) |
| 1208 shelf->SetAutoHideBehavior(new_auto_hide_behavior); |
| 1209 else |
| 1210 UpdateVisibilityState(); |
| 1211 gesture_drag_status_ = GESTURE_DRAG_NONE; |
| 1212 } |
| 1213 |
| 1214 void ShelfLayoutManager::CancelGestureDrag() { |
| 1215 gesture_drag_status_ = GESTURE_DRAG_CANCEL_IN_PROGRESS; |
| 1216 UpdateVisibilityState(); |
| 1217 gesture_drag_status_ = GESTURE_DRAG_NONE; |
| 1218 } |
| 1219 |
| 1195 } // namespace ash | 1220 } // namespace ash |
| OLD | NEW |