| 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/wm/window_cycle_list.h" | 5 #include "ash/wm/window_cycle_list.h" |
| 6 | 6 |
| 7 #include <list> | 7 #include <list> |
| 8 #include <map> | 8 #include <map> |
| 9 | 9 |
| 10 #include "ash/public/cpp/shell_window_ids.h" | 10 #include "ash/public/cpp/shell_window_ids.h" |
| 11 #include "ash/root_window_controller.h" | 11 #include "ash/root_window_controller.h" |
| 12 #include "ash/shell.h" | 12 #include "ash/shell.h" |
| 13 #include "ash/wm/mru_window_tracker.h" | 13 #include "ash/wm/mru_window_tracker.h" |
| 14 #include "ash/wm/window_mirror_view.h" |
| 14 #include "ash/wm/window_state.h" | 15 #include "ash/wm/window_state.h" |
| 16 #include "ash/wm/window_state_aura.h" |
| 17 #include "ash/wm/window_util.h" |
| 15 #include "ash/wm_window.h" | 18 #include "ash/wm_window.h" |
| 16 #include "base/command_line.h" | 19 #include "base/command_line.h" |
| 17 #include "ui/accessibility/ax_node_data.h" | 20 #include "ui/accessibility/ax_node_data.h" |
| 18 #include "ui/compositor/scoped_layer_animation_settings.h" | 21 #include "ui/compositor/scoped_layer_animation_settings.h" |
| 19 #include "ui/display/display.h" | 22 #include "ui/display/display.h" |
| 20 #include "ui/display/screen.h" | 23 #include "ui/display/screen.h" |
| 21 #include "ui/gfx/canvas.h" | 24 #include "ui/gfx/canvas.h" |
| 22 #include "ui/views/background.h" | 25 #include "ui/views/background.h" |
| 23 #include "ui/views/border.h" | 26 #include "ui/views/border.h" |
| 24 #include "ui/views/controls/label.h" | 27 #include "ui/views/controls/label.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 53 } | 56 } |
| 54 | 57 |
| 55 private: | 58 private: |
| 56 std::unique_ptr<views::Painter> painter_; | 59 std::unique_ptr<views::Painter> painter_; |
| 57 | 60 |
| 58 DISALLOW_COPY_AND_ASSIGN(LayerFillBackgroundPainter); | 61 DISALLOW_COPY_AND_ASSIGN(LayerFillBackgroundPainter); |
| 59 }; | 62 }; |
| 60 | 63 |
| 61 } // namespace | 64 } // namespace |
| 62 | 65 |
| 63 // This view represents a single WmWindow by displaying a title and a thumbnail | 66 // This view represents a single aura::Window by displaying a title and a |
| 64 // of the window's contents. | 67 // thumbnail of the window's contents. |
| 65 class WindowPreviewView : public views::View, public aura::WindowObserver { | 68 class WindowPreviewView : public views::View, public aura::WindowObserver { |
| 66 public: | 69 public: |
| 67 explicit WindowPreviewView(WmWindow* window) | 70 explicit WindowPreviewView(aura::Window* window) |
| 68 : window_title_(new views::Label), | 71 : window_title_(new views::Label), |
| 69 preview_background_(new views::View), | 72 preview_background_(new views::View), |
| 70 mirror_view_(window->CreateViewWithRecreatedLayers().release()), | 73 mirror_view_(new wm::WindowMirrorView(window)), |
| 71 window_observer_(this) { | 74 window_observer_(this) { |
| 72 window_observer_.Add(window->aura_window()); | 75 window_observer_.Add(window); |
| 73 window_title_->SetText(window->aura_window()->GetTitle()); | 76 window_title_->SetText(window->GetTitle()); |
| 74 window_title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 77 window_title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 75 window_title_->SetEnabledColor(SK_ColorWHITE); | 78 window_title_->SetEnabledColor(SK_ColorWHITE); |
| 76 window_title_->SetAutoColorReadabilityEnabled(false); | 79 window_title_->SetAutoColorReadabilityEnabled(false); |
| 77 // Background is not fully opaque, so subpixel rendering won't look good. | 80 // Background is not fully opaque, so subpixel rendering won't look good. |
| 78 window_title_->SetSubpixelRenderingEnabled(false); | 81 window_title_->SetSubpixelRenderingEnabled(false); |
| 79 // The base font is 12pt (for English) so this comes out to 14pt. | 82 // The base font is 12pt (for English) so this comes out to 14pt. |
| 80 const int kLabelSizeDelta = 2; | 83 const int kLabelSizeDelta = 2; |
| 81 window_title_->SetFontList( | 84 window_title_->SetFontList( |
| 82 window_title_->font_list().DeriveWithSizeDelta(kLabelSizeDelta)); | 85 window_title_->font_list().DeriveWithSizeDelta(kLabelSizeDelta)); |
| 83 const int kAboveLabelPadding = 5; | 86 const int kAboveLabelPadding = 5; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 const int kBetweenChildPaddingDip = 10; | 231 const int kBetweenChildPaddingDip = 10; |
| 229 views::BoxLayout* layout = new views::BoxLayout( | 232 views::BoxLayout* layout = new views::BoxLayout( |
| 230 views::BoxLayout::kHorizontal, kInsideBorderPaddingDip, | 233 views::BoxLayout::kHorizontal, kInsideBorderPaddingDip, |
| 231 kInsideBorderPaddingDip, kBetweenChildPaddingDip); | 234 kInsideBorderPaddingDip, kBetweenChildPaddingDip); |
| 232 layout->set_cross_axis_alignment( | 235 layout->set_cross_axis_alignment( |
| 233 views::BoxLayout::CROSS_AXIS_ALIGNMENT_START); | 236 views::BoxLayout::CROSS_AXIS_ALIGNMENT_START); |
| 234 mirror_container_->SetLayoutManager(layout); | 237 mirror_container_->SetLayoutManager(layout); |
| 235 mirror_container_->SetPaintToLayer(); | 238 mirror_container_->SetPaintToLayer(); |
| 236 mirror_container_->layer()->SetFillsBoundsOpaquely(false); | 239 mirror_container_->layer()->SetFillsBoundsOpaquely(false); |
| 237 | 240 |
| 238 for (WmWindow* window : windows) { | 241 for (auto* window : windows) { |
| 239 // |mirror_container_| owns |view|. | 242 // |mirror_container_| owns |view|. |
| 240 views::View* view = new WindowPreviewView(window); | 243 views::View* view = new WindowPreviewView(window); |
| 241 window_view_map_[window] = view; | 244 window_view_map_[window] = view; |
| 242 mirror_container_->AddChildView(view); | 245 mirror_container_->AddChildView(view); |
| 243 } | 246 } |
| 244 | 247 |
| 245 // The background needs to be painted to fill the layer, not the View, | 248 // The background needs to be painted to fill the layer, not the View, |
| 246 // because the layer animates bounds changes but the View's bounds change | 249 // because the layer animates bounds changes but the View's bounds change |
| 247 // immediately. | 250 // immediately. |
| 248 highlight_view_->set_background(new LayerFillBackgroundPainter( | 251 highlight_view_->set_background(new LayerFillBackgroundPainter( |
| 249 views::Painter::CreateRoundRectWith1PxBorderPainter( | 252 views::Painter::CreateRoundRectWith1PxBorderPainter( |
| 250 SkColorSetA(SK_ColorWHITE, 0x4D), SkColorSetA(SK_ColorWHITE, 0x33), | 253 SkColorSetA(SK_ColorWHITE, 0x4D), SkColorSetA(SK_ColorWHITE, 0x33), |
| 251 kBackgroundCornerRadius))); | 254 kBackgroundCornerRadius))); |
| 252 highlight_view_->SetPaintToLayer(); | 255 highlight_view_->SetPaintToLayer(); |
| 253 | 256 |
| 254 highlight_view_->layer()->SetFillsBoundsOpaquely(false); | 257 highlight_view_->layer()->SetFillsBoundsOpaquely(false); |
| 255 | 258 |
| 256 AddChildView(highlight_view_); | 259 AddChildView(highlight_view_); |
| 257 AddChildView(mirror_container_); | 260 AddChildView(mirror_container_); |
| 258 } | 261 } |
| 259 | 262 |
| 260 ~WindowCycleView() override {} | 263 ~WindowCycleView() override {} |
| 261 | 264 |
| 262 void SetTargetWindow(WmWindow* target) { | 265 void SetTargetWindow(aura::Window* target) { |
| 263 target_window_ = target; | 266 target_window_ = target; |
| 264 if (GetWidget()) { | 267 if (GetWidget()) { |
| 265 Layout(); | 268 Layout(); |
| 266 if (target_window_) | 269 if (target_window_) |
| 267 window_view_map_[target_window_]->RequestFocus(); | 270 window_view_map_[target_window_]->RequestFocus(); |
| 268 } | 271 } |
| 269 } | 272 } |
| 270 | 273 |
| 271 void HandleWindowDestruction(WmWindow* destroying_window, | 274 void HandleWindowDestruction(aura::Window* destroying_window, |
| 272 WmWindow* new_target) { | 275 aura::Window* new_target) { |
| 273 auto view_iter = window_view_map_.find(destroying_window); | 276 auto view_iter = window_view_map_.find(destroying_window); |
| 274 views::View* preview = view_iter->second; | 277 views::View* preview = view_iter->second; |
| 275 views::View* parent = preview->parent(); | 278 views::View* parent = preview->parent(); |
| 276 DCHECK_EQ(mirror_container_, parent); | 279 DCHECK_EQ(mirror_container_, parent); |
| 277 window_view_map_.erase(view_iter); | 280 window_view_map_.erase(view_iter); |
| 278 delete preview; | 281 delete preview; |
| 279 // With one of its children now gone, we must re-layout |mirror_container_|. | 282 // With one of its children now gone, we must re-layout |mirror_container_|. |
| 280 // This must happen before SetTargetWindow() to make sure our own Layout() | 283 // This must happen before SetTargetWindow() to make sure our own Layout() |
| 281 // works correctly when it's calculating highlight bounds. | 284 // works correctly when it's calculating highlight bounds. |
| 282 parent->Layout(); | 285 parent->Layout(); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 flags.setAntiAlias(true); | 364 flags.setAntiAlias(true); |
| 362 corner_radius = kBackgroundCornerRadius; | 365 corner_radius = kBackgroundCornerRadius; |
| 363 } | 366 } |
| 364 canvas->DrawRoundRect(shield_bounds, corner_radius, flags); | 367 canvas->DrawRoundRect(shield_bounds, corner_radius, flags); |
| 365 } | 368 } |
| 366 | 369 |
| 367 View* GetInitiallyFocusedView() override { | 370 View* GetInitiallyFocusedView() override { |
| 368 return window_view_map_[target_window_]; | 371 return window_view_map_[target_window_]; |
| 369 } | 372 } |
| 370 | 373 |
| 371 WmWindow* target_window() { return target_window_; } | 374 aura::Window* target_window() { return target_window_; } |
| 372 | 375 |
| 373 private: | 376 private: |
| 374 std::map<WmWindow*, views::View*> window_view_map_; | 377 std::map<aura::Window*, views::View*> window_view_map_; |
| 375 views::View* mirror_container_; | 378 views::View* mirror_container_; |
| 376 views::View* highlight_view_; | 379 views::View* highlight_view_; |
| 377 WmWindow* target_window_; | 380 aura::Window* target_window_; |
| 378 | 381 |
| 379 DISALLOW_COPY_AND_ASSIGN(WindowCycleView); | 382 DISALLOW_COPY_AND_ASSIGN(WindowCycleView); |
| 380 }; | 383 }; |
| 381 | 384 |
| 382 WindowCycleList::WindowCycleList(const WindowList& windows) | 385 WindowCycleList::WindowCycleList(const WindowList& windows) |
| 383 : windows_(windows), | 386 : windows_(windows), |
| 384 screen_observer_(this) { | 387 screen_observer_(this) { |
| 385 if (!ShouldShowUi()) | 388 if (!ShouldShowUi()) |
| 386 Shell::Get()->mru_window_tracker()->SetIgnoreActivations(true); | 389 Shell::Get()->mru_window_tracker()->SetIgnoreActivations(true); |
| 387 | 390 |
| 388 for (WmWindow* window : windows_) | 391 for (auto* window : windows_) |
| 389 window->aura_window()->AddObserver(this); | 392 window->AddObserver(this); |
| 390 | 393 |
| 391 if (ShouldShowUi()) { | 394 if (ShouldShowUi()) { |
| 392 if (g_disable_initial_delay) { | 395 if (g_disable_initial_delay) { |
| 393 InitWindowCycleView(); | 396 InitWindowCycleView(); |
| 394 } else { | 397 } else { |
| 395 show_ui_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(150), | 398 show_ui_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(150), |
| 396 this, &WindowCycleList::InitWindowCycleView); | 399 this, &WindowCycleList::InitWindowCycleView); |
| 397 } | 400 } |
| 398 } | 401 } |
| 399 } | 402 } |
| 400 | 403 |
| 401 WindowCycleList::~WindowCycleList() { | 404 WindowCycleList::~WindowCycleList() { |
| 402 if (!ShouldShowUi()) | 405 if (!ShouldShowUi()) |
| 403 Shell::Get()->mru_window_tracker()->SetIgnoreActivations(false); | 406 Shell::Get()->mru_window_tracker()->SetIgnoreActivations(false); |
| 404 | 407 |
| 405 for (WmWindow* window : windows_) | 408 for (auto* window : windows_) |
| 406 window->aura_window()->RemoveObserver(this); | 409 window->RemoveObserver(this); |
| 407 | 410 |
| 408 if (!windows_.empty() && user_did_accept_) { | 411 if (!windows_.empty() && user_did_accept_) { |
| 409 WmWindow* target_window = windows_[current_index_]; | 412 auto* target_window = windows_[current_index_]; |
| 410 target_window->Show(); | 413 target_window->Show(); |
| 411 target_window->GetWindowState()->Activate(); | 414 wm::GetWindowState(target_window)->Activate(); |
| 412 } | 415 } |
| 413 | 416 |
| 414 if (cycle_ui_widget_) | 417 if (cycle_ui_widget_) |
| 415 cycle_ui_widget_->Close(); | 418 cycle_ui_widget_->Close(); |
| 416 | 419 |
| 417 // |this| is responsible for notifying |cycle_view_| when windows are | 420 // |this| is responsible for notifying |cycle_view_| when windows are |
| 418 // destroyed. Since |this| is going away, clobber |cycle_view_|. Otherwise | 421 // destroyed. Since |this| is going away, clobber |cycle_view_|. Otherwise |
| 419 // there will be a race where a window closes after now but before the | 422 // there will be a race where a window closes after now but before the |
| 420 // Widget::Close() call above actually destroys |cycle_view_|. See | 423 // Widget::Close() call above actually destroys |cycle_view_|. See |
| 421 // crbug.com/681207 | 424 // crbug.com/681207 |
| 422 if (cycle_view_) | 425 if (cycle_view_) |
| 423 cycle_view_->DestroyContents(); | 426 cycle_view_->DestroyContents(); |
| 424 } | 427 } |
| 425 | 428 |
| 426 void WindowCycleList::Step(WindowCycleController::Direction direction) { | 429 void WindowCycleList::Step(WindowCycleController::Direction direction) { |
| 427 if (windows_.empty()) | 430 if (windows_.empty()) |
| 428 return; | 431 return; |
| 429 | 432 |
| 430 // When there is only one window, we should give feedback to the user. If the | 433 // When there is only one window, we should give feedback to the user. If the |
| 431 // window is minimized, we should also show it. | 434 // window is minimized, we should also show it. |
| 432 if (windows_.size() == 1) { | 435 if (windows_.size() == 1) { |
| 433 windows_[0]->Animate(::wm::WINDOW_ANIMATION_TYPE_BOUNCE); | 436 ::wm::AnimateWindow(windows_[0], ::wm::WINDOW_ANIMATION_TYPE_BOUNCE); |
| 434 windows_[0]->Show(); | 437 windows_[0]->Show(); |
| 435 windows_[0]->GetWindowState()->Activate(); | 438 wm::GetWindowState(windows_[0])->Activate(); |
| 436 return; | 439 return; |
| 437 } | 440 } |
| 438 | 441 |
| 439 DCHECK(static_cast<size_t>(current_index_) < windows_.size()); | 442 DCHECK(static_cast<size_t>(current_index_) < windows_.size()); |
| 440 | 443 |
| 441 if (!cycle_view_ && current_index_ == 0) { | 444 if (!cycle_view_ && current_index_ == 0) { |
| 442 // Special case the situation where we're cycling forward but the MRU window | 445 // Special case the situation where we're cycling forward but the MRU window |
| 443 // is not active. This occurs when all windows are minimized. The starting | 446 // is not active. This occurs when all windows are minimized. The starting |
| 444 // window should be the first one rather than the second. | 447 // window should be the first one rather than the second. |
| 445 if (direction == WindowCycleController::FORWARD && !windows_[0]->IsActive()) | 448 if (direction == WindowCycleController::FORWARD && |
| 449 !wm::IsActiveWindow(windows_[0])) |
| 446 current_index_ = -1; | 450 current_index_ = -1; |
| 447 } | 451 } |
| 448 | 452 |
| 449 // We're in a valid cycle, so step forward or backward. | 453 // We're in a valid cycle, so step forward or backward. |
| 450 current_index_ += direction == WindowCycleController::FORWARD ? 1 : -1; | 454 current_index_ += direction == WindowCycleController::FORWARD ? 1 : -1; |
| 451 | 455 |
| 452 // Wrap to window list size. | 456 // Wrap to window list size. |
| 453 current_index_ = (current_index_ + windows_.size()) % windows_.size(); | 457 current_index_ = (current_index_ + windows_.size()) % windows_.size(); |
| 454 DCHECK(windows_[current_index_]); | 458 DCHECK(windows_[current_index_]); |
| 455 | 459 |
| 456 if (ShouldShowUi()) { | 460 if (ShouldShowUi()) { |
| 457 if (current_index_ > 1) | 461 if (current_index_ > 1) |
| 458 InitWindowCycleView(); | 462 InitWindowCycleView(); |
| 459 | 463 |
| 460 if (cycle_view_) | 464 if (cycle_view_) |
| 461 cycle_view_->SetTargetWindow(windows_[current_index_]); | 465 cycle_view_->SetTargetWindow(windows_[current_index_]); |
| 462 } | 466 } |
| 463 } | 467 } |
| 464 | 468 |
| 465 // static | 469 // static |
| 466 void WindowCycleList::DisableInitialDelayForTesting() { | 470 void WindowCycleList::DisableInitialDelayForTesting() { |
| 467 g_disable_initial_delay = true; | 471 g_disable_initial_delay = true; |
| 468 } | 472 } |
| 469 | 473 |
| 470 void WindowCycleList::OnWindowDestroying(aura::Window* window) { | 474 void WindowCycleList::OnWindowDestroying(aura::Window* window) { |
| 471 window->RemoveObserver(this); | 475 window->RemoveObserver(this); |
| 472 | 476 |
| 473 WindowList::iterator i = | 477 WindowList::iterator i = std::find(windows_.begin(), windows_.end(), window); |
| 474 std::find(windows_.begin(), windows_.end(), WmWindow::Get(window)); | |
| 475 // TODO(oshima): Change this back to DCHECK once crbug.com/483491 is fixed. | 478 // TODO(oshima): Change this back to DCHECK once crbug.com/483491 is fixed. |
| 476 CHECK(i != windows_.end()); | 479 CHECK(i != windows_.end()); |
| 477 int removed_index = static_cast<int>(i - windows_.begin()); | 480 int removed_index = static_cast<int>(i - windows_.begin()); |
| 478 windows_.erase(i); | 481 windows_.erase(i); |
| 479 if (current_index_ > removed_index || | 482 if (current_index_ > removed_index || |
| 480 current_index_ == static_cast<int>(windows_.size())) { | 483 current_index_ == static_cast<int>(windows_.size())) { |
| 481 current_index_--; | 484 current_index_--; |
| 482 } | 485 } |
| 483 | 486 |
| 484 if (cycle_view_) { | 487 if (cycle_view_) { |
| 485 WmWindow* new_target_window = | 488 auto* new_target_window = |
| 486 windows_.empty() ? nullptr : windows_[current_index_]; | 489 windows_.empty() ? nullptr : windows_[current_index_]; |
| 487 cycle_view_->HandleWindowDestruction(WmWindow::Get(window), | 490 cycle_view_->HandleWindowDestruction(window, new_target_window); |
| 488 new_target_window); | |
| 489 if (windows_.empty()) { | 491 if (windows_.empty()) { |
| 490 // This deletes us. | 492 // This deletes us. |
| 491 Shell::Get()->window_cycle_controller()->CancelCycling(); | 493 Shell::Get()->window_cycle_controller()->CancelCycling(); |
| 492 return; | 494 return; |
| 493 } | 495 } |
| 494 } | 496 } |
| 495 } | 497 } |
| 496 | 498 |
| 497 void WindowCycleList::OnDisplayAdded(const display::Display& new_display) {} | 499 void WindowCycleList::OnDisplayAdded(const display::Display& new_display) {} |
| 498 | 500 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 widget_rect.set_height(widget_height); | 544 widget_rect.set_height(widget_height); |
| 543 params.bounds = widget_rect; | 545 params.bounds = widget_rect; |
| 544 widget->Init(params); | 546 widget->Init(params); |
| 545 | 547 |
| 546 screen_observer_.Add(display::Screen::GetScreen()); | 548 screen_observer_.Add(display::Screen::GetScreen()); |
| 547 widget->Show(); | 549 widget->Show(); |
| 548 cycle_ui_widget_ = widget; | 550 cycle_ui_widget_ = widget; |
| 549 } | 551 } |
| 550 | 552 |
| 551 } // namespace ash | 553 } // namespace ash |
| OLD | NEW |