1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/renderer_host/input/motion_event_web.h"
6
7#include "base/logging.h"
8#include "content/common/input/web_touch_event_traits.h"
9
10using blink::WebInputEvent;
11using blink::WebTouchEvent;
12using blink::WebTouchPoint;
13
14namespace content {
15namespace {
16
17ui::MotionEvent::Action GetActionFrom(const WebTouchEvent& event) {
18  DCHECK(event.touchesLength);
19  switch (event.type) {
20    case WebInputEvent::TouchStart:
21      if (WebTouchEventTraits::AllTouchPointsHaveState(
22              event, WebTouchPoint::StatePressed))
23        return ui::MotionEvent::ACTION_DOWN;
24      else
25        return ui::MotionEvent::ACTION_POINTER_DOWN;
26    case WebInputEvent::TouchEnd:
27      if (WebTouchEventTraits::AllTouchPointsHaveState(
28              event, WebTouchPoint::StateReleased))
29        return ui::MotionEvent::ACTION_UP;
30      else
31        return ui::MotionEvent::ACTION_POINTER_UP;
32    case WebInputEvent::TouchCancel:
33      DCHECK(WebTouchEventTraits::AllTouchPointsHaveState(
34          event, WebTouchPoint::StateCancelled));
35      return ui::MotionEvent::ACTION_CANCEL;
36    case WebInputEvent::TouchMove:
37      return ui::MotionEvent::ACTION_MOVE;
38    default:
39      break;
40  };
41  NOTREACHED()
42      << "Unable to derive a valid MotionEvent::Action from the WebTouchEvent.";
43  return ui::MotionEvent::ACTION_CANCEL;
44}
45
46int GetActionIndexFrom(const WebTouchEvent& event) {
47  for (size_t i = 0; i < event.touchesLength; ++i) {
48    if (event.touches[i].state != WebTouchPoint::StateUndefined &&
49        event.touches[i].state != WebTouchPoint::StateStationary)
50      return i;
51  }
52  return -1;
53}
54
55}  // namespace
56
57MotionEventWeb::MotionEventWeb(const WebTouchEvent& event)
58    : event_(event),
59      cached_action_(GetActionFrom(event)),
60      cached_action_index_(GetActionIndexFrom(event)) {
61  DCHECK_GT(GetPointerCount(), 0U);
62}
63
64MotionEventWeb::~MotionEventWeb() {}
65
66int MotionEventWeb::GetId() const {
67  return 0;
68}
69
70MotionEventWeb::Action MotionEventWeb::GetAction() const {
71  return cached_action_;
72}
73
74int MotionEventWeb::GetActionIndex() const { return cached_action_index_; }
75
76size_t MotionEventWeb::GetPointerCount() const { return event_.touchesLength; }
77
78int MotionEventWeb::GetPointerId(size_t pointer_index) const {
79  DCHECK_LT(pointer_index, GetPointerCount());
80  return event_.touches[pointer_index].id;
81}
82
83float MotionEventWeb::GetX(size_t pointer_index) const {
84  DCHECK_LT(pointer_index, GetPointerCount());
85  return event_.touches[pointer_index].position.x;
86}
87
88float MotionEventWeb::GetY(size_t pointer_index) const {
89  DCHECK_LT(pointer_index, GetPointerCount());
90  return event_.touches[pointer_index].position.y;
91}
92
93float MotionEventWeb::GetRawX(size_t pointer_index) const {
94  DCHECK_LT(pointer_index, GetPointerCount());
95  return event_.touches[pointer_index].screenPosition.x;
96}
97
98float MotionEventWeb::GetRawY(size_t pointer_index) const {
99  DCHECK_LT(pointer_index, GetPointerCount());
100  return event_.touches[pointer_index].screenPosition.y;
101}
102
103float MotionEventWeb::GetTouchMajor(size_t pointer_index) const {
104  DCHECK_LT(pointer_index, GetPointerCount());
105  // TODO(jdduke): We should be a bit more careful about axes here.
106  return 2.f * std::max(event_.touches[pointer_index].radiusX,
107                        event_.touches[pointer_index].radiusY);
108}
109
110float MotionEventWeb::GetPressure(size_t pointer_index) const {
111  return 0.f;
112}
113
114base::TimeTicks MotionEventWeb::GetEventTime() const {
115  return base::TimeTicks() +
116         base::TimeDelta::FromMicroseconds(event_.timeStampSeconds *
117                                           base::Time::kMicrosecondsPerSecond);
118}
119
120size_t MotionEventWeb::GetHistorySize() const { return 0; }
121
122base::TimeTicks MotionEventWeb::GetHistoricalEventTime(
123    size_t historical_index) const {
124  NOTIMPLEMENTED();
125  return base::TimeTicks();
126}
127
128float MotionEventWeb::GetHistoricalTouchMajor(size_t pointer_index,
129                                              size_t historical_index) const {
130  NOTIMPLEMENTED();
131  return 0.f;
132}
133
134float MotionEventWeb::GetHistoricalX(size_t pointer_index,
135                                     size_t historical_index) const {
136  NOTIMPLEMENTED();
137  return 0.f;
138}
139
140float MotionEventWeb::GetHistoricalY(size_t pointer_index,
141                                     size_t historical_index) const {
142  NOTIMPLEMENTED();
143  return 0.f;
144}
145
146ui::MotionEvent::ToolType MotionEventWeb::GetToolType(
147    size_t pointer_index) const {
148  NOTIMPLEMENTED();
149  return TOOL_TYPE_UNKNOWN;
150}
151
152int MotionEventWeb::GetButtonState() const {
153  NOTIMPLEMENTED();
154  return 0;
155}
156
157scoped_ptr<ui::MotionEvent> MotionEventWeb::Clone() const {
158  return scoped_ptr<MotionEvent>(new MotionEventWeb(event_));
159}
160
161scoped_ptr<ui::MotionEvent> MotionEventWeb::Cancel() const {
162  WebTouchEvent cancel_event(event_);
163  WebTouchEventTraits::ResetTypeAndTouchStates(
164      blink::WebInputEvent::TouchCancel,
165      // TODO(rbyers): Shouldn't we use a fresh timestamp?
166      event_.timeStampSeconds,
167      &cancel_event);
168  return scoped_ptr<MotionEvent>(new MotionEventWeb(cancel_event));
169}
170
171}  // namespace content
172