Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: ash/wm/overview/window_overview.cc

Issue 251103005: Added arrow key navigation to Overview Mode (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase with latest changes, test stub (don't look into that yet!) Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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_overview.h" 5 #include "ash/wm/overview/window_overview.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <functional>
8 9
9 #include "ash/metrics/user_metrics_recorder.h" 10 #include "ash/metrics/user_metrics_recorder.h"
10 #include "ash/screen_util.h" 11 #include "ash/screen_util.h"
11 #include "ash/shell.h" 12 #include "ash/shell.h"
12 #include "ash/shell_window_ids.h" 13 #include "ash/shell_window_ids.h"
13 #include "ash/switchable_windows.h" 14 #include "ash/switchable_windows.h"
14 #include "ash/wm/overview/scoped_transform_overview_window.h" 15 #include "ash/wm/overview/scoped_transform_overview_window.h"
15 #include "ash/wm/overview/window_selector.h" 16 #include "ash/wm/overview/window_selector.h"
16 #include "ash/wm/overview/window_selector_item.h" 17 #include "ash/wm/overview/window_selector_item.h"
17 #include "base/metrics/histogram.h" 18 #include "base/metrics/histogram.h"
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 ui::LayerAnimationSequence* sequence) { 117 ui::LayerAnimationSequence* sequence) {
117 } 118 }
118 119
119 } // namespace 120 } // namespace
120 121
121 WindowOverview::WindowOverview(WindowSelector* window_selector, 122 WindowOverview::WindowOverview(WindowSelector* window_selector,
122 WindowSelectorItemList* windows, 123 WindowSelectorItemList* windows,
123 aura::Window* single_root_window) 124 aura::Window* single_root_window)
124 : window_selector_(window_selector), 125 : window_selector_(window_selector),
125 windows_(windows), 126 windows_(windows),
126 selection_index_(0), 127 selected_window_(NULL),
127 single_root_window_(single_root_window), 128 single_root_window_(single_root_window),
128 overview_start_time_(base::Time::Now()), 129 overview_start_time_(base::Time::Now()),
129 cursor_client_(NULL) { 130 cursor_client_(NULL) {
131 main_grid_.root_window = secondary_grid_.root_window = NULL;
tdanderson 2014/04/29 14:46:27 Initialize on two lines instead of one.
Nina 2014/04/29 18:31:40 Done.
130 Shell* shell = Shell::GetInstance(); 132 Shell* shell = Shell::GetInstance();
131 shell->OnOverviewModeStarting(); 133 shell->OnOverviewModeStarting();
132 for (WindowSelectorItemList::iterator iter = windows_->begin(); 134 for (WindowSelectorItemList::iterator iter = windows_->begin();
133 iter != windows_->end(); ++iter) { 135 iter != windows_->end(); ++iter) {
134 (*iter)->PrepareForOverview(); 136 (*iter)->PrepareForOverview();
135 } 137 }
136 PositionWindows(/* animate */ true); 138 PositionWindows(/* animate */ true);
137 DCHECK(!windows_->empty()); 139 DCHECK(!windows_->empty());
138 cursor_client_ = aura::client::GetCursorClient( 140 cursor_client_ = aura::client::GetCursorClient(
139 windows_->front()->GetRootWindow()); 141 windows_->front()->GetRootWindow());
(...skipping 30 matching lines...) Expand all
170 ash::Shell* shell = ash::Shell::GetInstance(); 172 ash::Shell* shell = ash::Shell::GetInstance();
171 shell->RemovePreTargetHandler(this); 173 shell->RemovePreTargetHandler(this);
172 shell->GetScreen()->RemoveObserver(this); 174 shell->GetScreen()->RemoveObserver(this);
173 UMA_HISTOGRAM_MEDIUM_TIMES( 175 UMA_HISTOGRAM_MEDIUM_TIMES(
174 "Ash.WindowSelector.TimeInOverview", 176 "Ash.WindowSelector.TimeInOverview",
175 base::Time::Now() - overview_start_time_); 177 base::Time::Now() - overview_start_time_);
176 shell->OnOverviewModeEnding(); 178 shell->OnOverviewModeEnding();
177 } 179 }
178 180
179 void WindowOverview::SetSelection(size_t index) { 181 void WindowOverview::SetSelection(size_t index) {
180 gfx::Rect target_bounds(GetSelectionBounds(index)); 182 MoveSelectionWidget((*windows_)[index], NULL);
183 }
184
185 void WindowOverview::MoveSelectionWidget(WindowSelectorItem* target,
186 gfx::Vector2d* fade_out_direction) {
187 gfx::Rect target_bounds(GetSelectionBounds(target));
188 aura::Window* root_window = target->GetRootWindow();
189 if (selection_widget_ && root_window !=
190 selection_widget_->GetNativeWindow()->GetRootWindow())
191 selection_widget_.reset();
181 192
182 if (selection_widget_) { 193 if (selection_widget_) {
183 // If the selection widget is already active, determine the animation to 194 // If the selection widget is already active, determine the animation to
184 // use to animate the widget to the new bounds. 195 // use to animate the widget to the new bounds.
185 int change = static_cast<int>(index) - static_cast<int>(selection_index_); 196 gfx::Display dst_display = gfx::Screen::GetScreenFor(
186 int windows = static_cast<int>(windows_->size()); 197 selection_widget_->GetNativeWindow())->GetDisplayMatching(
187 // If moving from the first to the last or last to the first index, 198 target_bounds);
188 // convert the delta to be +/- 1. 199 aura::Window* old_selection = selection_widget_->GetNativeWindow();
189 if (windows > 2 && abs(change) == windows - 1) {
190 if (change < 0)
191 change += windows;
192 else
193 change -= windows;
194 }
195 if (selection_index_ < windows_->size() &&
196 (*windows_)[selection_index_]->target_bounds().y() !=
197 (*windows_)[index]->target_bounds().y() &&
198 abs(change) == 1) {
199 // The selection has changed forward or backwards by one with a change
200 // in the height of the target. In this case create a new selection widget
201 // to fade in on the new position and animate and fade out the old one.
202 gfx::Display dst_display = gfx::Screen::GetScreenFor(
203 selection_widget_->GetNativeWindow())->GetDisplayMatching(
204 target_bounds);
205 gfx::Vector2d fade_out_direction(
206 change * ((*windows_)[selection_index_]->target_bounds().width() +
207 2 * kWindowMargin), 0);
208 aura::Window* old_selection = selection_widget_->GetNativeWindow();
209 200
201 // If a fade out direction is specified, animate the widget accordingly.
202 if (fade_out_direction) {
tdanderson 2014/04/29 14:46:27 Is this check needed? Under which circumstances wo
Nina 2014/04/29 18:31:40 Yes, in alt-tabbing mode (through SetSelection)
210 // CleanupWidgetAfterAnimationObserver will delete itself (and the 203 // CleanupWidgetAfterAnimationObserver will delete itself (and the
211 // widget) when the animation is complete. 204 // widget) when the animation is complete.
212 new CleanupWidgetAfterAnimationObserver(selection_widget_.Pass()); 205 new CleanupWidgetAfterAnimationObserver(selection_widget_.Pass());
213 ui::ScopedLayerAnimationSettings animation_settings( 206 ui::ScopedLayerAnimationSettings animation_settings(
214 old_selection->layer()->GetAnimator()); 207 old_selection->layer()->GetAnimator());
215 animation_settings.SetTransitionDuration( 208 animation_settings.SetTransitionDuration(
216 base::TimeDelta::FromMilliseconds( 209 base::TimeDelta::FromMilliseconds(
217 kOverviewSelectorTransitionMilliseconds)); 210 kOverviewSelectorTransitionMilliseconds));
218 animation_settings.SetPreemptionStrategy( 211 animation_settings.SetPreemptionStrategy(
219 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 212 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
220 old_selection->SetBoundsInScreen( 213 old_selection->SetBoundsInScreen(
221 GetSelectionBounds(selection_index_) + fade_out_direction, 214 GetSelectionBounds(selected_window_) + (*fade_out_direction),
222 dst_display); 215 dst_display);
223 old_selection->Hide(); 216 old_selection->Hide();
224 old_selection->layer()->SetOpacity(0); 217 old_selection->layer()->SetOpacity(0);
225 InitializeSelectionWidget(); 218 InitializeSelectionWidget(root_window);
226 selection_widget_->GetNativeWindow()->SetBoundsInScreen( 219 selection_widget_->GetNativeWindow()->SetBoundsInScreen(
227 target_bounds - fade_out_direction, dst_display); 220 target_bounds - (*fade_out_direction), dst_display);
228 // New selection widget starts with 0 opacity and fades in. 221 // New selection widget starts with 0 opacity and fades in.
229 selection_widget_->GetNativeWindow()->layer()->SetOpacity(0); 222 selection_widget_->GetNativeWindow()->layer()->SetOpacity(0);
230 } 223 }
231 ui::ScopedLayerAnimationSettings animation_settings( 224 ui::ScopedLayerAnimationSettings animation_settings(
232 selection_widget_->GetNativeWindow()->layer()->GetAnimator()); 225 selection_widget_->GetNativeWindow()->layer()->GetAnimator());
233 animation_settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( 226 animation_settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
234 kOverviewSelectorTransitionMilliseconds)); 227 kOverviewSelectorTransitionMilliseconds));
235 animation_settings.SetPreemptionStrategy( 228 animation_settings.SetPreemptionStrategy(
236 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 229 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
237 selection_widget_->SetBounds(target_bounds); 230 selection_widget_->SetBounds(target_bounds);
238 selection_widget_->GetNativeWindow()->layer()->SetOpacity( 231 selection_widget_->GetNativeWindow()->layer()->SetOpacity(
239 kWindowOverviewSelectionOpacity); 232 kWindowOverviewSelectionOpacity);
240 } else { 233 } else {
241 InitializeSelectionWidget(); 234 InitializeSelectionWidget(root_window);
242 selection_widget_->SetBounds(target_bounds); 235 selection_widget_->SetBounds(target_bounds);
243 } 236 }
244 selection_index_ = index; 237 selected_window_ = target;
238 target->get_window_label()->GetContentsView()->
239 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true);
245 } 240 }
246 241
247 void WindowOverview::OnWindowsChanged() { 242 void WindowOverview::OnWindowsChanged() {
248 PositionWindows(/* animate */ true); 243 PositionWindows(/* animate */ true);
249 } 244 }
250 245
251 void WindowOverview::MoveToSingleRootWindow(aura::Window* root_window) { 246 void WindowOverview::MoveToSingleRootWindow(aura::Window* root_window) {
252 single_root_window_ = root_window; 247 single_root_window_ = root_window;
253 PositionWindows(/* animate */ true); 248 PositionWindows(/* animate */ true);
254 } 249 }
255 250
256 void WindowOverview::OnKeyEvent(ui::KeyEvent* event) { 251 void WindowOverview::OnKeyEvent(ui::KeyEvent* event) {
257 if (GetTargetedWindow(static_cast<aura::Window*>(event->target()))) 252 if (GetTargetedWindow(static_cast<aura::Window*>(event->target())))
258 event->StopPropagation(); 253 event->StopPropagation();
259 if (event->type() != ui::ET_KEY_PRESSED) 254 if (event->type() != ui::ET_KEY_PRESSED)
260 return; 255 return;
261 256
262 if (event->key_code() == ui::VKEY_ESCAPE) 257 if (!event->IsAltDown() || event->key_code() == ui::VKEY_ESCAPE)
263 window_selector_->CancelSelection(); 258 switch (event->key_code()) {
259 case ui::VKEY_ESCAPE:
260 event->StopPropagation();
261 window_selector_->CancelSelection();
262 break;
263 case ui::VKEY_RETURN:
264 event->StopPropagation();
265 window_selector_->SelectWindow(selected_window_->SelectionWindow());
266 break;
267 case ui::VKEY_RIGHT:
268 event->StopPropagation();
269 MoveSelector(WindowOverview::RIGHT);
270 break;
271 case ui::VKEY_LEFT:
272 event->StopPropagation();
273 MoveSelector(WindowOverview::LEFT);
274 break;
275 case ui::VKEY_UP:
276 event->StopPropagation();
277 MoveSelector(WindowOverview::UP);
278 break;
279 case ui::VKEY_DOWN:
280 event->StopPropagation();
281 MoveSelector(WindowOverview::DOWN);
282 default:
283 // Not a key we are interested in.
284 break;
285 }
264 } 286 }
265 287
266 void WindowOverview::OnMouseEvent(ui::MouseEvent* event) { 288 void WindowOverview::OnMouseEvent(ui::MouseEvent* event) {
267 aura::Window* target = GetEventTarget(event); 289 aura::Window* target = GetEventTarget(event);
268 if (!target) 290 if (!target)
269 return; 291 return;
270 292
271 event->SetHandled(); 293 event->SetHandled();
272 if (event->type() != ui::ET_MOUSE_RELEASED) 294 if (event->type() != ui::ET_MOUSE_RELEASED)
273 return; 295 return;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 void WindowOverview::PositionWindows(bool animate) { 396 void WindowOverview::PositionWindows(bool animate) {
375 if (single_root_window_) { 397 if (single_root_window_) {
376 std::vector<WindowSelectorItem*> windows; 398 std::vector<WindowSelectorItem*> windows;
377 for (WindowSelectorItemList::iterator iter = windows_->begin(); 399 for (WindowSelectorItemList::iterator iter = windows_->begin();
378 iter != windows_->end(); ++iter) { 400 iter != windows_->end(); ++iter) {
379 windows.push_back(*iter); 401 windows.push_back(*iter);
380 } 402 }
381 PositionWindowsOnRoot(single_root_window_, windows, animate); 403 PositionWindowsOnRoot(single_root_window_, windows, animate);
382 } else { 404 } else {
383 aura::Window::Windows root_window_list = Shell::GetAllRootWindows(); 405 aura::Window::Windows root_window_list = Shell::GetAllRootWindows();
406 secondary_grid_.windows = main_grid_.windows = 0;
tdanderson 2014/04/29 14:46:27 Two lines.
Nina 2014/04/29 18:31:40 Done.
384 for (size_t i = 0; i < root_window_list.size(); ++i) 407 for (size_t i = 0; i < root_window_list.size(); ++i)
385 PositionWindowsFromRoot(root_window_list[i], animate); 408 PositionWindowsFromRoot(root_window_list[i], animate);
409 if (selection_widget_)
410 ResetSelectionWidget();
386 } 411 }
387 } 412 }
388 413
389 void WindowOverview::PositionWindowsFromRoot(aura::Window* root_window, 414 void WindowOverview::PositionWindowsFromRoot(aura::Window* root_window,
390 bool animate) { 415 bool animate) {
391 std::vector<WindowSelectorItem*> windows; 416 std::vector<WindowSelectorItem*> windows;
392 for (WindowSelectorItemList::iterator iter = windows_->begin(); 417 for (WindowSelectorItemList::iterator iter = windows_->begin();
393 iter != windows_->end(); ++iter) { 418 iter != windows_->end(); ++iter) {
394 if ((*iter)->GetRootWindow() == root_window) 419 if ((*iter)->GetRootWindow() == root_window)
395 windows.push_back(*iter); 420 windows.push_back(*iter);
396 } 421 }
397 PositionWindowsOnRoot(root_window, windows, animate); 422 PositionWindowsOnRoot(root_window, windows, animate);
398 } 423 }
399 424
425 void WindowOverview::ResetSelectionWidget() {
426 bool selected_window_removed = true;
427 for (size_t i = 0; i < windows_->size() && selected_window_removed; ++i) {
tdanderson 2014/04/29 14:46:27 No {} needed since the body of the for loop is a s
Nina 2014/04/29 18:31:40 Done.
428 selected_window_removed = !((windows_->get()[i]) == selected_window_);
429 }
430
431 if (!selected_window_removed) {
432 // If the currently selected window has not been destroyed, move the
433 // selection widget to its new position.
434 MoveSelectionWidget(selected_window_, NULL);
435 } else {
436 if (arrow_cursor_.x == 0 && arrow_cursor_.y == 0) {
437 // If in the top right position, determine whether we should move to the
438 // next display (RIGHT) since there are no windows on the current one, or
439 // select the closest remaining window (NONE).
440 if ((arrow_cursor_.primary_display && main_grid_.windows == 0) ||
441 (!arrow_cursor_.primary_display && secondary_grid_.windows == 0))
442 MoveSelector(WindowOverview::RIGHT);
443 else
444 MoveSelector(WindowOverview::NONE);
445 } else {
446 // The destroyed window had other windows behind it, move to the closest
447 // one.
448 MoveSelector(WindowOverview::LEFT);
449 }
450 }
451 }
452
400 void WindowOverview::PositionWindowsOnRoot( 453 void WindowOverview::PositionWindowsOnRoot(
401 aura::Window* root_window, 454 aura::Window* root_window,
402 const std::vector<WindowSelectorItem*>& windows, 455 const std::vector<WindowSelectorItem*>& windows,
403 bool animate) { 456 bool animate) {
404 if (windows.empty()) 457 if (windows.empty())
405 return; 458 return;
406 459
460 WindowGrid grid;
tdanderson 2014/04/29 14:46:27 Declare this right before initialization (line 479
Nina 2014/04/29 18:31:40 Done.
461
407 gfx::Size window_size; 462 gfx::Size window_size;
408 gfx::Rect total_bounds = ScreenUtil::ConvertRectToScreen( 463 gfx::Rect total_bounds = ScreenUtil::ConvertRectToScreen(
409 root_window, 464 root_window,
410 ScreenUtil::GetDisplayWorkAreaBoundsInParent( 465 ScreenUtil::GetDisplayWorkAreaBoundsInParent(
411 Shell::GetContainer(root_window, kShellWindowId_DefaultContainer))); 466 Shell::GetContainer(root_window, kShellWindowId_DefaultContainer)));
412 467
413 // Find the minimum number of windows per row that will fit all of the 468 // Find the minimum number of windows per row that will fit all of the
414 // windows on screen. 469 // windows on screen.
415 size_t columns = std::max( 470 size_t columns = std::max(
416 total_bounds.width() > total_bounds.height() ? kMinCardsMajor : 1, 471 total_bounds.width() > total_bounds.height() ? kMinCardsMajor : 1,
417 static_cast<int>(ceil(sqrt(total_bounds.width() * windows.size() / 472 static_cast<int>(ceil(sqrt(total_bounds.width() * windows.size() /
418 (kCardAspectRatio * total_bounds.height()))))); 473 (kCardAspectRatio * total_bounds.height())))));
419 size_t rows = ((windows.size() + columns - 1) / columns); 474 size_t rows = ((windows.size() + columns - 1) / columns);
420 window_size.set_width(std::min( 475 window_size.set_width(std::min(
421 static_cast<int>(total_bounds.width() / columns), 476 static_cast<int>(total_bounds.width() / columns),
422 static_cast<int>(total_bounds.height() * kCardAspectRatio / rows))); 477 static_cast<int>(total_bounds.height() * kCardAspectRatio / rows)));
423 window_size.set_height(window_size.width() / kCardAspectRatio); 478 window_size.set_height(window_size.width() / kCardAspectRatio);
424 479
480 for (size_t i = 0; i < columns; ++i) {
481 std::vector<WindowSelectorItem*> inner_vector;
482 grid.window_matrix.push_back(inner_vector);
483 }
484 grid.windows = windows.size();
485
425 // Calculate the X and Y offsets necessary to center the grid. 486 // Calculate the X and Y offsets necessary to center the grid.
426 int x_offset = total_bounds.x() + ((windows.size() >= columns ? 0 : 487 int x_offset = total_bounds.x() + ((windows.size() >= columns ? 0 :
427 (columns - windows.size()) * window_size.width()) + 488 (columns - windows.size()) * window_size.width()) +
428 (total_bounds.width() - columns * window_size.width())) / 2; 489 (total_bounds.width() - columns * window_size.width())) / 2;
429 int y_offset = total_bounds.y() + (total_bounds.height() - 490 int y_offset = total_bounds.y() + (total_bounds.height() -
430 rows * window_size.height()) / 2; 491 rows * window_size.height()) / 2;
431 for (size_t i = 0; i < windows.size(); ++i) { 492 for (size_t i = 0; i < windows.size(); ++i) {
432 gfx::Transform transform; 493 gfx::Transform transform;
433 int column = i % columns; 494 int column = i % columns;
434 int row = i / columns; 495 int row = i / columns;
435 gfx::Rect target_bounds(window_size.width() * column + x_offset, 496 gfx::Rect target_bounds(window_size.width() * column + x_offset,
436 window_size.height() * row + y_offset, 497 window_size.height() * row + y_offset,
437 window_size.width(), 498 window_size.width(),
438 window_size.height()); 499 window_size.height());
439 target_bounds.Inset(kWindowMargin, kWindowMargin); 500 target_bounds.Inset(kWindowMargin, kWindowMargin);
440 windows[i]->SetBounds(root_window, target_bounds, animate); 501 windows[i]->SetBounds(root_window, target_bounds, animate);
502 grid.window_matrix[column].push_back(windows[i]);
503 }
504
505 grid.root_window = root_window;
506 // Under certain circumstances it is possible that we have more columns than
507 // windows. In this case, trim down the number to simplify movement
508 // calculations.
509 if (columns > windows.size())
510 grid.columns = windows.size();
511 else
512 grid.columns = columns;
513 grid.rows = rows;
514
515 if (!main_grid_.root_window || main_grid_.root_window == grid.root_window) {
516 main_grid_ = grid;
517 } else {
518 secondary_grid_ = grid;
441 } 519 }
442 } 520 }
443 521
444 void WindowOverview::InitializeSelectionWidget() { 522 void WindowOverview::InitializeSelectionWidget(aura::Window* root_window) {
445 selection_widget_.reset(new views::Widget); 523 selection_widget_.reset(new views::Widget);
446 views::Widget::InitParams params; 524 views::Widget::InitParams params;
447 params.type = views::Widget::InitParams::TYPE_POPUP; 525 params.type = views::Widget::InitParams::TYPE_POPUP;
448 params.can_activate = false; 526 params.can_activate = false;
449 params.keep_on_top = false; 527 params.keep_on_top = false;
450 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 528 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
451 params.opacity = views::Widget::InitParams::OPAQUE_WINDOW; 529 params.opacity = views::Widget::InitParams::OPAQUE_WINDOW;
452 params.parent = Shell::GetContainer(single_root_window_ 530 params.parent = Shell::GetContainer(single_root_window_
453 ? single_root_window_ 531 ? single_root_window_
454 : windows_->front()->GetRootWindow(), 532 : root_window,
455 kShellWindowId_DefaultContainer); 533 kShellWindowId_DefaultContainer);
456 params.accept_events = false; 534 params.accept_events = false;
457 selection_widget_->set_focus_on_creation(false); 535 selection_widget_->set_focus_on_creation(false);
458 selection_widget_->Init(params); 536 selection_widget_->Init(params);
459 views::View* content_view = new views::View; 537 views::View* content_view = new views::View;
460 content_view->set_background( 538 content_view->set_background(
461 views::Background::CreateSolidBackground(kWindowOverviewSelectionColor)); 539 views::Background::CreateSolidBackground(kWindowOverviewSelectionColor));
462 selection_widget_->SetContentsView(content_view); 540 selection_widget_->SetContentsView(content_view);
463 selection_widget_->Show(); 541 selection_widget_->Show();
464 selection_widget_->GetNativeWindow()->parent()->StackChildAtBottom( 542 selection_widget_->GetNativeWindow()->parent()->StackChildAtBottom(
465 selection_widget_->GetNativeWindow()); 543 selection_widget_->GetNativeWindow());
466 selection_widget_->GetNativeWindow()->layer()->SetOpacity( 544 selection_widget_->GetNativeWindow()->layer()->SetOpacity(
467 kWindowOverviewSelectionOpacity); 545 kWindowOverviewSelectionOpacity);
468 } 546 }
469 547
470 gfx::Rect WindowOverview::GetSelectionBounds(size_t index) { 548 void WindowOverview::MoveSelector(Direction direction) {
471 gfx::Rect bounds((*windows_)[index]->bounds()); 549 // If we don't have a selection, simply initialize the cursor on the first
550 // window on the primary monitor.
551 if (!selection_widget_) {
552 arrow_cursor_.x = 0;
553 arrow_cursor_.y = 0;
554 arrow_cursor_.primary_display = true;
555 }
556 // The following pointers simplify the movement logic.
557 WindowGrid* current_grid;
558 WindowGrid* other_grid;
559 if (arrow_cursor_.primary_display) {
560 current_grid = &main_grid_;
561 other_grid = &secondary_grid_;
562 } else {
563 current_grid = &secondary_grid_;
564 other_grid = &main_grid_;
565 }
566 if (other_grid->windows == 0)
567 other_grid = current_grid;
568
569 bool old_grid = arrow_cursor_.primary_display;
570
571 gfx::Vector2d fade_direction(0, 0);
572
573 if (selection_widget_) {
574 switch (direction) {
575 case WindowOverview::RIGHT:
576 fade_direction.set_x(1);
577 ++arrow_cursor_.x;
578 if (arrow_cursor_.x >= current_grid->columns ||
tdanderson 2014/04/29 14:46:27 Don't align your boolean operators in this way. Se
Nina 2014/04/29 18:31:40 Done.
579 (arrow_cursor_.y == current_grid->rows - 1 &&
580 current_grid->windows % current_grid->columns != 0 &&
581 arrow_cursor_.x >= current_grid->windows
582 % current_grid->columns)) {
583 arrow_cursor_.x = 0;
584 if (++arrow_cursor_.y >= current_grid->rows) {
585 arrow_cursor_.y = 0;
586 arrow_cursor_.primary_display = !arrow_cursor_.primary_display;
587 }
588 }
589 break;
590 case WindowOverview::LEFT:
591 fade_direction.set_x(-1);
592 if (arrow_cursor_.x == 0) {
593 if (arrow_cursor_.y == 0) {
594 if (other_grid->windows % other_grid->columns == 0)
595 arrow_cursor_.x = other_grid->columns - 1;
596 else
597 arrow_cursor_.x = other_grid->windows % other_grid->columns - 1;
598 arrow_cursor_.y = other_grid->rows - 1;
599 arrow_cursor_.primary_display = !arrow_cursor_.primary_display;
600 } else {
601 arrow_cursor_.x = current_grid->columns - 1;
602 --arrow_cursor_.y;
603 }
604 } else {
605 --arrow_cursor_.x;
606 }
607 break;
608 case WindowOverview::DOWN:
609 fade_direction.set_y(1);
610 ++arrow_cursor_.y;
611 if (arrow_cursor_.y >= current_grid->rows ||
612 (current_grid->windows % current_grid->columns != 0 &&
613 arrow_cursor_.y >= current_grid->rows - 1 &&
614 arrow_cursor_.x >= current_grid->windows % current_grid->columns)) {
615 arrow_cursor_.y = 0;
616 ++arrow_cursor_.x;
617 if (arrow_cursor_.x >= current_grid->columns) {
618 arrow_cursor_.x = 0;
619 arrow_cursor_.primary_display = !arrow_cursor_.primary_display;
620 }
621 }
622 break;
623 case WindowOverview::UP:
624 fade_direction.set_y(-1);
625 if (arrow_cursor_.y <= 0) {
626 if (arrow_cursor_.x <= 0) {
627 arrow_cursor_.x = other_grid->columns - 1;
628 if (other_grid->windows % other_grid->columns != 0 &&
629 arrow_cursor_.x >= other_grid->windows % other_grid->columns)
630 arrow_cursor_.y = other_grid->rows - 2;
631 else
632 arrow_cursor_.y = other_grid->rows - 1;
633 arrow_cursor_.primary_display = !arrow_cursor_.primary_display;
634 } else {
635 --arrow_cursor_.x;
636 if (current_grid->windows % current_grid->columns != 0 &&
637 arrow_cursor_.x >= current_grid->windows % current_grid->columns)
638 arrow_cursor_.y = current_grid->rows - 2;
639 else
640 arrow_cursor_.y = current_grid->rows - 1;
641 }
642 } else {
643 --arrow_cursor_.y;
644 }
645 break;
646 case WindowOverview::NONE:
647 break;
648 }
649 }
650
651 // If the movement indicates a change of grid but there are no windows there,
652 // force the movement to the same grid.
653 if (arrow_cursor_.primary_display != old_grid &&
654 (other_grid->windows == 0 || current_grid == other_grid))
655 arrow_cursor_.primary_display = !arrow_cursor_.primary_display;
656
657 if (arrow_cursor_.primary_display && main_grid_.windows == 0)
658 // This should only happen on a movement that tries to change the display
659 // right after closing the last window on the main display.
660 arrow_cursor_.primary_display = false;
661
662 if (selected_window_) {
663 fade_direction.set_x(
664 fade_direction.x() * GetSelectionBounds(selected_window_).width());
665 fade_direction.set_y(
666 fade_direction.y() * GetSelectionBounds(selected_window_).height());
667 }
668
669 if (arrow_cursor_.primary_display)
tdanderson 2014/04/29 14:46:27 Use {} here since the body of if/else exceeds one
Nina 2014/04/29 18:31:40 Done.
670 MoveSelectionWidget(main_grid_.
671 window_matrix[arrow_cursor_.x][arrow_cursor_.y],
672 &fade_direction);
673 else
674 MoveSelectionWidget(secondary_grid_.
675 window_matrix[arrow_cursor_.x][arrow_cursor_.y],
676 &fade_direction);
677 }
678
679 gfx::Rect WindowOverview::GetSelectionBounds(WindowSelectorItem* window) {
680 gfx::Rect bounds(window->bounds());
472 bounds.Inset(-kWindowOverviewSelectionPadding, 681 bounds.Inset(-kWindowOverviewSelectionPadding,
473 -kWindowOverviewSelectionPadding); 682 -kWindowOverviewSelectionPadding);
474 return bounds; 683 return bounds;
475 } 684 }
476
477 } // namespace ash 685 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698