1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file.
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ash/touch/touch_hud_debug.h"
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ash/display/display_manager.h"
8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ash/root_window_controller.h"
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ash/shell.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/json/json_string_value_serializer.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/string_number_conversions.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/stringprintf.h"
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/utf_string_conversions.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "third_party/skia/include/core/SkPath.h"
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h"
16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event.h"
17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/animation_delegate.h"
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/canvas.h"
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/display.h"
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/size.h"
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/transform.h"
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/views/controls/label.h"
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/views/layout/box_layout.h"
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/views/widget/widget.h"
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(USE_X11)
27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <X11/extensions/XInput2.h>
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <X11/Xlib.h>
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/events/x/device_data_manager_x11.h"
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace ash {
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kPointRadius = 20;
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst SkColor kColors[] = {
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SK_ColorYELLOW,
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SK_ColorGREEN,
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SK_ColorRED,
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SK_ColorBLUE,
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SK_ColorGRAY,
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SK_ColorMAGENTA,
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SK_ColorCYAN,
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SK_ColorWHITE,
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SK_ColorBLACK,
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SkColorSetRGB(0xFF, 0x8C, 0x00),
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SkColorSetRGB(0x8B, 0x45, 0x13),
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SkColorSetRGB(0xFF, 0xDE, 0xAD),
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kAlpha = 0x60;
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kMaxPaths = arraysize(kColors);
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kReducedScale = 10;
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst char* GetTouchEventLabel(ui::EventType type) {
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (type) {
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case ui::ET_UNKNOWN:
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return " ";
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case ui::ET_TOUCH_PRESSED:
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return "P";
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case ui::ET_TOUCH_MOVED:
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return "M";
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case ui::ET_TOUCH_RELEASED:
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return "R";
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case ui::ET_TOUCH_CANCELLED:
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return "C";
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default:
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return "?";
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint GetTrackingId(const ui::TouchEvent& event) {
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!event.HasNativeEvent())
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return 0;
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(USE_XI2_MT)
76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  double tracking_id;
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (manager->GetEventData(*event.native_event(),
79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID,
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            &tracking_id)) {
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return static_cast<int>(tracking_id);
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint GetSourceDeviceId(const ui::TouchEvent& event) {
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!event.HasNativeEvent())
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return 0;
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(USE_X11)
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  XEvent* xev = event.native_event();
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return static_cast<XIDeviceEvent*>(xev->xcookie.data)->sourceid;
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// A TouchPointLog represents a single touch-event of a touch point.
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstruct TouchPointLog {
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  explicit TouchPointLog(const ui::TouchEvent& touch)
101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : id(touch.touch_id()),
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        type(touch.type()),
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        location(touch.root_location()),
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        timestamp(touch.time_stamp().InMillisecondsF()),
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        radius_x(touch.radius_x()),
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        radius_y(touch.radius_y()),
107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        pressure(touch.force()),
108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        tracking_id(GetTrackingId(touch)),
109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        source_device(GetSourceDeviceId(touch)) {
110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Populates a dictionary value with all the information about the touch
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // point.
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> GetAsDictionary() const {
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    value->SetInteger("id", id);
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    value->SetString("type", std::string(GetTouchEventLabel(type)));
119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    value->SetString("location", location.ToString());
120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    value->SetDouble("timestamp", timestamp);
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    value->SetDouble("radius_x", radius_x);
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    value->SetDouble("radius_y", radius_y);
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    value->SetDouble("pressure", pressure);
124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    value->SetInteger("tracking_id", tracking_id);
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    value->SetInteger("source_device", source_device);
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return value.Pass();
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int id;
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ui::EventType type;
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gfx::Point location;
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  double timestamp;
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  float radius_x;
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  float radius_y;
136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  float pressure;
137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int tracking_id;
138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int source_device;
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// A TouchTrace keeps track of all the touch events of a single touch point
142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// (starting from a touch-press and ending at a touch-release or touch-cancel).
143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass TouchTrace {
144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  typedef std::vector<TouchPointLog>::iterator iterator;
146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  typedef std::vector<TouchPointLog>::const_iterator const_iterator;
147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  typedef std::vector<TouchPointLog>::reverse_iterator reverse_iterator;
148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  typedef std::vector<TouchPointLog>::const_reverse_iterator
149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      const_reverse_iterator;
150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TouchTrace() {
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void AddTouchPoint(const ui::TouchEvent& touch) {
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    log_.push_back(TouchPointLog(touch));
156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const std::vector<TouchPointLog>& log() const { return log_; }
159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool active() const {
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return !log_.empty() && log_.back().type != ui::ET_TOUCH_RELEASED &&
162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        log_.back().type != ui::ET_TOUCH_CANCELLED;
163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Returns a list containing data from all events for the touch point.
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> GetAsList() const {
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::ListValue> list(new base::ListValue());
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (const_iterator i = log_.begin(); i != log_.end(); ++i)
169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      list->Append((*i).GetAsDictionary().release());
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return list.Pass();
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void Reset() {
174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    log_.clear();
175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<TouchPointLog> log_;
179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DISALLOW_COPY_AND_ASSIGN(TouchTrace);
181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// A TouchLog keeps track of all touch events of all touch points.
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass TouchLog {
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TouchLog() : next_trace_index_(0) {
187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void AddTouchPoint(const ui::TouchEvent& touch) {
190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (touch.type() == ui::ET_TOUCH_PRESSED)
191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      StartTrace(touch);
192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    AddToTrace(touch);
193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void Reset() {
196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    next_trace_index_ = 0;
197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (int i = 0; i < kMaxPaths; ++i)
198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      traces_[i].Reset();
199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> GetAsList() const {
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::ListValue> list(new base::ListValue());
203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (int i = 0; i < kMaxPaths; ++i) {
204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (!traces_[i].log().empty())
205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        list->Append(traces_[i].GetAsList().release());
206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return list.Pass();
208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int GetTraceIndex(int touch_id) const {
211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return touch_id_to_trace_index_.at(touch_id);
212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const TouchTrace* traces() const {
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return traces_;
216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void StartTrace(const ui::TouchEvent& touch) {
220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Find the first inactive spot; otherwise, overwrite the one
221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // |next_trace_index_| is pointing to.
222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int old_trace_index = next_trace_index_;
223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    do {
224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (!traces_[next_trace_index_].active())
225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        break;
226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      next_trace_index_ = (next_trace_index_ + 1) % kMaxPaths;
227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    } while (next_trace_index_ != old_trace_index);
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int touch_id = touch.touch_id();
229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    traces_[next_trace_index_].Reset();
230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    touch_id_to_trace_index_[touch_id] = next_trace_index_;
231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    next_trace_index_ = (next_trace_index_ + 1) % kMaxPaths;
232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void AddToTrace(const ui::TouchEvent& touch) {
235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int touch_id = touch.touch_id();
236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int trace_index = touch_id_to_trace_index_[touch_id];
237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    traces_[trace_index].AddTouchPoint(touch);
238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TouchTrace traces_[kMaxPaths];
241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int next_trace_index_;
242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::map<int, int> touch_id_to_trace_index_;
244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DISALLOW_COPY_AND_ASSIGN(TouchLog);
246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// TouchHudCanvas draws touch traces in |FULLSCREEN| and |REDUCED_SCALE| modes.
249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass TouchHudCanvas : public views::View {
250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  explicit TouchHudCanvas(const TouchLog& touch_log)
252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : touch_log_(touch_log),
253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        scale_(1) {
254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SetPaintToLayer(true);
255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SetFillsBoundsOpaquely(false);
256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    paint_.setStyle(SkPaint::kFill_Style);
258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual ~TouchHudCanvas() {}
261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void SetScale(int scale) {
263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (scale_ == scale)
264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return;
265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scale_ = scale;
266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    gfx::Transform transform;
267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    transform.Scale(1. / scale_, 1. / scale_);
268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    layer()->SetTransform(transform);
269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int scale() const { return scale_; }
272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void TouchPointAdded(int touch_id) {
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int trace_index = touch_log_.GetTraceIndex(touch_id);
275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const TouchTrace& trace = touch_log_.traces()[trace_index];
276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const TouchPointLog& point = trace.log().back();
277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (point.type == ui::ET_TOUCH_PRESSED)
278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      StartedTrace(trace_index);
279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (point.type != ui::ET_TOUCH_CANCELLED)
280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      AddedPointToTrace(trace_index);
281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void Clear() {
284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (int i = 0; i < kMaxPaths; ++i)
285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      paths_[i].reset();
286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SchedulePaint();
288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void StartedTrace(int trace_index) {
292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    paths_[trace_index].reset();
293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    colors_[trace_index] = SkColorSetA(kColors[trace_index], kAlpha);
294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void AddedPointToTrace(int trace_index) {
297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const TouchTrace& trace = touch_log_.traces()[trace_index];
298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const TouchPointLog& point = trace.log().back();
299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const gfx::Point& location = point.location;
300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SkScalar x = SkIntToScalar(location.x());
301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SkScalar y = SkIntToScalar(location.y());
302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SkPoint last;
303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!paths_[trace_index].getLastPt(&last) || x != last.x() ||
304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        y != last.y()) {
305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      paths_[trace_index].addCircle(x, y, SkIntToScalar(kPointRadius));
306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SchedulePaint();
307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Overridden from views::View.
311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (int i = 0; i < kMaxPaths; ++i) {
313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (paths_[i].countPoints() == 0)
314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        continue;
315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      paint_.setColor(colors_[i]);
316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      canvas->DrawPath(paths_[i], paint_);
317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SkPaint paint_;
321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const TouchLog& touch_log_;
323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SkPath paths_[kMaxPaths];
324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SkColor colors_[kMaxPaths];
325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int scale_;
327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DISALLOW_COPY_AND_ASSIGN(TouchHudCanvas);
329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TouchHudDebug::TouchHudDebug(aura::Window* initial_root)
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    : TouchObserverHUD(initial_root),
333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      mode_(FULLSCREEN),
334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      touch_log_(new TouchLog()),
335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      canvas_(NULL),
336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      label_container_(NULL) {
337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const gfx::Display& display =
338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      Shell::GetInstance()->display_manager()->GetDisplayForId(display_id());
339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  views::View* content = widget()->GetContentsView();
341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  canvas_ = new TouchHudCanvas(*touch_log_);
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  content->AddChildView(canvas_);
344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const gfx::Size& display_size = display.size();
346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  canvas_->SetSize(display_size);
347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  label_container_ = new views::View;
349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  label_container_->SetLayoutManager(new views::BoxLayout(
350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      views::BoxLayout::kVertical, 0, 0, 0));
351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (int i = 0; i < kMaxTouchPoints; ++i) {
353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    touch_labels_[i] = new views::Label;
354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    touch_labels_[i]->SetBackgroundColor(SkColorSetARGB(0, 255, 255, 255));
3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    touch_labels_[i]->SetShadows(gfx::ShadowValues(
3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        1, gfx::ShadowValue(gfx::Point(1, 1), 0, SK_ColorWHITE)));
357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    label_container_->AddChildView(touch_labels_[i]);
358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  label_container_->SetX(0);
360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  label_container_->SetY(display_size.height() / kReducedScale);
361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  label_container_->SetSize(label_container_->GetPreferredSize());
362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  label_container_->SetVisible(false);
363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  content->AddChildView(label_container_);
364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTouchHudDebug::~TouchHudDebug() {
367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<base::DictionaryValue> TouchHudDebug::GetAllAsDictionary() {
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  aura::Window::Windows roots = Shell::GetInstance()->GetAllRootWindows();
373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (aura::Window::Windows::iterator iter = roots.begin();
374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      iter != roots.end(); ++iter) {
375c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    RootWindowController* controller = GetRootWindowController(*iter);
376c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TouchHudDebug* hud = controller->touch_hud_debug();
377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (hud) {
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      scoped_ptr<base::ListValue> list = hud->GetLogAsList();
379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (!list->empty())
380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        value->Set(base::Int64ToString(hud->display_id()), list.release());
381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return value.Pass();
384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid TouchHudDebug::ChangeToNextMode() {
387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (mode_) {
388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case FULLSCREEN:
389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SetMode(REDUCED_SCALE);
390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case REDUCED_SCALE:
392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SetMode(INVISIBLE);
393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case INVISIBLE:
395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SetMode(FULLSCREEN);
396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<base::ListValue> TouchHudDebug::GetLogAsList() const {
401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return touch_log_->GetAsList();
402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid TouchHudDebug::Clear() {
405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (widget()->IsVisible()) {
406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    canvas_->Clear();
407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (int i = 0; i < kMaxTouchPoints; ++i)
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      touch_labels_[i]->SetText(base::string16());
409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    label_container_->SetSize(label_container_->GetPreferredSize());
410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid TouchHudDebug::SetMode(Mode mode) {
414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (mode_ == mode)
415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  mode_ = mode;
417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (mode) {
418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case FULLSCREEN:
419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      label_container_->SetVisible(false);
420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      canvas_->SetVisible(true);
421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      canvas_->SetScale(1);
422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      canvas_->SchedulePaint();
423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      widget()->Show();
424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case REDUCED_SCALE:
426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      label_container_->SetVisible(true);
427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      canvas_->SetVisible(true);
428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      canvas_->SetScale(kReducedScale);
429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      canvas_->SchedulePaint();
430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      widget()->Show();
431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case INVISIBLE:
433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      widget()->Hide();
434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid TouchHudDebug::UpdateTouchPointLabel(int index) {
439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int trace_index = touch_log_->GetTraceIndex(index);
440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const TouchTrace& trace = touch_log_->traces()[trace_index];
441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TouchTrace::const_reverse_iterator point = trace.log().rbegin();
442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ui::EventType touch_status = point->type;
443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  float touch_radius = std::max(point->radius_x, point->radius_y);
444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  while (point != trace.log().rend() && point->type == ui::ET_TOUCH_CANCELLED)
445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    point++;
446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(point != trace.log().rend());
447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  gfx::Point touch_position = point->location;
448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string string = base::StringPrintf("%2d: %s %s (%.4f)",
450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                          index,
451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                          GetTouchEventLabel(touch_status),
452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                          touch_position.ToString().c_str(),
453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                          touch_radius);
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  touch_labels_[index]->SetText(base::UTF8ToUTF16(string));
455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid TouchHudDebug::OnTouchEvent(ui::TouchEvent* event) {
458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (event->touch_id() >= kMaxTouchPoints)
459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  touch_log_->AddTouchPoint(*event);
462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  canvas_->TouchPointAdded(event->touch_id());
463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UpdateTouchPointLabel(event->touch_id());
464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  label_container_->SetSize(label_container_->GetPreferredSize());
465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
467cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void TouchHudDebug::OnDisplayMetricsChanged(const gfx::Display& display,
468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                            uint32_t metrics) {
469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TouchObserverHUD::OnDisplayMetricsChanged(display, metrics);
470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (display.id() != display_id() || !(metrics & DISPLAY_METRIC_BOUNDS))
472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const gfx::Size& size = display.size();
474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  canvas_->SetSize(size);
475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  label_container_->SetY(size.height() / kReducedScale);
476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid TouchHudDebug::SetHudForRootWindowController(
479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    RootWindowController* controller) {
480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  controller->set_touch_hud_debug(this);
481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid TouchHudDebug::UnsetHudForRootWindowController(
484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    RootWindowController* controller) {
485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  controller->set_touch_hud_debug(NULL);
486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace ash
489