OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/panels/panel_layout_manager.h" | 5 #include "ash/wm/panels/panel_layout_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <map> | 8 #include <map> |
9 | 9 |
10 #include "ash/screen_util.h" | 10 #include "ash/screen_util.h" |
11 #include "ash/shelf/shelf.h" | 11 #include "ash/shelf/shelf.h" |
12 #include "ash/shelf/shelf_layout_manager.h" | 12 #include "ash/shelf/shelf_layout_manager.h" |
13 #include "ash/shelf/shelf_types.h" | 13 #include "ash/shelf/shelf_types.h" |
14 #include "ash/shelf/shelf_util.h" | |
15 #include "ash/shelf/shelf_widget.h" | 14 #include "ash/shelf/shelf_widget.h" |
16 #include "ash/shell.h" | 15 #include "ash/shell.h" |
17 #include "ash/shell_window_ids.h" | 16 #include "ash/shell_window_ids.h" |
18 #include "ash/wm/window_animations.h" | 17 #include "ash/wm/window_animations.h" |
19 #include "ash/wm/window_state.h" | 18 #include "ash/wm/window_state.h" |
20 #include "ash/wm/window_util.h" | 19 #include "ash/wm/window_util.h" |
21 #include "base/auto_reset.h" | 20 #include "base/auto_reset.h" |
22 #include "base/bind.h" | 21 #include "base/bind.h" |
23 #include "base/bind_helpers.h" | 22 #include "base/bind_helpers.h" |
24 #include "third_party/skia/include/core/SkColor.h" | 23 #include "third_party/skia/include/core/SkColor.h" |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 aura::Window* old_parent = child->parent(); | 356 aura::Window* old_parent = child->parent(); |
358 aura::client::ParentWindowWithContext( | 357 aura::client::ParentWindowWithContext( |
359 child, child, child->GetRootWindow()->GetBoundsInScreen()); | 358 child, child, child->GetRootWindow()->GetBoundsInScreen()); |
360 wm::ReparentTransientChildrenOfChild(child, old_parent, child->parent()); | 359 wm::ReparentTransientChildrenOfChild(child, old_parent, child->parent()); |
361 DCHECK(child->parent()->id() != kShellWindowId_PanelContainer); | 360 DCHECK(child->parent()->id() != kShellWindowId_PanelContainer); |
362 return; | 361 return; |
363 } | 362 } |
364 PanelInfo panel_info; | 363 PanelInfo panel_info; |
365 panel_info.window = child; | 364 panel_info.window = child; |
366 panel_info.callout_widget = new PanelCalloutWidget(panel_container_); | 365 panel_info.callout_widget = new PanelCalloutWidget(panel_container_); |
367 panel_info.slide_in = child != dragged_panel_; | 366 if (child != dragged_panel_) { |
| 367 // Set the panel to 0 opacity until it has been positioned to prevent it |
| 368 // from flashing briefly at position (0, 0). |
| 369 child->layer()->SetOpacity(0); |
| 370 panel_info.slide_in = true; |
| 371 } |
368 panel_windows_.push_back(panel_info); | 372 panel_windows_.push_back(panel_info); |
369 child->AddObserver(this); | |
370 wm::GetWindowState(child)->AddObserver(this); | 373 wm::GetWindowState(child)->AddObserver(this); |
371 Relayout(); | 374 Relayout(); |
372 } | 375 } |
373 | 376 |
374 void PanelLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { | 377 void PanelLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { |
375 } | 378 } |
376 | 379 |
377 void PanelLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) { | 380 void PanelLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) { |
378 if (child->type() == ui::wm::WINDOW_TYPE_POPUP) | 381 if (child->type() == ui::wm::WINDOW_TYPE_POPUP) |
379 return; | 382 return; |
380 PanelList::iterator found = | 383 PanelList::iterator found = |
381 std::find(panel_windows_.begin(), panel_windows_.end(), child); | 384 std::find(panel_windows_.begin(), panel_windows_.end(), child); |
382 if (found != panel_windows_.end()) { | 385 if (found != panel_windows_.end()) { |
383 delete found->callout_widget; | 386 delete found->callout_widget; |
384 panel_windows_.erase(found); | 387 panel_windows_.erase(found); |
385 } | 388 } |
386 if (restore_windows_on_shelf_visible_) | |
387 restore_windows_on_shelf_visible_->Remove(child); | |
388 child->RemoveObserver(this); | |
389 wm::GetWindowState(child)->RemoveObserver(this); | 389 wm::GetWindowState(child)->RemoveObserver(this); |
390 | 390 |
391 if (dragged_panel_ == child) | 391 if (dragged_panel_ == child) |
392 dragged_panel_ = NULL; | 392 dragged_panel_ = NULL; |
393 | 393 |
394 if (last_active_panel_ == child) | 394 if (last_active_panel_ == child) |
395 last_active_panel_ = NULL; | 395 last_active_panel_ = NULL; |
396 | 396 |
397 Relayout(); | 397 Relayout(); |
398 } | 398 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 // PanelLayoutManager, ash::ShellObserver implementation: | 452 // PanelLayoutManager, ash::ShellObserver implementation: |
453 | 453 |
454 void PanelLayoutManager::OnShelfAlignmentChanged(aura::Window* root_window) { | 454 void PanelLayoutManager::OnShelfAlignmentChanged(aura::Window* root_window) { |
455 if (panel_container_->GetRootWindow() == root_window) | 455 if (panel_container_->GetRootWindow() == root_window) |
456 Relayout(); | 456 Relayout(); |
457 } | 457 } |
458 | 458 |
459 ///////////////////////////////////////////////////////////////////////////// | 459 ///////////////////////////////////////////////////////////////////////////// |
460 // PanelLayoutManager, WindowObserver implementation: | 460 // PanelLayoutManager, WindowObserver implementation: |
461 | 461 |
462 void PanelLayoutManager::OnWindowPropertyChanged(aura::Window* window, | |
463 const void* key, | |
464 intptr_t old) { | |
465 // Trigger a relayout to position the panels whenever the panel icon is set | |
466 // or changes. | |
467 if (key == kShelfID) | |
468 Relayout(); | |
469 } | |
470 | |
471 ///////////////////////////////////////////////////////////////////////////// | |
472 // PanelLayoutManager, WindowStateObserver implementation: | |
473 | |
474 void PanelLayoutManager::OnPostWindowStateTypeChange( | 462 void PanelLayoutManager::OnPostWindowStateTypeChange( |
475 wm::WindowState* window_state, | 463 wm::WindowState* window_state, |
476 wm::WindowStateType old_type) { | 464 wm::WindowStateType old_type) { |
477 // If the shelf is currently hidden then windows will not actually be shown | 465 // If the shelf is currently hidden then windows will not actually be shown |
478 // but the set to restore when the shelf becomes visible is updated. | 466 // but the set to restore when the shelf becomes visible is updated. |
479 if (restore_windows_on_shelf_visible_) { | 467 if (restore_windows_on_shelf_visible_) { |
480 if (window_state->IsMinimized()) { | 468 if (window_state->IsMinimized()) { |
481 MinimizePanel(window_state->window()); | 469 MinimizePanel(window_state->window()); |
482 restore_windows_on_shelf_visible_->Remove(window_state->window()); | 470 restore_windows_on_shelf_visible_->Remove(window_state->window()); |
483 } else { | 471 } else { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 ui::ScopedLayerAnimationSettings panel_slide_settings(layer->GetAnimator()); | 545 ui::ScopedLayerAnimationSettings panel_slide_settings(layer->GetAnimator()); |
558 panel_slide_settings.SetPreemptionStrategy( | 546 panel_slide_settings.SetPreemptionStrategy( |
559 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | 547 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
560 panel_slide_settings.SetTransitionDuration( | 548 panel_slide_settings.SetTransitionDuration( |
561 base::TimeDelta::FromMilliseconds(kPanelSlideDurationMilliseconds)); | 549 base::TimeDelta::FromMilliseconds(kPanelSlideDurationMilliseconds)); |
562 gfx::Rect bounds(panel->bounds()); | 550 gfx::Rect bounds(panel->bounds()); |
563 bounds.Offset(GetSlideInAnimationOffset( | 551 bounds.Offset(GetSlideInAnimationOffset( |
564 shelf_->shelf_widget()->GetAlignment())); | 552 shelf_->shelf_widget()->GetAlignment())); |
565 SetChildBoundsDirect(panel, bounds); | 553 SetChildBoundsDirect(panel, bounds); |
566 panel->Hide(); | 554 panel->Hide(); |
567 layer->SetOpacity(0); | 555 PanelList::iterator found = |
| 556 std::find(panel_windows_.begin(), panel_windows_.end(), panel); |
| 557 if (found != panel_windows_.end()) { |
| 558 layer->SetOpacity(0); |
| 559 // The next time the window is visible it should slide into place. |
| 560 found->slide_in = true; |
| 561 } |
568 if (wm::IsActiveWindow(panel)) | 562 if (wm::IsActiveWindow(panel)) |
569 wm::DeactivateWindow(panel); | 563 wm::DeactivateWindow(panel); |
570 Relayout(); | 564 Relayout(); |
571 } | 565 } |
572 | 566 |
573 void PanelLayoutManager::RestorePanel(aura::Window* panel) { | 567 void PanelLayoutManager::RestorePanel(aura::Window* panel) { |
574 PanelList::iterator found = | 568 panel->Show(); |
575 std::find(panel_windows_.begin(), panel_windows_.end(), panel); | |
576 DCHECK(found != panel_windows_.end()); | |
577 found->slide_in = true; | |
578 Relayout(); | 569 Relayout(); |
579 } | 570 } |
580 | 571 |
581 void PanelLayoutManager::Relayout() { | 572 void PanelLayoutManager::Relayout() { |
582 if (!shelf_ || !shelf_->shelf_widget()) | 573 if (!shelf_ || !shelf_->shelf_widget()) |
583 return; | 574 return; |
584 | 575 |
585 if (in_layout_) | 576 if (in_layout_) |
586 return; | 577 return; |
587 base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true); | 578 base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true); |
588 | 579 |
589 ShelfAlignment alignment = shelf_->shelf_widget()->GetAlignment(); | 580 ShelfAlignment alignment = shelf_->shelf_widget()->GetAlignment(); |
590 bool horizontal = alignment == SHELF_ALIGNMENT_TOP || | 581 bool horizontal = alignment == SHELF_ALIGNMENT_TOP || |
591 alignment == SHELF_ALIGNMENT_BOTTOM; | 582 alignment == SHELF_ALIGNMENT_BOTTOM; |
592 gfx::Rect shelf_bounds = ash::ScreenUtil::ConvertRectFromScreen( | 583 gfx::Rect shelf_bounds = ash::ScreenUtil::ConvertRectFromScreen( |
593 panel_container_, shelf_->shelf_widget()->GetWindowBoundsInScreen()); | 584 panel_container_, shelf_->shelf_widget()->GetWindowBoundsInScreen()); |
594 int panel_start_bounds = kPanelIdealSpacing; | 585 int panel_start_bounds = kPanelIdealSpacing; |
595 int panel_end_bounds = horizontal ? | 586 int panel_end_bounds = horizontal ? |
596 panel_container_->bounds().width() - kPanelIdealSpacing : | 587 panel_container_->bounds().width() - kPanelIdealSpacing : |
597 panel_container_->bounds().height() - kPanelIdealSpacing; | 588 panel_container_->bounds().height() - kPanelIdealSpacing; |
598 aura::Window* active_panel = NULL; | 589 aura::Window* active_panel = NULL; |
599 std::vector<VisiblePanelPositionInfo> visible_panels; | 590 std::vector<VisiblePanelPositionInfo> visible_panels; |
600 for (PanelList::iterator iter = panel_windows_.begin(); | 591 for (PanelList::iterator iter = panel_windows_.begin(); |
601 iter != panel_windows_.end(); ++iter) { | 592 iter != panel_windows_.end(); ++iter) { |
602 aura::Window* panel = iter->window; | 593 aura::Window* panel = iter->window; |
603 iter->callout_widget->SetAlignment(alignment); | 594 iter->callout_widget->SetAlignment(alignment); |
604 | 595 |
605 // Consider the dragged panel as part of the layout as long as it is | 596 // Consider the dragged panel as part of the layout as long as it is |
606 // touching the shelf. | 597 // touching the shelf. |
607 if ((!panel->IsVisible() && !iter->slide_in) || | 598 if (!panel->IsVisible() || |
608 (panel == dragged_panel_ && | 599 (panel == dragged_panel_ && |
609 !BoundsAdjacent(panel->bounds(), shelf_bounds))) { | 600 !BoundsAdjacent(panel->bounds(), shelf_bounds))) { |
610 continue; | 601 continue; |
611 } | 602 } |
612 | 603 |
613 // If the shelf is currently hidden (full-screen mode), minimize panel until | 604 // If the shelf is currently hidden (full-screen mode), minimize panel until |
614 // full-screen mode is exited. When a panel is dragged from another display | 605 // full-screen mode is exited. When a panel is dragged from another display |
615 // the shelf state does not update before the panel is added so we exclude | 606 // the shelf state does not update before the panel is added so we exclude |
616 // the dragged panel. | 607 // the dragged panel. |
617 if (panel != dragged_panel_ && restore_windows_on_shelf_visible_) { | 608 if (panel != dragged_panel_ && restore_windows_on_shelf_visible_) { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 if (horizontal) { | 691 if (horizontal) { |
701 bounds.set_x(visible_panels[i].major_pos - | 692 bounds.set_x(visible_panels[i].major_pos - |
702 visible_panels[i].major_length / 2); | 693 visible_panels[i].major_length / 2); |
703 } else { | 694 } else { |
704 bounds.set_y(visible_panels[i].major_pos - | 695 bounds.set_y(visible_panels[i].major_pos - |
705 visible_panels[i].major_length / 2); | 696 visible_panels[i].major_length / 2); |
706 } | 697 } |
707 | 698 |
708 ui::Layer* layer = visible_panels[i].window->layer(); | 699 ui::Layer* layer = visible_panels[i].window->layer(); |
709 if (slide_in) { | 700 if (slide_in) { |
710 // New windows shift up from the shelf into position and fade in. | 701 // New windows shift up from the shelf into position. |
711 layer->SetOpacity(0); | |
712 gfx::Rect initial_bounds(bounds); | 702 gfx::Rect initial_bounds(bounds); |
713 initial_bounds.Offset(GetSlideInAnimationOffset(alignment)); | 703 initial_bounds.Offset(GetSlideInAnimationOffset(alignment)); |
714 SetChildBoundsDirect(visible_panels[i].window, initial_bounds); | 704 SetChildBoundsDirect(visible_panels[i].window, initial_bounds); |
715 // Set on shelf so that the panel animates into its target position. | 705 // Set on shelf so that the panel animates into its target position. |
716 on_shelf = true; | 706 on_shelf = true; |
717 } | 707 } |
718 | 708 |
719 if (on_shelf) { | 709 if (on_shelf) { |
720 ui::ScopedLayerAnimationSettings panel_slide_settings( | 710 ui::ScopedLayerAnimationSettings panel_slide_settings( |
721 layer->GetAnimator()); | 711 layer->GetAnimator()); |
722 panel_slide_settings.SetPreemptionStrategy( | 712 panel_slide_settings.SetPreemptionStrategy( |
723 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | 713 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
724 panel_slide_settings.SetTransitionDuration( | 714 panel_slide_settings.SetTransitionDuration( |
725 base::TimeDelta::FromMilliseconds(kPanelSlideDurationMilliseconds)); | 715 base::TimeDelta::FromMilliseconds(kPanelSlideDurationMilliseconds)); |
726 SetChildBoundsDirect(visible_panels[i].window, bounds); | 716 SetChildBoundsDirect(visible_panels[i].window, bounds); |
727 if (slide_in) { | 717 if (slide_in) |
728 layer->SetOpacity(1); | 718 layer->SetOpacity(1); |
729 visible_panels[i].window->Show(); | |
730 } | |
731 } else { | 719 } else { |
732 // If the shelf moved don't animate, move immediately to the new | 720 // If the shelf moved don't animate, move immediately to the new |
733 // target location. | 721 // target location. |
734 SetChildBoundsDirect(visible_panels[i].window, bounds); | 722 SetChildBoundsDirect(visible_panels[i].window, bounds); |
735 } | 723 } |
736 } | 724 } |
737 | 725 |
738 UpdateStacking(active_panel); | 726 UpdateStacking(active_panel); |
739 UpdateCallouts(); | 727 UpdateCallouts(); |
740 } | 728 } |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
890 // keyboard::KeyboardControllerObserver implementation: | 878 // keyboard::KeyboardControllerObserver implementation: |
891 | 879 |
892 void PanelLayoutManager::OnKeyboardBoundsChanging( | 880 void PanelLayoutManager::OnKeyboardBoundsChanging( |
893 const gfx::Rect& keyboard_bounds) { | 881 const gfx::Rect& keyboard_bounds) { |
894 // This bounds change will have caused a change to the Shelf which does not | 882 // This bounds change will have caused a change to the Shelf which does not |
895 // propogate automatically to this class, so manually recalculate bounds. | 883 // propogate automatically to this class, so manually recalculate bounds. |
896 OnWindowResized(); | 884 OnWindowResized(); |
897 } | 885 } |
898 | 886 |
899 } // namespace ash | 887 } // namespace ash |
OLD | NEW |