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