| 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/frame_painter.h" | 5 #include "ash/wm/frame_painter.h" |
| 6 | 6 |
| 7 #include "ash/ash_constants.h" | 7 #include "ash/ash_constants.h" |
| 8 #include "ash/shell.h" | 8 #include "ash/shell.h" |
| 9 #include "ash/shell_window_ids.h" | 9 #include "ash/shell_window_ids.h" |
| 10 #include "ash/wm/property_util.h" | 10 #include "ash/wm/property_util.h" |
| 11 #include "ash/wm/window_properties.h" | 11 #include "ash/wm/window_properties.h" |
| 12 #include "ash/wm/window_util.h" | 12 #include "ash/wm/window_util.h" |
| 13 #include "ash/wm/workspace_controller.h" | |
| 14 #include "base/logging.h" // DCHECK | 13 #include "base/logging.h" // DCHECK |
| 15 #include "grit/ash_resources.h" | 14 #include "grit/ash_resources.h" |
| 16 #include "third_party/skia/include/core/SkCanvas.h" | 15 #include "third_party/skia/include/core/SkCanvas.h" |
| 17 #include "third_party/skia/include/core/SkColor.h" | 16 #include "third_party/skia/include/core/SkColor.h" |
| 18 #include "third_party/skia/include/core/SkPaint.h" | 17 #include "third_party/skia/include/core/SkPaint.h" |
| 19 #include "third_party/skia/include/core/SkPath.h" | 18 #include "third_party/skia/include/core/SkPath.h" |
| 20 #include "ui/aura/client/aura_constants.h" | 19 #include "ui/aura/client/aura_constants.h" |
| 21 #include "ui/aura/env.h" | 20 #include "ui/aura/env.h" |
| 22 #include "ui/aura/root_window.h" | 21 #include "ui/aura/root_window.h" |
| 23 #include "ui/aura/window.h" | 22 #include "ui/aura/window.h" |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 FramePainter::~FramePainter() { | 159 FramePainter::~FramePainter() { |
| 161 // Sometimes we are destroyed before the window closes, so ensure we clean up. | 160 // Sometimes we are destroyed before the window closes, so ensure we clean up. |
| 162 if (window_) { | 161 if (window_) { |
| 163 aura::RootWindow* root = window_->GetRootWindow(); | 162 aura::RootWindow* root = window_->GetRootWindow(); |
| 164 if (root && | 163 if (root && |
| 165 root->GetProperty(internal::kSoloWindowFramePainterKey) == this) { | 164 root->GetProperty(internal::kSoloWindowFramePainterKey) == this) { |
| 166 root->SetProperty(internal::kSoloWindowFramePainterKey, | 165 root->SetProperty(internal::kSoloWindowFramePainterKey, |
| 167 static_cast<FramePainter*>(NULL)); | 166 static_cast<FramePainter*>(NULL)); |
| 168 } | 167 } |
| 169 window_->RemoveObserver(this); | 168 window_->RemoveObserver(this); |
| 169 if (root) |
| 170 root->RemoveObserver(this); |
| 170 } | 171 } |
| 171 instances_->erase(this); | 172 instances_->erase(this); |
| 172 } | 173 } |
| 173 | 174 |
| 174 void FramePainter::Init(views::Widget* frame, | 175 void FramePainter::Init(views::Widget* frame, |
| 175 views::View* window_icon, | 176 views::View* window_icon, |
| 176 views::ImageButton* size_button, | 177 views::ImageButton* size_button, |
| 177 views::ImageButton* close_button, | 178 views::ImageButton* close_button, |
| 178 SizeButtonBehavior behavior) { | 179 SizeButtonBehavior behavior) { |
| 179 DCHECK(frame); | 180 DCHECK(frame); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 209 kResizeOutsideBoundsScaleForTouch); | 210 kResizeOutsideBoundsScaleForTouch); |
| 210 // Ensure we get resize cursors just inside our bounds as well. | 211 // Ensure we get resize cursors just inside our bounds as well. |
| 211 window_->set_hit_test_bounds_override_inner( | 212 window_->set_hit_test_bounds_override_inner( |
| 212 gfx::Insets(kResizeInsideBoundsSize, kResizeInsideBoundsSize, | 213 gfx::Insets(kResizeInsideBoundsSize, kResizeInsideBoundsSize, |
| 213 kResizeInsideBoundsSize, kResizeInsideBoundsSize)); | 214 kResizeInsideBoundsSize, kResizeInsideBoundsSize)); |
| 214 | 215 |
| 215 // Watch for maximize/restore/fullscreen state changes. Observer removes | 216 // Watch for maximize/restore/fullscreen state changes. Observer removes |
| 216 // itself in OnWindowDestroying() below, or in the destructor if we go away | 217 // itself in OnWindowDestroying() below, or in the destructor if we go away |
| 217 // before the window. | 218 // before the window. |
| 218 window_->AddObserver(this); | 219 window_->AddObserver(this); |
| 220 aura::Window* root = window_->GetRootWindow(); |
| 221 if (root) |
| 222 root->AddObserver(this); |
| 219 | 223 |
| 220 // If there is already a solo window in the same root, this initialization | 224 // If there is already a solo window in the same root, this initialization |
| 221 // should turn off its solo-mode. | 225 // should turn off its solo-mode. |
| 222 UpdateSoloWindowFramePainter(NULL); | 226 UpdateSoloWindowFramePainter(NULL); |
| 223 } | 227 } |
| 224 | 228 |
| 225 // static | 229 // static |
| 226 void FramePainter::UpdateSoloWindowHeader(RootWindow* root_window) { | 230 void FramePainter::UpdateSoloWindowHeader(RootWindow* root_window) { |
| 227 // Use a separate function here so callers outside of FramePainter don't need | 231 // Use a separate function here so callers outside of FramePainter don't need |
| 228 // to know about "ignorable_window". | 232 // to know about "ignorable_window". |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 frame_->non_client_view()->SchedulePaintInRect( | 580 frame_->non_client_view()->SchedulePaintInRect( |
| 577 GetTitleBounds(view, title_font)); | 581 GetTitleBounds(view, title_font)); |
| 578 } | 582 } |
| 579 | 583 |
| 580 /////////////////////////////////////////////////////////////////////////////// | 584 /////////////////////////////////////////////////////////////////////////////// |
| 581 // aura::WindowObserver overrides: | 585 // aura::WindowObserver overrides: |
| 582 | 586 |
| 583 void FramePainter::OnWindowPropertyChanged(aura::Window* window, | 587 void FramePainter::OnWindowPropertyChanged(aura::Window* window, |
| 584 const void* key, | 588 const void* key, |
| 585 intptr_t old) { | 589 intptr_t old) { |
| 590 // When either 'kWindowTrackedByWorkspaceKey' changes or |
| 591 // 'kCyclingThroughWorkspacesKey' changes, we are going to paint the header |
| 592 // differently. Schedule a paint to ensure everything is updated correctly. |
| 586 if (key == internal::kWindowTrackedByWorkspaceKey && | 593 if (key == internal::kWindowTrackedByWorkspaceKey && |
| 587 GetTrackedByWorkspace(window)) { | 594 GetTrackedByWorkspace(window)) { |
| 588 // When 'kWindowTrackedByWorkspaceKey' changes we're going to paint the | 595 frame_->non_client_view()->SchedulePaint(); |
| 589 // header differently. Schedule a paint to ensure everything is updated | 596 } else if (key == internal::kCyclingThroughWorkspacesKey) { |
| 590 // correctly. | |
| 591 frame_->non_client_view()->SchedulePaint(); | 597 frame_->non_client_view()->SchedulePaint(); |
| 592 } | 598 } |
| 599 |
| 593 if (key != aura::client::kShowStateKey) | 600 if (key != aura::client::kShowStateKey) |
| 594 return; | 601 return; |
| 595 | 602 |
| 596 // Maximized and fullscreen windows don't want resize handles overlapping the | 603 // Maximized and fullscreen windows don't want resize handles overlapping the |
| 597 // content area, because when the user moves the cursor to the right screen | 604 // content area, because when the user moves the cursor to the right screen |
| 598 // edge we want them to be able to hit the scroll bar. | 605 // edge we want them to be able to hit the scroll bar. |
| 599 if (ash::wm::IsWindowMaximized(window) || | 606 if (ash::wm::IsWindowMaximized(window) || |
| 600 ash::wm::IsWindowFullscreen(window)) { | 607 ash::wm::IsWindowFullscreen(window)) { |
| 601 window->set_hit_test_bounds_override_inner(gfx::Insets()); | 608 window->set_hit_test_bounds_override_inner(gfx::Insets()); |
| 602 } else { | 609 } else { |
| 603 window->set_hit_test_bounds_override_inner( | 610 window->set_hit_test_bounds_override_inner( |
| 604 gfx::Insets(kResizeInsideBoundsSize, kResizeInsideBoundsSize, | 611 gfx::Insets(kResizeInsideBoundsSize, kResizeInsideBoundsSize, |
| 605 kResizeInsideBoundsSize, kResizeInsideBoundsSize)); | 612 kResizeInsideBoundsSize, kResizeInsideBoundsSize)); |
| 606 } | 613 } |
| 607 } | 614 } |
| 608 | 615 |
| 609 void FramePainter::OnWindowVisibilityChanged(aura::Window* window, | 616 void FramePainter::OnWindowVisibilityChanged(aura::Window* window, |
| 610 bool visible) { | 617 bool visible) { |
| 618 // Ignore updates from the root window. |
| 619 if (window != window_) |
| 620 return; |
| 621 |
| 611 // Window visibility change may trigger the change of window solo-ness in a | 622 // Window visibility change may trigger the change of window solo-ness in a |
| 612 // different window. | 623 // different window. |
| 613 UpdateSoloWindowFramePainter(visible ? NULL : window_); | 624 UpdateSoloWindowFramePainter(visible ? NULL : window_); |
| 614 } | 625 } |
| 615 | 626 |
| 616 void FramePainter::OnWindowDestroying(aura::Window* destroying) { | 627 void FramePainter::OnWindowDestroying(aura::Window* destroying) { |
| 617 DCHECK_EQ(window_, destroying); | 628 aura::Window* root = window_->GetRootWindow(); |
| 629 DCHECK(destroying == window_ || destroying == root); |
| 630 |
| 618 // Must be removed here and not in the destructor, as the aura::Window is | 631 // Must be removed here and not in the destructor, as the aura::Window is |
| 619 // already destroyed when our destructor runs. | 632 // already destroyed when our destructor runs. |
| 620 window_->RemoveObserver(this); | 633 window_->RemoveObserver(this); |
| 634 if (root) |
| 635 root->RemoveObserver(this); |
| 621 | 636 |
| 622 // For purposes of painting and solo window computation, we're done. | 637 // For purposes of painting and solo window computation, we're done. |
| 623 instances_->erase(this); | 638 instances_->erase(this); |
| 624 | 639 |
| 625 // If we have two or more windows open and we close this one, we might trigger | 640 // If we have two or more windows open and we close this one, we might trigger |
| 626 // the solo window appearance for another window. | 641 // the solo window appearance for another window. |
| 627 UpdateSoloWindowFramePainter(window_); | 642 UpdateSoloWindowFramePainter(window_); |
| 628 | 643 |
| 629 window_ = NULL; | 644 window_ = NULL; |
| 630 } | 645 } |
| 631 | 646 |
| 632 void FramePainter::OnWindowBoundsChanged(aura::Window* window, | 647 void FramePainter::OnWindowBoundsChanged(aura::Window* window, |
| 633 const gfx::Rect& old_bounds, | 648 const gfx::Rect& old_bounds, |
| 634 const gfx::Rect& new_bounds) { | 649 const gfx::Rect& new_bounds) { |
| 650 // Ignore updates from the root window. |
| 651 if (window != window_) |
| 652 return; |
| 653 |
| 635 // TODO(sky): this isn't quite right. What we really want is a method that | 654 // TODO(sky): this isn't quite right. What we really want is a method that |
| 636 // returns bounds ignoring transforms on certain windows (such as workspaces). | 655 // returns bounds ignoring transforms on certain windows (such as workspaces). |
| 637 if (!frame_->IsMaximized() && | 656 if (!frame_->IsMaximized() && |
| 638 ((old_bounds.y() == 0 && new_bounds.y() != 0) || | 657 ((old_bounds.y() == 0 && new_bounds.y() != 0) || |
| 639 (old_bounds.y() != 0 && new_bounds.y() == 0))) { | 658 (old_bounds.y() != 0 && new_bounds.y() == 0))) { |
| 640 SchedulePaintForHeader(); | 659 SchedulePaintForHeader(); |
| 641 } | 660 } |
| 642 } | 661 } |
| 643 | 662 |
| 644 void FramePainter::OnWindowAddedToRootWindow(aura::Window* window) { | 663 void FramePainter::OnWindowAddedToRootWindow(aura::Window* window) { |
| 664 DCHECK_EQ(window_, window); |
| 665 window->GetRootWindow()->AddObserver(this); |
| 666 |
| 645 // Needs to trigger the window appearance change if the window moves across | 667 // Needs to trigger the window appearance change if the window moves across |
| 646 // root windows and a solo window is already in the new root. | 668 // root windows and a solo window is already in the new root. |
| 647 UpdateSoloWindowFramePainter(NULL); | 669 UpdateSoloWindowFramePainter(NULL); |
| 648 } | 670 } |
| 649 | 671 |
| 650 void FramePainter::OnWindowRemovingFromRootWindow(aura::Window* window) { | 672 void FramePainter::OnWindowRemovingFromRootWindow(aura::Window* window) { |
| 673 DCHECK_EQ(window_, window); |
| 674 window->GetRootWindow()->RemoveObserver(this); |
| 675 |
| 651 // Needs to trigger the window appearance change if the window moves across | 676 // Needs to trigger the window appearance change if the window moves across |
| 652 // root windows and only one window is left in the previous root. Because | 677 // root windows and only one window is left in the previous root. Because |
| 653 // |window| is not yet moved, |window| has to be ignored. | 678 // |window| is not yet moved, |window| has to be ignored. |
| 654 UpdateSoloWindowFramePainter(window); | 679 UpdateSoloWindowFramePainter(window); |
| 655 } | 680 } |
| 656 | 681 |
| 657 /////////////////////////////////////////////////////////////////////////////// | 682 /////////////////////////////////////////////////////////////////////////////// |
| 658 // ui::AnimationDelegate overrides: | 683 // ui::AnimationDelegate overrides: |
| 659 | 684 |
| 660 void FramePainter::AnimationProgressed(const ui::Animation* animation) { | 685 void FramePainter::AnimationProgressed(const ui::Animation* animation) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 | 723 |
| 699 int FramePainter::GetHeaderOpacity(HeaderMode header_mode, | 724 int FramePainter::GetHeaderOpacity(HeaderMode header_mode, |
| 700 int theme_frame_id, | 725 int theme_frame_id, |
| 701 const gfx::ImageSkia* theme_frame_overlay) { | 726 const gfx::ImageSkia* theme_frame_overlay) { |
| 702 // User-provided themes are painted fully opaque. | 727 // User-provided themes are painted fully opaque. |
| 703 if (frame_->GetThemeProvider()->HasCustomImage(theme_frame_id)) | 728 if (frame_->GetThemeProvider()->HasCustomImage(theme_frame_id)) |
| 704 return kFullyOpaque; | 729 return kFullyOpaque; |
| 705 if (theme_frame_overlay) | 730 if (theme_frame_overlay) |
| 706 return kFullyOpaque; | 731 return kFullyOpaque; |
| 707 | 732 |
| 708 // Maximized windows with workspace2 are totally transparent, except those not | 733 // Maximized windows with workspaces are totally transparent, except: |
| 709 // tracked by workspace code (which are used for tab dragging). | 734 // - For windows whose workspace is not tracked by the workspace code (which |
| 710 if (frame_->IsMaximized() && GetTrackedByWorkspace(frame_->GetNativeWindow())) | 735 // are used for tab dragging). |
| 736 // - When the user is cycling through workspaces. |
| 737 if (frame_->IsMaximized() && |
| 738 GetTrackedByWorkspace(frame_->GetNativeWindow()) && |
| 739 !IsCyclingThroughWorkspaces()) { |
| 711 return 0; | 740 return 0; |
| 741 } |
| 712 | 742 |
| 713 // Single browser window is very transparent. | 743 // Single browser window is very transparent. |
| 714 if (UseSoloWindowHeader()) | 744 if (UseSoloWindowHeader()) |
| 715 return kSoloWindowOpacity; | 745 return kSoloWindowOpacity; |
| 716 | 746 |
| 717 // Otherwise, change transparency based on window activation status. | 747 // Otherwise, change transparency based on window activation status. |
| 718 if (header_mode == ACTIVE) | 748 if (header_mode == ACTIVE) |
| 719 return kActiveWindowOpacity; | 749 return kActiveWindowOpacity; |
| 720 return kInactiveWindowOpacity; | 750 return kInactiveWindowOpacity; |
| 721 } | 751 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 750 hit_code == HTTOPLEFT) | 780 hit_code == HTTOPLEFT) |
| 751 return HTTOP; | 781 return HTTOP; |
| 752 return (hit_code == HTBOTTOMRIGHT || | 782 return (hit_code == HTBOTTOMRIGHT || |
| 753 hit_code == HTBOTTOM || | 783 hit_code == HTBOTTOM || |
| 754 hit_code == HTBOTTOMLEFT) ? HTBOTTOM : HTNOWHERE; | 784 hit_code == HTBOTTOMLEFT) ? HTBOTTOM : HTNOWHERE; |
| 755 } | 785 } |
| 756 } | 786 } |
| 757 return hit_code; | 787 return hit_code; |
| 758 } | 788 } |
| 759 | 789 |
| 790 bool FramePainter::IsCyclingThroughWorkspaces() const { |
| 791 aura::RootWindow* root = window_->GetRootWindow(); |
| 792 return root && root->GetProperty(internal::kCyclingThroughWorkspacesKey); |
| 793 } |
| 794 |
| 760 bool FramePainter::UseSoloWindowHeader() { | 795 bool FramePainter::UseSoloWindowHeader() { |
| 761 aura::RootWindow* root = window_->GetRootWindow(); | 796 aura::RootWindow* root = window_->GetRootWindow(); |
| 762 if (!root || root->GetProperty(internal::kIgnoreSoloWindowFramePainterPolicy)) | 797 if (!root || root->GetProperty(internal::kIgnoreSoloWindowFramePainterPolicy)) |
| 763 return false; | 798 return false; |
| 764 return (root->GetProperty(internal::kSoloWindowFramePainterKey) == this); | 799 return (root->GetProperty(internal::kSoloWindowFramePainterKey) == this); |
| 765 } | 800 } |
| 766 | 801 |
| 767 // static | 802 // static |
| 768 FramePainter* FramePainter::GetSoloPainterInRoot(RootWindow* root_window, | 803 FramePainter* FramePainter::GetSoloPainterInRoot(RootWindow* root_window, |
| 769 Window* ignorable_window) { | 804 Window* ignorable_window) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 int title_y = | 876 int title_y = |
| 842 (view->GetBoundsForClientView().y() - title_font.GetHeight()) / 2; | 877 (view->GetBoundsForClientView().y() - title_font.GetHeight()) / 2; |
| 843 return gfx::Rect( | 878 return gfx::Rect( |
| 844 title_x, | 879 title_x, |
| 845 std::max(0, title_y), | 880 std::max(0, title_y), |
| 846 std::max(0, size_button_->x() - kTitleLogoSpacing - title_x), | 881 std::max(0, size_button_->x() - kTitleLogoSpacing - title_x), |
| 847 title_font.GetHeight()); | 882 title_font.GetHeight()); |
| 848 } | 883 } |
| 849 | 884 |
| 850 } // namespace ash | 885 } // namespace ash |
| OLD | NEW |