diff options
22 files changed, 246 insertions, 50 deletions
@@ -159,6 +159,7 @@ Eduardo Lima (Etrunko) <eblima@gmail.com> Eduardo Lima (Etrunko) <eduardo.lima@intel.com> Edward Baker <edward.baker@intel.com> Edward Crossman <tedoc2000@gmail.com> +Eero Häkkinen <eero.hakkinen@intel.com> Eero Häkkinen <e.hakkinen@samsung.com> Egor Starkov <egor.starkov@samsung.com> Ehsan Akhgari <ehsan.akhgari@gmail.com> diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc index 6046ba2..18b8722 100644 --- a/content/browser/android/content_view_core_impl.cc +++ b/content/browser/android/content_view_core_impl.cc @@ -879,6 +879,8 @@ jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env, jfloat touch_minor_1, jfloat orientation_0, jfloat orientation_1, + jfloat tilt_0, + jfloat tilt_1, jfloat raw_pos_x, jfloat raw_pos_y, jint android_tool_type_0, @@ -897,6 +899,7 @@ jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env, touch_major_0, touch_minor_0, orientation_0, + tilt_0, android_tool_type_0); MotionEventAndroid::Pointer pointer1(pointer_id_1, pos_x_1, @@ -904,6 +907,7 @@ jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env, touch_major_1, touch_minor_1, orientation_1, + tilt_1, android_tool_type_1); MotionEventAndroid event(1.f / dpi_scale(), env, diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h index 4fd7ccb..55157a1 100644 --- a/content/browser/android/content_view_core_impl.h +++ b/content/browser/android/content_view_core_impl.h @@ -105,6 +105,8 @@ class ContentViewCoreImpl : public ContentViewCore, jfloat touch_minor_1, jfloat orientation_0, jfloat orientation_1, + jfloat tilt_0, + jfloat tilt_1, jfloat raw_pos_x, jfloat raw_pos_y, jint android_tool_type_0, diff --git a/content/browser/renderer_host/input/motion_event_android.cc b/content/browser/renderer_host/input/motion_event_android.cc index 4d30a3f..6392e90 100644 --- a/content/browser/renderer_host/input/motion_event_android.cc +++ b/content/browser/renderer_host/input/motion_event_android.cc @@ -129,6 +129,7 @@ MotionEventAndroid::Pointer::Pointer(jint id, jfloat touch_major_pixels, jfloat touch_minor_pixels, jfloat orientation_rad, + jfloat tilt_rad, jint tool_type) : id(id), pos_x_pixels(pos_x_pixels), @@ -136,6 +137,7 @@ MotionEventAndroid::Pointer::Pointer(jint id, touch_major_pixels(touch_major_pixels), touch_minor_pixels(touch_minor_pixels), orientation_rad(orientation_rad), + tilt_rad(tilt_rad), tool_type(tool_type) { } @@ -144,6 +146,7 @@ MotionEventAndroid::CachedPointer::CachedPointer() touch_major(0), touch_minor(0), orientation(0), + tilt(0), tool_type(TOOL_TYPE_UNKNOWN) { } @@ -273,6 +276,16 @@ float MotionEventAndroid::GetPressure(size_t pointer_index) const { AttachCurrentThread(), event_.obj(), pointer_index); } +float MotionEventAndroid::GetTilt(size_t pointer_index) const { + DCHECK_LT(pointer_index, cached_pointer_count_); + if (pointer_index < MAX_POINTERS_TO_CACHE) + return cached_pointers_[pointer_index].tilt; + if (!event_.obj()) + return 0.f; + return ToValidFloat(Java_MotionEvent_getAxisValueF_I_I( + AttachCurrentThread(), event_.obj(), AXIS_TILT, pointer_index)); +} + base::TimeTicks MotionEventAndroid::GetEventTime() const { return cached_time_; } @@ -336,6 +349,7 @@ MotionEventAndroid::CachedPointer MotionEventAndroid::FromAndroidPointer( result.touch_major = ToDips(pointer.touch_major_pixels); result.touch_minor = ToDips(pointer.touch_minor_pixels); result.orientation = ToValidFloat(pointer.orientation_rad); + result.tilt = ToValidFloat(pointer.tilt_rad); result.tool_type = FromAndroidToolType(pointer.tool_type); return result; } diff --git a/content/browser/renderer_host/input/motion_event_android.h b/content/browser/renderer_host/input/motion_event_android.h index bf4dfed..d581ce0 100644 --- a/content/browser/renderer_host/input/motion_event_android.h +++ b/content/browser/renderer_host/input/motion_event_android.h @@ -29,6 +29,7 @@ class CONTENT_EXPORT MotionEventAndroid : public ui::MotionEvent { jfloat touch_major_pixels, jfloat touch_minor_pixels, jfloat orientation_rad, + jfloat tilt_rad, jint tool_type); jint id; jfloat pos_x_pixels; @@ -36,6 +37,7 @@ class CONTENT_EXPORT MotionEventAndroid : public ui::MotionEvent { jfloat touch_major_pixels; jfloat touch_minor_pixels; jfloat orientation_rad; + jfloat tilt_rad; jint tool_type; }; @@ -71,6 +73,7 @@ class CONTENT_EXPORT MotionEventAndroid : public ui::MotionEvent { float GetTouchMinor(size_t pointer_index) const override; float GetOrientation(size_t pointer_index) const override; float GetPressure(size_t pointer_index) const override; + float GetTilt(size_t pointer_index) const override; base::TimeTicks GetEventTime() const override; size_t GetHistorySize() const override; base::TimeTicks GetHistoricalEventTime( @@ -120,6 +123,7 @@ class CONTENT_EXPORT MotionEventAndroid : public ui::MotionEvent { float touch_major; float touch_minor; float orientation; + float tilt; ToolType tool_type; } cached_pointers_[MAX_POINTERS_TO_CACHE]; diff --git a/content/browser/renderer_host/input/motion_event_android_unittest.cc b/content/browser/renderer_host/input/motion_event_android_unittest.cc index 9a33b31..c888aca 100644 --- a/content/browser/renderer_host/input/motion_event_android_unittest.cc +++ b/content/browser/renderer_host/input/motion_event_android_unittest.cc @@ -39,9 +39,9 @@ TEST(MotionEventAndroidTest, Constructor) { base::TimeTicks event_time = base::TimeTicks() + base::TimeDelta::FromMilliseconds(event_time_ms); MotionEventAndroid::Pointer p0( - 1, 13.7f, -7.13f, 5.3f, 1.2f, 0.1f, kAndroidToolTypeFinger); + 1, 13.7f, -7.13f, 5.3f, 1.2f, 0.1f, 0.2f, kAndroidToolTypeFinger); MotionEventAndroid::Pointer p1( - 2, -13.7f, 7.13f, 3.5f, 12.1f, -0.1f, kAndroidToolTypeFinger); + 2, -13.7f, 7.13f, 3.5f, 12.1f, -0.1f, -0.4f, kAndroidToolTypeFinger); float raw_offset = -3.f; int pointer_count = 2; int history_size = 0; @@ -77,6 +77,8 @@ TEST(MotionEventAndroidTest, Constructor) { EXPECT_EQ(p1.touch_minor_pixels * kPixToDip, event.GetTouchMinor(1)); EXPECT_EQ(p0.orientation_rad, event.GetOrientation(0)); EXPECT_EQ(p1.orientation_rad, event.GetOrientation(1)); + EXPECT_EQ(p0.tilt_rad, event.GetTilt(0)); + EXPECT_EQ(p1.tilt_rad, event.GetTilt(1)); EXPECT_EQ(p0.id, event.GetPointerId(0)); EXPECT_EQ(p1.id, event.GetPointerId(1)); EXPECT_EQ(MotionEvent::TOOL_TYPE_FINGER, event.GetToolType(0)); @@ -90,8 +92,8 @@ TEST(MotionEventAndroidTest, Constructor) { TEST(MotionEventAndroidTest, Clone) { const int pointer_count = 1; MotionEventAndroid::Pointer p0( - 1, 13.7f, -7.13f, 5.3f, 1.2f, 0.1f, kAndroidToolTypeFinger); - MotionEventAndroid::Pointer p1(0, 0, 0, 0, 0, 0, 0); + 1, 13.7f, -7.13f, 5.3f, 1.2f, 0.1f, 0.2f, kAndroidToolTypeFinger); + MotionEventAndroid::Pointer p1(0, 0, 0, 0, 0, 0, 0, 0); MotionEventAndroid event(kPixToDip, base::android::AttachCurrentThread(), nullptr, @@ -115,8 +117,8 @@ TEST(MotionEventAndroidTest, Cancel) { const int event_time_ms = 5; const int pointer_count = 1; MotionEventAndroid::Pointer p0( - 1, 13.7f, -7.13f, 5.3f, 1.2f, 0.1f, kAndroidToolTypeFinger); - MotionEventAndroid::Pointer p1(0, 0, 0, 0, 0, 0, 0); + 1, 13.7f, -7.13f, 5.3f, 1.2f, 0.1f, 0.2f, kAndroidToolTypeFinger); + MotionEventAndroid::Pointer p1(0, 0, 0, 0, 0, 0, 0, 0); MotionEventAndroid event(kPixToDip, base::android::AttachCurrentThread(), nullptr, @@ -148,8 +150,8 @@ TEST(MotionEventAndroidTest, InvalidOrientationsSanitized) { int pointer_count = 2; float orientation0 = 1e10f; float orientation1 = std::numeric_limits<float>::quiet_NaN(); - MotionEventAndroid::Pointer p0(0, 0, 0, 0, 0, orientation0, 0); - MotionEventAndroid::Pointer p1(1, 0, 0, 0, 0, orientation1, 0); + MotionEventAndroid::Pointer p0(0, 0, 0, 0, 0, orientation0, 0, 0); + MotionEventAndroid::Pointer p1(1, 0, 0, 0, 0, orientation1, 0, 0); MotionEventAndroid event(kPixToDip, base::android::AttachCurrentThread(), nullptr, @@ -172,8 +174,8 @@ TEST(MotionEventAndroidTest, InvalidOrientationsSanitized) { TEST(MotionEventAndroidTest, NonEmptyHistoryForNonMoveEventsSanitized) { int pointer_count = 1; size_t history_size = 5; - MotionEventAndroid::Pointer p0(0, 0, 0, 0, 0, 0, 0); - MotionEventAndroid::Pointer p1(0, 0, 0, 0, 0, 0, 0); + MotionEventAndroid::Pointer p0(0, 0, 0, 0, 0, 0, 0, 0); + MotionEventAndroid::Pointer p1(0, 0, 0, 0, 0, 0, 0, 0); MotionEventAndroid event(kPixToDip, base::android::AttachCurrentThread(), nullptr, @@ -194,9 +196,9 @@ TEST(MotionEventAndroidTest, NonEmptyHistoryForNonMoveEventsSanitized) { TEST(MotionEventAndroidTest, ActionIndexForPointerDown) { MotionEventAndroid::Pointer p0( - 1, 13.7f, -7.13f, 5.3f, 1.2f, 0.1f, kAndroidToolTypeFinger); + 1, 13.7f, -7.13f, 5.3f, 1.2f, 0.1f, 0.2f, kAndroidToolTypeFinger); MotionEventAndroid::Pointer p1( - 2, -13.7f, 7.13f, 3.5f, 12.1f, -0.1f, kAndroidToolTypeFinger); + 2, -13.7f, 7.13f, 3.5f, 12.1f, -0.1f, -0.4f, kAndroidToolTypeFinger); int pointer_count = 2; int history_size = 0; int action_index = 1; diff --git a/content/browser/renderer_host/input/motion_event_web.cc b/content/browser/renderer_host/input/motion_event_web.cc index ddc3037..30f141b 100644 --- a/content/browser/renderer_host/input/motion_event_web.cc +++ b/content/browser/renderer_host/input/motion_event_web.cc @@ -130,26 +130,62 @@ float MotionEventWeb::GetTouchMinor(size_t pointer_index) const { float MotionEventWeb::GetOrientation(size_t pointer_index) const { DCHECK_LT(pointer_index, GetPointerCount()); - float rotation_angle_rad = event_.touches[pointer_index].rotationAngle + float orientation_rad = event_.touches[pointer_index].rotationAngle * M_PI / 180.f; - DCHECK(0 <= rotation_angle_rad && rotation_angle_rad <= M_PI_2) + DCHECK(0 <= orientation_rad && orientation_rad <= M_PI_2) << "Unexpected touch rotation angle"; - if (event_.touches[pointer_index].radiusX - > event_.touches[pointer_index].radiusY) { + if (GetToolType(pointer_index) == TOOL_TYPE_STYLUS) { + const WebPointerProperties& pointer = event_.touches[pointer_index]; + + if (pointer.tiltY <= 0 && pointer.tiltX < 0) { + // Stylus is tilted to the left away from the user or straight + // to the left thus the orientation should be within [pi/2,pi). + orientation_rad += static_cast<float>(M_PI_2); + } else if (pointer.tiltY < 0 && pointer.tiltX >= 0) { + // Stylus is tilted to the right away from the user or straight away + // from the user thus the orientation should be within [-pi,-pi/2). + orientation_rad -= static_cast<float>(M_PI); + } else if (pointer.tiltY >= 0 && pointer.tiltX > 0) { + // Stylus is tilted to the right towards the user or straight + // to the right thus the orientation should be within [-pi/2,0). + orientation_rad -= static_cast<float>(M_PI_2); + } + } else if (event_.touches[pointer_index].radiusX + > event_.touches[pointer_index].radiusY) { // The case radiusX == radiusY is omitted from here on purpose: for circles, // we want to pass the angle (which could be any value in such cases but - // always seem to be set to zero) unchanged. - rotation_angle_rad -= (float) M_PI_2; + // always seems to be set to zero) unchanged. + orientation_rad -= static_cast<float>(M_PI_2); } - return rotation_angle_rad; + return orientation_rad; } float MotionEventWeb::GetPressure(size_t pointer_index) const { return 0.f; } +float MotionEventWeb::GetTilt(size_t pointer_index) const { + DCHECK_LT(pointer_index, GetPointerCount()); + + if (GetToolType(pointer_index) != TOOL_TYPE_STYLUS) + return 0.f; + + const WebPointerProperties& pointer = event_.touches[pointer_index]; + + float tilt_x_r = sin(pointer.tiltX * M_PI / 180.f); + float tilt_x_z = cos(pointer.tiltX * M_PI / 180.f); + float tilt_y_r = sin(pointer.tiltY * M_PI / 180.f); + float tilt_y_z = cos(pointer.tiltY * M_PI / 180.f); + float r_x = tilt_x_r * tilt_y_z; + float r_y = tilt_y_r * tilt_x_z; + float r = sqrt(r_x * r_x + r_y * r_y); + float z = tilt_x_z * tilt_y_z; + + return atan2(r, z); +} + base::TimeTicks MotionEventWeb::GetEventTime() const { return base::TimeTicks() + base::TimeDelta::FromMicroseconds(event_.timeStampSeconds * diff --git a/content/browser/renderer_host/input/motion_event_web.h b/content/browser/renderer_host/input/motion_event_web.h index 34e9541..1aac855 100644 --- a/content/browser/renderer_host/input/motion_event_web.h +++ b/content/browser/renderer_host/input/motion_event_web.h @@ -5,13 +5,14 @@ #ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_MOTION_EVENT_WEB_H_ #define CONTENT_BROWSER_RENDERER_HOST_INPUT_MOTION_EVENT_WEB_H_ +#include "content/common/content_export.h" #include "third_party/WebKit/public/web/WebInputEvent.h" #include "ui/events/gesture_detection/motion_event.h" namespace content { // Implementation of ui::MotionEvent wrapping a WebTouchEvent. -class MotionEventWeb : public ui::MotionEvent { +class CONTENT_EXPORT MotionEventWeb : public ui::MotionEvent { public: explicit MotionEventWeb(const blink::WebTouchEvent& event); ~MotionEventWeb() override; @@ -30,6 +31,7 @@ class MotionEventWeb : public ui::MotionEvent { float GetTouchMinor(size_t pointer_index) const override; float GetOrientation(size_t pointer_index) const override; float GetPressure(size_t pointer_index) const override; + float GetTilt(size_t pointer_index) const override; base::TimeTicks GetEventTime() const override; ToolType GetToolType(size_t pointer_index) const override; int GetButtonState() const override; diff --git a/content/browser/renderer_host/input/motion_event_web_unittest.cc b/content/browser/renderer_host/input/motion_event_web_unittest.cc new file mode 100644 index 0000000..d126ea7 --- /dev/null +++ b/content/browser/renderer_host/input/motion_event_web_unittest.cc @@ -0,0 +1,78 @@ +// Copyright 2015 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. + +// MSVC++ requires this to be set before any other includes to get M_PI. +#define _USE_MATH_DEFINES + +#include <cmath> + +#include "content/browser/renderer_host/input/motion_event_web.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/blink/blink_event_util.h" +#include "ui/events/gesture_detection/motion_event_generic.h" +#include "ui/events/test/motion_event_test_utils.h" + +using ui::MotionEvent; +using ui::MotionEventGeneric; +using ui::PointerProperties; + +namespace content { + +TEST(MotionEventWebTest, Constructor) { + const float pi = static_cast<float>(M_PI); + const float orientations[] = { + -pi, -2.f * pi / 3, -pi / 2, -pi / 3, 0.f, pi / 3, pi / 2, 2.f * pi / 3}; + const float tilts[] = {0.f, pi / 4, pi / 3}; + const MotionEvent::ToolType tool_types[] = {MotionEvent::TOOL_TYPE_FINGER, + MotionEvent::TOOL_TYPE_STYLUS, + MotionEvent::TOOL_TYPE_MOUSE}; + + base::TimeTicks event_time = base::TimeTicks::Now(); + PointerProperties pp; + MotionEventGeneric generic_event(MotionEvent::ACTION_MOVE, event_time, pp); + + for (MotionEvent::ToolType tool_type : tool_types) { + for (float orientation : orientations) { + for (float tilt : tilts) { + PointerProperties pp2; + pp2.orientation = orientation; + pp2.tilt = tilt; + pp2.tool_type = tool_type; + size_t pointer_index = generic_event.PushPointer(pp2); + EXPECT_GT(pointer_index, 0u); + + blink::WebTouchEvent web_touch_event = + CreateWebTouchEventFromMotionEvent(generic_event, true); + + MotionEventWeb event(web_touch_event); + EXPECT_EQ(tool_type, event.GetToolType(pointer_index)); + if (tool_type == MotionEvent::TOOL_TYPE_STYLUS) { + // Web touch event touch point tilt plane angles are stored as ints, + // thus the tilt precision is 1 degree and the error should not be + // greater than 0.5 degrees. + EXPECT_NEAR(tilt, event.GetTilt(pointer_index), 0.5f * M_PI / 180.f) + << " orientation=" << orientation; + } else { + EXPECT_EQ(0.f, event.GetTilt(pointer_index)); + } + if (tool_type == MotionEvent::TOOL_TYPE_STYLUS && tilt > 0.f) { + // Full stylus tilt orientation information survives above event + // conversions only if there is a non-zero stylus tilt angle. + // See: http://crbug.com/251330 + EXPECT_NEAR(orientation, event.GetOrientation(pointer_index), 1e-4) + << " tilt=" << tilt; + } else { + // For non-stylus pointers and for styluses with a zero tilt angle, + // orientation quadrant information is lost. + EXPECT_NEAR(fmod(orientation + M_PI + 1e-4, M_PI_2) - 1e-4, + event.GetOrientation(pointer_index), 1e-4); + } + + generic_event.RemovePointerAt(pointer_index); + } + } + } +} + +} // namespace content diff --git a/content/browser/renderer_host/input/touch_emulator.cc b/content/browser/renderer_host/input/touch_emulator.cc index 460716d..e095b9d 100644 --- a/content/browser/renderer_host/input/touch_emulator.cc +++ b/content/browser/renderer_host/input/touch_emulator.cc @@ -446,6 +446,8 @@ void TouchEmulator::FillTouchEventAndPoint(const WebMouseEvent& mouse_event) { point.screenPosition.x = mouse_event.globalX; point.position.y = mouse_event.y; point.screenPosition.y = mouse_event.globalY; + point.tiltX = 0; + point.tiltY = 0; } bool TouchEmulator::InPinchGestureMode() const { diff --git a/content/browser/renderer_host/input/touch_event_queue.cc b/content/browser/renderer_host/input/touch_event_queue.cc index 9de8093..8f3a6a9 100644 --- a/content/browser/renderer_host/input/touch_event_queue.cc +++ b/content/browser/renderer_host/input/touch_event_queue.cc @@ -56,7 +56,9 @@ bool HasPointChanged(const WebTouchPoint& point_1, point_1.radiusX != point_2.radiusX || point_1.radiusY != point_2.radiusY || point_1.rotationAngle != point_2.rotationAngle || - point_1.force != point_2.force) { + point_1.force != point_2.force || + point_1.tiltX != point_2.tiltX || + point_1.tiltY != point_2.tiltY) { return true; } return false; diff --git a/content/browser/renderer_host/input/web_input_event_util_unittest.cc b/content/browser/renderer_host/input/web_input_event_util_unittest.cc index 862d6c1..439e2c1 100644 --- a/content/browser/renderer_host/input/web_input_event_util_unittest.cc +++ b/content/browser/renderer_host/input/web_input_event_util_unittest.cc @@ -28,6 +28,10 @@ using ui::MotionEventGeneric; namespace content { TEST(WebInputEventUtilTest, MotionEventConversion) { + + const MotionEvent::ToolType tool_types[] = {MotionEvent::TOOL_TYPE_FINGER, + MotionEvent::TOOL_TYPE_STYLUS, + MotionEvent::TOOL_TYPE_MOUSE}; ui::PointerProperties pointer(5, 10, 40); pointer.id = 15; pointer.raw_x = 20; @@ -35,34 +39,45 @@ TEST(WebInputEventUtilTest, MotionEventConversion) { pointer.pressure = 30; pointer.touch_minor = 35; pointer.orientation = static_cast<float>(-M_PI / 2); - MotionEventGeneric event( - MotionEvent::ACTION_DOWN, base::TimeTicks::Now(), pointer); - event.set_flags(ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN); - event.set_unique_event_id(123456U); + pointer.tilt = static_cast<float>(-M_PI / 3); + for (MotionEvent::ToolType tool_type : tool_types) { + pointer.tool_type = tool_type; + MotionEventGeneric event( + MotionEvent::ACTION_DOWN, base::TimeTicks::Now(), pointer); + event.set_flags(ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN); + event.set_unique_event_id(123456U); - WebTouchEvent expected_event; - expected_event.type = WebInputEvent::TouchStart; - expected_event.touchesLength = 1; - expected_event.timeStampSeconds = - (event.GetEventTime() - base::TimeTicks()).InSecondsF(); - expected_event.modifiers = WebInputEvent::ShiftKey | WebInputEvent::AltKey; - WebTouchPoint expected_pointer; - expected_pointer.id = pointer.id; - expected_pointer.state = WebTouchPoint::StatePressed; - expected_pointer.position = blink::WebFloatPoint(pointer.x, pointer.y); - expected_pointer.screenPosition = - blink::WebFloatPoint(pointer.raw_x, pointer.raw_y); - expected_pointer.radiusX = pointer.touch_major / 2.f; - expected_pointer.radiusY = pointer.touch_minor / 2.f; - expected_pointer.rotationAngle = 0.f; - expected_pointer.force = pointer.pressure; - expected_event.touches[0] = expected_pointer; - expected_event.uniqueTouchEventId = 123456U; + WebTouchEvent expected_event; + expected_event.type = WebInputEvent::TouchStart; + expected_event.touchesLength = 1; + expected_event.timeStampSeconds = + (event.GetEventTime() - base::TimeTicks()).InSecondsF(); + expected_event.modifiers = WebInputEvent::ShiftKey | WebInputEvent::AltKey; + WebTouchPoint expected_pointer; + expected_pointer.id = pointer.id; + expected_pointer.state = WebTouchPoint::StatePressed; + expected_pointer.position = blink::WebFloatPoint(pointer.x, pointer.y); + expected_pointer.screenPosition = + blink::WebFloatPoint(pointer.raw_x, pointer.raw_y); + expected_pointer.radiusX = pointer.touch_major / 2.f; + expected_pointer.radiusY = pointer.touch_minor / 2.f; + expected_pointer.rotationAngle = 0.f; + expected_pointer.force = pointer.pressure; + if (tool_type == MotionEvent::TOOL_TYPE_STYLUS) { + expected_pointer.tiltX = -60; + expected_pointer.tiltY = 0; + } else { + expected_pointer.tiltX = 0; + expected_pointer.tiltY = 0; + } + expected_event.touches[0] = expected_pointer; + expected_event.uniqueTouchEventId = 123456U; - WebTouchEvent actual_event = - ui::CreateWebTouchEventFromMotionEvent(event, false); - EXPECT_EQ(WebInputEventTraits::ToString(expected_event), - WebInputEventTraits::ToString(actual_event)); + WebTouchEvent actual_event = + ui::CreateWebTouchEventFromMotionEvent(event, false); + EXPECT_EQ(WebInputEventTraits::ToString(expected_event), + WebInputEventTraits::ToString(actual_event)); + } } TEST(WebInputEventUtilTest, ScrollUpdateConversion) { diff --git a/content/common/input/synthetic_web_input_event_builders.cc b/content/common/input/synthetic_web_input_event_builders.cc index d2f4c39..470951a 100644 --- a/content/common/input/synthetic_web_input_event_builders.cc +++ b/content/common/input/synthetic_web_input_event_builders.cc @@ -182,6 +182,7 @@ int SyntheticWebTouchEvent::PressPoint(float x, float y) { point.radiusX = point.radiusY = 1.f; point.rotationAngle = 1.f; point.force = 1.f; + point.tiltX = point.tiltY = 0; ++touchesLength; WebTouchEventTraits::ResetType( WebInputEvent::TouchStart, timeStampSeconds, this); diff --git a/content/common/input/web_input_event_traits.cc b/content/common/input/web_input_event_traits.cc index 0a71bb8..2d98dcd 100644 --- a/content/common/input/web_input_event_traits.cc +++ b/content/common/input/web_input_event_traits.cc @@ -93,7 +93,8 @@ void ApppendEventDetails(const WebGestureEvent& event, std::string* result) { void ApppendTouchPointDetails(const WebTouchPoint& point, std::string* result) { StringAppendF(result, " (ID: %d, State: %d, ScreenPos: (%f, %f), Pos: (%f, %f)," - " Radius: (%f, %f), Rot: %f, Force: %f),\n", + " Radius: (%f, %f), Rot: %f, Force: %f," + " Tilt: (%d, %d)),\n", point.id, point.state, point.screenPosition.x, @@ -103,7 +104,9 @@ void ApppendTouchPointDetails(const WebTouchPoint& point, std::string* result) { point.radiusX, point.radiusY, point.rotationAngle, - point.force); + point.force, + point.tiltX, + point.tiltY); } void ApppendEventDetails(const WebTouchEvent& event, std::string* result) { diff --git a/content/content_tests.gypi b/content/content_tests.gypi index cbfdb7b..04ba14e 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -528,6 +528,7 @@ 'browser/renderer_host/input/mock_input_ack_handler.h', 'browser/renderer_host/input/mock_input_router_client.cc', 'browser/renderer_host/input/mock_input_router_client.h', + 'browser/renderer_host/input/motion_event_web_unittest.cc', 'browser/renderer_host/input/mouse_wheel_rails_filter_unittest_mac.cc', 'browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc', 'browser/renderer_host/input/stylus_text_selector_unittest.cc', diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java index a3e7fd3..dfbe5f2 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java @@ -1222,6 +1222,8 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Screen event.getTouchMajor(), pointerCount > 1 ? event.getTouchMajor(1) : 0, event.getTouchMinor(), pointerCount > 1 ? event.getTouchMinor(1) : 0, event.getOrientation(), pointerCount > 1 ? event.getOrientation(1) : 0, + event.getAxisValue(MotionEvent.AXIS_TILT), + pointerCount > 1 ? event.getAxisValue(MotionEvent.AXIS_TILT, 1) : 0, event.getRawX(), event.getRawY(), event.getToolType(0), pointerCount > 1 ? event.getToolType(1) : MotionEvent.TOOL_TYPE_UNKNOWN, @@ -3312,6 +3314,7 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Screen float touchMajor0, float touchMajor1, float touchMinor0, float touchMinor1, float orientation0, float orientation1, + float tilt0, float tilt1, float rawX, float rawY, int androidToolType0, int androidToolType1, int androidButtonState, int androidMetaState, diff --git a/ui/events/blink/blink_event_util.cc b/ui/events/blink/blink_event_util.cc index 659adf3..5ceb267 100644 --- a/ui/events/blink/blink_event_util.cc +++ b/ui/events/blink/blink_event_util.cc @@ -125,7 +125,8 @@ WebTouchPoint CreateWebTouchPoint(const MotionEvent& event, DCHECK_LE(minor_radius, major_radius); DCHECK(!major_radius || minor_radius); - float orientation_deg = event.GetOrientation(pointer_index) * 180.f / M_PI; + float orientation_rad = event.GetOrientation(pointer_index); + float orientation_deg = orientation_rad * 180.f / M_PI; DCHECK_GE(major_radius, 0); DCHECK_GE(minor_radius, 0); DCHECK_GE(major_radius, minor_radius); @@ -158,6 +159,18 @@ WebTouchPoint CreateWebTouchPoint(const MotionEvent& event, touch.force = event.GetPressure(pointer_index); + if (event.GetToolType(pointer_index) == MotionEvent::TOOL_TYPE_STYLUS) { + // A stylus points to a direction specified by orientation and tilts to + // the opposite direction. Coordinate system is left-handed. + float tilt_rad = event.GetTilt(pointer_index); + float r = sin(tilt_rad); + float z = cos(tilt_rad); + touch.tiltX = lround(atan2(sin(-orientation_rad) * r, z) * 180.f / M_PI); + touch.tiltY = lround(atan2(cos(-orientation_rad) * r, z) * 180.f / M_PI); + } else { + touch.tiltX = touch.tiltY = 0; + } + return touch; } diff --git a/ui/events/gesture_detection/motion_event.h b/ui/events/gesture_detection/motion_event.h index a20abf5..f06e0840 100644 --- a/ui/events/gesture_detection/motion_event.h +++ b/ui/events/gesture_detection/motion_event.h @@ -65,6 +65,7 @@ class GESTURE_DETECTION_EXPORT MotionEvent { virtual float GetTouchMinor(size_t pointer_index) const = 0; virtual float GetOrientation(size_t pointer_index) const = 0; virtual float GetPressure(size_t pointer_index) const = 0; + virtual float GetTilt(size_t pointer_index) const = 0; virtual ToolType GetToolType(size_t pointer_index) const = 0; virtual int GetButtonState() const = 0; virtual int GetFlags() const = 0; @@ -103,6 +104,7 @@ class GESTURE_DETECTION_EXPORT MotionEvent { float GetOrientation() const { return GetOrientation(0); } float GetPressure() const { return GetPressure(0); } + float GetTilt() const { return GetTilt(0); } ToolType GetToolType() const { return GetToolType(0); } // O(N) search of pointers (use sparingly!). Returns -1 if |id| nonexistent. diff --git a/ui/events/gesture_detection/motion_event_buffer_unittest.cc b/ui/events/gesture_detection/motion_event_buffer_unittest.cc index 5e23bd5..21a9408 100644 --- a/ui/events/gesture_detection/motion_event_buffer_unittest.cc +++ b/ui/events/gesture_detection/motion_event_buffer_unittest.cc @@ -101,6 +101,7 @@ class MotionEventBufferTest : public testing::Test, EXPECT_EQ(a.GetTouchMinor(i), b.GetTouchMinor(bi)); EXPECT_EQ(a.GetOrientation(i), b.GetOrientation(bi)); EXPECT_EQ(a.GetPressure(i), b.GetPressure(bi)); + EXPECT_EQ(a.GetTilt(i), b.GetTilt(bi)); EXPECT_EQ(a.GetToolType(i), b.GetToolType(bi)); } diff --git a/ui/events/gesture_detection/motion_event_generic.cc b/ui/events/gesture_detection/motion_event_generic.cc index be367bd..56d3839 100644 --- a/ui/events/gesture_detection/motion_event_generic.cc +++ b/ui/events/gesture_detection/motion_event_generic.cc @@ -29,6 +29,7 @@ PointerProperties::PointerProperties(float x, float y, float touch_major) touch_major(touch_major), touch_minor(0), orientation(0), + tilt(0), source_device_id(0) { } @@ -44,6 +45,7 @@ PointerProperties::PointerProperties(const MotionEvent& event, touch_major(event.GetTouchMajor(pointer_index)), touch_minor(event.GetTouchMinor(pointer_index)), orientation(event.GetOrientation(pointer_index)), + tilt(event.GetTilt(pointer_index)), source_device_id(0) { } @@ -170,6 +172,11 @@ float MotionEventGeneric::GetPressure(size_t pointer_index) const { return pointers_[pointer_index].pressure; } +float MotionEventGeneric::GetTilt(size_t pointer_index) const { + DCHECK_LT(pointer_index, pointers_->size()); + return pointers_[pointer_index].tilt; +} + MotionEvent::ToolType MotionEventGeneric::GetToolType( size_t pointer_index) const { DCHECK_LT(pointer_index, pointers_->size()); diff --git a/ui/events/gesture_detection/motion_event_generic.h b/ui/events/gesture_detection/motion_event_generic.h index 2a9a606..71dc92b 100644 --- a/ui/events/gesture_detection/motion_event_generic.h +++ b/ui/events/gesture_detection/motion_event_generic.h @@ -34,6 +34,7 @@ struct GESTURE_DETECTION_EXPORT PointerProperties { float touch_major; float touch_minor; float orientation; + float tilt; // source_device_id is only used on Aura. int source_device_id; }; @@ -62,6 +63,7 @@ class GESTURE_DETECTION_EXPORT MotionEventGeneric : public MotionEvent { float GetTouchMinor(size_t pointer_index) const override; float GetOrientation(size_t pointer_index) const override; float GetPressure(size_t pointer_index) const override; + float GetTilt(size_t pointer_index) const override; ToolType GetToolType(size_t pointer_index) const override; int GetButtonState() const override; int GetFlags() const override; diff --git a/ui/events/test/motion_event_test_utils.cc b/ui/events/test/motion_event_test_utils.cc index 0a3f80d..ec05291 100644 --- a/ui/events/test/motion_event_test_utils.cc +++ b/ui/events/test/motion_event_test_utils.cc @@ -213,6 +213,7 @@ std::string ToString(const MotionEvent& event) { << event.GetTouchMinor(pi) << ")" << "\n Orientation: " << event.GetOrientation(pi) << "\n Pressure: " << event.GetPressure(pi) + << "\n Tilt: " << event.GetTilt(pi) << "\n Tool: " << event.GetToolType(pi); if (history_size) { ss << "\n History: ["; |