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// MSVC++ requires this to be set before any other includes to get M_PI. 6#define _USE_MATH_DEFINES 7 8#include "content/browser/renderer_host/input/motion_event_web.h" 9 10#include <cmath> 11 12#include "base/logging.h" 13#include "content/browser/renderer_host/input/web_input_event_util.h" 14#include "content/common/input/web_touch_event_traits.h" 15 16using blink::WebInputEvent; 17using blink::WebTouchEvent; 18using blink::WebTouchPoint; 19 20namespace content { 21namespace { 22 23ui::MotionEvent::Action GetActionFrom(const WebTouchEvent& event) { 24 DCHECK(event.touchesLength); 25 switch (event.type) { 26 case WebInputEvent::TouchStart: 27 if (WebTouchEventTraits::AllTouchPointsHaveState( 28 event, WebTouchPoint::StatePressed)) 29 return ui::MotionEvent::ACTION_DOWN; 30 else 31 return ui::MotionEvent::ACTION_POINTER_DOWN; 32 case WebInputEvent::TouchEnd: 33 if (WebTouchEventTraits::AllTouchPointsHaveState( 34 event, WebTouchPoint::StateReleased)) 35 return ui::MotionEvent::ACTION_UP; 36 else 37 return ui::MotionEvent::ACTION_POINTER_UP; 38 case WebInputEvent::TouchCancel: 39 DCHECK(WebTouchEventTraits::AllTouchPointsHaveState( 40 event, WebTouchPoint::StateCancelled)); 41 return ui::MotionEvent::ACTION_CANCEL; 42 case WebInputEvent::TouchMove: 43 return ui::MotionEvent::ACTION_MOVE; 44 default: 45 break; 46 }; 47 NOTREACHED() 48 << "Unable to derive a valid MotionEvent::Action from the WebTouchEvent."; 49 return ui::MotionEvent::ACTION_CANCEL; 50} 51 52int GetActionIndexFrom(const WebTouchEvent& event) { 53 for (size_t i = 0; i < event.touchesLength; ++i) { 54 if (event.touches[i].state != WebTouchPoint::StateUndefined && 55 event.touches[i].state != WebTouchPoint::StateStationary) 56 return i; 57 } 58 return -1; 59} 60 61} // namespace 62 63MotionEventWeb::MotionEventWeb(const WebTouchEvent& event) 64 : event_(event), 65 cached_action_(GetActionFrom(event)), 66 cached_action_index_(GetActionIndexFrom(event)) { 67 DCHECK_GT(GetPointerCount(), 0U); 68} 69 70MotionEventWeb::~MotionEventWeb() {} 71 72int MotionEventWeb::GetId() const { 73 return 0; 74} 75 76MotionEventWeb::Action MotionEventWeb::GetAction() const { 77 return cached_action_; 78} 79 80int MotionEventWeb::GetActionIndex() const { return cached_action_index_; } 81 82size_t MotionEventWeb::GetPointerCount() const { return event_.touchesLength; } 83 84int MotionEventWeb::GetPointerId(size_t pointer_index) const { 85 DCHECK_LT(pointer_index, GetPointerCount()); 86 return event_.touches[pointer_index].id; 87} 88 89float MotionEventWeb::GetX(size_t pointer_index) const { 90 DCHECK_LT(pointer_index, GetPointerCount()); 91 return event_.touches[pointer_index].position.x; 92} 93 94float MotionEventWeb::GetY(size_t pointer_index) const { 95 DCHECK_LT(pointer_index, GetPointerCount()); 96 return event_.touches[pointer_index].position.y; 97} 98 99float MotionEventWeb::GetRawX(size_t pointer_index) const { 100 DCHECK_LT(pointer_index, GetPointerCount()); 101 return event_.touches[pointer_index].screenPosition.x; 102} 103 104float MotionEventWeb::GetRawY(size_t pointer_index) const { 105 DCHECK_LT(pointer_index, GetPointerCount()); 106 return event_.touches[pointer_index].screenPosition.y; 107} 108 109float MotionEventWeb::GetTouchMajor(size_t pointer_index) const { 110 DCHECK_LT(pointer_index, GetPointerCount()); 111 return 2.f * std::max(event_.touches[pointer_index].radiusX, 112 event_.touches[pointer_index].radiusY); 113} 114 115float MotionEventWeb::GetTouchMinor(size_t pointer_index) const { 116 DCHECK_LT(pointer_index, GetPointerCount()); 117 return 2.f * std::min(event_.touches[pointer_index].radiusX, 118 event_.touches[pointer_index].radiusY); 119} 120 121float MotionEventWeb::GetOrientation(size_t pointer_index) const { 122 DCHECK_LT(pointer_index, GetPointerCount()); 123 124 float rotation_angle_rad = event_.touches[pointer_index].rotationAngle 125 * M_PI / 180.f; 126 DCHECK(0 <= rotation_angle_rad && rotation_angle_rad <= M_PI_2) 127 << "Unexpected touch rotation angle"; 128 129 if (event_.touches[pointer_index].radiusX 130 > event_.touches[pointer_index].radiusY) { 131 // The case radiusX == radiusY is omitted from here on purpose: for circles, 132 // we want to pass the angle (which could be any value in such cases but 133 // always seem to be set to zero) unchanged. 134 rotation_angle_rad -= (float) M_PI_2; 135 } 136 137 return rotation_angle_rad; 138} 139 140float MotionEventWeb::GetPressure(size_t pointer_index) const { 141 return 0.f; 142} 143 144base::TimeTicks MotionEventWeb::GetEventTime() const { 145 return base::TimeTicks() + 146 base::TimeDelta::FromMicroseconds(event_.timeStampSeconds * 147 base::Time::kMicrosecondsPerSecond); 148} 149 150ui::MotionEvent::ToolType MotionEventWeb::GetToolType( 151 size_t pointer_index) const { 152 // TODO(jdduke): Plumb tool type from the platform event, crbug.com/404128. 153 DCHECK_LT(pointer_index, GetPointerCount()); 154 return TOOL_TYPE_UNKNOWN; 155} 156 157int MotionEventWeb::GetButtonState() const { 158 NOTIMPLEMENTED(); 159 return 0; 160} 161 162int MotionEventWeb::GetFlags() const { 163 return WebEventModifiersToEventFlags(event_.modifiers); 164} 165 166scoped_ptr<ui::MotionEvent> MotionEventWeb::Clone() const { 167 return scoped_ptr<MotionEvent>(new MotionEventWeb(event_)); 168} 169 170scoped_ptr<ui::MotionEvent> MotionEventWeb::Cancel() const { 171 WebTouchEvent cancel_event(event_); 172 WebTouchEventTraits::ResetTypeAndTouchStates( 173 blink::WebInputEvent::TouchCancel, 174 // TODO(rbyers): Shouldn't we use a fresh timestamp? 175 event_.timeStampSeconds, 176 &cancel_event); 177 return scoped_ptr<MotionEvent>(new MotionEventWeb(cancel_event)); 178} 179 180} // namespace content 181