window_preview.cc 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // Copyright 2018 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/shelf/window_preview.h"
  5. #include "ash/public/cpp/shelf_config.h"
  6. #include "ash/resources/vector_icons/vector_icons.h"
  7. #include "ash/wm/window_preview_view.h"
  8. #include "ash/wm/window_util.h"
  9. #include "base/bind.h"
  10. #include "ui/aura/window.h"
  11. #include "ui/color/color_id.h"
  12. #include "ui/color/color_provider.h"
  13. #include "ui/gfx/color_palette.h"
  14. #include "ui/gfx/paint_vector_icon.h"
  15. #include "ui/views/background.h"
  16. #include "ui/views/controls/button/image_button.h"
  17. #include "ui/views/controls/label.h"
  18. namespace ash {
  19. // The margins around window titles.
  20. constexpr int kTitleLineHeight = 20;
  21. constexpr int kTitleMarginTop = 10;
  22. constexpr int kTitleMarginBottom = 10;
  23. constexpr int kTitleMarginRight = 16;
  24. // The width and height of close buttons.
  25. constexpr int kCloseButtonSize = 36;
  26. constexpr int kCloseButtonImageSize = 24;
  27. constexpr int kCloseButtonSideBleed = 8;
  28. constexpr SkColor kCloseButtonColor = SK_ColorWHITE;
  29. constexpr SkColor kPreviewContainerBgColor =
  30. SkColorSetA(gfx::kGoogleGrey100, 0x24);
  31. constexpr int kPreviewBorderRadius = 4;
  32. WindowPreview::WindowPreview(aura::Window* window, Delegate* delegate)
  33. : delegate_(delegate) {
  34. preview_view_ =
  35. new WindowPreviewView(window, /*trilinear_filtering_on_init=*/false);
  36. preview_container_view_ = new views::View();
  37. preview_container_view_->SetBackground(views::CreateRoundedRectBackground(
  38. kPreviewContainerBgColor, kPreviewBorderRadius));
  39. title_ = new views::Label(window->GetTitle());
  40. close_button_ = new views::ImageButton(base::BindRepeating(
  41. &WindowPreview::CloseButtonPressed, base::Unretained(this)));
  42. close_button_->SetFocusBehavior(FocusBehavior::NEVER);
  43. AddChildView(preview_container_view_);
  44. AddChildView(preview_view_);
  45. AddChildView(title_);
  46. AddChildView(close_button_);
  47. }
  48. WindowPreview::~WindowPreview() = default;
  49. gfx::Size WindowPreview::CalculatePreferredSize() const {
  50. // The preview itself will always be strictly contained within its container,
  51. // so only the container's size matters to calculate the preferred size.
  52. const gfx::Size container_size = GetPreviewContainerSize();
  53. const int title_height_with_padding =
  54. kTitleLineHeight + kTitleMarginTop + kTitleMarginBottom;
  55. return gfx::Size(container_size.width(),
  56. container_size.height() + title_height_with_padding);
  57. }
  58. void WindowPreview::Layout() {
  59. gfx::Rect content_rect = GetContentsBounds();
  60. gfx::Size title_size = title_->CalculatePreferredSize();
  61. int title_height_with_padding =
  62. kTitleLineHeight + kTitleMarginTop + kTitleMarginBottom;
  63. int title_width =
  64. std::min(title_size.width(),
  65. content_rect.width() - kCloseButtonSize - kTitleMarginRight);
  66. title_->SetBoundsRect(gfx::Rect(content_rect.x(),
  67. content_rect.y() + kTitleMarginTop,
  68. title_width, kTitleLineHeight));
  69. close_button_->SetBoundsRect(
  70. gfx::Rect(content_rect.right() - kCloseButtonSize + kCloseButtonSideBleed,
  71. content_rect.y(), kCloseButtonSize, kCloseButtonSize));
  72. const gfx::Size container_size = GetPreviewContainerSize();
  73. gfx::Size mirror_size = preview_view_->CalculatePreferredSize();
  74. float preview_ratio = static_cast<float>(mirror_size.width()) /
  75. static_cast<float>(mirror_size.height());
  76. int preview_height = ShelfConfig::Get()->shelf_tooltip_preview_height();
  77. int preview_width = preview_height * preview_ratio;
  78. if (preview_ratio > ShelfConfig::Get()->shelf_tooltip_preview_max_ratio()) {
  79. // Very wide window.
  80. preview_width = ShelfConfig::Get()->shelf_tooltip_preview_max_width();
  81. preview_height =
  82. ShelfConfig::Get()->shelf_tooltip_preview_max_width() / preview_ratio;
  83. }
  84. // Center the actual preview over the container, horizontally and vertically.
  85. gfx::Point preview_offset_from_container(
  86. (container_size.width() - preview_width) / 2,
  87. (container_size.height() - preview_height) / 2);
  88. const int preview_container_top =
  89. content_rect.y() + title_height_with_padding;
  90. preview_container_view_->SetBoundsRect(
  91. gfx::Rect(content_rect.x(), preview_container_top, container_size.width(),
  92. container_size.height()));
  93. preview_view_->SetBoundsRect(
  94. gfx::Rect(content_rect.x() + preview_offset_from_container.x(),
  95. preview_container_top + preview_offset_from_container.y(),
  96. preview_width, preview_height));
  97. }
  98. bool WindowPreview::OnMousePressed(const ui::MouseEvent& event) {
  99. if (!preview_view_->bounds().Contains(event.location()))
  100. return false;
  101. aura::Window* target = preview_view_->window();
  102. if (target) {
  103. // The window might have been closed in the mean time.
  104. // TODO: Use WindowObserver to listen to when previewed windows are
  105. // being closed and remove this condition.
  106. wm::ActivateWindow(target);
  107. // This will have the effect of deleting this view.
  108. delegate_->OnPreviewActivated(this);
  109. }
  110. return true;
  111. }
  112. const char* WindowPreview::GetClassName() const {
  113. return "WindowPreview";
  114. }
  115. void WindowPreview::OnThemeChanged() {
  116. views::View::OnThemeChanged();
  117. const auto* color_provider = GetColorProvider();
  118. SkColor background_color =
  119. color_provider->GetColor(ui::kColorTooltipBackground);
  120. title_->SetEnabledColor(
  121. color_provider->GetColor(ui::kColorTooltipForeground));
  122. title_->SetBackgroundColor(background_color);
  123. // The background is not opaque, so we can't do subpixel rendering.
  124. title_->SetSubpixelRenderingEnabled(false);
  125. close_button_->SetImage(
  126. views::Button::STATE_NORMAL,
  127. gfx::CreateVectorIcon(kOverviewWindowCloseIcon, kCloseButtonColor));
  128. close_button_->SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
  129. close_button_->SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
  130. close_button_->SetMinimumImageSize(
  131. gfx::Size(kCloseButtonImageSize, kCloseButtonImageSize));
  132. }
  133. gfx::Size WindowPreview::GetPreviewContainerSize() const {
  134. return gfx::Size(
  135. std::min(delegate_->GetMaxPreviewRatio() *
  136. ShelfConfig::Get()->shelf_tooltip_preview_height(),
  137. static_cast<float>(
  138. ShelfConfig::Get()->shelf_tooltip_preview_max_width())),
  139. ShelfConfig::Get()->shelf_tooltip_preview_height());
  140. }
  141. void WindowPreview::CloseButtonPressed() {
  142. // The window might have been closed in the mean time.
  143. // TODO: Use WindowObserver to listen to when previewed windows are
  144. // being closed and remove this condition.
  145. aura::Window* target = preview_view_->window();
  146. if (!target)
  147. return;
  148. window_util::CloseWidgetForWindow(target);
  149. // This will have the effect of deleting this view.
  150. delegate_->OnPreviewDismissed(this);
  151. }
  152. } // namespace ash