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.h" |
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 |