| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/overview/window_grid.h" | 5 #include "ash/wm/overview/window_grid.h" |
| 6 | 6 |
| 7 #include "ash/screen_util.h" | 7 #include "ash/screen_util.h" |
| 8 #include "ash/shell.h" | 8 #include "ash/shell.h" |
| 9 #include "ash/shell_window_ids.h" | 9 #include "ash/shell_window_ids.h" |
| 10 #include "ash/wm/overview/scoped_transform_overview_window.h" | 10 #include "ash/wm/overview/scoped_transform_overview_window.h" |
| 11 #include "ash/wm/overview/window_selector.h" | 11 #include "ash/wm/overview/window_selector.h" |
| 12 #include "ash/wm/overview/window_selector_item.h" | 12 #include "ash/wm/overview/window_selector_item.h" |
| 13 #include "ash/wm/overview/window_selector_panels.h" | 13 #include "ash/wm/overview/window_selector_panels.h" |
| 14 #include "ash/wm/overview/window_selector_window.h" | 14 #include "ash/wm/overview/window_selector_window.h" |
| 15 #include "ash/wm/window_state.h" | 15 #include "ash/wm/window_state.h" |
| 16 #include "base/i18n/string_search.cc" |
| 16 #include "base/memory/scoped_vector.h" | 17 #include "base/memory/scoped_vector.h" |
| 17 #include "third_party/skia/include/core/SkColor.h" | 18 #include "third_party/skia/include/core/SkColor.h" |
| 18 #include "ui/aura/window.h" | 19 #include "ui/aura/window.h" |
| 19 #include "ui/compositor/layer_animation_observer.h" | 20 #include "ui/compositor/layer_animation_observer.h" |
| 20 #include "ui/compositor/scoped_layer_animation_settings.h" | 21 #include "ui/compositor/scoped_layer_animation_settings.h" |
| 21 #include "ui/gfx/animation/tween.h" | 22 #include "ui/gfx/animation/tween.h" |
| 22 #include "ui/gfx/vector2d.h" | 23 #include "ui/gfx/vector2d.h" |
| 23 #include "ui/views/background.h" | 24 #include "ui/views/background.h" |
| 24 #include "ui/views/view.h" | 25 #include "ui/views/view.h" |
| 25 #include "ui/views/widget/widget.h" | 26 #include "ui/views/widget/widget.h" |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 static_cast<int>(total_bounds.width() / num_columns_), | 191 static_cast<int>(total_bounds.width() / num_columns_), |
| 191 static_cast<int>(total_bounds.height() * kCardAspectRatio / num_rows))); | 192 static_cast<int>(total_bounds.height() * kCardAspectRatio / num_rows))); |
| 192 window_size.set_height(window_size.width() / kCardAspectRatio); | 193 window_size.set_height(window_size.width() / kCardAspectRatio); |
| 193 | 194 |
| 194 // Calculate the X and Y offsets necessary to center the grid. | 195 // Calculate the X and Y offsets necessary to center the grid. |
| 195 int x_offset = total_bounds.x() + ((window_list_.size() >= num_columns_ ? 0 : | 196 int x_offset = total_bounds.x() + ((window_list_.size() >= num_columns_ ? 0 : |
| 196 (num_columns_ - window_list_.size()) * window_size.width()) + | 197 (num_columns_ - window_list_.size()) * window_size.width()) + |
| 197 (total_bounds.width() - num_columns_ * window_size.width())) / 2; | 198 (total_bounds.width() - num_columns_ * window_size.width())) / 2; |
| 198 int y_offset = total_bounds.y() + (total_bounds.height() - | 199 int y_offset = total_bounds.y() + (total_bounds.height() - |
| 199 num_rows * window_size.height()) / 2; | 200 num_rows * window_size.height()) / 2; |
| 201 |
| 200 for (size_t i = 0; i < window_list_.size(); ++i) { | 202 for (size_t i = 0; i < window_list_.size(); ++i) { |
| 201 gfx::Transform transform; | 203 gfx::Transform transform; |
| 202 int column = i % num_columns_; | 204 int column = i % num_columns_; |
| 203 int row = i / num_columns_; | 205 int row = i / num_columns_; |
| 204 gfx::Rect target_bounds(window_size.width() * column + x_offset, | 206 gfx::Rect target_bounds(window_size.width() * column + x_offset, |
| 205 window_size.height() * row + y_offset, | 207 window_size.height() * row + y_offset, |
| 206 window_size.width(), | 208 window_size.width(), |
| 207 window_size.height()); | 209 window_size.height()); |
| 208 window_list_[i]->SetBounds(root_window_, target_bounds, animate); | 210 window_list_[i]->SetBounds(root_window_, target_bounds, animate); |
| 209 } | 211 } |
| 210 | 212 |
| 211 // If we have less than |kMinCardsMajor| windows, adjust the column_ value to | 213 // If we have less than |kMinCardsMajor| windows, adjust the column_ value to |
| 212 // reflect how many "real" columns we have. | 214 // reflect how many "real" columns we have. |
| 213 if (num_columns_ > window_list_.size()) | 215 if (num_columns_ > window_list_.size()) |
| 214 num_columns_ = window_list_.size(); | 216 num_columns_ = window_list_.size(); |
| 215 | 217 |
| 216 // If the selection widget is active, reposition it without any animation. | 218 // If the selection widget is active, reposition it without any animation. |
| 217 if (selection_widget_) | 219 if (selection_widget_) |
| 218 MoveSelectionWidgetToTarget(animate); | 220 MoveSelectionWidgetToTarget(animate); |
| 219 } | 221 } |
| 220 | 222 |
| 221 bool WindowGrid::Move(WindowSelector::Direction direction) { | 223 bool WindowGrid::Move(WindowSelector::Direction direction, bool animate) { |
| 222 bool recreate_selection_widget = false; | 224 bool recreate_selection_widget = false; |
| 223 bool out_of_bounds = false; | 225 bool out_of_bounds = false; |
| 224 if (!selection_widget_) { | 226 if (!selection_widget_) { |
| 225 switch (direction) { | 227 switch (direction) { |
| 226 case WindowSelector::LEFT: | 228 case WindowSelector::LEFT: |
| 227 selected_index_ = window_list_.size() - 1; | 229 selected_index_ = window_list_.size() - 1; |
| 228 break; | 230 break; |
| 229 case WindowSelector::UP: | 231 case WindowSelector::UP: |
| 230 selected_index_ = | 232 selected_index_ = |
| 231 (window_list_.size() / num_columns_) * num_columns_ - 1; | 233 (window_list_.size() / num_columns_) * num_columns_ - 1; |
| 232 break; | 234 break; |
| 233 case WindowSelector::RIGHT: | 235 case WindowSelector::RIGHT: |
| 234 case WindowSelector::DOWN: | 236 case WindowSelector::DOWN: |
| 235 selected_index_ = 0; | 237 selected_index_ = 0; |
| 236 break; | 238 break; |
| 237 } | 239 } |
| 238 } else { | 240 } |
| 241 while (SelectedWindow()->dimmed() || selection_widget_) { |
| 239 switch (direction) { | 242 switch (direction) { |
| 240 case WindowSelector::RIGHT: | 243 case WindowSelector::RIGHT: |
| 241 if (selected_index_ >= window_list_.size() - 1) | 244 if (selected_index_ >= window_list_.size() - 1) |
| 242 out_of_bounds = true; | 245 out_of_bounds = true; |
| 243 selected_index_++; | 246 selected_index_++; |
| 244 if (selected_index_ % num_columns_ == 0) | 247 if (selected_index_ % num_columns_ == 0) |
| 245 recreate_selection_widget = true; | 248 recreate_selection_widget = true; |
| 246 break; | 249 break; |
| 247 case WindowSelector::LEFT: | 250 case WindowSelector::LEFT: |
| 248 if (selected_index_ == 0) | 251 if (selected_index_ == 0) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 265 out_of_bounds = true; | 268 out_of_bounds = true; |
| 266 if (selected_index_ < num_columns_) { | 269 if (selected_index_ < num_columns_) { |
| 267 selected_index_ += num_columns_ * | 270 selected_index_ += num_columns_ * |
| 268 ((window_list_.size() - selected_index_) / num_columns_) - 1; | 271 ((window_list_.size() - selected_index_) / num_columns_) - 1; |
| 269 recreate_selection_widget = true; | 272 recreate_selection_widget = true; |
| 270 } else { | 273 } else { |
| 271 selected_index_ -= num_columns_; | 274 selected_index_ -= num_columns_; |
| 272 } | 275 } |
| 273 break; | 276 break; |
| 274 } | 277 } |
| 278 // Exit the loop if we broke free from the grid or found an active item. |
| 279 if (out_of_bounds || !SelectedWindow()->dimmed()) |
| 280 break; |
| 275 } | 281 } |
| 276 | 282 |
| 277 MoveSelectionWidget(direction, recreate_selection_widget, out_of_bounds); | 283 MoveSelectionWidget(direction, recreate_selection_widget, |
| 284 out_of_bounds, animate); |
| 278 return out_of_bounds; | 285 return out_of_bounds; |
| 279 } | 286 } |
| 280 | 287 |
| 281 WindowSelectorItem* WindowGrid::SelectedWindow() const { | 288 WindowSelectorItem* WindowGrid::SelectedWindow() const { |
| 282 CHECK(selected_index_ < window_list_.size()); | 289 CHECK(selected_index_ < window_list_.size()); |
| 283 return window_list_[selected_index_]; | 290 return window_list_[selected_index_]; |
| 284 } | 291 } |
| 285 | 292 |
| 286 bool WindowGrid::Contains(const aura::Window* window) const { | 293 bool WindowGrid::Contains(const aura::Window* window) const { |
| 287 return std::find_if(window_list_.begin(), window_list_.end(), | 294 return std::find_if(window_list_.begin(), window_list_.end(), |
| 288 WindowSelectorItemTargetComparator(window)) != | 295 WindowSelectorItemTargetComparator(window)) != |
| 289 window_list_.end(); | 296 window_list_.end(); |
| 290 } | 297 } |
| 291 | 298 |
| 299 void WindowGrid::FilterItems(const base::string16& pattern) { |
| 300 base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents finder(pattern); |
| 301 for (ScopedVector<WindowSelectorItem>::iterator iter = window_list_.begin(); |
| 302 iter != window_list_.end(); iter++) { |
| 303 if (finder.Search((*iter)->SelectionWindow()->title(), NULL, NULL)) { |
| 304 (*iter)->SetDimmed(false); |
| 305 } else { |
| 306 (*iter)->SetDimmed(true); |
| 307 if (selection_widget_ && SelectedWindow() == *iter) |
| 308 selection_widget_.reset(); |
| 309 } |
| 310 } |
| 311 } |
| 312 |
| 292 void WindowGrid::OnWindowDestroying(aura::Window* window) { | 313 void WindowGrid::OnWindowDestroying(aura::Window* window) { |
| 293 window->RemoveObserver(this); | 314 window->RemoveObserver(this); |
| 294 observed_windows_.erase(window); | 315 observed_windows_.erase(window); |
| 295 ScopedVector<WindowSelectorItem>::iterator iter = | 316 ScopedVector<WindowSelectorItem>::iterator iter = |
| 296 std::find_if(window_list_.begin(), window_list_.end(), | 317 std::find_if(window_list_.begin(), window_list_.end(), |
| 297 WindowSelectorItemComparator(window)); | 318 WindowSelectorItemComparator(window)); |
| 298 | 319 |
| 299 DCHECK(iter != window_list_.end()); | 320 DCHECK(iter != window_list_.end()); |
| 300 | 321 |
| 301 (*iter)->RemoveWindow(window); | 322 (*iter)->RemoveWindow(window); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 gfx::Vector2d fade_out_direction = | 397 gfx::Vector2d fade_out_direction = |
| 377 GetSlideVectorForFadeIn(direction, target_bounds); | 398 GetSlideVectorForFadeIn(direction, target_bounds); |
| 378 gfx::Display dst_display = gfx::Screen::GetScreenFor(root_window_)-> | 399 gfx::Display dst_display = gfx::Screen::GetScreenFor(root_window_)-> |
| 379 GetDisplayMatching(target_bounds); | 400 GetDisplayMatching(target_bounds); |
| 380 selection_widget_->GetNativeWindow()->SetBoundsInScreen( | 401 selection_widget_->GetNativeWindow()->SetBoundsInScreen( |
| 381 target_bounds - fade_out_direction, dst_display); | 402 target_bounds - fade_out_direction, dst_display); |
| 382 } | 403 } |
| 383 | 404 |
| 384 void WindowGrid::MoveSelectionWidget(WindowSelector::Direction direction, | 405 void WindowGrid::MoveSelectionWidget(WindowSelector::Direction direction, |
| 385 bool recreate_selection_widget, | 406 bool recreate_selection_widget, |
| 386 bool out_of_bounds) { | 407 bool out_of_bounds, |
| 408 bool animate) { |
| 387 // If the selection widget is already active, fade it out in the selection | 409 // If the selection widget is already active, fade it out in the selection |
| 388 // direction. | 410 // direction. |
| 389 if (selection_widget_ && (recreate_selection_widget || out_of_bounds)) { | 411 if (selection_widget_ && (recreate_selection_widget || out_of_bounds)) { |
| 390 // Animate the old selection widget and then destroy it. | 412 // Animate the old selection widget and then destroy it. |
| 391 views::Widget* old_selection = selection_widget_.get(); | 413 views::Widget* old_selection = selection_widget_.get(); |
| 392 gfx::Vector2d fade_out_direction = | 414 gfx::Vector2d fade_out_direction = |
| 393 GetSlideVectorForFadeIn( | 415 GetSlideVectorForFadeIn( |
| 394 direction, old_selection->GetNativeWindow()->bounds()); | 416 direction, old_selection->GetNativeWindow()->bounds()); |
| 395 | 417 |
| 396 ui::ScopedLayerAnimationSettings animation_settings( | 418 ui::ScopedLayerAnimationSettings animation_settings( |
| (...skipping 16 matching lines...) Expand all Loading... |
| 413 if (out_of_bounds) | 435 if (out_of_bounds) |
| 414 return; | 436 return; |
| 415 | 437 |
| 416 if (!selection_widget_) | 438 if (!selection_widget_) |
| 417 InitSelectionWidget(direction); | 439 InitSelectionWidget(direction); |
| 418 // Send an a11y alert so that if ChromeVox is enabled, the item label is | 440 // Send an a11y alert so that if ChromeVox is enabled, the item label is |
| 419 // read. | 441 // read. |
| 420 SelectedWindow()->SendFocusAlert(); | 442 SelectedWindow()->SendFocusAlert(); |
| 421 // The selection widget is moved to the newly selected item in the same | 443 // The selection widget is moved to the newly selected item in the same |
| 422 // grid. | 444 // grid. |
| 423 MoveSelectionWidgetToTarget(true); | 445 MoveSelectionWidgetToTarget(animate); |
| 424 } | 446 } |
| 425 | 447 |
| 426 void WindowGrid::MoveSelectionWidgetToTarget(bool animate) { | 448 void WindowGrid::MoveSelectionWidgetToTarget(bool animate) { |
| 427 if (animate) { | 449 if (animate) { |
| 428 ui::ScopedLayerAnimationSettings animation_settings( | 450 ui::ScopedLayerAnimationSettings animation_settings( |
| 429 selection_widget_->GetNativeWindow()->layer()->GetAnimator()); | 451 selection_widget_->GetNativeWindow()->layer()->GetAnimator()); |
| 430 animation_settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( | 452 animation_settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( |
| 431 kOverviewSelectorTransitionMilliseconds)); | 453 kOverviewSelectorTransitionMilliseconds)); |
| 432 animation_settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN); | 454 animation_settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN); |
| 433 animation_settings.SetPreemptionStrategy( | 455 animation_settings.SetPreemptionStrategy( |
| 434 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | 456 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
| 435 selection_widget_->SetBounds(SelectedWindow()->target_bounds()); | 457 selection_widget_->SetBounds(SelectedWindow()->target_bounds()); |
| 436 selection_widget_->SetOpacity(kWindowOverviewSelectorOpacity); | 458 selection_widget_->SetOpacity(kWindowOverviewSelectorOpacity); |
| 437 return; | 459 return; |
| 438 } | 460 } |
| 439 selection_widget_->SetBounds(SelectedWindow()->target_bounds()); | 461 selection_widget_->SetBounds(SelectedWindow()->target_bounds()); |
| 440 selection_widget_->SetOpacity(kWindowOverviewSelectorOpacity); | 462 selection_widget_->SetOpacity(kWindowOverviewSelectorOpacity); |
| 441 } | 463 } |
| 442 | 464 |
| 443 } // namespace ash | 465 } // namespace ash |
| OLD | NEW |