Drive: Add BatchableRequest subclass.
[chromium-blink-merge.git] / ui / events / gestures / motion_event_aura.cc
blob174918fedc5a545da380fd2efd3205e36c3e3258
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.
5 // MSVC++ requires this to be set before any other includes to get M_PI.
6 #define _USE_MATH_DEFINES
8 #include "ui/events/gestures/motion_event_aura.h"
10 #include <cmath>
12 #include "base/logging.h"
13 #include "ui/events/gesture_detection/gesture_configuration.h"
15 namespace ui {
16 namespace {
18 PointerProperties GetPointerPropertiesFromTouchEvent(const TouchEvent& touch) {
19 PointerProperties pointer_properties;
20 pointer_properties.x = touch.x();
21 pointer_properties.y = touch.y();
22 pointer_properties.raw_x = touch.root_location_f().x();
23 pointer_properties.raw_y = touch.root_location_f().y();
24 pointer_properties.id = touch.touch_id();
25 pointer_properties.pressure = touch.force();
26 pointer_properties.source_device_id = touch.source_device_id();
28 float radius_x = touch.radius_x();
29 float radius_y = touch.radius_y();
30 float rotation_angle_rad = touch.rotation_angle() * M_PI / 180.f;
32 DCHECK_GE(radius_x, 0) << "Unexpected x-radius < 0";
33 DCHECK_GE(radius_y, 0) << "Unexpected y-radius < 0";
34 DCHECK(0 <= rotation_angle_rad && rotation_angle_rad < M_PI)
35 << "Unexpected touch rotation angle";
37 // Make the angle acute to ease subsequent logic. The angle range effectively
38 // changes from [0, pi) to [0, pi/2).
39 if (rotation_angle_rad >= M_PI_2) {
40 rotation_angle_rad -= static_cast<float>(M_PI_2);
41 std::swap(radius_x, radius_y);
44 if (radius_x > radius_y) {
45 // The case radius_x == radius_y is omitted from here on purpose: for
46 // circles, we want to pass the angle (which could be any value in such
47 // cases but always seem to be set to zero) unchanged.
48 pointer_properties.touch_major = 2.f * radius_x;
49 pointer_properties.touch_minor = 2.f * radius_y;
50 pointer_properties.orientation = rotation_angle_rad - M_PI_2;
51 } else {
52 pointer_properties.touch_major = 2.f * radius_y;
53 pointer_properties.touch_minor = 2.f * radius_x;
54 pointer_properties.orientation = rotation_angle_rad;
57 if (!pointer_properties.touch_major) {
58 pointer_properties.touch_major =
59 2.f * GestureConfiguration::GetInstance()->default_radius();
60 pointer_properties.touch_minor =
61 2.f * GestureConfiguration::GetInstance()->default_radius();
62 pointer_properties.orientation = 0;
65 // TODO(jdduke): Plumb tool type from the platform, crbug.com/404128.
66 pointer_properties.tool_type = MotionEvent::TOOL_TYPE_UNKNOWN;
68 return pointer_properties;
71 } // namespace
73 MotionEventAura::MotionEventAura() {
74 set_action_index(-1);
77 MotionEventAura::~MotionEventAura() {
80 bool MotionEventAura::OnTouch(const TouchEvent& touch) {
81 int index = FindPointerIndexOfId(touch.touch_id());
82 bool pointer_id_is_active = index != -1;
84 if (touch.type() == ET_TOUCH_PRESSED && pointer_id_is_active) {
85 // TODO(tdresser): This should return false (or NOTREACHED()), and
86 // ignore the touch; however, there is at least one case where we
87 // need to allow a touch press from a currently used touch id. See
88 // crbug.com/446852 for details.
90 // Cancel the existing touch, before handling the touch press.
91 TouchEvent cancel(ET_TOUCH_CANCELLED, touch.location(), touch.touch_id(),
92 touch.time_stamp());
93 OnTouch(cancel);
94 CleanupRemovedTouchPoints(cancel);
95 DCHECK_EQ(-1, FindPointerIndexOfId(touch.touch_id()));
96 } else if (touch.type() != ET_TOUCH_PRESSED && !pointer_id_is_active) {
97 // We could have an active touch stream transfered to us, resulting in touch
98 // move or touch up events without associated touch down events. Ignore
99 // them.
100 return false;
103 if (touch.type() == ET_TOUCH_MOVED && touch.x() == GetX(index) &&
104 touch.y() == GetY(index)) {
105 return false;
108 switch (touch.type()) {
109 case ET_TOUCH_PRESSED:
110 AddTouch(touch);
111 break;
112 case ET_TOUCH_RELEASED:
113 case ET_TOUCH_CANCELLED:
114 // Removing these touch points needs to be postponed until after the
115 // MotionEvent has been dispatched. This cleanup occurs in
116 // CleanupRemovedTouchPoints.
117 UpdateTouch(touch);
118 break;
119 case ET_TOUCH_MOVED:
120 UpdateTouch(touch);
121 break;
122 default:
123 NOTREACHED();
124 return false;
127 UpdateCachedAction(touch);
128 set_flags(touch.flags());
129 set_event_time(touch.time_stamp() + base::TimeTicks());
130 return true;
133 int MotionEventAura::GetId() const {
134 return GetPointerId(0);
137 void MotionEventAura::CleanupRemovedTouchPoints(const TouchEvent& event) {
138 if (event.type() != ET_TOUCH_RELEASED &&
139 event.type() != ET_TOUCH_CANCELLED) {
140 return;
143 DCHECK(GetPointerCount());
144 int index_to_delete = GetIndexFromId(event.touch_id());
145 set_action_index(0);
146 pointer(index_to_delete) = pointer(GetPointerCount() - 1);
147 PopPointer();
150 int MotionEventAura::GetSourceDeviceId(size_t pointer_index) const {
151 DCHECK_LT(pointer_index, GetPointerCount());
152 return pointer(pointer_index).source_device_id;
155 void MotionEventAura::AddTouch(const TouchEvent& touch) {
156 if (GetPointerCount() == MotionEvent::MAX_TOUCH_POINT_COUNT)
157 return;
159 PushPointer(GetPointerPropertiesFromTouchEvent(touch));
162 void MotionEventAura::UpdateTouch(const TouchEvent& touch) {
163 pointer(GetIndexFromId(touch.touch_id())) =
164 GetPointerPropertiesFromTouchEvent(touch);
167 void MotionEventAura::UpdateCachedAction(const TouchEvent& touch) {
168 DCHECK(GetPointerCount());
169 switch (touch.type()) {
170 case ET_TOUCH_PRESSED:
171 if (GetPointerCount() == 1) {
172 set_action(ACTION_DOWN);
173 } else {
174 set_action(ACTION_POINTER_DOWN);
175 set_action_index(GetIndexFromId(touch.touch_id()));
177 break;
178 case ET_TOUCH_RELEASED:
179 if (GetPointerCount() == 1) {
180 set_action(ACTION_UP);
181 } else {
182 set_action(ACTION_POINTER_UP);
183 set_action_index(GetIndexFromId(touch.touch_id()));
185 break;
186 case ET_TOUCH_CANCELLED:
187 set_action(ACTION_CANCEL);
188 break;
189 case ET_TOUCH_MOVED:
190 set_action(ACTION_MOVE);
191 break;
192 default:
193 NOTREACHED();
194 break;
198 int MotionEventAura::GetIndexFromId(int id) const {
199 int index = FindPointerIndexOfId(id);
200 DCHECK_GE(index, 0);
201 DCHECK_LT(index, static_cast<int>(GetPointerCount()));
202 return index;
205 } // namespace ui