hud_display.cc 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. // Copyright 2020 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/hud_display/hud_display.h"
  5. #include "ash/fast_ink/view_tree_host_root_view.h"
  6. #include "ash/fast_ink/view_tree_host_widget.h"
  7. #include "ash/frame/non_client_frame_view_ash.h"
  8. #include "ash/hud_display/graphs_container_view.h"
  9. #include "ash/hud_display/hud_constants.h"
  10. #include "ash/hud_display/hud_header_view.h"
  11. #include "ash/hud_display/hud_properties.h"
  12. #include "ash/hud_display/hud_settings_view.h"
  13. #include "ash/hud_display/tab_strip.h"
  14. #include "ash/public/cpp/shell_window_ids.h"
  15. #include "ash/root_window_controller.h"
  16. #include "ash/shell.h"
  17. #include "base/bind.h"
  18. #include "base/strings/utf_string_conversions.h"
  19. #include "components/vector_icons/vector_icons.h"
  20. #include "ui/aura/window.h"
  21. #include "ui/base/hit_test.h"
  22. #include "ui/base/metadata/metadata_impl_macros.h"
  23. #include "ui/compositor/layer.h"
  24. #include "ui/events/base_event_utils.h"
  25. #include "ui/views/background.h"
  26. #include "ui/views/border.h"
  27. #include "ui/views/layout/box_layout.h"
  28. #include "ui/views/layout/fill_layout.h"
  29. #include "ui/views/widget/native_widget.h"
  30. #include "ui/views/widget/widget.h"
  31. #include "ui/views/widget/widget_delegate.h"
  32. namespace ash {
  33. namespace hud_display {
  34. namespace {
  35. // Header height.
  36. constexpr int kHUDHeaderHeight =
  37. kHUDSettingsIconSize + 2 * kHUDSettingsIconBorder;
  38. // Margin below header.
  39. constexpr int kHUDHeaderMargin = 5;
  40. // Graph height.
  41. constexpr int kHUDGraphHeight = 300;
  42. // Graph width/height including bordering reference lines.
  43. constexpr int kHUDGraphWidthWithReferenceLines =
  44. kHUDGraphWidth + 2 * kHUDGraphReferenceLineWidth;
  45. constexpr int kHUDGraphHeightWithReferenceLines =
  46. kHUDGraphHeight + 2 * kHUDGraphReferenceLineWidth;
  47. // HUD window width.
  48. constexpr int kHUDWidth = kHUDGraphWidthWithReferenceLines + 2 * kHUDInset;
  49. // Top inset + header + header margin + bottom inset. Used to compute the HUD
  50. // window height. Just add the graph height or settings height as appropriate.
  51. constexpr int kHUDFrameHeight =
  52. kHUDInset + kHUDHeaderHeight + kHUDHeaderMargin + kHUDInset;
  53. // HUD window height with graph.
  54. constexpr int kHUDHeightWithGraph =
  55. kHUDFrameHeight + kHUDGraphHeightWithReferenceLines;
  56. views::Widget* g_hud_widget = nullptr;
  57. // True if HUD should be initialized as overlay.
  58. bool g_hud_overlay_mode = true;
  59. // ClientView that return HTNOWHERE by default. A child view can receive event
  60. // by setting kHitTestComponentKey property to HTCLIENT.
  61. class HTClientView : public views::ClientView {
  62. public:
  63. METADATA_HEADER(HTClientView);
  64. HTClientView(HUDDisplayView* hud_display,
  65. views::Widget* widget,
  66. views::View* contents_view)
  67. : views::ClientView(widget, contents_view), hud_display_(hud_display) {}
  68. HTClientView(const HTClientView&) = delete;
  69. HTClientView& operator=(const HTClientView&) = delete;
  70. ~HTClientView() override = default;
  71. // views::ClientView
  72. int NonClientHitTest(const gfx::Point& point) override {
  73. return hud_display_->NonClientHitTest(point);
  74. }
  75. HUDDisplayView* GetHUDDisplayViewForTesting() { return hud_display_; }
  76. private:
  77. HUDDisplayView* hud_display_;
  78. };
  79. BEGIN_METADATA(HTClientView, views::ClientView)
  80. END_METADATA
  81. std::unique_ptr<views::ClientView> MakeClientView(views::Widget* widget) {
  82. auto view = std::make_unique<HUDDisplayView>();
  83. auto* weak_view = view.get();
  84. return std::make_unique<HTClientView>(weak_view, widget, view.release());
  85. }
  86. void InitializeFrameView(views::WidgetDelegate* delegate) {
  87. auto* frame_view = static_cast<NonClientFrameViewAsh*>(
  88. delegate->GetWidget()->non_client_view()->frame_view());
  89. // TODO(oshima): support component type with TYPE_WINDOW_FLAMELESS widget.
  90. if (frame_view)
  91. frame_view->SetFrameEnabled(false);
  92. }
  93. } // namespace
  94. ////////////////////////////////////////////////////////////////////////////////
  95. // HUDDisplayView, public:
  96. BEGIN_METADATA(HUDDisplayView, views::View)
  97. END_METADATA
  98. // static
  99. void HUDDisplayView::Destroy() {
  100. delete g_hud_widget;
  101. g_hud_widget = nullptr;
  102. }
  103. // static
  104. void HUDDisplayView::Toggle() {
  105. if (g_hud_widget) {
  106. Destroy();
  107. return;
  108. }
  109. auto delegate = std::make_unique<views::WidgetDelegate>();
  110. delegate->SetClientViewFactory(base::BindOnce(&MakeClientView));
  111. delegate->RegisterWidgetInitializedCallback(
  112. base::BindOnce(&InitializeFrameView, base::Unretained(delegate.get())));
  113. delegate->SetOwnedByWidget(true);
  114. views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
  115. params.delegate = delegate.release();
  116. params.parent = Shell::GetContainer(Shell::GetPrimaryRootWindow(),
  117. kShellWindowId_OverlayContainer);
  118. params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  119. params.bounds = gfx::Rect(kHUDWidth, kHUDHeightWithGraph);
  120. auto* widget = CreateViewTreeHostWidget(std::move(params));
  121. widget->GetLayer()->SetName("HUDDisplayView");
  122. static_cast<ViewTreeHostRootView*>(widget->GetRootView())
  123. ->SetIsOverlayCandidate(g_hud_overlay_mode);
  124. widget->Show();
  125. g_hud_widget = widget;
  126. }
  127. // static
  128. bool HUDDisplayView::IsShown() {
  129. return g_hud_widget;
  130. }
  131. HUDDisplayView::HUDDisplayView() {
  132. DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
  133. // Layout:
  134. // ----------------------
  135. // | Header | // Buttons, tabs, controls
  136. // ----------------------
  137. // | | // Data views full-size, z-stacked.
  138. // | Data |
  139. // | |
  140. // ----------------------
  141. // Create two child views for header and data. Vertically stacked.
  142. views::BoxLayout* layout_manager =
  143. SetLayoutManager(std::make_unique<views::BoxLayout>(
  144. views::BoxLayout::Orientation::kVertical));
  145. layout_manager->set_cross_axis_alignment(
  146. views::BoxLayout::CrossAxisAlignment::kStretch);
  147. header_view_ = AddChildView(std::make_unique<HUDHeaderView>(this));
  148. views::View* data = AddChildView(std::make_unique<views::View>());
  149. // Data view takes the rest of the host view.
  150. layout_manager->SetFlexForView(data, 1, /*use_min_size=*/false);
  151. // Setup header.
  152. header_view_->tab_strip()->AddTabButton(HUDDisplayMode::CPU, u"CPU");
  153. header_view_->tab_strip()->AddTabButton(HUDDisplayMode::MEMORY, u"RAM");
  154. header_view_->tab_strip()->AddTabButton(HUDDisplayMode::FPS, u"FPS");
  155. // Setup data.
  156. data->SetBackground(views::CreateSolidBackground(kHUDBackground));
  157. data->SetBorder(views::CreateEmptyBorder(
  158. gfx::Insets::TLBR(kHUDHeaderMargin, kHUDInset, kHUDInset, kHUDInset)));
  159. // We have two child views z-stacked.
  160. // The bottom one is GraphsContainerView with all the graph lines.
  161. // The top one is settings UI overlay.
  162. data->SetLayoutManager(std::make_unique<views::FillLayout>());
  163. graphs_container_ =
  164. data->AddChildView(std::make_unique<GraphsContainerView>());
  165. settings_view_ = data->AddChildView(std::make_unique<HUDSettingsView>(this));
  166. settings_view_->SetVisible(false);
  167. // CPU display is active by default.
  168. SetDisplayMode(HUDDisplayMode::CPU);
  169. }
  170. HUDDisplayView::~HUDDisplayView() {
  171. DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
  172. }
  173. // There is only one button.
  174. void HUDDisplayView::OnSettingsToggle() {
  175. gfx::Rect bounds = g_hud_widget->GetWindowBoundsInScreen();
  176. // Here we are checking the settings visibility before we toggle it. We must
  177. // keep in mind that it is the opposite of what it will be.
  178. bounds.set_height(settings_view_->GetVisible()
  179. ? kHUDHeightWithGraph
  180. : kHUDFrameHeight +
  181. settings_view_->GetPreferredSize().height());
  182. g_hud_widget->SetBounds(bounds);
  183. settings_view_->ToggleVisibility();
  184. graphs_container_->SetVisible(!settings_view_->GetVisible());
  185. }
  186. bool HUDDisplayView::IsOverlay() {
  187. return static_cast<ViewTreeHostRootView*>(GetWidget()->GetRootView())
  188. ->GetIsOverlayCandidate();
  189. }
  190. void HUDDisplayView::ToggleOverlay() {
  191. g_hud_overlay_mode = !g_hud_overlay_mode;
  192. static_cast<ViewTreeHostRootView*>(GetWidget()->GetRootView())
  193. ->SetIsOverlayCandidate(g_hud_overlay_mode);
  194. }
  195. // static
  196. HUDDisplayView* HUDDisplayView::GetForTesting() {
  197. if (!g_hud_widget)
  198. return nullptr;
  199. HTClientView* client_view =
  200. static_cast<HTClientView*>(g_hud_widget->client_view());
  201. if (!client_view)
  202. return nullptr;
  203. return client_view->GetHUDDisplayViewForTesting(); // IN-TEST
  204. }
  205. HUDSettingsView* HUDDisplayView::GetSettingsViewForTesting() {
  206. return settings_view_;
  207. }
  208. void HUDDisplayView::ToggleSettingsForTesting() {
  209. OnSettingsToggle();
  210. }
  211. int HUDDisplayView::NonClientHitTest(const gfx::Point& point) {
  212. const View* view = GetEventHandlerForPoint(point);
  213. if (!view)
  214. return HTNOWHERE;
  215. return view->GetProperty(kHUDClickHandler);
  216. }
  217. void HUDDisplayView::SetDisplayMode(HUDDisplayMode display_mode) {
  218. graphs_container_->SetMode(display_mode);
  219. header_view_->tab_strip()->ActivateTab(display_mode);
  220. }
  221. } // namespace hud_display
  222. } // namespace ash