Commit fefc6c1f authored by Alexander Alekseev's avatar Alexander Alekseev Committed by Commit Bot

Ash HUD: Show CPU usage graph in Ash debug HUD averlay.

This CL adds CPU usage graph to the Ash HUD overlay:
  Gray - Idle
  Blue - User
  Red - System
  Magenta - Other

Internally this Cl adds support for switching between graphs (CPU and RAM).

Bug: 1085713, 1101715
Change-Id: I6ea1a07d77122c160ddb2229eb6ce5eb4cc829bf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2355553Reviewed-by: default avatarAlexander Alekseev <alemate@chromium.org>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Commit-Queue: Alexander Alekseev <alemate@chromium.org>
Cr-Commit-Position: refs/heads/master@{#799566}
parent ad7f580a
...@@ -460,10 +460,16 @@ component("ash") { ...@@ -460,10 +460,16 @@ component("ash") {
"host/root_window_transformer.h", "host/root_window_transformer.h",
"host/transformer_helper.cc", "host/transformer_helper.cc",
"host/transformer_helper.h", "host/transformer_helper.h",
"hud_display/cpu_graph_page_view.cc",
"hud_display/cpu_graph_page_view.h",
"hud_display/cpu_status.cc",
"hud_display/cpu_status.h",
"hud_display/data_source.cc", "hud_display/data_source.cc",
"hud_display/data_source.h", "hud_display/data_source.h",
"hud_display/graph.cc", "hud_display/graph.cc",
"hud_display/graph.h", "hud_display/graph.h",
"hud_display/graph_page_view_base.cc",
"hud_display/graph_page_view_base.h",
"hud_display/graphs_container_view.cc", "hud_display/graphs_container_view.cc",
"hud_display/graphs_container_view.h", "hud_display/graphs_container_view.h",
"hud_display/hud_constants.h", "hud_display/hud_constants.h",
...@@ -475,6 +481,8 @@ component("ash") { ...@@ -475,6 +481,8 @@ component("ash") {
"hud_display/hud_properties.h", "hud_display/hud_properties.h",
"hud_display/hud_settings_view.cc", "hud_display/hud_settings_view.cc",
"hud_display/hud_settings_view.h", "hud_display/hud_settings_view.h",
"hud_display/memory_graph_page_view.cc",
"hud_display/memory_graph_page_view.h",
"hud_display/memory_status.cc", "hud_display/memory_status.cc",
"hud_display/memory_status.h", "hud_display/memory_status.h",
"hud_display/tab_strip.cc", "hud_display/tab_strip.cc",
......
// 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/cpu_graph_page_view.h"
#include <numeric>
#include "ash/hud_display/hud_constants.h"
#include "ui/gfx/canvas.h"
namespace ash {
namespace hud_display {
////////////////////////////////////////////////////////////////////////////////
// CpuGraphPageView, public:
BEGIN_METADATA(CpuGraphPageView)
METADATA_PARENT_CLASS(GraphPageViewBase)
END_METADATA()
CpuGraphPageView::CpuGraphPageView()
: cpu_other_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::SOLID,
SkColorSetA(SK_ColorMAGENTA, kHUDAlpha)),
cpu_system_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::SOLID,
SkColorSetA(SK_ColorRED, kHUDAlpha)),
cpu_user_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::SOLID,
SkColorSetA(SK_ColorBLUE, kHUDAlpha)),
cpu_idle_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::SOLID,
SkColorSetA(SK_ColorDKGRAY, kHUDAlpha)) {}
CpuGraphPageView::~CpuGraphPageView() = default;
////////////////////////////////////////////////////////////////////////////////
void CpuGraphPageView::OnPaint(gfx::Canvas* canvas) {
// TODO: Should probably update last graph point more often than shift graph.
// Layout graphs.
const gfx::Rect rect = GetContentsBounds();
cpu_other_.Layout(rect, nullptr /* base*/);
cpu_system_.Layout(rect, &cpu_other_);
cpu_user_.Layout(rect, &cpu_system_);
cpu_idle_.Layout(rect, &cpu_user_);
// Paint damaged area now that all parameters have been determined.
cpu_other_.Draw(canvas);
cpu_system_.Draw(canvas);
cpu_user_.Draw(canvas);
cpu_idle_.Draw(canvas);
}
void CpuGraphPageView::UpdateData(const DataSource::Snapshot& snapshot) {
// TODO: Should probably update last graph point more often than shift graph.
const float total = snapshot.cpu_idle_part + snapshot.cpu_user_part +
snapshot.cpu_system_part + snapshot.cpu_other_part;
// Nothing to do if data is not available yet (sum < 1%).
if (total < 0.01)
return;
// Assume total already equals 1, no need to re-weight.
// Update graph data.
cpu_other_.AddValue(snapshot.cpu_other_part);
cpu_system_.AddValue(snapshot.cpu_system_part);
cpu_user_.AddValue(snapshot.cpu_user_part);
cpu_idle_.AddValue(snapshot.cpu_idle_part);
}
} // namespace hud_display
} // namespace ash
// 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.
#ifndef ASH_HUD_DISPLAY_CPU_GRAPH_PAGE_VIEW_H_
#define ASH_HUD_DISPLAY_CPU_GRAPH_PAGE_VIEW_H_
#include "ash/hud_display/graph.h"
#include "ash/hud_display/graph_page_view_base.h"
namespace ash {
namespace hud_display {
// Draws CPU graphs;
class CpuGraphPageView : public GraphPageViewBase {
public:
METADATA_HEADER(CpuGraphPageView);
CpuGraphPageView();
CpuGraphPageView(const CpuGraphPageView&) = delete;
CpuGraphPageView& operator=(const CpuGraphPageView&) = delete;
~CpuGraphPageView() override;
// view::
void OnPaint(gfx::Canvas* canvas) override;
// Update page data from the new snapshot.
void UpdateData(const DataSource::Snapshot& snapshot) override;
private:
// Stacked, percent of CPU ticks per interval:
Graph cpu_other_;
Graph cpu_system_;
Graph cpu_user_;
Graph cpu_idle_;
};
} // namespace hud_display
} // namespace ash
#endif // ASH_HUD_DISPLAY_CPU_GRAPH_PAGE_VIEW_H_
// 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/cpu_status.h"
#include <cinttypes>
#include <cstdio>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/notreached.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
namespace ash {
namespace hud_display {
namespace {
constexpr char kProcStatFile[] = "/proc/stat";
std::string ReadProcFile(const base::FilePath& path) {
// Synchronously reading files in /proc and /sys are safe.
base::ThreadRestrictions::ScopedAllowIO allow_io;
std::string result;
base::ReadFileToString(path, &result);
return result;
}
} // namespace
CpuStats GetProcStatCPU() {
const std::string stat = ReadProcFile(base::FilePath(kProcStatFile));
// First string should be total Cpu statistics.
if (!base::StartsWith(stat, "cpu ", base::CompareCase::SENSITIVE)) {
NOTREACHED();
return CpuStats();
}
const size_t newline_pos = stat.find('\n');
if (newline_pos == std::string::npos) {
NOTREACHED();
return CpuStats();
}
// Parse first line only.
// Format is described in [man 5 proc] and in kernel source proc/stat.c .
// https://github.com/torvalds/linux/blob/master/fs/proc/stat.c#L150-L160
CpuStats stats;
int assigned =
sscanf(stat.c_str(),
"cpu %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64
" %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 "",
&stats.user, &stats.nice, &stats.system, &stats.idle,
&stats.iowait, &stats.irq, &stats.softirq, &stats.steal,
&stats.guest, &stats.guest_nice);
DCHECK_EQ(assigned, 10);
return stats;
}
} // namespace hud_display
} // namespace ash
// 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.
#ifndef ASH_HUD_DISPLAY_CPU_STATUS_H_
#define ASH_HUD_DISPLAY_CPU_STATUS_H_
#include <cstdint>
namespace ash {
namespace hud_display {
// All CPU entries from /proc/stat.
struct CpuStats {
// These are the raw values read from /proc/stat, so as noted below,
// their interpretation depends on the architechture. But we are using them
// to plot relative values (0% - 100%) and thus the absolute values are not
// important.
// [man 5 proc]: Time, measured in units of USER_HZ (1/100ths of a second on
// most architectures, use sysconf(_SC_CLK_TCK) to obtain the right value).
uint64_t user; // Time spent in user mode.
uint64_t nice; // Time spent in user mode with low priority (nice)
uint64_t system; // Time spent in system mode.
uint64_t idle; // Time spent in the idle task. (follows /proc/uptme)
uint64_t iowait; // Time waiting for I/O to complete. Not reliable.
uint64_t irq; // Time servicing interrupts.
uint64_t softirq; // Time servicing softirqs.
uint64_t steal; // Stolen time, which is the time spent in other operating
// systems when running in a virtualized environment.
uint64_t guest; // Time spent running a virtual CPU for guest operating
// systems under the control of the Linux kernel.
uint64_t guest_nice; // Time spent running a niced guest (virtual CPU for
// guest operating systems under the control of the
// Linux kernel).
};
// Parses current /proc/stat and restuns current values.
CpuStats GetProcStatCPU();
} // namespace hud_display
} // namespace ash
#endif // ASH_HUD_DISPLAY_CPU_STATUS_H_
...@@ -25,6 +25,44 @@ int64_t EstimatePhysicalRAMSize(int64_t total_ram) { ...@@ -25,6 +25,44 @@ int64_t EstimatePhysicalRAMSize(int64_t total_ram) {
} }
return total_ram; return total_ram;
} }
// Calculates counter difference with respect to overflow.
CpuStats Delta(const CpuStats& newer, const CpuStats& older) {
static_assert(sizeof(CpuStats) == sizeof(uint64_t) * 10,
"This method should be updated when CpuStats is changed.");
// Calculates (left - right) assuming |left| and |right| are increasing
// unsigned counters with respect to possible counter overflow.
auto minus = [](const size_t& left, const size_t right) {
return left > right ? (left - right)
: (left + (std::numeric_limits<size_t>::max() - right));
};
CpuStats result;
result.user = minus(newer.user, older.user);
result.nice = minus(newer.nice, older.nice);
result.system = minus(newer.system, older.system);
result.idle = minus(newer.idle, older.idle);
result.iowait = minus(newer.iowait, older.iowait);
result.irq = minus(newer.irq, older.irq);
result.softirq = minus(newer.softirq, older.softirq);
result.steal = minus(newer.steal, older.steal);
result.guest = minus(newer.guest, older.guest);
result.guest_nice = minus(newer.guest_nice, older.guest_nice);
return result;
}
// Returns sum of all entries. This is useful for deltas to calculate
// percentage.
size_t Sum(const CpuStats& stats) {
static_assert(sizeof(CpuStats) == sizeof(uint64_t) * 10,
"This method should be updated when CpuStats is changed.");
return stats.user + stats.nice + stats.system + stats.idle + stats.iowait +
stats.irq + stats.softirq + stats.steal + stats.guest +
stats.guest_nice;
}
} // anonymous namespace } // anonymous namespace
// -------------------------------- // --------------------------------
...@@ -35,7 +73,11 @@ int64_t EstimatePhysicalRAMSize(int64_t total_ram) { ...@@ -35,7 +73,11 @@ int64_t EstimatePhysicalRAMSize(int64_t total_ram) {
DataSource::Snapshot::Snapshot() = default; DataSource::Snapshot::Snapshot() = default;
DataSource::Snapshot::Snapshot(const Snapshot&) = default; DataSource::Snapshot::Snapshot(const Snapshot&) = default;
DataSource::DataSource() = default; DataSource::DataSource() {
cpu_stats_base_ = {0};
cpu_stats_latest_ = {0};
}
DataSource::~DataSource() = default; DataSource::~DataSource() = default;
DataSource::Snapshot DataSource::GetSnapshotAndReset() { DataSource::Snapshot DataSource::GetSnapshotAndReset() {
...@@ -43,6 +85,27 @@ DataSource::Snapshot DataSource::GetSnapshotAndReset() { ...@@ -43,6 +85,27 @@ DataSource::Snapshot DataSource::GetSnapshotAndReset() {
Refresh(); Refresh();
Snapshot snapshot = GetSnapshot(); Snapshot snapshot = GetSnapshot();
if (cpu_stats_base_.user > 0) {
// Calculate CPU graph values for the last interval.
CpuStats cpu_stats_delta = Delta(cpu_stats_latest_, cpu_stats_base_);
const double cpu_ticks_total = Sum(cpu_stats_delta);
// Makes sure that the given value is between 0 and 1 and converts to
// float.
auto to_0_1 = [](const double& value) -> float {
return std::min(1.0f, std::max(0.0f, static_cast<float>(value)));
};
snapshot.cpu_idle_part = cpu_stats_delta.idle / cpu_ticks_total;
snapshot.cpu_user_part =
(cpu_stats_delta.user + cpu_stats_delta.nice) / cpu_ticks_total;
snapshot.cpu_system_part = cpu_stats_delta.system / cpu_ticks_total;
// The remaining part is "other".
snapshot.cpu_other_part =
to_0_1(1 - snapshot.cpu_idle_part - snapshot.cpu_user_part -
snapshot.cpu_system_part);
}
ResetCounters(); ResetCounters();
return snapshot; return snapshot;
} }
...@@ -53,6 +116,9 @@ DataSource::Snapshot DataSource::GetSnapshot() const { ...@@ -53,6 +116,9 @@ DataSource::Snapshot DataSource::GetSnapshot() const {
void DataSource::ResetCounters() { void DataSource::ResetCounters() {
snapshot_ = Snapshot(); snapshot_ = Snapshot();
cpu_stats_base_ = cpu_stats_latest_;
cpu_stats_latest_ = {0};
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
...@@ -83,6 +149,8 @@ void DataSource::Refresh() { ...@@ -83,6 +149,8 @@ void DataSource::Refresh() {
snapshot_.gpu_rss = std::max(snapshot_.gpu_rss, memory_status.gpu_rss()); snapshot_.gpu_rss = std::max(snapshot_.gpu_rss, memory_status.gpu_rss());
snapshot_.gpu_kernel = snapshot_.gpu_kernel =
std::max(snapshot_.gpu_kernel, memory_status.gpu_kernel()); std::max(snapshot_.gpu_kernel, memory_status.gpu_kernel());
cpu_stats_latest_ = GetProcStatCPU();
} }
} // namespace hud_display } // namespace hud_display
......
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
#define ASH_HUD_DISPLAY_DATA_SOURCE_H_ #define ASH_HUD_DISPLAY_DATA_SOURCE_H_
#include <cstdint> #include <cstdint>
#include <limits> #include <limits>
#include "ash/hud_display/cpu_status.h"
namespace ash { namespace ash {
namespace hud_display { namespace hud_display {
...@@ -44,13 +44,19 @@ class DataSource { ...@@ -44,13 +44,19 @@ class DataSource {
int64_t renderers_rss = 0; int64_t renderers_rss = 0;
// Amount of RSS Shared memory used by Chrome type=renderer processes. // Amount of RSS Shared memory used by Chrome type=renderer processes.
int64_t renderers_rss_shared = 0; int64_t renderers_rss_shared = 0;
// CPU stats are calculated only in GetSnapshotAndReset().
// CPU usage values should sum to 1.
float cpu_idle_part = 0; // Amount spent in idle state.
float cpu_user_part = 0; // Amount spent in user + nice mode.
float cpu_system_part = 0; // Amount spent in system mode.
float cpu_other_part = 0; // Other states: irq, etc.
}; };
DataSource(); DataSource();
~DataSource();
DataSource(const DataSource&) = delete; DataSource(const DataSource&) = delete;
DataSource& operator=(const DataSource&) = delete; DataSource& operator=(const DataSource&) = delete;
~DataSource();
Snapshot GetSnapshotAndReset(); Snapshot GetSnapshotAndReset();
...@@ -62,6 +68,12 @@ class DataSource { ...@@ -62,6 +68,12 @@ class DataSource {
// Current system snapshot. // Current system snapshot.
Snapshot snapshot_; Snapshot snapshot_;
// Last CPU stats snapshot.
CpuStats cpu_stats_latest_;
// Last stats before Reset() to calculate delta.
CpuStats cpu_stats_base_;
}; };
} // namespace hud_display } // namespace hud_display
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <vector> #include <vector>
#include "ash/hud_display/hud_constants.h"
#include "base/containers/ring_buffer.h" #include "base/containers/ring_buffer.h"
#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point.h"
...@@ -21,11 +22,10 @@ namespace hud_display { ...@@ -21,11 +22,10 @@ namespace hud_display {
class Graph { class Graph {
public: public:
// Graph screen size (that is passed in Layout()) should match (ring buffer // Graph screen size (that is used in Layout()) should match (ring buffer
// size - 1) to prevent scaling, because RingBuffer always keeps one element // size - 1) to prevent scaling, because RingBuffer always keeps one element
// unused. // unused.
static constexpr size_t kDefaultWidth = 190; using Data = base::RingBuffer<float, kDefaultGraphWidth + 1>;
using Data = base::RingBuffer<float, kDefaultWidth + 1>;
enum class Baseline { enum class Baseline {
BASELINE_BOTTOM, // Positive values will be drawn from the bottom border BASELINE_BOTTOM, // Positive values will be drawn from the bottom border
......
// 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/graph_page_view_base.h"
namespace ash {
namespace hud_display {
BEGIN_METADATA(GraphPageViewBase)
METADATA_PARENT_CLASS(View)
END_METADATA()
GraphPageViewBase::GraphPageViewBase() {
DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
}
GraphPageViewBase::~GraphPageViewBase() {
DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
}
} // namespace hud_display
} // namespace ash
// 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.
#ifndef ASH_HUD_DISPLAY_GRAPH_PAGE_VIEW_BASE_H_
#define ASH_HUD_DISPLAY_GRAPH_PAGE_VIEW_BASE_H_
#include "ash/hud_display/data_source.h"
#include "base/sequence_checker.h"
#include "ui/views/view.h"
namespace ash {
namespace hud_display {
// Interface for a single graph page.
class GraphPageViewBase : public views::View {
public:
METADATA_HEADER(GraphPageViewBase);
GraphPageViewBase();
GraphPageViewBase(const GraphPageViewBase&) = delete;
GraphPageViewBase& operator=(const GraphPageViewBase&) = delete;
~GraphPageViewBase() override;
// Update page data from the new snapshot.
virtual void UpdateData(const DataSource::Snapshot& snapshot) = 0;
private:
SEQUENCE_CHECKER(ui_sequence_checker_);
};
} // namespace hud_display
} // namespace ash
#endif // ASH_HUD_DISPLAY_GRAPH_PAGE_VIEW_BASE_H_
...@@ -6,10 +6,12 @@ ...@@ -6,10 +6,12 @@
#include <numeric> #include <numeric>
#include "ash/hud_display/cpu_graph_page_view.h"
#include "ash/hud_display/hud_constants.h" #include "ash/hud_display/hud_constants.h"
#include "ash/hud_display/memory_graph_page_view.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/task/post_task.h" #include "base/task/post_task.h"
#include "ui/gfx/canvas.h" #include "ui/views/layout/fill_layout.h"
namespace ash { namespace ash {
namespace hud_display { namespace hud_display {
...@@ -28,33 +30,19 @@ BEGIN_METADATA(GraphsContainerView) ...@@ -28,33 +30,19 @@ BEGIN_METADATA(GraphsContainerView)
METADATA_PARENT_CLASS(View) METADATA_PARENT_CLASS(View)
END_METADATA() END_METADATA()
GraphsContainerView::GraphsContainerView() GraphsContainerView::GraphsContainerView() {
: graph_chrome_rss_private_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::SOLID,
SkColorSetA(SK_ColorRED, kHUDAlpha)),
graph_mem_free_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::NONE,
SkColorSetA(SK_ColorDKGRAY, kHUDAlpha)),
graph_mem_used_unknown_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::SOLID,
SkColorSetA(SK_ColorLTGRAY, kHUDAlpha)),
graph_renderers_rss_private_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::SOLID,
SkColorSetA(SK_ColorCYAN, kHUDAlpha)),
graph_arc_rss_private_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::SOLID,
SkColorSetA(SK_ColorMAGENTA, kHUDAlpha)),
graph_gpu_rss_private_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::SOLID,
SkColorSetA(SK_ColorRED, kHUDAlpha)),
graph_gpu_kernel_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::SOLID,
SkColorSetA(SK_ColorYELLOW, kHUDAlpha)),
graph_chrome_rss_shared_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::NONE,
SkColorSetA(SK_ColorBLUE, kHUDAlpha)) {
DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
// Make all graph pages take the whole view and make sure that only one
// is shown at a time.
SetLayoutManager(std::make_unique<views::FillLayout>());
// Adds another graphs page.
AddChildView(std::make_unique<MemoryGraphPageView>())
->SetID(static_cast<int>(DisplayMode::MEMORY_DISPLAY));
AddChildView(std::make_unique<CpuGraphPageView>())
->SetID(static_cast<int>(DisplayMode::CPU_DISPLAY));
refresh_timer_.Start(FROM_HERE, kGraphsDataRefreshInterval, this, refresh_timer_.Start(FROM_HERE, kGraphsDataRefreshInterval, this,
&GraphsContainerView::UpdateData); &GraphsContainerView::UpdateData);
} }
...@@ -63,86 +51,24 @@ GraphsContainerView::~GraphsContainerView() { ...@@ -63,86 +51,24 @@ GraphsContainerView::~GraphsContainerView() {
DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_);
} }
////////////////////////////////////////////////////////////////////////////////
void GraphsContainerView::OnPaint(gfx::Canvas* canvas) {
// TODO: Should probably update last graph point more often than shift graph.
// Layout graphs.
const gfx::Rect rect = GetContentsBounds();
graph_chrome_rss_private_.Layout(rect, nullptr /* base*/);
graph_mem_free_.Layout(rect, &graph_chrome_rss_private_);
graph_mem_used_unknown_.Layout(rect, &graph_mem_free_);
graph_renderers_rss_private_.Layout(rect, &graph_mem_used_unknown_);
graph_arc_rss_private_.Layout(rect, &graph_renderers_rss_private_);
graph_gpu_rss_private_.Layout(rect, &graph_arc_rss_private_);
graph_gpu_kernel_.Layout(rect, &graph_gpu_rss_private_);
// Not stacked.
graph_chrome_rss_shared_.Layout(rect, nullptr /* base*/);
// Paint damaged area now that all parameters have been determined.
graph_chrome_rss_private_.Draw(canvas);
graph_mem_free_.Draw(canvas);
graph_mem_used_unknown_.Draw(canvas);
graph_renderers_rss_private_.Draw(canvas);
graph_arc_rss_private_.Draw(canvas);
graph_gpu_rss_private_.Draw(canvas);
graph_gpu_kernel_.Draw(canvas);
graph_chrome_rss_shared_.Draw(canvas);
}
void GraphsContainerView::UpdateData() { void GraphsContainerView::UpdateData() {
// TODO: Should probably update last graph point more often than shift graph.
const DataSource::Snapshot snapshot = data_source_.GetSnapshotAndReset(); const DataSource::Snapshot snapshot = data_source_.GetSnapshotAndReset();
for (auto* child : children())
static_cast<GraphPageViewBase*>(child)->UpdateData(snapshot);
SchedulePaint();
}
const double total = snapshot.total_ram; void GraphsContainerView::SetMode(DisplayMode mode) {
// Nothing to do if data is not available yet. auto* selected = GetViewByID(static_cast<int>(mode));
if (total < 1) if (!selected) {
DCHECK(selected);
return; return;
}
for (auto* child : children())
child->SetVisible(false);
const float chrome_rss_private = selected->SetVisible(true);
(snapshot.browser_rss - snapshot.browser_rss_shared) / total;
const float mem_free = snapshot.free_ram / total;
// mem_used_unknown is calculated below.
const float renderers_rss_private =
(snapshot.renderers_rss - snapshot.renderers_rss_shared) / total;
const float arc_rss_private =
(snapshot.arc_rss - snapshot.arc_rss_shared) / total;
const float gpu_rss_private =
(snapshot.gpu_rss - snapshot.gpu_rss_shared) / total;
const float gpu_kernel = snapshot.gpu_kernel / total;
// not stacked.
const float chrome_rss_shared = snapshot.browser_rss_shared / total;
std::vector<float> used_buckets;
used_buckets.push_back(chrome_rss_private);
used_buckets.push_back(mem_free);
used_buckets.push_back(renderers_rss_private);
used_buckets.push_back(arc_rss_private);
used_buckets.push_back(gpu_rss_private);
used_buckets.push_back(gpu_kernel);
float mem_used_unknown =
1 - std::accumulate(used_buckets.begin(), used_buckets.end(), 0.0f);
if (mem_used_unknown < 0)
LOG(WARNING) << "mem_used_unknown=" << mem_used_unknown << " < 0 !";
// Update graph data.
graph_chrome_rss_private_.AddValue(chrome_rss_private);
graph_mem_free_.AddValue(mem_free);
graph_mem_used_unknown_.AddValue(std::max(mem_used_unknown, 0.0f));
graph_renderers_rss_private_.AddValue(renderers_rss_private);
graph_arc_rss_private_.AddValue(arc_rss_private);
graph_gpu_rss_private_.AddValue(gpu_rss_private);
graph_gpu_kernel_.AddValue(gpu_kernel);
// Not stacked.
graph_chrome_rss_shared_.AddValue(chrome_rss_shared);
if (GetVisible())
SchedulePaint();
} }
} // namespace hud_display } // namespace hud_display
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#define ASH_HUD_DISPLAY_GRAPHS_CONTAINER_VIEW_H_ #define ASH_HUD_DISPLAY_GRAPHS_CONTAINER_VIEW_H_
#include "ash/hud_display/data_source.h" #include "ash/hud_display/data_source.h"
#include "ash/hud_display/graph.h" #include "ash/hud_display/graph_page_view_base.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "ui/views/view.h" #include "ui/views/view.h"
...@@ -14,48 +14,29 @@ ...@@ -14,48 +14,29 @@
namespace ash { namespace ash {
namespace hud_display { namespace hud_display {
enum class DisplayMode;
// GraphsContainerView class draws a bunch of graphs. // GraphsContainerView class draws a bunch of graphs.
class GraphsContainerView : public views::View { class GraphsContainerView : public views::View {
public: public:
METADATA_HEADER(GraphsContainerView); METADATA_HEADER(GraphsContainerView);
GraphsContainerView(); GraphsContainerView();
~GraphsContainerView() override;
GraphsContainerView(const GraphsContainerView&) = delete; GraphsContainerView(const GraphsContainerView&) = delete;
GraphsContainerView& operator=(const GraphsContainerView&) = delete; GraphsContainerView& operator=(const GraphsContainerView&) = delete;
~GraphsContainerView() override;
// view::
void OnPaint(gfx::Canvas* canvas) override;
// Synchrnously reads system counters and updates data. // Synchrnously reads system counters and updates data.
void UpdateData(); void UpdateData();
// Updates graphs display to match given mode.
void SetMode(DisplayMode mode);
private: private:
// HUD is updatd with new data every tick. // HUD is updatd with new data every tick.
base::RepeatingTimer refresh_timer_; base::RepeatingTimer refresh_timer_;
// --- Stacked: // Source of graphs data.
// Share of the total RAM occupied by Chrome browser private RSS.
Graph graph_chrome_rss_private_;
// Share of the total RAM reported as Free memory be kernel.
Graph graph_mem_free_;
// Total RAM - other graphs in this stack.
Graph graph_mem_used_unknown_;
// Share of the total RAM occupied by Chrome type=renderer processes private
// RSS.
Graph graph_renderers_rss_private_;
// Share of the total RAM occupied by ARC++ processes private RSS.
Graph graph_arc_rss_private_;
// Share of the total RAM occupied by Chrome type=gpu process private RSS.
Graph graph_gpu_rss_private_;
// Share of the total RAM used by kernel GPU driver.
Graph graph_gpu_kernel_;
// Not stacked:
// Share of the total RAM occupied by Chrome browser process shared RSS.
Graph graph_chrome_rss_shared_;
DataSource data_source_; DataSource data_source_;
SEQUENCE_CHECKER(ui_sequence_checker_); SEQUENCE_CHECKER(ui_sequence_checker_);
......
...@@ -33,10 +33,15 @@ constexpr int kHUDSettingsIconSize = 18; ...@@ -33,10 +33,15 @@ constexpr int kHUDSettingsIconSize = 18;
// where needed. // where needed.
constexpr int kHUDInset = 5; constexpr int kHUDInset = 5;
// Defines both the pixel width of the graphs and the amount of data stored
// in each graph ring buffer.
static constexpr size_t kDefaultGraphWidth = 190;
// HUD display modes. // HUD display modes.
enum class DisplayModes { enum class DisplayMode {
CPU_DISPLAY =
1, // First value should be different from default Views::ID = 0.
MEMORY_DISPLAY, MEMORY_DISPLAY,
DEFAULT = MEMORY_DISPLAY
}; };
} // namespace hud_display } // namespace hud_display
......
...@@ -96,7 +96,7 @@ void HUDDisplayView::Toggle() { ...@@ -96,7 +96,7 @@ void HUDDisplayView::Toggle() {
kShellWindowId_OverlayContainer); kShellWindowId_OverlayContainer);
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.bounds = params.bounds =
gfx::Rect(Graph::kDefaultWidth + 2 * kHUDInset, kHUDViewDefaultHeight); gfx::Rect(kDefaultGraphWidth + 2 * kHUDInset, kHUDViewDefaultHeight);
auto* widget = CreateViewTreeHostWidget(std::move(params)); auto* widget = CreateViewTreeHostWidget(std::move(params));
widget->GetLayer()->SetName("HUDDisplayView"); widget->GetLayer()->SetName("HUDDisplayView");
widget->Show(); widget->Show();
...@@ -132,8 +132,10 @@ HUDDisplayView::HUDDisplayView() { ...@@ -132,8 +132,10 @@ HUDDisplayView::HUDDisplayView() {
// Setup header. // Setup header.
// TODO: Add tab buttons via: // TODO: Add tab buttons via:
// header_view_->tab_strip()->AddTabButton(this, DisplayModes::MEMORY_DISPLAY, header_view_->tab_strip()->AddTabButton(this, DisplayMode::CPU_DISPLAY,
// base::ASCIIToUTF16("RAM")); base::ASCIIToUTF16("CPU"));
header_view_->tab_strip()->AddTabButton(this, DisplayMode::MEMORY_DISPLAY,
base::ASCIIToUTF16("RAM"));
// Setup data. // Setup data.
data->SetBackground(views::CreateSolidBackground(kHUDBackground)); data->SetBackground(views::CreateSolidBackground(kHUDBackground));
...@@ -148,6 +150,9 @@ HUDDisplayView::HUDDisplayView() { ...@@ -148,6 +150,9 @@ HUDDisplayView::HUDDisplayView() {
data->AddChildView(std::make_unique<GraphsContainerView>()); data->AddChildView(std::make_unique<GraphsContainerView>());
settings_view_ = data->AddChildView(std::make_unique<HUDSettingsView>()); settings_view_ = data->AddChildView(std::make_unique<HUDSettingsView>());
settings_view_->SetVisible(false); settings_view_->SetVisible(false);
// CPU display is active by default.
SetDisplayMode(DisplayMode::CPU_DISPLAY);
} }
HUDDisplayView::~HUDDisplayView() { HUDDisplayView::~HUDDisplayView() {
...@@ -162,9 +167,9 @@ int HUDDisplayView::NonClientHitTest(const gfx::Point& point) { ...@@ -162,9 +167,9 @@ int HUDDisplayView::NonClientHitTest(const gfx::Point& point) {
return view->GetProperty(kHUDClickHandler); return view->GetProperty(kHUDClickHandler);
} }
void HUDDisplayView::TabButtonPressed(const HUDTabButton* tab_button) { void HUDDisplayView::SetDisplayMode(DisplayMode display_mode) {
header_view_->tab_strip()->ActivateTab(tab_button); graphs_container_->SetMode(display_mode);
// TODO: switch on tab_button->display_mode(). header_view_->tab_strip()->ActivateTab(display_mode);
} }
views::ClientView* HUDDisplayView::CreateClientView(views::Widget* widget) { views::ClientView* HUDDisplayView::CreateClientView(views::Widget* widget) {
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#ifndef ASH_HUD_DISPLAY_HUD_DISPLAY_H_ #ifndef ASH_HUD_DISPLAY_HUD_DISPLAY_H_
#define ASH_HUD_DISPLAY_HUD_DISPLAY_H_ #define ASH_HUD_DISPLAY_HUD_DISPLAY_H_
#include "ash/hud_display/hud_constants.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "ui/views/controls/button/button.h" #include "ui/views/controls/button/button.h"
#include "ui/views/widget/widget_delegate.h" #include "ui/views/widget/widget_delegate.h"
...@@ -13,10 +12,10 @@ ...@@ -13,10 +12,10 @@
namespace ash { namespace ash {
namespace hud_display { namespace hud_display {
enum class DisplayMode;
class GraphsContainerView; class GraphsContainerView;
class HUDHeaderView; class HUDHeaderView;
class HUDSettingsView; class HUDSettingsView;
class HUDTabButton;
// HUDDisplayView class can be used to display a system monitoring overview. // HUDDisplayView class can be used to display a system monitoring overview.
class HUDDisplayView : public views::WidgetDelegateView, class HUDDisplayView : public views::WidgetDelegateView,
...@@ -48,7 +47,7 @@ class HUDDisplayView : public views::WidgetDelegateView, ...@@ -48,7 +47,7 @@ class HUDDisplayView : public views::WidgetDelegateView,
int NonClientHitTest(const gfx::Point& point); int NonClientHitTest(const gfx::Point& point);
// Changes UI display mode. // Changes UI display mode.
void TabButtonPressed(const HUDTabButton* tab_button); void SetDisplayMode(const DisplayMode display_mode);
private: private:
HUDHeaderView* header_view_ = nullptr; // not owned HUDHeaderView* header_view_ = nullptr; // not owned
......
// 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/memory_graph_page_view.h"
#include <numeric>
#include "ash/hud_display/hud_constants.h"
#include "ui/gfx/canvas.h"
namespace ash {
namespace hud_display {
////////////////////////////////////////////////////////////////////////////////
// MemoryGraphPageView, public:
BEGIN_METADATA(MemoryGraphPageView)
METADATA_PARENT_CLASS(GraphPageViewBase)
END_METADATA()
MemoryGraphPageView::MemoryGraphPageView()
: graph_chrome_rss_private_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::SOLID,
SkColorSetA(SK_ColorRED, kHUDAlpha)),
graph_mem_free_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::NONE,
SkColorSetA(SK_ColorDKGRAY, kHUDAlpha)),
graph_mem_used_unknown_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::SOLID,
SkColorSetA(SK_ColorLTGRAY, kHUDAlpha)),
graph_renderers_rss_private_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::SOLID,
SkColorSetA(SK_ColorCYAN, kHUDAlpha)),
graph_arc_rss_private_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::SOLID,
SkColorSetA(SK_ColorMAGENTA, kHUDAlpha)),
graph_gpu_rss_private_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::SOLID,
SkColorSetA(SK_ColorRED, kHUDAlpha)),
graph_gpu_kernel_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::SOLID,
SkColorSetA(SK_ColorYELLOW, kHUDAlpha)),
graph_chrome_rss_shared_(Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::NONE,
SkColorSetA(SK_ColorBLUE, kHUDAlpha)) {}
MemoryGraphPageView::~MemoryGraphPageView() = default;
////////////////////////////////////////////////////////////////////////////////
void MemoryGraphPageView::OnPaint(gfx::Canvas* canvas) {
// TODO: Should probably update last graph point more often than shift graph.
// Layout graphs.
const gfx::Rect rect = GetContentsBounds();
graph_chrome_rss_private_.Layout(rect, /*base=*/nullptr);
graph_mem_free_.Layout(rect, &graph_chrome_rss_private_);
graph_mem_used_unknown_.Layout(rect, &graph_mem_free_);
graph_renderers_rss_private_.Layout(rect, &graph_mem_used_unknown_);
graph_arc_rss_private_.Layout(rect, &graph_renderers_rss_private_);
graph_gpu_rss_private_.Layout(rect, &graph_arc_rss_private_);
graph_gpu_kernel_.Layout(rect, &graph_gpu_rss_private_);
// Not stacked.
graph_chrome_rss_shared_.Layout(rect, /*base=*/nullptr);
// Paint damaged area now that all parameters have been determined.
graph_chrome_rss_private_.Draw(canvas);
graph_mem_free_.Draw(canvas);
graph_mem_used_unknown_.Draw(canvas);
graph_renderers_rss_private_.Draw(canvas);
graph_arc_rss_private_.Draw(canvas);
graph_gpu_rss_private_.Draw(canvas);
graph_gpu_kernel_.Draw(canvas);
graph_chrome_rss_shared_.Draw(canvas);
}
void MemoryGraphPageView::UpdateData(const DataSource::Snapshot& snapshot) {
// TODO: Should probably update last graph point more often than shift graph.
const double total = snapshot.total_ram;
// Nothing to do if data is not available yet.
if (total < 1)
return;
const float chrome_rss_private =
(snapshot.browser_rss - snapshot.browser_rss_shared) / total;
const float mem_free = snapshot.free_ram / total;
// mem_used_unknown is calculated below.
const float renderers_rss_private =
(snapshot.renderers_rss - snapshot.renderers_rss_shared) / total;
const float arc_rss_private =
(snapshot.arc_rss - snapshot.arc_rss_shared) / total;
const float gpu_rss_private =
(snapshot.gpu_rss - snapshot.gpu_rss_shared) / total;
const float gpu_kernel = snapshot.gpu_kernel / total;
// not stacked.
const float chrome_rss_shared = snapshot.browser_rss_shared / total;
std::vector<float> used_buckets;
used_buckets.push_back(chrome_rss_private);
used_buckets.push_back(mem_free);
used_buckets.push_back(renderers_rss_private);
used_buckets.push_back(arc_rss_private);
used_buckets.push_back(gpu_rss_private);
used_buckets.push_back(gpu_kernel);
float mem_used_unknown =
1 - std::accumulate(used_buckets.begin(), used_buckets.end(), 0.0f);
if (mem_used_unknown < 0)
LOG(WARNING) << "mem_used_unknown=" << mem_used_unknown << " < 0 !";
// Update graph data.
graph_chrome_rss_private_.AddValue(chrome_rss_private);
graph_mem_free_.AddValue(mem_free);
graph_mem_used_unknown_.AddValue(std::max(mem_used_unknown, 0.0f));
graph_renderers_rss_private_.AddValue(renderers_rss_private);
graph_arc_rss_private_.AddValue(arc_rss_private);
graph_gpu_rss_private_.AddValue(gpu_rss_private);
graph_gpu_kernel_.AddValue(gpu_kernel);
// Not stacked.
graph_chrome_rss_shared_.AddValue(chrome_rss_shared);
}
} // namespace hud_display
} // namespace ash
// 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.
#ifndef ASH_HUD_DISPLAY_MEMORY_GRAPH_PAGE_VIEW_H_
#define ASH_HUD_DISPLAY_MEMORY_GRAPH_PAGE_VIEW_H_
#include "ash/hud_display/graph.h"
#include "ash/hud_display/graph_page_view_base.h"
namespace ash {
namespace hud_display {
// MemoryGraphPageView class draws memory graphs.
class MemoryGraphPageView : public GraphPageViewBase {
public:
METADATA_HEADER(MemoryGraphPageView);
MemoryGraphPageView();
MemoryGraphPageView(const MemoryGraphPageView&) = delete;
MemoryGraphPageView& operator=(const MemoryGraphPageView&) = delete;
~MemoryGraphPageView() override;
// view::
void OnPaint(gfx::Canvas* canvas) override;
// Update page data from the new snapshot.
void UpdateData(const DataSource::Snapshot& snapshot) override;
private:
// --- Stacked:
// Share of the total RAM occupied by Chrome browser private RSS.
Graph graph_chrome_rss_private_;
// Share of the total RAM reported as Free memory be kernel.
Graph graph_mem_free_;
// Total RAM - other graphs in this stack.
Graph graph_mem_used_unknown_;
// Share of the total RAM occupied by Chrome type=renderer processes private
// RSS.
Graph graph_renderers_rss_private_;
// Share of the total RAM occupied by ARC++ processes private RSS.
Graph graph_arc_rss_private_;
// Share of the total RAM occupied by Chrome type=gpu process private RSS.
Graph graph_gpu_rss_private_;
// Share of the total RAM used by kernel GPU driver.
Graph graph_gpu_kernel_;
// Not stacked:
// Share of the total RAM occupied by Chrome browser process shared RSS.
Graph graph_chrome_rss_shared_;
};
} // namespace hud_display
} // namespace ash
#endif // ASH_HUD_DISPLAY_MEMORY_GRAPH_PAGE_VIEW_H_
...@@ -77,7 +77,7 @@ END_METADATA() ...@@ -77,7 +77,7 @@ END_METADATA()
HUDTabButton::HUDTabButton(Style style, HUDTabButton::HUDTabButton(Style style,
HUDTabStrip* tab_strip, HUDTabStrip* tab_strip,
const DisplayModes display_mode, const DisplayMode display_mode,
const base::string16& text) const base::string16& text)
: views::LabelButton(tab_strip, text), : views::LabelButton(tab_strip, text),
style_(style), style_(style),
...@@ -171,8 +171,9 @@ HUDTabStrip::HUDTabStrip(HUDDisplayView* hud) : hud_(hud) { ...@@ -171,8 +171,9 @@ HUDTabStrip::HUDTabStrip(HUDDisplayView* hud) : hud_(hud) {
HUDTabStrip::~HUDTabStrip() = default; HUDTabStrip::~HUDTabStrip() = default;
HUDTabButton* HUDTabStrip::AddTabButton(HUDDisplayView* hud, HUDTabButton* HUDTabStrip::AddTabButton(HUDDisplayView* hud,
const DisplayModes display_mode, const DisplayMode display_mode,
const base::string16& label) { const base::string16& label) {
CHECK_NE(static_cast<int>(display_mode), 0);
// Make first tab active by default. // Make first tab active by default.
HUDTabButton* tab_button = AddChildView(std::make_unique<HUDTabButton>( HUDTabButton* tab_button = AddChildView(std::make_unique<HUDTabButton>(
tabs_.size() ? HUDTabButton::Style::RIGHT : HUDTabButton::Style::ACTIVE, tabs_.size() ? HUDTabButton::Style::RIGHT : HUDTabButton::Style::ACTIVE,
...@@ -185,14 +186,14 @@ void HUDTabStrip::ButtonPressed(views::Button* sender, ...@@ -185,14 +186,14 @@ void HUDTabStrip::ButtonPressed(views::Button* sender,
const ui::Event& /*event*/) { const ui::Event& /*event*/) {
for (const auto* tab : tabs_) { for (const auto* tab : tabs_) {
if (tab == sender) { if (tab == sender) {
hud_->TabButtonPressed(tab); hud_->SetDisplayMode(tab->display_mode());
return; return;
} }
} }
NOTREACHED(); NOTREACHED();
} }
void HUDTabStrip::ActivateTab(const views::View* active_tab_button) { void HUDTabStrip::ActivateTab(const DisplayMode mode) {
// True if we find given active tab. // True if we find given active tab.
bool found = false; bool found = false;
...@@ -201,7 +202,7 @@ void HUDTabStrip::ActivateTab(const views::View* active_tab_button) { ...@@ -201,7 +202,7 @@ void HUDTabStrip::ActivateTab(const views::View* active_tab_button) {
tab->SetStyle(HUDTabButton::Style::RIGHT); tab->SetStyle(HUDTabButton::Style::RIGHT);
continue; continue;
} }
if (tab == active_tab_button) { if (tab->display_mode() == mode) {
found = true; found = true;
tab->SetStyle(HUDTabButton::Style::ACTIVE); tab->SetStyle(HUDTabButton::Style::ACTIVE);
continue; continue;
......
...@@ -37,7 +37,7 @@ class HUDTabButton : public views::LabelButton { ...@@ -37,7 +37,7 @@ class HUDTabButton : public views::LabelButton {
HUDTabButton(Style style, HUDTabButton(Style style,
HUDTabStrip* tab_strip, HUDTabStrip* tab_strip,
const DisplayModes display_mode, const DisplayMode display_mode,
const base::string16& text); const base::string16& text);
HUDTabButton(const HUDTabButton&) = delete; HUDTabButton(const HUDTabButton&) = delete;
HUDTabButton& operator=(const HUDTabButton&) = delete; HUDTabButton& operator=(const HUDTabButton&) = delete;
...@@ -46,7 +46,7 @@ class HUDTabButton : public views::LabelButton { ...@@ -46,7 +46,7 @@ class HUDTabButton : public views::LabelButton {
void SetStyle(Style style); void SetStyle(Style style);
DisplayModes display_mode() const { return display_mode_; } DisplayMode display_mode() const { return display_mode_; }
protected: protected:
// views::LabelButton: // views::LabelButton:
...@@ -56,7 +56,7 @@ class HUDTabButton : public views::LabelButton { ...@@ -56,7 +56,7 @@ class HUDTabButton : public views::LabelButton {
Style style_ = Style::LEFT; Style style_ = Style::LEFT;
// Tab activation sends this display mode to the HUD. // Tab activation sends this display mode to the HUD.
DisplayModes display_mode_ = DisplayModes::DEFAULT; DisplayMode display_mode_;
}; };
class HUDTabStrip : public views::View, public views::ButtonListener { class HUDTabStrip : public views::View, public views::ButtonListener {
...@@ -71,14 +71,14 @@ class HUDTabStrip : public views::View, public views::ButtonListener { ...@@ -71,14 +71,14 @@ class HUDTabStrip : public views::View, public views::ButtonListener {
~HUDTabStrip() override; ~HUDTabStrip() override;
HUDTabButton* AddTabButton(HUDDisplayView* hud, HUDTabButton* AddTabButton(HUDDisplayView* hud,
const DisplayModes display_mode, const DisplayMode display_mode,
const base::string16& label); const base::string16& label);
// views::ButtonListener // views::ButtonListener
void ButtonPressed(views::Button* sender, const ui::Event& event) override; void ButtonPressed(views::Button* sender, const ui::Event& event) override;
// Mark tabs around the active one need repaint to modify borders. // Mark tabs around the active one need repaint to modify borders.
void ActivateTab(const views::View* active_tab_button); void ActivateTab(DisplayMode mode);
private: private:
HUDDisplayView* hud_; HUDDisplayView* hud_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment