OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |