window_mini_view.cc 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // Copyright 2019 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_mini_view.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "ash/style/ash_color_provider.h"
  8. #include "ash/wm/window_preview_view.h"
  9. #include "ash/wm/wm_highlight_item_border.h"
  10. #include "chromeos/ui/base/window_properties.h"
  11. #include "ui/accessibility/ax_enums.mojom.h"
  12. #include "ui/accessibility/ax_node_data.h"
  13. #include "ui/aura/client/aura_constants.h"
  14. #include "ui/aura/window.h"
  15. #include "ui/base/metadata/metadata_impl_macros.h"
  16. #include "ui/compositor/layer.h"
  17. #include "ui/gfx/image/image_skia_operations.h"
  18. #include "ui/views/controls/image_view.h"
  19. #include "ui/views/controls/label.h"
  20. #include "ui/views/layout/box_layout.h"
  21. #include "ui/views/layout/fill_layout.h"
  22. #include "ui/views/layout/layout_provider.h"
  23. #include "ui/wm/core/window_util.h"
  24. namespace ash {
  25. namespace {
  26. // The font delta of the window title.
  27. constexpr int kLabelFontDelta = 2;
  28. // Values of the backdrop.
  29. constexpr int kBackdropBorderRoundingDp = 4;
  30. std::u16string GetWindowTitle(aura::Window* window) {
  31. aura::Window* transient_root = wm::GetTransientRoot(window);
  32. const std::u16string* overview_title =
  33. transient_root->GetProperty(chromeos::kWindowOverviewTitleKey);
  34. return (overview_title && !overview_title->empty())
  35. ? *overview_title
  36. : transient_root->GetTitle();
  37. }
  38. } // namespace
  39. WindowMiniView::~WindowMiniView() = default;
  40. constexpr gfx::Size WindowMiniView::kIconSize;
  41. constexpr int WindowMiniView::kHeaderPaddingDp;
  42. void WindowMiniView::SetBackdropVisibility(bool visible) {
  43. if (!backdrop_view_ && !visible)
  44. return;
  45. if (!backdrop_view_) {
  46. backdrop_view_ = AddChildView(std::make_unique<views::View>());
  47. backdrop_view_->SetPaintToLayer(ui::LAYER_SOLID_COLOR);
  48. ui::Layer* layer = backdrop_view_->layer();
  49. layer->SetFillsBoundsOpaquely(false);
  50. layer->SetColor(AshColorProvider::Get()->GetControlsLayerColor(
  51. AshColorProvider::ControlsLayerType::kControlBackgroundColorInactive));
  52. layer->SetRoundedCornerRadius(
  53. gfx::RoundedCornersF(kBackdropBorderRoundingDp));
  54. layer->SetIsFastRoundedCorner(true);
  55. backdrop_view_->SetCanProcessEventsWithinSubtree(false);
  56. Layout();
  57. }
  58. backdrop_view_->SetVisible(visible);
  59. }
  60. void WindowMiniView::SetShowPreview(bool show) {
  61. if (show == !!preview_view_)
  62. return;
  63. if (!show) {
  64. RemoveChildView(preview_view_);
  65. delete preview_view_;
  66. preview_view_ = nullptr;
  67. return;
  68. }
  69. if (!source_window_)
  70. return;
  71. preview_view_ = AddChildView(std::make_unique<WindowPreviewView>(
  72. source_window_,
  73. /*trilinear_filtering_on_init=*/false));
  74. preview_view_->SetPaintToLayer();
  75. preview_view_->layer()->SetFillsBoundsOpaquely(false);
  76. Layout();
  77. }
  78. void WindowMiniView::UpdatePreviewRoundedCorners(bool show) {
  79. if (!preview_view())
  80. return;
  81. ui::Layer* layer = preview_view()->layer();
  82. DCHECK(layer);
  83. const float scale = layer->transform().To2dScale().x();
  84. const float rounding = views::LayoutProvider::Get()->GetCornerRadiusMetric(
  85. views::Emphasis::kLow);
  86. const gfx::RoundedCornersF radii(show ? rounding / scale : 0.0f);
  87. layer->SetRoundedCornerRadius(radii);
  88. layer->SetIsFastRoundedCorner(true);
  89. }
  90. void WindowMiniView::UpdateBorderState(bool show) {
  91. border_ptr_->SetFocused(show);
  92. SchedulePaint();
  93. }
  94. gfx::Rect WindowMiniView::GetHeaderBounds() const {
  95. gfx::Rect header_bounds = GetContentsBounds();
  96. header_bounds.set_height(kHeaderHeightDp);
  97. return header_bounds;
  98. }
  99. gfx::Size WindowMiniView::GetPreviewViewSize() const {
  100. DCHECK(preview_view_);
  101. return preview_view_->GetPreferredSize();
  102. }
  103. WindowMiniView::WindowMiniView(aura::Window* source_window)
  104. : source_window_(source_window) {
  105. SetPaintToLayer();
  106. layer()->SetFillsBoundsOpaquely(false);
  107. window_observation_.Observe(source_window);
  108. header_view_ = AddChildView(std::make_unique<views::View>());
  109. header_view_->SetPaintToLayer();
  110. header_view_->layer()->SetFillsBoundsOpaquely(false);
  111. views::BoxLayout* layout =
  112. header_view_->SetLayoutManager(std::make_unique<views::BoxLayout>(
  113. views::BoxLayout::Orientation::kHorizontal, gfx::Insets(),
  114. kHeaderPaddingDp));
  115. title_label_ = header_view_->AddChildView(
  116. std::make_unique<views::Label>(GetWindowTitle(source_window_)));
  117. title_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
  118. title_label_->SetAutoColorReadabilityEnabled(false);
  119. title_label_->SetSubpixelRenderingEnabled(false);
  120. title_label_->SetFontList(gfx::FontList().Derive(
  121. kLabelFontDelta, gfx::Font::NORMAL, gfx::Font::Weight::MEDIUM));
  122. layout->SetFlexForView(title_label_, 1);
  123. auto border =
  124. std::make_unique<WmHighlightItemBorder>(kBackdropBorderRoundingDp);
  125. border_ptr_ = border.get();
  126. SetBorder(std::move(border));
  127. }
  128. void WindowMiniView::UpdateIconView() {
  129. DCHECK(source_window_);
  130. aura::Window* transient_root = wm::GetTransientRoot(source_window_);
  131. // Prefer kAppIconKey over kWindowIconKey as the app icon is typically larger.
  132. gfx::ImageSkia* icon = transient_root->GetProperty(aura::client::kAppIconKey);
  133. if (!icon || icon->size().IsEmpty())
  134. icon = transient_root->GetProperty(aura::client::kWindowIconKey);
  135. if (!icon)
  136. return;
  137. if (!icon_view_) {
  138. icon_view_ =
  139. header_view_->AddChildViewAt(std::make_unique<views::ImageView>(), 0);
  140. }
  141. icon_view_->SetImage(gfx::ImageSkiaOperations::CreateResizedImage(
  142. *icon, skia::ImageOperations::RESIZE_BEST, kIconSize));
  143. }
  144. gfx::Rect WindowMiniView::GetContentAreaBounds() const {
  145. gfx::Rect bounds(GetContentsBounds());
  146. bounds.Inset(gfx::Insets::TLBR(kHeaderHeightDp, 0, 0, 0));
  147. return bounds;
  148. }
  149. void WindowMiniView::Layout() {
  150. const gfx::Rect content_area_bounds = GetContentAreaBounds();
  151. if (backdrop_view_)
  152. backdrop_view_->SetBoundsRect(content_area_bounds);
  153. if (preview_view_) {
  154. gfx::Rect preview_bounds = content_area_bounds;
  155. preview_bounds.ClampToCenteredSize(GetPreviewViewSize());
  156. preview_view_->SetBoundsRect(preview_bounds);
  157. }
  158. header_view_->SetBoundsRect(GetHeaderBounds());
  159. }
  160. void WindowMiniView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
  161. // This may be called after `OnWindowDestroying`. `this` should be destroyed
  162. // shortly by the owner (OverviewItem/WindowCycleView) but there may be a
  163. // small window where `source_window_` is null. Speculative fix for
  164. // https://crbug.com/1274775.
  165. if (!source_window_)
  166. return;
  167. node_data->role = ax::mojom::Role::kWindow;
  168. node_data->SetName(wm::GetTransientRoot(source_window_)->GetTitle());
  169. }
  170. void WindowMiniView::OnThemeChanged() {
  171. views::View::OnThemeChanged();
  172. title_label_->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor(
  173. AshColorProvider::ContentLayerType::kTextColorPrimary));
  174. }
  175. void WindowMiniView::OnWindowPropertyChanged(aura::Window* window,
  176. const void* key,
  177. intptr_t old) {
  178. // Update the icon if it changes in the middle of an overview or alt tab
  179. // session (due to device scale factor change or other).
  180. if (key != aura::client::kAppIconKey && key != aura::client::kWindowIconKey)
  181. return;
  182. UpdateIconView();
  183. }
  184. void WindowMiniView::OnWindowDestroying(aura::Window* window) {
  185. if (window != source_window_)
  186. return;
  187. window_observation_.Reset();
  188. source_window_ = nullptr;
  189. SetShowPreview(false);
  190. }
  191. void WindowMiniView::OnWindowTitleChanged(aura::Window* window) {
  192. title_label_->SetText(GetWindowTitle(window));
  193. }
  194. BEGIN_METADATA(WindowMiniView, views::View)
  195. END_METADATA
  196. } // namespace ash