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