123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388 |
- // Copyright 2013 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/touch/touch_hud_debug.h"
- #include <algorithm>
- #include <string>
- #include <vector>
- #include "ash/root_window_controller.h"
- #include "ash/shell.h"
- #include "base/strings/stringprintf.h"
- #include "base/strings/utf_string_conversions.h"
- #include "third_party/skia/include/core/SkPath.h"
- #include "ui/aura/window_event_dispatcher.h"
- #include "ui/compositor/layer.h"
- #include "ui/display/display.h"
- #include "ui/display/manager/display_manager.h"
- #include "ui/events/event.h"
- #include "ui/gfx/canvas.h"
- #include "ui/gfx/color_utils.h"
- #include "ui/gfx/geometry/size.h"
- #include "ui/gfx/geometry/transform.h"
- #include "ui/gfx/geometry/vector2d.h"
- #include "ui/views/controls/label.h"
- #include "ui/views/layout/box_layout.h"
- #include "ui/views/widget/widget.h"
- namespace ash {
- const int kPointRadius = 20;
- const SkColor kColors[] = {
- SK_ColorYELLOW,
- SK_ColorGREEN,
- SK_ColorRED,
- SK_ColorBLUE,
- SK_ColorGRAY,
- SK_ColorMAGENTA,
- SK_ColorCYAN,
- SK_ColorWHITE,
- SK_ColorBLACK,
- SkColorSetRGB(0xFF, 0x8C, 0x00),
- SkColorSetRGB(0x8B, 0x45, 0x13),
- SkColorSetRGB(0xFF, 0xDE, 0xAD),
- };
- const int kAlpha = 0x60;
- const int kMaxPaths = std::size(kColors);
- const int kReducedScale = 10;
- const char* GetTouchEventLabel(ui::EventType type) {
- switch (type) {
- case ui::ET_UNKNOWN:
- return " ";
- case ui::ET_TOUCH_PRESSED:
- return "P";
- case ui::ET_TOUCH_MOVED:
- return "M";
- case ui::ET_TOUCH_RELEASED:
- return "R";
- case ui::ET_TOUCH_CANCELLED:
- return "C";
- default:
- break;
- }
- return "?";
- }
- // A TouchPointLog represents a single touch-event of a touch point.
- struct TouchPointLog {
- public:
- explicit TouchPointLog(const ui::TouchEvent& touch)
- : type(touch.type()),
- location(touch.root_location()),
- radius_x(touch.pointer_details().radius_x),
- radius_y(touch.pointer_details().radius_y) {}
- ui::EventType type;
- gfx::Point location;
- float radius_x;
- float radius_y;
- };
- // A TouchTrace keeps track of all the touch events of a single touch point
- // (starting from a touch-press and ending at a touch-release or touch-cancel).
- class TouchTrace {
- public:
- typedef std::vector<TouchPointLog>::iterator iterator;
- typedef std::vector<TouchPointLog>::const_iterator const_iterator;
- typedef std::vector<TouchPointLog>::reverse_iterator reverse_iterator;
- typedef std::vector<TouchPointLog>::const_reverse_iterator
- const_reverse_iterator;
- TouchTrace() = default;
- TouchTrace(const TouchTrace&) = delete;
- TouchTrace& operator=(const TouchTrace&) = delete;
- void AddTouchPoint(const ui::TouchEvent& touch) {
- log_.push_back(TouchPointLog(touch));
- }
- const std::vector<TouchPointLog>& log() const { return log_; }
- bool active() const {
- return !log_.empty() && log_.back().type != ui::ET_TOUCH_RELEASED &&
- log_.back().type != ui::ET_TOUCH_CANCELLED;
- }
- void Reset() { log_.clear(); }
- private:
- std::vector<TouchPointLog> log_;
- };
- // A TouchLog keeps track of all touch events of all touch points.
- class TouchLog {
- public:
- TouchLog() : next_trace_index_(0) {}
- TouchLog(const TouchLog&) = delete;
- TouchLog& operator=(const TouchLog&) = delete;
- void AddTouchPoint(const ui::TouchEvent& touch) {
- if (touch.type() == ui::ET_TOUCH_PRESSED)
- StartTrace(touch);
- AddToTrace(touch);
- }
- void Reset() {
- next_trace_index_ = 0;
- for (int i = 0; i < kMaxPaths; ++i)
- traces_[i].Reset();
- }
- int GetTraceIndex(int touch_id) const {
- return touch_id_to_trace_index_.at(touch_id);
- }
- const TouchTrace* traces() const { return traces_; }
- private:
- void StartTrace(const ui::TouchEvent& touch) {
- // Find the first inactive spot; otherwise, overwrite the one
- // |next_trace_index_| is pointing to.
- int old_trace_index = next_trace_index_;
- do {
- if (!traces_[next_trace_index_].active())
- break;
- next_trace_index_ = (next_trace_index_ + 1) % kMaxPaths;
- } while (next_trace_index_ != old_trace_index);
- int touch_id = touch.pointer_details().id;
- traces_[next_trace_index_].Reset();
- touch_id_to_trace_index_[touch_id] = next_trace_index_;
- next_trace_index_ = (next_trace_index_ + 1) % kMaxPaths;
- }
- void AddToTrace(const ui::TouchEvent& touch) {
- int touch_id = touch.pointer_details().id;
- int trace_index = touch_id_to_trace_index_[touch_id];
- traces_[trace_index].AddTouchPoint(touch);
- }
- TouchTrace traces_[kMaxPaths];
- int next_trace_index_;
- std::map<int, int> touch_id_to_trace_index_;
- };
- // TouchHudCanvas draws touch traces in |FULLSCREEN| and |REDUCED_SCALE| modes.
- class TouchHudCanvas : public views::View {
- public:
- explicit TouchHudCanvas(const TouchLog& touch_log)
- : touch_log_(touch_log), scale_(1) {
- SetPaintToLayer();
- layer()->SetFillsBoundsOpaquely(false);
- flags_.setStyle(cc::PaintFlags::kFill_Style);
- }
- TouchHudCanvas(const TouchHudCanvas&) = delete;
- TouchHudCanvas& operator=(const TouchHudCanvas&) = delete;
- ~TouchHudCanvas() override = default;
- void SetScale(int scale) {
- if (scale_ == scale)
- return;
- scale_ = scale;
- gfx::Transform transform;
- transform.Scale(1. / scale_, 1. / scale_);
- layer()->SetTransform(transform);
- }
- int scale() const { return scale_; }
- void TouchPointAdded(int touch_id) {
- int trace_index = touch_log_.GetTraceIndex(touch_id);
- const TouchTrace& trace = touch_log_.traces()[trace_index];
- const TouchPointLog& point = trace.log().back();
- if (point.type == ui::ET_TOUCH_PRESSED)
- StartedTrace(trace_index);
- if (point.type != ui::ET_TOUCH_CANCELLED)
- AddedPointToTrace(trace_index);
- }
- void Clear() {
- for (int i = 0; i < kMaxPaths; ++i)
- paths_[i].reset();
- SchedulePaint();
- }
- private:
- void StartedTrace(int trace_index) {
- paths_[trace_index].reset();
- colors_[trace_index] = SkColorSetA(kColors[trace_index], kAlpha);
- }
- void AddedPointToTrace(int trace_index) {
- const TouchTrace& trace = touch_log_.traces()[trace_index];
- const TouchPointLog& point = trace.log().back();
- const gfx::Point& location = point.location;
- SkScalar x = SkIntToScalar(location.x());
- SkScalar y = SkIntToScalar(location.y());
- SkPoint last;
- if (!paths_[trace_index].getLastPt(&last) || x != last.x() ||
- y != last.y()) {
- paths_[trace_index].addCircle(x, y, SkIntToScalar(kPointRadius));
- SchedulePaint();
- }
- }
- // Overridden from views::View.
- void OnPaint(gfx::Canvas* canvas) override {
- for (int i = 0; i < kMaxPaths; ++i) {
- if (paths_[i].countPoints() == 0)
- continue;
- flags_.setColor(colors_[i]);
- canvas->DrawPath(paths_[i], flags_);
- }
- }
- cc::PaintFlags flags_;
- const TouchLog& touch_log_;
- SkPath paths_[kMaxPaths];
- SkColor colors_[kMaxPaths];
- int scale_;
- };
- TouchHudDebug::TouchHudDebug(aura::Window* initial_root)
- : TouchObserverHud(initial_root, "TouchHudDebug"),
- mode_(FULLSCREEN),
- touch_log_(new TouchLog()),
- canvas_(new TouchHudCanvas(*touch_log_)),
- label_container_(new views::View()) {
- const display::Display& display =
- Shell::Get()->display_manager()->GetDisplayForId(display_id());
- views::View* content = widget()->GetContentsView();
- content->AddChildView(canvas_);
- const gfx::Size& display_size = display.size();
- canvas_->SetSize(display_size);
- label_container_->SetLayoutManager(std::make_unique<views::BoxLayout>(
- views::BoxLayout::Orientation::kVertical));
- constexpr SkColor kShadowColor = SK_ColorWHITE;
- const SkColor label_color =
- color_utils::GetColorWithMaxContrast(kShadowColor);
- for (int i = 0; i < kMaxTouchPoints; ++i) {
- touch_labels_[i] = new views::Label;
- touch_labels_[i]->SetEnabledColor(label_color);
- touch_labels_[i]->SetBackgroundColor(SK_ColorTRANSPARENT);
- touch_labels_[i]->SetShadows(gfx::ShadowValues(
- 1, gfx::ShadowValue(gfx::Vector2d(1, 1), 0, kShadowColor)));
- label_container_->AddChildView(touch_labels_[i]);
- }
- label_container_->SetX(0);
- label_container_->SetY(display_size.height() / kReducedScale);
- label_container_->SetSize(label_container_->GetPreferredSize());
- label_container_->SetVisible(false);
- content->AddChildView(label_container_);
- }
- TouchHudDebug::~TouchHudDebug() = default;
- void TouchHudDebug::ChangeToNextMode() {
- switch (mode_) {
- case FULLSCREEN:
- SetMode(REDUCED_SCALE);
- break;
- case REDUCED_SCALE:
- SetMode(INVISIBLE);
- break;
- case INVISIBLE:
- SetMode(FULLSCREEN);
- break;
- }
- }
- void TouchHudDebug::Clear() {
- if (widget()->IsVisible()) {
- canvas_->Clear();
- for (int i = 0; i < kMaxTouchPoints; ++i)
- touch_labels_[i]->SetText(std::u16string());
- label_container_->SetSize(label_container_->GetPreferredSize());
- }
- }
- void TouchHudDebug::SetMode(Mode mode) {
- if (mode_ == mode)
- return;
- mode_ = mode;
- switch (mode) {
- case FULLSCREEN:
- label_container_->SetVisible(false);
- canvas_->SetVisible(true);
- canvas_->SetScale(1);
- canvas_->SchedulePaint();
- widget()->Show();
- break;
- case REDUCED_SCALE:
- label_container_->SetVisible(true);
- canvas_->SetVisible(true);
- canvas_->SetScale(kReducedScale);
- canvas_->SchedulePaint();
- widget()->Show();
- break;
- case INVISIBLE:
- widget()->Hide();
- break;
- }
- }
- void TouchHudDebug::UpdateTouchPointLabel(int index) {
- int trace_index = touch_log_->GetTraceIndex(index);
- const TouchTrace& trace = touch_log_->traces()[trace_index];
- TouchTrace::const_reverse_iterator point = trace.log().rbegin();
- ui::EventType touch_status = point->type;
- float touch_radius = std::max(point->radius_x, point->radius_y);
- while (point != trace.log().rend() && point->type == ui::ET_TOUCH_CANCELLED)
- point++;
- DCHECK(point != trace.log().rend());
- gfx::Point touch_position = point->location;
- std::string string = base::StringPrintf(
- "%2d: %s %s (%.4f)", index, GetTouchEventLabel(touch_status),
- touch_position.ToString().c_str(), touch_radius);
- touch_labels_[index]->SetText(base::UTF8ToUTF16(string));
- }
- void TouchHudDebug::OnTouchEvent(ui::TouchEvent* event) {
- if (event->pointer_details().id >= kMaxTouchPoints)
- return;
- touch_log_->AddTouchPoint(*event);
- canvas_->TouchPointAdded(event->pointer_details().id);
- UpdateTouchPointLabel(event->pointer_details().id);
- label_container_->SetSize(label_container_->GetPreferredSize());
- }
- void TouchHudDebug::OnDisplayMetricsChanged(const display::Display& display,
- uint32_t metrics) {
- TouchObserverHud::OnDisplayMetricsChanged(display, metrics);
- if (display.id() != display_id() || !(metrics & DISPLAY_METRIC_BOUNDS))
- return;
- const gfx::Size& size = display.size();
- canvas_->SetSize(size);
- label_container_->SetY(size.height() / kReducedScale);
- }
- void TouchHudDebug::SetHudForRootWindowController(
- RootWindowController* controller) {
- controller->set_touch_hud_debug(this);
- }
- void TouchHudDebug::UnsetHudForRootWindowController(
- RootWindowController* controller) {
- controller->set_touch_hud_debug(NULL);
- }
- } // namespace ash
|