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

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

Issue 358553004: Added text filtering to Overview Mode (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added another test. Created 6 years, 5 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_selector.h" 5 #include "ash/wm/overview/window_selector.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "ash/accessibility_delegate.h" 9 #include "ash/accessibility_delegate.h"
10 #include "ash/ash_switches.h" 10 #include "ash/ash_switches.h"
11 #include "ash/metrics/user_metrics_recorder.h" 11 #include "ash/metrics/user_metrics_recorder.h"
12 #include "ash/root_window_controller.h" 12 #include "ash/root_window_controller.h"
13 #include "ash/shell.h" 13 #include "ash/shell.h"
14 #include "ash/shell_window_ids.h" 14 #include "ash/shell_window_ids.h"
15 #include "ash/switchable_windows.h" 15 #include "ash/switchable_windows.h"
16 #include "ash/wm/overview/scoped_transform_overview_window.h" 16 #include "ash/wm/overview/scoped_transform_overview_window.h"
17 #include "ash/wm/overview/window_grid.h" 17 #include "ash/wm/overview/window_grid.h"
18 #include "ash/wm/overview/window_selector_delegate.h" 18 #include "ash/wm/overview/window_selector_delegate.h"
19 #include "ash/wm/overview/window_selector_item.h" 19 #include "ash/wm/overview/window_selector_item.h"
20 #include "ash/wm/window_state.h" 20 #include "ash/wm/window_state.h"
21 #include "base/auto_reset.h" 21 #include "base/auto_reset.h"
22 #include "base/command_line.h"
22 #include "base/metrics/histogram.h" 23 #include "base/metrics/histogram.h"
23 #include "ui/aura/client/focus_client.h" 24 #include "ui/aura/client/focus_client.h"
24 #include "ui/aura/window.h" 25 #include "ui/aura/window.h"
25 #include "ui/aura/window_event_dispatcher.h" 26 #include "ui/aura/window_event_dispatcher.h"
26 #include "ui/aura/window_observer.h" 27 #include "ui/aura/window_observer.h"
27 #include "ui/compositor/scoped_layer_animation_settings.h" 28 #include "ui/compositor/scoped_layer_animation_settings.h"
28 #include "ui/events/event.h" 29 #include "ui/events/event.h"
29 #include "ui/gfx/screen.h" 30 #include "ui/gfx/screen.h"
31 #include "ui/views/border.h"
32 #include "ui/views/controls/textfield/textfield.h"
30 #include "ui/wm/core/window_util.h" 33 #include "ui/wm/core/window_util.h"
31 #include "ui/wm/public/activation_client.h" 34 #include "ui/wm/public/activation_client.h"
32 35
33 namespace ash { 36 namespace ash {
34 37
35 namespace { 38 namespace {
36 39
40 // The proportion of screen width that the text filter takes.
41 const float kTextFilterScreenProportion = 0.5;
42
43 // The height of the text filter.
44 const int kTextFilterHeight = 50;
45
46 // Solid shadow length from the text filter.
47 const int kVerticalShadowOffset = 1;
48
49 // Amount of blur applied to the text filter shadow.
50 const int kShadowBlur = 10;
51
52 // Text filter shadow color.
53 const SkColor kTextFilterShadow = 0xB0000000;
54
37 // A comparator for locating a grid with a given root window. 55 // A comparator for locating a grid with a given root window.
38 struct RootWindowGridComparator 56 struct RootWindowGridComparator
39 : public std::unary_function<WindowGrid*, bool> { 57 : public std::unary_function<WindowGrid*, bool> {
40 explicit RootWindowGridComparator(const aura::Window* root_window) 58 explicit RootWindowGridComparator(const aura::Window* root_window)
41 : root_window_(root_window) { 59 : root_window_(root_window) {
42 } 60 }
43 61
44 bool operator()(WindowGrid* grid) const { 62 bool operator()(WindowGrid* grid) const {
45 return (grid->root_window() == root_window_); 63 return (grid->root_window() == root_window_);
46 } 64 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 void UpdateShelfVisibility() { 98 void UpdateShelfVisibility() {
81 Shell::RootWindowControllerList root_window_controllers = 99 Shell::RootWindowControllerList root_window_controllers =
82 Shell::GetInstance()->GetAllRootWindowControllers(); 100 Shell::GetInstance()->GetAllRootWindowControllers();
83 for (Shell::RootWindowControllerList::iterator iter = 101 for (Shell::RootWindowControllerList::iterator iter =
84 root_window_controllers.begin(); 102 root_window_controllers.begin();
85 iter != root_window_controllers.end(); ++iter) { 103 iter != root_window_controllers.end(); ++iter) {
86 (*iter)->UpdateShelfVisibility(); 104 (*iter)->UpdateShelfVisibility();
87 } 105 }
88 } 106 }
89 107
108 // Initializes the text filter on the top of the main root window and requests
109 // focus on its textfield.
110 views::Widget* CreateTextFilter(views::TextfieldController* controller,
111 aura::Window* root_window) {
112 views::Widget* widget = new views::Widget;
113 views::Widget::InitParams params;
114 params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
115 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
116 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
117 params.parent =
118 Shell::GetContainer(root_window, ash::kShellWindowId_OverlayContainer);
119 params.accept_events = true;
120 params.bounds = gfx::Rect(
121 root_window->bounds().width() / 2 * (1 - kTextFilterScreenProportion), 0,
122 root_window->bounds().width() * kTextFilterScreenProportion,
123 kTextFilterHeight);
124 widget->Init(params);
125
126 views::Textfield* textfield = new views::Textfield;
127 textfield->set_controller(controller);
128 textfield->SetBackgroundColor(SK_ColorTRANSPARENT);
129 textfield->SetBorder(views::Border::NullBorder());
130 textfield->SetTextColor(SK_ColorWHITE);
131 textfield->set_shadows(gfx::ShadowValues(1, gfx::ShadowValue(
132 gfx::Point(0, kVerticalShadowOffset), kShadowBlur, kTextFilterShadow)));
133 widget->SetContentsView(textfield);
134
135 gfx::Transform transform;
136 transform.Translate(0, -kTextFilterHeight);
137 widget->GetNativeWindow()->SetTransform(transform);
138 widget->Show();
139 textfield->RequestFocus();
140
141 return widget;
142 }
143
90 } // namespace 144 } // namespace
91 145
92 WindowSelector::WindowSelector(const WindowList& windows, 146 WindowSelector::WindowSelector(const WindowList& windows,
93 WindowSelectorDelegate* delegate) 147 WindowSelectorDelegate* delegate)
94 : delegate_(delegate), 148 : delegate_(delegate),
95 restore_focus_window_(aura::client::GetFocusClient( 149 restore_focus_window_(aura::client::GetFocusClient(
96 Shell::GetPrimaryRootWindow())->GetFocusedWindow()), 150 Shell::GetPrimaryRootWindow())->GetFocusedWindow()),
97 ignore_activations_(false), 151 ignore_activations_(false),
98 selected_grid_index_(0), 152 selected_grid_index_(0),
99 overview_start_time_(base::Time::Now()), 153 overview_start_time_(base::Time::Now()),
100 num_key_presses_(0), 154 num_key_presses_(0),
101 num_items_(0) { 155 num_items_(0),
156 showing_selection_widget_(false) {
102 DCHECK(delegate_); 157 DCHECK(delegate_);
103 Shell* shell = Shell::GetInstance(); 158 Shell* shell = Shell::GetInstance();
104 shell->OnOverviewModeStarting(); 159 shell->OnOverviewModeStarting();
105 160
106 if (restore_focus_window_) 161 if (restore_focus_window_)
107 restore_focus_window_->AddObserver(this); 162 restore_focus_window_->AddObserver(this);
108 163
109 const aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 164 const aura::Window::Windows root_windows = Shell::GetAllRootWindows();
110 for (aura::Window::Windows::const_iterator iter = root_windows.begin(); 165 for (aura::Window::Windows::const_iterator iter = root_windows.begin();
111 iter != root_windows.end(); iter++) { 166 iter != root_windows.end(); iter++) {
112 // Observed switchable containers for newly created windows on all root 167 // Observed switchable containers for newly created windows on all root
113 // windows. 168 // windows.
114 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { 169 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) {
115 aura::Window* container = Shell::GetContainer(*iter, 170 aura::Window* container = Shell::GetContainer(*iter,
116 kSwitchableWindowContainerIds[i]); 171 kSwitchableWindowContainerIds[i]);
117 container->AddObserver(this); 172 container->AddObserver(this);
118 observed_windows_.insert(container); 173 observed_windows_.insert(container);
119 } 174 }
120 scoped_ptr<WindowGrid> grid(new WindowGrid(*iter, windows, this)); 175 scoped_ptr<WindowGrid> grid(new WindowGrid(*iter, windows, this));
121 if (grid->empty()) 176 if (grid->empty())
122 continue; 177 continue;
123 num_items_ += grid->size(); 178 num_items_ += grid->size();
124 grid_list_.push_back(grid.release()); 179 grid_list_.push_back(grid.release());
125 } 180 }
126 181
127 DCHECK(!grid_list_.empty()); 182 DCHECK(!grid_list_.empty());
128 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.Items", num_items_); 183 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.Items", num_items_);
129 184
185 text_filter_widget_.reset(
186 CreateTextFilter(this, Shell::GetPrimaryRootWindow()));
187
130 shell->activation_client()->AddObserver(this); 188 shell->activation_client()->AddObserver(this);
131 189
132 // Remove focus from active window before entering overview.
133 aura::client::GetFocusClient(
134 Shell::GetPrimaryRootWindow())->FocusWindow(NULL);
135
136 shell->PrependPreTargetHandler(this);
137 shell->GetScreen()->AddObserver(this); 190 shell->GetScreen()->AddObserver(this);
138 shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW); 191 shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW);
139 HideAndTrackNonOverviewWindows(); 192 HideAndTrackNonOverviewWindows();
140 // Send an a11y alert. 193 // Send an a11y alert.
141 shell->accessibility_delegate()->TriggerAccessibilityAlert( 194 shell->accessibility_delegate()->TriggerAccessibilityAlert(
142 A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED); 195 A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED);
143 196
144 UpdateShelfVisibility(); 197 UpdateShelfVisibility();
145 } 198 }
146 199
(...skipping 14 matching lines...) Expand all
161 ui::ScopedLayerAnimationSettings settings( 214 ui::ScopedLayerAnimationSettings settings(
162 (*iter)->layer()->GetAnimator()); 215 (*iter)->layer()->GetAnimator());
163 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( 216 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
164 ScopedTransformOverviewWindow::kTransitionMilliseconds)); 217 ScopedTransformOverviewWindow::kTransitionMilliseconds));
165 settings.SetPreemptionStrategy( 218 settings.SetPreemptionStrategy(
166 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 219 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
167 (*iter)->layer()->SetOpacity(1); 220 (*iter)->layer()->SetOpacity(1);
168 (*iter)->Show(); 221 (*iter)->Show();
169 } 222 }
170 223
171 shell->RemovePreTargetHandler(this);
172 shell->GetScreen()->RemoveObserver(this); 224 shell->GetScreen()->RemoveObserver(this);
173 225
174 size_t remaining_items = 0; 226 size_t remaining_items = 0;
175 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin(); 227 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin();
176 iter != grid_list_.end(); iter++) { 228 iter != grid_list_.end(); iter++) {
177 remaining_items += (*iter)->size(); 229 remaining_items += (*iter)->size();
178 } 230 }
179 231
180 DCHECK(num_items_ >= remaining_items); 232 DCHECK(num_items_ >= remaining_items);
181 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.OverviewClosedItems", 233 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.OverviewClosedItems",
(...skipping 18 matching lines...) Expand all
200 ScopedVector<WindowGrid>::iterator iter = 252 ScopedVector<WindowGrid>::iterator iter =
201 std::find(grid_list_.begin(), grid_list_.end(), grid); 253 std::find(grid_list_.begin(), grid_list_.end(), grid);
202 DCHECK(iter != grid_list_.end()); 254 DCHECK(iter != grid_list_.end());
203 grid_list_.erase(iter); 255 grid_list_.erase(iter);
204 // TODO(nsatragno): Use the previous index for more than two displays. 256 // TODO(nsatragno): Use the previous index for more than two displays.
205 selected_grid_index_ = 0; 257 selected_grid_index_ = 0;
206 if (grid_list_.empty()) 258 if (grid_list_.empty())
207 CancelSelection(); 259 CancelSelection();
208 } 260 }
209 261
210 void WindowSelector::OnKeyEvent(ui::KeyEvent* event) { 262 bool WindowSelector::HandleKeyEvent(views::Textfield* sender,
211 if (event->type() != ui::ET_KEY_PRESSED) 263 const ui::KeyEvent& key_event) {
212 return; 264 if (key_event.type() != ui::ET_KEY_PRESSED)
265 return false;
213 266
214 switch (event->key_code()) { 267 switch (key_event.key_code()) {
215 case ui::VKEY_ESCAPE: 268 case ui::VKEY_ESCAPE:
216 CancelSelection(); 269 CancelSelection();
217 break; 270 break;
218 case ui::VKEY_UP: 271 case ui::VKEY_UP:
219 num_key_presses_++; 272 num_key_presses_++;
220 Move(WindowSelector::UP); 273 Move(WindowSelector::UP, true);
221 break; 274 break;
222 case ui::VKEY_DOWN: 275 case ui::VKEY_DOWN:
223 num_key_presses_++; 276 num_key_presses_++;
224 Move(WindowSelector::DOWN); 277 Move(WindowSelector::DOWN, true);
225 break; 278 break;
226 case ui::VKEY_RIGHT: 279 case ui::VKEY_RIGHT:
227 num_key_presses_++; 280 num_key_presses_++;
228 Move(WindowSelector::RIGHT); 281 Move(WindowSelector::RIGHT, true);
229 break; 282 break;
230 case ui::VKEY_LEFT: 283 case ui::VKEY_LEFT:
231 num_key_presses_++; 284 num_key_presses_++;
232 Move(WindowSelector::LEFT); 285 Move(WindowSelector::LEFT, true);
233 break; 286 break;
234 case ui::VKEY_RETURN: 287 case ui::VKEY_RETURN:
235 // Ignore if no item is selected. 288 // Ignore if no item is selected.
236 if (!grid_list_[selected_grid_index_]->is_selecting()) 289 if (!grid_list_[selected_grid_index_]->is_selecting())
237 return; 290 return false;
238 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.ArrowKeyPresses", 291 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.ArrowKeyPresses",
239 num_key_presses_); 292 num_key_presses_);
240 UMA_HISTOGRAM_CUSTOM_COUNTS( 293 UMA_HISTOGRAM_CUSTOM_COUNTS(
241 "Ash.WindowSelector.KeyPressesOverItemsRatio", 294 "Ash.WindowSelector.KeyPressesOverItemsRatio",
242 (num_key_presses_ * 100) / num_items_, 1, 300, 30); 295 (num_key_presses_ * 100) / num_items_, 1, 300, 30);
243 Shell::GetInstance()->metrics()->RecordUserMetricsAction( 296 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
244 UMA_WINDOW_OVERVIEW_ENTER_KEY); 297 UMA_WINDOW_OVERVIEW_ENTER_KEY);
245 wm::GetWindowState(grid_list_[selected_grid_index_]-> 298 wm::GetWindowState(grid_list_[selected_grid_index_]->
246 SelectedWindow()->SelectionWindow())->Activate(); 299 SelectedWindow()->SelectionWindow())->Activate();
247 break; 300 break;
248 default: 301 default:
249 // Not a key we are interested in. 302 // Not a key we are interested in, allow the textfield to handle it.
250 return; 303 return false;
251 } 304 }
252 event->StopPropagation(); 305 return true;
253 } 306 }
254 307
255 void WindowSelector::OnDisplayAdded(const gfx::Display& display) { 308 void WindowSelector::OnDisplayAdded(const gfx::Display& display) {
256 } 309 }
257 310
258 void WindowSelector::OnDisplayRemoved(const gfx::Display& display) { 311 void WindowSelector::OnDisplayRemoved(const gfx::Display& display) {
259 // TODO(nsatragno): Keep window selection active on remaining displays. 312 // TODO(nsatragno): Keep window selection active on remaining displays.
260 CancelSelection(); 313 CancelSelection();
261 } 314 }
262 315
(...skipping 20 matching lines...) Expand all
283 336
284 void WindowSelector::OnWindowDestroying(aura::Window* window) { 337 void WindowSelector::OnWindowDestroying(aura::Window* window) {
285 window->RemoveObserver(this); 338 window->RemoveObserver(this);
286 observed_windows_.erase(window); 339 observed_windows_.erase(window);
287 if (window == restore_focus_window_) 340 if (window == restore_focus_window_)
288 restore_focus_window_ = NULL; 341 restore_focus_window_ = NULL;
289 } 342 }
290 343
291 void WindowSelector::OnWindowActivated(aura::Window* gained_active, 344 void WindowSelector::OnWindowActivated(aura::Window* gained_active,
292 aura::Window* lost_active) { 345 aura::Window* lost_active) {
293 if (ignore_activations_ || !gained_active) 346 if (ignore_activations_ ||
347 !gained_active ||
348 gained_active == text_filter_widget_->GetNativeWindow()) {
294 return; 349 return;
350 }
295 351
296 ScopedVector<WindowGrid>::iterator grid = 352 ScopedVector<WindowGrid>::iterator grid =
297 std::find_if(grid_list_.begin(), grid_list_.end(), 353 std::find_if(grid_list_.begin(), grid_list_.end(),
298 RootWindowGridComparator(gained_active->GetRootWindow())); 354 RootWindowGridComparator(gained_active->GetRootWindow()));
299 if (grid == grid_list_.end()) 355 if (grid == grid_list_.end())
300 return; 356 return;
301 const std::vector<WindowSelectorItem*> windows = (*grid)->window_list(); 357 const std::vector<WindowSelectorItem*> windows = (*grid)->window_list();
302 358
303 ScopedVector<WindowSelectorItem>::const_iterator iter = std::find_if( 359 ScopedVector<WindowSelectorItem>::const_iterator iter = std::find_if(
304 windows.begin(), windows.end(), 360 windows.begin(), windows.end(),
305 WindowSelectorItemTargetComparator(gained_active)); 361 WindowSelectorItemTargetComparator(gained_active));
306 362
307 if (iter != windows.end()) 363 if (iter != windows.end())
308 (*iter)->RestoreWindowOnExit(gained_active); 364 (*iter)->RestoreWindowOnExit(gained_active);
309 365
310 // Don't restore focus on exit if a window was just activated. 366 // Don't restore focus on exit if a window was just activated.
311 ResetFocusRestoreWindow(false); 367 ResetFocusRestoreWindow(false);
312 CancelSelection(); 368 CancelSelection();
313 } 369 }
314 370
315 void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active, 371 void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active,
316 aura::Window* actual_active) { 372 aura::Window* actual_active) {
317 OnWindowActivated(request_active, actual_active); 373 OnWindowActivated(request_active, actual_active);
318 } 374 }
319 375
376 void WindowSelector::ContentsChanged(views::Textfield* sender,
377 const base::string16& new_contents) {
378 if (CommandLine::ForCurrentProcess()->HasSwitch(
379 switches::kAshDisableTextFilteringInOverviewMode)) {
380 return;
381 }
382
383 bool should_show_selection_widget = !new_contents.empty();
384
flackr 2014/07/02 15:50:42 nit: no need for newline here.
Nina 2014/07/02 17:39:05 Done.
385 if (showing_selection_widget_ != should_show_selection_widget) {
386 ui::ScopedLayerAnimationSettings animation_settings(
387 text_filter_widget_->GetNativeWindow()->layer()->GetAnimator());
388 animation_settings.SetPreemptionStrategy(
389 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
390 animation_settings.SetTweenType(showing_selection_widget_ ?
391 gfx::Tween::FAST_OUT_LINEAR_IN : gfx::Tween::LINEAR_OUT_SLOW_IN);
392
393 gfx::Transform transform;
394 if (should_show_selection_widget)
395 transform.Translate(0, 0);
396 else
397 transform.Translate(0, -kTextFilterHeight);
398
399 text_filter_widget_->GetNativeWindow()->SetTransform(transform);
400 showing_selection_widget_ = should_show_selection_widget;
401 }
402 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin();
403 iter != grid_list_.end(); iter++) {
404 (*iter)->FilterItems(new_contents);
405 }
406
407 // If the selection widget is not active, execute a Move() command so that it
408 // shows up on the first undimmed item.
409 if (grid_list_[selected_grid_index_]->is_selecting())
410 return;
411 Move(WindowSelector::RIGHT, false);
412 }
413
320 void WindowSelector::PositionWindows(bool animate) { 414 void WindowSelector::PositionWindows(bool animate) {
321 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin(); 415 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin();
322 iter != grid_list_.end(); iter++) { 416 iter != grid_list_.end(); iter++) {
323 (*iter)->PositionWindows(animate); 417 (*iter)->PositionWindows(animate);
324 } 418 }
325 } 419 }
326 420
327 void WindowSelector::HideAndTrackNonOverviewWindows() { 421 void WindowSelector::HideAndTrackNonOverviewWindows() {
328 // Add the windows to hidden_windows first so that if any are destroyed 422 // Add the windows to hidden_windows first so that if any are destroyed
329 // while hiding them they are tracked. 423 // while hiding them they are tracked.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 } 466 }
373 // If the window is in the observed_windows_ list it needs to continue to be 467 // If the window is in the observed_windows_ list it needs to continue to be
374 // observed. 468 // observed.
375 if (observed_windows_.find(restore_focus_window_) == 469 if (observed_windows_.find(restore_focus_window_) ==
376 observed_windows_.end()) { 470 observed_windows_.end()) {
377 restore_focus_window_->RemoveObserver(this); 471 restore_focus_window_->RemoveObserver(this);
378 } 472 }
379 restore_focus_window_ = NULL; 473 restore_focus_window_ = NULL;
380 } 474 }
381 475
382 void WindowSelector::Move(Direction direction) { 476 void WindowSelector::Move(Direction direction, bool animate) {
383 bool overflowed = grid_list_[selected_grid_index_]->Move(direction); 477 // Keep calling Move() on the grids until one of them reports no overflow or
384 if (overflowed) { 478 // we made a full cycle on all the grids.
385 // The grid reported that the movement command corresponds to the next 479 for (size_t i = 0;
386 // root window, identify it and call Move() on it to initialize the 480 i <= grid_list_.size() &&
387 // selection widget. 481 grid_list_[selected_grid_index_]->Move(direction, animate); i++) {
388 // TODO(nsatragno): If there are more than two monitors, move between grids 482 // TODO(nsatragno): If there are more than two monitors, move between grids
389 // in the requested direction. 483 // in the requested direction.
390 selected_grid_index_ = (selected_grid_index_ + 1) % grid_list_.size(); 484 selected_grid_index_ = (selected_grid_index_ + 1) % grid_list_.size();
391 grid_list_[selected_grid_index_]->Move(direction);
392 } 485 }
393 } 486 }
394 487
395 } // namespace ash 488 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698