window_dimmer.cc 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // Copyright 2015 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/wm/window_dimmer.h"
  5. #include "ash/root_window_controller.h"
  6. #include "ash/style/ash_color_provider_source.h"
  7. #include "ash/style/style_util.h"
  8. #include "base/time/time.h"
  9. #include "ui/aura/window.h"
  10. #include "ui/color/color_id.h"
  11. #include "ui/color/color_provider.h"
  12. #include "ui/color/color_provider_source_observer.h"
  13. #include "ui/compositor/layer.h"
  14. #include "ui/wm/core/visibility_controller.h"
  15. #include "ui/wm/core/window_animations.h"
  16. namespace ash {
  17. namespace {
  18. const int kDefaultDimAnimationDurationMs = 200;
  19. const float kDefaultDimOpacity = 0.5f;
  20. } // namespace
  21. WindowDimmer::WindowDimmer(aura::Window* parent,
  22. bool animate,
  23. Delegate* delegate)
  24. : parent_(parent),
  25. window_(new aura::Window(nullptr, aura::client::WINDOW_TYPE_NORMAL)),
  26. delegate_(delegate) {
  27. window_->Init(ui::LAYER_SOLID_COLOR);
  28. window_->SetName("Dimming Window");
  29. if (animate) {
  30. ::wm::SetWindowVisibilityChangesAnimated(window_);
  31. ::wm::SetWindowVisibilityAnimationType(
  32. window_, ::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
  33. ::wm::SetWindowVisibilityAnimationDuration(
  34. window_, base::Milliseconds(kDefaultDimAnimationDurationMs));
  35. }
  36. window_->AddObserver(this);
  37. SetDimOpacity(kDefaultDimOpacity);
  38. parent->AddChild(window_);
  39. parent->AddObserver(this);
  40. parent->StackChildAtTop(window_);
  41. // The window is not fully opaque. Set the transparent bit so that it
  42. // interacts properly with aura::WindowOcclusionTracker.
  43. // https://crbug.com/833814
  44. window_->SetTransparent(true);
  45. window_->SetBounds(gfx::Rect(parent_->bounds().size()));
  46. // `this` may already start observing the color provider source through
  47. // `OnWindowAddedToRootWindow` if `window_` is alreadyed added to the root
  48. // window.
  49. if (!GetColorProviderSource()) {
  50. auto* color_provider_source =
  51. StyleUtil::GetColorProviderSourceForWindow(window_);
  52. if (color_provider_source)
  53. ui::ColorProviderSourceObserver::Observe(color_provider_source);
  54. }
  55. }
  56. WindowDimmer::~WindowDimmer() {
  57. if (parent_)
  58. parent_->RemoveObserver(this);
  59. if (window_) {
  60. window_->RemoveObserver(this);
  61. // See class description for details on ownership.
  62. delete window_;
  63. }
  64. }
  65. void WindowDimmer::SetDimOpacity(float target_opacity) {
  66. // Once this function is called, reset the `dim_color_type_`, which means we
  67. // don't need to update the color on window's layer on native theme updated.
  68. // Since after this call the color on the layer will be updated to the default
  69. // dimming color which is Black.
  70. dim_color_type_.reset();
  71. DCHECK(window_);
  72. window_->layer()->SetColor(SkColorSetA(SK_ColorBLACK, 255 * target_opacity));
  73. }
  74. void WindowDimmer::SetDimColor(ui::ColorId color_id) {
  75. DCHECK(window_);
  76. dim_color_type_ = color_id;
  77. UpdateDimColor();
  78. }
  79. void WindowDimmer::OnWindowBoundsChanged(aura::Window* window,
  80. const gfx::Rect& old_bounds,
  81. const gfx::Rect& new_bounds,
  82. ui::PropertyChangeReason reason) {
  83. if (window == parent_)
  84. window_->SetBounds(gfx::Rect(new_bounds.size()));
  85. }
  86. void WindowDimmer::OnWindowDestroying(aura::Window* window) {
  87. if (window == parent_) {
  88. parent_->RemoveObserver(this);
  89. parent_ = nullptr;
  90. if (delegate_) {
  91. delegate_->OnDimmedWindowDestroying(window);
  92. // `this` can be deleted above. So don't access any member after this.
  93. }
  94. } else {
  95. DCHECK_EQ(window_, window);
  96. window_->RemoveObserver(this);
  97. window_ = nullptr;
  98. }
  99. }
  100. void WindowDimmer::OnWindowHierarchyChanging(
  101. const HierarchyChangeParams& params) {
  102. if (params.receiver == window_ && params.target == params.receiver) {
  103. // This may happen on a display change or some unexpected condition. Hide
  104. // the window to ensure it isn't obscuring the wrong thing.
  105. window_->Hide();
  106. }
  107. }
  108. void WindowDimmer::OnWindowParentChanged(aura::Window* window,
  109. aura::Window* parent) {
  110. if (delegate_ && window == parent_)
  111. delegate_->OnDimmedWindowParentChanged(window);
  112. }
  113. void WindowDimmer::OnWindowAddedToRootWindow(aura::Window* window) {
  114. if (GetColorProviderSource())
  115. return;
  116. // There's a chance when `this` is being created, `window_` is not added to
  117. // the root window yet, hence we should observe the `color_provider_source`
  118. // which is owned by the `RootWindowController` here.
  119. auto* color_provider_source =
  120. StyleUtil::GetColorProviderSourceForWindow(window);
  121. DCHECK(color_provider_source);
  122. ui::ColorProviderSourceObserver::Observe(color_provider_source);
  123. UpdateDimColor();
  124. }
  125. void WindowDimmer::OnColorProviderChanged() {
  126. UpdateDimColor();
  127. }
  128. void WindowDimmer::UpdateDimColor() {
  129. if (!window_)
  130. return;
  131. if (!dim_color_type_.has_value())
  132. return;
  133. auto* color_provider_source = GetColorProviderSource();
  134. if (!color_provider_source)
  135. return;
  136. auto dimming_color = color_provider_source->GetColorProvider()->GetColor(
  137. dim_color_type_.value());
  138. DCHECK_NE(SkColorGetA(dimming_color), SK_AlphaOPAQUE);
  139. window_->layer()->SetColor(dimming_color);
  140. }
  141. } // namespace ash