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 #include <set> | 8 #include <set> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
85 }; | 85 }; |
86 | 86 |
87 // A comparator for locating a selectable window given a targeted window. | 87 // A comparator for locating a selectable window given a targeted window. |
88 struct WindowSelectorItemTargetComparator | 88 struct WindowSelectorItemTargetComparator |
89 : public std::unary_function<WindowSelectorItem*, bool> { | 89 : public std::unary_function<WindowSelectorItem*, bool> { |
90 explicit WindowSelectorItemTargetComparator(const aura::Window* target_window) | 90 explicit WindowSelectorItemTargetComparator(const aura::Window* target_window) |
91 : target(target_window) { | 91 : target(target_window) { |
92 } | 92 } |
93 | 93 |
94 bool operator()(WindowSelectorItem* window) const { | 94 bool operator()(WindowSelectorItem* window) const { |
95 return window->Contains(target); | 95 return window->GetWindow() == target; |
96 } | 96 } |
97 | 97 |
98 const aura::Window* target; | 98 const aura::Window* target; |
99 }; | 99 }; |
100 | 100 |
101 // A comparator for locating a selector item for a given root. | 101 // A comparator for locating a selector item for a given root. |
102 struct WindowSelectorItemForRoot | 102 struct WindowSelectorItemForRoot |
103 : public std::unary_function<WindowSelectorItem*, bool> { | 103 : public std::unary_function<WindowSelectorItem*, bool> { |
104 explicit WindowSelectorItemForRoot(const aura::Window* root) | 104 explicit WindowSelectorItemForRoot(const aura::Window* root) |
105 : root_window(root) { | 105 : root_window(root) { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
210 textfield->RequestFocus(); | 210 textfield->RequestFocus(); |
211 | 211 |
212 return widget; | 212 return widget; |
213 } | 213 } |
214 | 214 |
215 } // namespace | 215 } // namespace |
216 | 216 |
217 const int WindowSelector::kTextFilterBottomEdge = | 217 const int WindowSelector::kTextFilterBottomEdge = |
218 kTextFilterDistanceFromTop + kTextFilterHeight; | 218 kTextFilterDistanceFromTop + kTextFilterHeight; |
219 | 219 |
220 WindowSelector::WindowSelector(const WindowList& windows, | 220 WindowSelector::WindowSelector(WindowSelectorDelegate* delegate) |
221 WindowSelectorDelegate* delegate) | |
222 : delegate_(delegate), | 221 : delegate_(delegate), |
223 restore_focus_window_(aura::client::GetFocusClient( | 222 restore_focus_window_(aura::client::GetFocusClient( |
224 Shell::GetPrimaryRootWindow())->GetFocusedWindow()), | 223 Shell::GetPrimaryRootWindow())->GetFocusedWindow()), |
225 ignore_activations_(false), | 224 ignore_activations_(false), |
226 selected_grid_index_(0), | 225 selected_grid_index_(0), |
227 overview_start_time_(base::Time::Now()), | 226 overview_start_time_(base::Time::Now()), |
228 num_key_presses_(0), | 227 num_key_presses_(0), |
229 num_items_(0), | 228 num_items_(0), |
230 showing_selection_widget_(false), | 229 showing_selection_widget_(false), |
231 text_filter_string_length_(0), | 230 text_filter_string_length_(0), |
232 num_times_textfield_cleared_(0) { | 231 num_times_textfield_cleared_(0), |
232 restoring_minimized_windows_(false) { | |
233 DCHECK(delegate_); | 233 DCHECK(delegate_); |
234 Shell* shell = Shell::GetInstance(); | 234 } |
235 shell->OnOverviewModeStarting(); | |
236 | 235 |
236 WindowSelector::~WindowSelector() { | |
237 RemoveAllObservers(); | |
238 } | |
239 | |
240 // NOTE: The work done in Init() is not done in the constructor because it may | |
241 // cause other, unrelated classes, (ie PanelLayoutManager) to make indirect | |
242 // calls to restoring_minimized_windows() on a partially constructed object. | |
243 void WindowSelector::Init(const WindowList& windows) { | |
237 if (restore_focus_window_) | 244 if (restore_focus_window_) |
238 restore_focus_window_->AddObserver(this); | 245 restore_focus_window_->AddObserver(this); |
239 | 246 |
240 const aura::Window::Windows root_windows = Shell::GetAllRootWindows(); | 247 const aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
241 for (aura::Window::Windows::const_iterator iter = root_windows.begin(); | 248 for (aura::Window::Windows::const_iterator iter = root_windows.begin(); |
242 iter != root_windows.end(); iter++) { | 249 iter != root_windows.end(); iter++) { |
243 // Observed switchable containers for newly created windows on all root | 250 // Observed switchable containers for newly created windows on all root |
244 // windows. | 251 // windows. |
245 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { | 252 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { |
246 aura::Window* container = Shell::GetContainer(*iter, | 253 aura::Window* container = Shell::GetContainer(*iter, |
247 kSwitchableWindowContainerIds[i]); | 254 kSwitchableWindowContainerIds[i]); |
248 container->AddObserver(this); | 255 container->AddObserver(this); |
249 observed_windows_.insert(container); | 256 observed_windows_.insert(container); |
250 } | 257 } |
251 | 258 |
252 // Hide the callout widgets for panels. It is safe to call this for | 259 // Hide the callout widgets for panels. It is safe to call this for |
253 // root windows that don't contain any panel windows. | 260 // root windows that don't contain any panel windows. |
254 static_cast<PanelLayoutManager*>( | 261 static_cast<PanelLayoutManager*>( |
255 Shell::GetContainer(*iter, kShellWindowId_PanelContainer) | 262 Shell::GetContainer(*iter, kShellWindowId_PanelContainer) |
256 ->layout_manager())->SetShowCalloutWidgets(false); | 263 ->layout_manager())->SetShowCalloutWidgets(false); |
257 | 264 |
258 scoped_ptr<WindowGrid> grid(new WindowGrid(*iter, windows, this)); | 265 scoped_ptr<WindowGrid> grid(new WindowGrid(*iter, windows, this)); |
259 if (grid->empty()) | 266 if (grid->empty()) |
260 continue; | 267 continue; |
261 num_items_ += grid->size(); | 268 num_items_ += grid->size(); |
262 grid_list_.push_back(grid.release()); | 269 grid_list_.push_back(grid.release()); |
263 } | 270 } |
264 | 271 |
265 // Do not call PrepareForOverview until all items are added to window_list_ as | 272 { |
266 // we don't want to cause any window updates until all windows in overview | 273 // The calls to WindowGrid::PrepareForOverview() and CreateTextFilter(...) |
267 // are observed. See http://crbug.com/384495. | 274 // requires some LayoutManagers (ie PanelLayoutManager) to perform layouts |
268 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin(); | 275 // so that windows are correctly visible and properly animated in overview |
269 iter != grid_list_.end(); ++iter) { | 276 // mode. Otherwise these layouts should be suppressed during overview mode |
270 (*iter)->PrepareForOverview(); | 277 // so they don't conflict with overview mode animations. The |
271 (*iter)->PositionWindows(true); | 278 // |restoring_minimized_windows_| flag enables the PanelLayoutManager to |
279 // make this decision. | |
280 base::AutoReset<bool> auto_restoring_minimized_windows( | |
281 &restoring_minimized_windows_, true); | |
282 | |
283 // Do not call PrepareForOverview until all items are added to window_list_ | |
284 // as we don't want to cause any window updates until all windows in | |
285 // overview are observed. See http://crbug.com/384495. | |
286 for (auto window_grid : grid_list_) { | |
oshima
2015/01/16 22:36:37
ditto
bruthig
2015/01/17 17:35:06
Done.
| |
287 window_grid->PrepareForOverview(); | |
288 window_grid->PositionWindows(true); | |
289 } | |
290 | |
291 text_filter_widget_.reset( | |
292 CreateTextFilter(this, Shell::GetPrimaryRootWindow())); | |
272 } | 293 } |
273 | 294 |
274 DCHECK(!grid_list_.empty()); | 295 DCHECK(!grid_list_.empty()); |
275 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.Items", num_items_); | 296 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.Items", num_items_); |
276 | 297 |
277 text_filter_widget_.reset( | 298 Shell* shell = Shell::GetInstance(); |
278 CreateTextFilter(this, Shell::GetPrimaryRootWindow())); | |
279 | 299 |
280 shell->activation_client()->AddObserver(this); | 300 shell->activation_client()->AddObserver(this); |
281 | 301 |
282 shell->GetScreen()->AddObserver(this); | 302 shell->GetScreen()->AddObserver(this); |
283 shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW); | 303 shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW); |
284 HideAndTrackNonOverviewWindows(); | 304 HideAndTrackNonOverviewWindows(); |
285 // Send an a11y alert. | 305 // Send an a11y alert. |
286 shell->accessibility_delegate()->TriggerAccessibilityAlert( | 306 shell->accessibility_delegate()->TriggerAccessibilityAlert( |
287 ui::A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED); | 307 ui::A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED); |
288 | 308 |
289 UpdateShelfVisibility(); | 309 UpdateShelfVisibility(); |
290 } | 310 } |
291 | 311 |
292 WindowSelector::~WindowSelector() { | 312 // NOTE: The work done in Shutdown() is not done in the destructor because it |
293 Shell* shell = Shell::GetInstance(); | 313 // may cause other, unrelated classes, (ie PanelLayoutManager) to make indirect |
294 | 314 // calls to restoring_minimized_windows() on a partially destructed object. |
315 void WindowSelector::Shutdown() { | |
295 ResetFocusRestoreWindow(true); | 316 ResetFocusRestoreWindow(true); |
296 for (std::set<aura::Window*>::iterator iter = observed_windows_.begin(); | 317 RemoveAllObservers(); |
297 iter != observed_windows_.end(); ++iter) { | |
298 (*iter)->RemoveObserver(this); | |
299 } | |
300 shell->activation_client()->RemoveObserver(this); | |
301 | 318 |
302 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); | 319 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
303 for (aura::Window::Windows::const_iterator iter = root_windows.begin(); | 320 for (aura::Window::Windows::const_iterator iter = root_windows.begin(); |
304 iter != root_windows.end(); iter++) { | 321 iter != root_windows.end(); iter++) { |
305 // Un-hide the callout widgets for panels. It is safe to call this for | 322 // Un-hide the callout widgets for panels. It is safe to call this for |
306 // root_windows that don't contain any panel windows. | 323 // root_windows that don't contain any panel windows. |
307 static_cast<PanelLayoutManager*>( | 324 static_cast<PanelLayoutManager*>( |
308 Shell::GetContainer(*iter, kShellWindowId_PanelContainer) | 325 Shell::GetContainer(*iter, kShellWindowId_PanelContainer) |
309 ->layout_manager())->SetShowCalloutWidgets(true); | 326 ->layout_manager())->SetShowCalloutWidgets(true); |
310 } | 327 } |
311 | 328 |
312 const aura::WindowTracker::Windows hidden_windows(hidden_windows_.windows()); | 329 const aura::WindowTracker::Windows hidden_windows(hidden_windows_.windows()); |
313 for (aura::WindowTracker::Windows::const_iterator iter = | 330 for (aura::WindowTracker::Windows::const_iterator iter = |
314 hidden_windows.begin(); iter != hidden_windows.end(); ++iter) { | 331 hidden_windows.begin(); iter != hidden_windows.end(); ++iter) { |
315 ScopedOverviewAnimationSettings animation_settings( | 332 ScopedOverviewAnimationSettings animation_settings( |
316 OverviewAnimationType::OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS, | 333 OverviewAnimationType::OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS, |
317 *iter); | 334 *iter); |
318 (*iter)->layer()->SetOpacity(1); | 335 (*iter)->layer()->SetOpacity(1); |
319 (*iter)->Show(); | 336 (*iter)->Show(); |
320 } | 337 } |
321 | 338 |
322 shell->GetScreen()->RemoveObserver(this); | |
323 | |
324 size_t remaining_items = 0; | 339 size_t remaining_items = 0; |
325 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin(); | 340 for (auto window_grid : grid_list_) { |
326 iter != grid_list_.end(); iter++) { | 341 for (auto window_selector_item : window_grid->window_list()) |
oshima
2015/01/16 22:36:37
ditto
bruthig
2015/01/17 17:35:06
Done.
| |
327 remaining_items += (*iter)->size(); | 342 window_selector_item->RestoreWindow(); |
343 remaining_items += window_grid->size(); | |
328 } | 344 } |
329 | 345 |
330 DCHECK(num_items_ >= remaining_items); | 346 DCHECK(num_items_ >= remaining_items); |
331 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.OverviewClosedItems", | 347 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.OverviewClosedItems", |
332 num_items_ - remaining_items); | 348 num_items_ - remaining_items); |
333 UMA_HISTOGRAM_MEDIUM_TIMES("Ash.WindowSelector.TimeInOverview", | 349 UMA_HISTOGRAM_MEDIUM_TIMES("Ash.WindowSelector.TimeInOverview", |
334 base::Time::Now() - overview_start_time_); | 350 base::Time::Now() - overview_start_time_); |
335 | 351 |
336 // Record metrics related to text filtering. | 352 // Record metrics related to text filtering. |
337 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.TextFilteringStringLength", | 353 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.TextFilteringStringLength", |
338 text_filter_string_length_); | 354 text_filter_string_length_); |
339 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.TextFilteringTextfieldCleared", | 355 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.TextFilteringTextfieldCleared", |
340 num_times_textfield_cleared_); | 356 num_times_textfield_cleared_); |
341 if (text_filter_string_length_) { | 357 if (text_filter_string_length_) { |
342 UMA_HISTOGRAM_MEDIUM_TIMES( | 358 UMA_HISTOGRAM_MEDIUM_TIMES( |
343 "Ash.WindowSelector.TimeInOverviewWithTextFiltering", | 359 "Ash.WindowSelector.TimeInOverviewWithTextFiltering", |
344 base::Time::Now() - overview_start_time_); | 360 base::Time::Now() - overview_start_time_); |
345 UMA_HISTOGRAM_COUNTS_100( | 361 UMA_HISTOGRAM_COUNTS_100( |
346 "Ash.WindowSelector.ItemsWhenTextFilteringUsed", | 362 "Ash.WindowSelector.ItemsWhenTextFilteringUsed", |
347 remaining_items); | 363 remaining_items); |
348 } | 364 } |
349 | 365 |
350 // TODO(flackr): Change this to OnOverviewModeEnded and move it to when | |
351 // everything is done. | |
352 shell->OnOverviewModeEnding(); | |
353 | |
354 // Clearing the window list resets the ignored_by_shelf flag on the windows. | 366 // Clearing the window list resets the ignored_by_shelf flag on the windows. |
355 grid_list_.clear(); | 367 grid_list_.clear(); |
356 UpdateShelfVisibility(); | 368 UpdateShelfVisibility(); |
357 } | 369 } |
358 | 370 |
371 void WindowSelector::RemoveAllObservers() { | |
372 Shell* shell = Shell::GetInstance(); | |
373 for (auto window : observed_windows_) { | |
oshima
2015/01/16 22:36:37
dutto
nuke {}
bruthig
2015/01/17 17:35:06
Done.
| |
374 window->RemoveObserver(this); | |
375 } | |
376 shell->activation_client()->RemoveObserver(this); | |
377 shell->GetScreen()->RemoveObserver(this); | |
378 if (restore_focus_window_) | |
379 restore_focus_window_->RemoveObserver(this); | |
380 } | |
381 | |
359 void WindowSelector::CancelSelection() { | 382 void WindowSelector::CancelSelection() { |
360 delegate_->OnSelectionEnded(); | 383 delegate_->OnSelectionEnded(); |
361 } | 384 } |
362 | 385 |
363 void WindowSelector::OnGridEmpty(WindowGrid* grid) { | 386 void WindowSelector::OnGridEmpty(WindowGrid* grid) { |
364 ScopedVector<WindowGrid>::iterator iter = | 387 ScopedVector<WindowGrid>::iterator iter = |
365 std::find(grid_list_.begin(), grid_list_.end(), grid); | 388 std::find(grid_list_.begin(), grid_list_.end(), grid); |
366 DCHECK(iter != grid_list_.end()); | 389 DCHECK(iter != grid_list_.end()); |
367 grid_list_.erase(iter); | 390 grid_list_.erase(iter); |
368 // TODO(flackr): Use the previous index for more than two displays. | 391 // TODO(flackr): Use the previous index for more than two displays. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
402 if (!grid_list_[selected_grid_index_]->is_selecting()) | 425 if (!grid_list_[selected_grid_index_]->is_selecting()) |
403 return false; | 426 return false; |
404 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.ArrowKeyPresses", | 427 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.ArrowKeyPresses", |
405 num_key_presses_); | 428 num_key_presses_); |
406 UMA_HISTOGRAM_CUSTOM_COUNTS( | 429 UMA_HISTOGRAM_CUSTOM_COUNTS( |
407 "Ash.WindowSelector.KeyPressesOverItemsRatio", | 430 "Ash.WindowSelector.KeyPressesOverItemsRatio", |
408 (num_key_presses_ * 100) / num_items_, 1, 300, 30); | 431 (num_key_presses_ * 100) / num_items_, 1, 300, 30); |
409 Shell::GetInstance()->metrics()->RecordUserMetricsAction( | 432 Shell::GetInstance()->metrics()->RecordUserMetricsAction( |
410 UMA_WINDOW_OVERVIEW_ENTER_KEY); | 433 UMA_WINDOW_OVERVIEW_ENTER_KEY); |
411 wm::GetWindowState(grid_list_[selected_grid_index_]-> | 434 wm::GetWindowState(grid_list_[selected_grid_index_]-> |
412 SelectedWindow()->SelectionWindow())->Activate(); | 435 SelectedWindow()->GetWindow())->Activate(); |
413 break; | 436 break; |
414 default: | 437 default: |
415 // Not a key we are interested in, allow the textfield to handle it. | 438 // Not a key we are interested in, allow the textfield to handle it. |
416 return false; | 439 return false; |
417 } | 440 } |
418 return true; | 441 return true; |
419 } | 442 } |
420 | 443 |
421 void WindowSelector::OnDisplayAdded(const gfx::Display& display) { | 444 void WindowSelector::OnDisplayAdded(const gfx::Display& display) { |
422 } | 445 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
467 RootWindowGridComparator(gained_active->GetRootWindow())); | 490 RootWindowGridComparator(gained_active->GetRootWindow())); |
468 if (grid == grid_list_.end()) | 491 if (grid == grid_list_.end()) |
469 return; | 492 return; |
470 const std::vector<WindowSelectorItem*> windows = (*grid)->window_list(); | 493 const std::vector<WindowSelectorItem*> windows = (*grid)->window_list(); |
471 | 494 |
472 ScopedVector<WindowSelectorItem>::const_iterator iter = std::find_if( | 495 ScopedVector<WindowSelectorItem>::const_iterator iter = std::find_if( |
473 windows.begin(), windows.end(), | 496 windows.begin(), windows.end(), |
474 WindowSelectorItemTargetComparator(gained_active)); | 497 WindowSelectorItemTargetComparator(gained_active)); |
475 | 498 |
476 if (iter != windows.end()) | 499 if (iter != windows.end()) |
477 (*iter)->RestoreWindowOnExit(gained_active); | 500 (*iter)->ShowWindowOnExit(); |
478 | 501 |
479 // Don't restore focus on exit if a window was just activated. | 502 // Don't restore focus on exit if a window was just activated. |
480 ResetFocusRestoreWindow(false); | 503 ResetFocusRestoreWindow(false); |
481 CancelSelection(); | 504 CancelSelection(); |
482 } | 505 } |
483 | 506 |
484 void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active, | 507 void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active, |
485 aura::Window* actual_active) { | 508 aura::Window* actual_active) { |
486 OnWindowActivated(request_active, actual_active); | 509 OnWindowActivated(request_active, actual_active); |
487 } | 510 } |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
595 for (size_t i = 0; | 618 for (size_t i = 0; |
596 i <= grid_list_.size() && | 619 i <= grid_list_.size() && |
597 grid_list_[selected_grid_index_]->Move(direction, animate); i++) { | 620 grid_list_[selected_grid_index_]->Move(direction, animate); i++) { |
598 // TODO(flackr): If there are more than two monitors, move between grids | 621 // TODO(flackr): If there are more than two monitors, move between grids |
599 // in the requested direction. | 622 // in the requested direction. |
600 selected_grid_index_ = (selected_grid_index_ + 1) % grid_list_.size(); | 623 selected_grid_index_ = (selected_grid_index_ + 1) % grid_list_.size(); |
601 } | 624 } |
602 } | 625 } |
603 | 626 |
604 } // namespace ash | 627 } // namespace ash |
OLD | NEW |