| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/common/wm/window_cycle_list.h" | 5 #include "ash/common/wm/window_cycle_list.h" |
| 6 | 6 |
| 7 #include <list> | 7 #include <list> |
| 8 #include <map> | 8 #include <map> |
| 9 | 9 |
| 10 #include "ash/common/ash_switches.h" | 10 #include "ash/common/ash_switches.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 #include "ui/views/controls/label.h" | 23 #include "ui/views/controls/label.h" |
| 24 #include "ui/views/layout/box_layout.h" | 24 #include "ui/views/layout/box_layout.h" |
| 25 #include "ui/views/painter.h" | 25 #include "ui/views/painter.h" |
| 26 #include "ui/views/view.h" | 26 #include "ui/views/view.h" |
| 27 #include "ui/views/widget/widget.h" | 27 #include "ui/views/widget/widget.h" |
| 28 #include "ui/views/widget/widget_delegate.h" | 28 #include "ui/views/widget/widget_delegate.h" |
| 29 #include "ui/wm/core/visibility_controller.h" | 29 #include "ui/wm/core/visibility_controller.h" |
| 30 | 30 |
| 31 namespace ash { | 31 namespace ash { |
| 32 | 32 |
| 33 namespace { |
| 34 |
| 35 bool g_disable_initial_delay = false; |
| 36 |
| 33 // Returns the window immediately below |window| in the current container. | 37 // Returns the window immediately below |window| in the current container. |
| 34 WmWindow* GetWindowBelow(WmWindow* window) { | 38 WmWindow* GetWindowBelow(WmWindow* window) { |
| 35 WmWindow* parent = window->GetParent(); | 39 WmWindow* parent = window->GetParent(); |
| 36 if (!parent) | 40 if (!parent) |
| 37 return nullptr; | 41 return nullptr; |
| 38 const WmWindow::Windows children = parent->GetChildren(); | 42 const WmWindow::Windows children = parent->GetChildren(); |
| 39 auto iter = std::find(children.begin(), children.end(), window); | 43 auto iter = std::find(children.begin(), children.end(), window); |
| 40 CHECK(*iter == window); | 44 CHECK(*iter == window); |
| 41 return (iter != children.begin()) ? *(iter - 1) : nullptr; | 45 return (iter != children.begin()) ? *(iter - 1) : nullptr; |
| 42 } | 46 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 54 views::Painter::PaintPainterAt(canvas, painter_.get(), | 58 views::Painter::PaintPainterAt(canvas, painter_.get(), |
| 55 gfx::Rect(view->layer()->size())); | 59 gfx::Rect(view->layer()->size())); |
| 56 } | 60 } |
| 57 | 61 |
| 58 private: | 62 private: |
| 59 std::unique_ptr<views::Painter> painter_; | 63 std::unique_ptr<views::Painter> painter_; |
| 60 | 64 |
| 61 DISALLOW_COPY_AND_ASSIGN(LayerFillBackgroundPainter); | 65 DISALLOW_COPY_AND_ASSIGN(LayerFillBackgroundPainter); |
| 62 }; | 66 }; |
| 63 | 67 |
| 68 } // namespace |
| 69 |
| 64 // This class restores and moves a window to the front of the stacking order for | 70 // This class restores and moves a window to the front of the stacking order for |
| 65 // the duration of the class's scope. | 71 // the duration of the class's scope. |
| 66 class ScopedShowWindow : public WmWindowObserver { | 72 class ScopedShowWindow : public WmWindowObserver { |
| 67 public: | 73 public: |
| 68 ScopedShowWindow(); | 74 ScopedShowWindow(); |
| 69 ~ScopedShowWindow() override; | 75 ~ScopedShowWindow() override; |
| 70 | 76 |
| 71 // Show |window| at the top of the stacking order. | 77 // Show |window| at the top of the stacking order. |
| 72 void Show(WmWindow* window); | 78 void Show(WmWindow* window); |
| 73 | 79 |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 AddChildView(highlight_view_); | 301 AddChildView(highlight_view_); |
| 296 AddChildView(mirror_container_); | 302 AddChildView(mirror_container_); |
| 297 } | 303 } |
| 298 | 304 |
| 299 ~WindowCycleView() override {} | 305 ~WindowCycleView() override {} |
| 300 | 306 |
| 301 void SetTargetWindow(WmWindow* target) { | 307 void SetTargetWindow(WmWindow* target) { |
| 302 target_window_ = target; | 308 target_window_ = target; |
| 303 if (GetWidget()) { | 309 if (GetWidget()) { |
| 304 Layout(); | 310 Layout(); |
| 305 DCHECK(Contains(GetFocusManager()->GetFocusedView())); | 311 if (target_window_) { |
| 306 window_view_map_[target_window_]->RequestFocus(); | 312 // In the window destruction case, we may have already removed the |
| 313 // focused view and hence not be the focused window. We should still |
| 314 // always be active, though. |
| 315 DCHECK_EQ(ash::WmShell::Get()->GetActiveWindow()->GetInternalWidget(), |
| 316 GetWidget()); |
| 317 window_view_map_[target_window_]->RequestFocus(); |
| 318 } |
| 307 } | 319 } |
| 308 } | 320 } |
| 309 | 321 |
| 310 void HandleWindowDestruction(WmWindow* destroying_window, | 322 void HandleWindowDestruction(WmWindow* destroying_window, |
| 311 WmWindow* new_target) { | 323 WmWindow* new_target) { |
| 312 auto view_iter = window_view_map_.find(destroying_window); | 324 auto view_iter = window_view_map_.find(destroying_window); |
| 313 view_iter->second->parent()->RemoveChildView(view_iter->second); | 325 views::View* parent = view_iter->second->parent(); |
| 326 DCHECK_EQ(mirror_container_, parent); |
| 327 parent->RemoveChildView(view_iter->second); |
| 314 window_view_map_.erase(view_iter); | 328 window_view_map_.erase(view_iter); |
| 329 // With one of its children now gone, we must re-layout |mirror_container_|. |
| 330 // This must happen before SetTargetWindow() to make sure our own Layout() |
| 331 // works correctly when it's calculating highlight bounds. |
| 332 parent->Layout(); |
| 315 SetTargetWindow(new_target); | 333 SetTargetWindow(new_target); |
| 316 } | 334 } |
| 317 | 335 |
| 318 // views::WidgetDelegateView overrides: | 336 // views::WidgetDelegateView overrides: |
| 319 gfx::Size GetPreferredSize() const override { | 337 gfx::Size GetPreferredSize() const override { |
| 320 return mirror_container_->GetPreferredSize(); | 338 return mirror_container_->GetPreferredSize(); |
| 321 } | 339 } |
| 322 | 340 |
| 323 void Layout() override { | 341 void Layout() override { |
| 324 if (!target_window_ || bounds().IsEmpty()) | 342 if (!target_window_ || bounds().IsEmpty()) |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 CancelRestore(); | 426 CancelRestore(); |
| 409 } else if (params.target == stack_window_above_) { | 427 } else if (params.target == stack_window_above_) { |
| 410 // If the window this window was above is removed, use the next window down | 428 // If the window this window was above is removed, use the next window down |
| 411 // as the restore marker. | 429 // as the restore marker. |
| 412 stack_window_above_ = GetWindowBelow(stack_window_above_); | 430 stack_window_above_ = GetWindowBelow(stack_window_above_); |
| 413 } | 431 } |
| 414 } | 432 } |
| 415 | 433 |
| 416 WindowCycleList::WindowCycleList(const WindowList& windows) | 434 WindowCycleList::WindowCycleList(const WindowList& windows) |
| 417 : windows_(windows), current_index_(0), cycle_view_(nullptr) { | 435 : windows_(windows), current_index_(0), cycle_view_(nullptr) { |
| 418 WmShell::Get()->mru_window_tracker()->SetIgnoreActivations(true); | 436 if (!ShouldShowUi()) |
| 437 WmShell::Get()->mru_window_tracker()->SetIgnoreActivations(true); |
| 419 | 438 |
| 420 for (WmWindow* window : windows_) | 439 for (WmWindow* window : windows_) |
| 421 window->AddObserver(this); | 440 window->AddObserver(this); |
| 422 | 441 |
| 423 if (ShouldShowUi()) { | 442 if (ShouldShowUi()) { |
| 424 show_ui_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(150), | 443 if (g_disable_initial_delay) { |
| 425 this, &WindowCycleList::InitWindowCycleView); | 444 InitWindowCycleView(); |
| 445 } else { |
| 446 show_ui_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(150), |
| 447 this, &WindowCycleList::InitWindowCycleView); |
| 448 } |
| 426 } | 449 } |
| 427 } | 450 } |
| 428 | 451 |
| 429 WindowCycleList::~WindowCycleList() { | 452 WindowCycleList::~WindowCycleList() { |
| 430 WmShell::Get()->mru_window_tracker()->SetIgnoreActivations(false); | 453 if (!ShouldShowUi()) |
| 454 WmShell::Get()->mru_window_tracker()->SetIgnoreActivations(false); |
| 455 |
| 431 for (WmWindow* window : windows_) | 456 for (WmWindow* window : windows_) |
| 432 window->RemoveObserver(this); | 457 window->RemoveObserver(this); |
| 433 | 458 |
| 434 if (showing_window_) { | 459 if (showing_window_) { |
| 435 showing_window_->CancelRestore(); | 460 showing_window_->CancelRestore(); |
| 436 } else if (!windows_.empty()) { | 461 } else if (!windows_.empty()) { |
| 437 WmWindow* target_window = windows_[current_index_]; | 462 WmWindow* target_window = windows_[current_index_]; |
| 438 target_window->Show(); | 463 target_window->Show(); |
| 439 target_window->GetWindowState()->Activate(); | 464 target_window->GetWindowState()->Activate(); |
| 440 } | 465 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 468 | 493 |
| 469 if (cycle_view_) | 494 if (cycle_view_) |
| 470 cycle_view_->SetTargetWindow(windows_[current_index_]); | 495 cycle_view_->SetTargetWindow(windows_[current_index_]); |
| 471 } else { | 496 } else { |
| 472 // Make sure the next window is visible. | 497 // Make sure the next window is visible. |
| 473 showing_window_.reset(new ScopedShowWindow); | 498 showing_window_.reset(new ScopedShowWindow); |
| 474 showing_window_->Show(windows_[current_index_]); | 499 showing_window_->Show(windows_[current_index_]); |
| 475 } | 500 } |
| 476 } | 501 } |
| 477 | 502 |
| 503 // static |
| 504 void WindowCycleList::DisableInitialDelayForTesting() { |
| 505 g_disable_initial_delay = true; |
| 506 } |
| 507 |
| 478 void WindowCycleList::OnWindowDestroying(WmWindow* window) { | 508 void WindowCycleList::OnWindowDestroying(WmWindow* window) { |
| 479 window->RemoveObserver(this); | 509 window->RemoveObserver(this); |
| 480 | 510 |
| 481 WindowList::iterator i = std::find(windows_.begin(), windows_.end(), window); | 511 WindowList::iterator i = std::find(windows_.begin(), windows_.end(), window); |
| 482 // TODO(oshima): Change this back to DCHECK once crbug.com/483491 is fixed. | 512 // TODO(oshima): Change this back to DCHECK once crbug.com/483491 is fixed. |
| 483 CHECK(i != windows_.end()); | 513 CHECK(i != windows_.end()); |
| 484 int removed_index = static_cast<int>(i - windows_.begin()); | 514 int removed_index = static_cast<int>(i - windows_.begin()); |
| 485 windows_.erase(i); | 515 windows_.erase(i); |
| 486 if (current_index_ > removed_index || | 516 if (current_index_ > removed_index || |
| 487 current_index_ == static_cast<int>(windows_.size())) { | 517 current_index_ == static_cast<int>(windows_.size())) { |
| 488 current_index_--; | 518 current_index_--; |
| 489 } | 519 } |
| 490 | 520 |
| 491 if (cycle_view_) { | 521 if (cycle_view_) { |
| 492 WmWindow* new_target_window = | 522 WmWindow* new_target_window = |
| 493 windows_.empty() ? nullptr : windows_[current_index_]; | 523 windows_.empty() ? nullptr : windows_[current_index_]; |
| 494 cycle_view_->HandleWindowDestruction(window, new_target_window); | 524 cycle_view_->HandleWindowDestruction(window, new_target_window); |
| 495 if (windows_.empty()) { | 525 if (windows_.empty()) { |
| 496 // This deletes us. | 526 // This deletes us. |
| 497 WmShell::Get()->window_cycle_controller()->StopCycling(); | 527 WmShell::Get()->window_cycle_controller()->StopCycling(); |
| 498 return; | 528 return; |
| 499 } | 529 } |
| 500 } | 530 } |
| 501 } | 531 } |
| 502 | 532 |
| 503 bool WindowCycleList::ShouldShowUi() { | 533 bool WindowCycleList::ShouldShowUi() { |
| 504 return windows_.size() > 1 && | 534 return windows_.size() > 1; |
| 505 base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 506 switches::kAshEnableWindowCycleUi); | |
| 507 } | 535 } |
| 508 | 536 |
| 509 void WindowCycleList::InitWindowCycleView() { | 537 void WindowCycleList::InitWindowCycleView() { |
| 510 if (cycle_view_) | 538 if (cycle_view_) |
| 511 return; | 539 return; |
| 512 | 540 |
| 513 cycle_view_ = new WindowCycleView(windows_); | 541 cycle_view_ = new WindowCycleView(windows_); |
| 514 cycle_view_->SetTargetWindow(windows_[current_index_]); | 542 cycle_view_->SetTargetWindow(windows_[current_index_]); |
| 515 | 543 |
| 516 WmWindow* root_window = WmShell::Get()->GetRootWindowForNewWindows(); | 544 WmWindow* root_window = WmShell::Get()->GetRootWindowForNewWindows(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 534 gfx::Rect widget_rect = widget->GetWorkAreaBoundsInScreen(); | 562 gfx::Rect widget_rect = widget->GetWorkAreaBoundsInScreen(); |
| 535 int widget_height = cycle_view_->GetPreferredSize().height(); | 563 int widget_height = cycle_view_->GetPreferredSize().height(); |
| 536 widget_rect.set_y((widget_rect.height() - widget_height) / 2); | 564 widget_rect.set_y((widget_rect.height() - widget_height) / 2); |
| 537 widget_rect.set_height(widget_height); | 565 widget_rect.set_height(widget_height); |
| 538 widget->SetBounds(widget_rect); | 566 widget->SetBounds(widget_rect); |
| 539 widget->Show(); | 567 widget->Show(); |
| 540 cycle_ui_widget_.reset(widget); | 568 cycle_ui_widget_.reset(widget); |
| 541 } | 569 } |
| 542 | 570 |
| 543 } // namespace ash | 571 } // namespace ash |
| OLD | NEW |