123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- // Copyright 2020 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/hud_display/hud_display.h"
- #include "ash/fast_ink/view_tree_host_root_view.h"
- #include "ash/fast_ink/view_tree_host_widget.h"
- #include "ash/frame/non_client_frame_view_ash.h"
- #include "ash/hud_display/graphs_container_view.h"
- #include "ash/hud_display/hud_constants.h"
- #include "ash/hud_display/hud_header_view.h"
- #include "ash/hud_display/hud_properties.h"
- #include "ash/hud_display/hud_settings_view.h"
- #include "ash/hud_display/tab_strip.h"
- #include "ash/public/cpp/shell_window_ids.h"
- #include "ash/root_window_controller.h"
- #include "ash/shell.h"
- #include "base/bind.h"
- #include "base/strings/utf_string_conversions.h"
- #include "components/vector_icons/vector_icons.h"
- #include "ui/aura/window.h"
- #include "ui/base/hit_test.h"
- #include "ui/base/metadata/metadata_impl_macros.h"
- #include "ui/compositor/layer.h"
- #include "ui/events/base_event_utils.h"
- #include "ui/views/background.h"
- #include "ui/views/border.h"
- #include "ui/views/layout/box_layout.h"
- #include "ui/views/layout/fill_layout.h"
- #include "ui/views/widget/native_widget.h"
- #include "ui/views/widget/widget.h"
- #include "ui/views/widget/widget_delegate.h"
- namespace ash {
- namespace hud_display {
- namespace {
- // Header height.
- constexpr int kHUDHeaderHeight =
- kHUDSettingsIconSize + 2 * kHUDSettingsIconBorder;
- // Margin below header.
- constexpr int kHUDHeaderMargin = 5;
- // Graph height.
- constexpr int kHUDGraphHeight = 300;
- // Graph width/height including bordering reference lines.
- constexpr int kHUDGraphWidthWithReferenceLines =
- kHUDGraphWidth + 2 * kHUDGraphReferenceLineWidth;
- constexpr int kHUDGraphHeightWithReferenceLines =
- kHUDGraphHeight + 2 * kHUDGraphReferenceLineWidth;
- // HUD window width.
- constexpr int kHUDWidth = kHUDGraphWidthWithReferenceLines + 2 * kHUDInset;
- // Top inset + header + header margin + bottom inset. Used to compute the HUD
- // window height. Just add the graph height or settings height as appropriate.
- constexpr int kHUDFrameHeight =
- kHUDInset + kHUDHeaderHeight + kHUDHeaderMargin + kHUDInset;
- // HUD window height with graph.
- constexpr int kHUDHeightWithGraph =
- kHUDFrameHeight + kHUDGraphHeightWithReferenceLines;
- views::Widget* g_hud_widget = nullptr;
- // True if HUD should be initialized as overlay.
- bool g_hud_overlay_mode = true;
- // ClientView that return HTNOWHERE by default. A child view can receive event
- // by setting kHitTestComponentKey property to HTCLIENT.
- class HTClientView : public views::ClientView {
- public:
- METADATA_HEADER(HTClientView);
- HTClientView(HUDDisplayView* hud_display,
- views::Widget* widget,
- views::View* contents_view)
- : views::ClientView(widget, contents_view), hud_display_(hud_display) {}
- HTClientView(const HTClientView&) = delete;
- HTClientView& operator=(const HTClientView&) = delete;
- ~HTClientView() override = default;
- // views::ClientView
- int NonClientHitTest(const gfx::Point& point) override {
- return hud_display_->NonClientHitTest(point);
- }
- HUDDisplayView* GetHUDDisplayViewForTesting() { return hud_display_; }
- private:
- HUDDisplayView* hud_display_;
- };
- BEGIN_METADATA(HTClientView, views::ClientView)
- END_METADATA
- std::unique_ptr<views::ClientView> MakeClientView(views::Widget* widget) {
- auto view = std::make_unique<HUDDisplayView>();
- auto* weak_view = view.get();
- return std::make_unique<HTClientView>(weak_view, widget, view.release());
- }
- void InitializeFrameView(views::WidgetDelegate* delegate) {
- auto* frame_view = static_cast<NonClientFrameViewAsh*>(
- delegate->GetWidget()->non_client_view()->frame_view());
- // TODO(oshima): support component type with TYPE_WINDOW_FLAMELESS widget.
- if (frame_view)
- frame_view->SetFrameEnabled(false);
- }
- } // namespace
- ////////////////////////////////////////////////////////////////////////////////
- // HUDDisplayView, public:
- BEGIN_METADATA(HUDDisplayView, views::View)
- END_METADATA
- // static
- void HUDDisplayView::Destroy() {
- delete g_hud_widget;
- g_hud_widget = nullptr;
- }
- // static
- void HUDDisplayView::Toggle() {
- if (g_hud_widget) {
- Destroy();
- return;
- }
- auto delegate = std::make_unique<views::WidgetDelegate>();
- delegate->SetClientViewFactory(base::BindOnce(&MakeClientView));
- delegate->RegisterWidgetInitializedCallback(
- base::BindOnce(&InitializeFrameView, base::Unretained(delegate.get())));
- delegate->SetOwnedByWidget(true);
- views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
- params.delegate = delegate.release();
- params.parent = Shell::GetContainer(Shell::GetPrimaryRootWindow(),
- kShellWindowId_OverlayContainer);
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.bounds = gfx::Rect(kHUDWidth, kHUDHeightWithGraph);
- auto* widget = CreateViewTreeHostWidget(std::move(params));
- widget->GetLayer()->SetName("HUDDisplayView");
- static_cast<ViewTreeHostRootView*>(widget->GetRootView())
- ->SetIsOverlayCandidate(g_hud_overlay_mode);
- widget->Show();
- g_hud_widget = widget;
- }
- // static
- bool HUDDisplayView::IsShown() {
- return g_hud_widget;
- }
- HUDDisplayView::HUDDisplayView() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
- // Layout:
- // ----------------------
- // | Header | // Buttons, tabs, controls
- // ----------------------
- // | | // Data views full-size, z-stacked.
- // | Data |
- // | |
- // ----------------------
- // Create two child views for header and data. Vertically stacked.
- views::BoxLayout* layout_manager =
- SetLayoutManager(std::make_unique<views::BoxLayout>(
- views::BoxLayout::Orientation::kVertical));
- layout_manager->set_cross_axis_alignment(
- views::BoxLayout::CrossAxisAlignment::kStretch);
- header_view_ = AddChildView(std::make_unique<HUDHeaderView>(this));
- views::View* data = AddChildView(std::make_unique<views::View>());
- // Data view takes the rest of the host view.
- layout_manager->SetFlexForView(data, 1, /*use_min_size=*/false);
- // Setup header.
- header_view_->tab_strip()->AddTabButton(HUDDisplayMode::CPU, u"CPU");
- header_view_->tab_strip()->AddTabButton(HUDDisplayMode::MEMORY, u"RAM");
- header_view_->tab_strip()->AddTabButton(HUDDisplayMode::FPS, u"FPS");
- // Setup data.
- data->SetBackground(views::CreateSolidBackground(kHUDBackground));
- data->SetBorder(views::CreateEmptyBorder(
- gfx::Insets::TLBR(kHUDHeaderMargin, kHUDInset, kHUDInset, kHUDInset)));
- // We have two child views z-stacked.
- // The bottom one is GraphsContainerView with all the graph lines.
- // The top one is settings UI overlay.
- data->SetLayoutManager(std::make_unique<views::FillLayout>());
- graphs_container_ =
- data->AddChildView(std::make_unique<GraphsContainerView>());
- settings_view_ = data->AddChildView(std::make_unique<HUDSettingsView>(this));
- settings_view_->SetVisible(false);
- // CPU display is active by default.
- SetDisplayMode(HUDDisplayMode::CPU);
- }
- HUDDisplayView::~HUDDisplayView() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
- }
- // There is only one button.
- void HUDDisplayView::OnSettingsToggle() {
- gfx::Rect bounds = g_hud_widget->GetWindowBoundsInScreen();
- // Here we are checking the settings visibility before we toggle it. We must
- // keep in mind that it is the opposite of what it will be.
- bounds.set_height(settings_view_->GetVisible()
- ? kHUDHeightWithGraph
- : kHUDFrameHeight +
- settings_view_->GetPreferredSize().height());
- g_hud_widget->SetBounds(bounds);
- settings_view_->ToggleVisibility();
- graphs_container_->SetVisible(!settings_view_->GetVisible());
- }
- bool HUDDisplayView::IsOverlay() {
- return static_cast<ViewTreeHostRootView*>(GetWidget()->GetRootView())
- ->GetIsOverlayCandidate();
- }
- void HUDDisplayView::ToggleOverlay() {
- g_hud_overlay_mode = !g_hud_overlay_mode;
- static_cast<ViewTreeHostRootView*>(GetWidget()->GetRootView())
- ->SetIsOverlayCandidate(g_hud_overlay_mode);
- }
- // static
- HUDDisplayView* HUDDisplayView::GetForTesting() {
- if (!g_hud_widget)
- return nullptr;
- HTClientView* client_view =
- static_cast<HTClientView*>(g_hud_widget->client_view());
- if (!client_view)
- return nullptr;
- return client_view->GetHUDDisplayViewForTesting(); // IN-TEST
- }
- HUDSettingsView* HUDDisplayView::GetSettingsViewForTesting() {
- return settings_view_;
- }
- void HUDDisplayView::ToggleSettingsForTesting() {
- OnSettingsToggle();
- }
- int HUDDisplayView::NonClientHitTest(const gfx::Point& point) {
- const View* view = GetEventHandlerForPoint(point);
- if (!view)
- return HTNOWHERE;
- return view->GetProperty(kHUDClickHandler);
- }
- void HUDDisplayView::SetDisplayMode(HUDDisplayMode display_mode) {
- graphs_container_->SetMode(display_mode);
- header_view_->tab_strip()->ActivateTab(display_mode);
- }
- } // namespace hud_display
- } // namespace ash
|