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