From db5aa7abc8a6ed76f6497e25821c8a2f3e27f5af Mon Sep 17 00:00:00 2001 From: sadrul Date: Thu, 25 Jun 2015 10:25:31 -0700 Subject: html_viewer: Correctly set axis and orientation of MotionEvent. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MotionEvent's orientation is in radian, and it falls within [-π/2, π/2). However, TouchEvent's rotation-angle is in degrees, and it falls within [0, 180). So make sure the conversion from rotation-angle to orientation happens correctly. Add PointerProperties::SetAxisAndOrientation() as a convenience function to do this correctly. This fixes a crash in mandoline when touching the screen in landspace mode. BUG=none Review URL: https://codereview.chromium.org/1202283005 Cr-Commit-Position: refs/heads/master@{#336187} --- .../gesture_detection/motion_event_generic.cc | 36 ++++++++++++++++ ui/events/gesture_detection/motion_event_generic.h | 6 +++ .../motion_event_generic_unittest.cc | 48 ++++++++++++++++++++++ ui/events/gestures/motion_event_aura.cc | 36 +--------------- 4 files changed, 92 insertions(+), 34 deletions(-) (limited to 'ui') diff --git a/ui/events/gesture_detection/motion_event_generic.cc b/ui/events/gesture_detection/motion_event_generic.cc index 2f2c34b..a90c72a 100644 --- a/ui/events/gesture_detection/motion_event_generic.cc +++ b/ui/events/gesture_detection/motion_event_generic.cc @@ -2,8 +2,13 @@ // 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 "ui/events/gesture_detection/motion_event_generic.h" +#include + #include "base/logging.h" #include "ui/events/base_event_utils.h" @@ -42,6 +47,37 @@ PointerProperties::PointerProperties(const MotionEvent& event, source_device_id(0) { } +void PointerProperties::SetAxesAndOrientation(float radius_x, + float radius_y, + float rotation_angle_degree) { + DCHECK(!touch_major && !touch_minor && !orientation); + float rotation_angle_rad = rotation_angle_degree * M_PI / 180.f; + DCHECK_GE(radius_x, 0) << "Unexpected x-radius < 0 (" << radius_x << ")"; + DCHECK_GE(radius_y, 0) << "Unexpected y-radius < 0 (" << radius_y << ")"; + DCHECK(0 <= rotation_angle_rad && rotation_angle_rad < M_PI) + << "Unexpected touch rotation angle " << rotation_angle_rad << " rad"; + + // Make the angle acute to ease subsequent logic. The angle range effectively + // changes from [0, pi) to [0, pi/2). + if (rotation_angle_rad >= M_PI_2) { + rotation_angle_rad -= static_cast(M_PI_2); + std::swap(radius_x, radius_y); + } + + if (radius_x > radius_y) { + // The case radius_x == radius_y 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. + touch_major = 2.f * radius_x; + touch_minor = 2.f * radius_y; + orientation = rotation_angle_rad - M_PI_2; + } else { + touch_major = 2.f * radius_y; + touch_minor = 2.f * radius_x; + orientation = rotation_angle_rad; + } +} + MotionEventGeneric::MotionEventGeneric(Action action, base::TimeTicks event_time, const PointerProperties& pointer) diff --git a/ui/events/gesture_detection/motion_event_generic.h b/ui/events/gesture_detection/motion_event_generic.h index 6357342..2a9a606 100644 --- a/ui/events/gesture_detection/motion_event_generic.h +++ b/ui/events/gesture_detection/motion_event_generic.h @@ -18,6 +18,12 @@ struct GESTURE_DETECTION_EXPORT PointerProperties { PointerProperties(float x, float y, float touch_major); PointerProperties(const MotionEvent& event, size_t pointer_index); + // Sets |touch_major|, |touch_minor|, and |orientation| from the given radius + // and rotation angle (in degrees). + void SetAxesAndOrientation(float radius_x, + float radius_y, + float rotation_angle_degree); + int id; MotionEvent::ToolType tool_type; float x; diff --git a/ui/events/gesture_detection/motion_event_generic_unittest.cc b/ui/events/gesture_detection/motion_event_generic_unittest.cc index 182eb1e..2e0294f 100644 --- a/ui/events/gesture_detection/motion_event_generic_unittest.cc +++ b/ui/events/gesture_detection/motion_event_generic_unittest.cc @@ -2,6 +2,11 @@ // 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 + #include "testing/gtest/include/gtest/gtest.h" #include "ui/events/event_constants.h" #include "ui/events/gesture_detection/motion_event_generic.h" @@ -177,6 +182,49 @@ TEST(MotionEventGenericTest, RemovePointerAt) { EXPECT_EQ(-1, event.FindPointerIndexOfId(0)); } +TEST(MotionEventGenericTest, AxisAndOrientation) { + { + PointerProperties properties; + float radius_x = 10; + float radius_y = 5; + float rotation_angle_deg = 0; + properties.SetAxesAndOrientation(radius_x, radius_y, rotation_angle_deg); + EXPECT_EQ(20, properties.touch_major); + EXPECT_EQ(10, properties.touch_minor); + EXPECT_NEAR(-M_PI_2, properties.orientation, 0.001); + } + { + PointerProperties properties; + float radius_x = 5; + float radius_y = 10; + float rotation_angle_deg = 0; + properties.SetAxesAndOrientation(radius_x, radius_y, rotation_angle_deg); + EXPECT_EQ(20, properties.touch_major); + EXPECT_EQ(10, properties.touch_minor); + EXPECT_NEAR(0, properties.orientation, 0.001); + } + { + PointerProperties properties; + float radius_x = 10; + float radius_y = 5; + float rotation_angle_deg = 179.99f; + properties.SetAxesAndOrientation(radius_x, radius_y, rotation_angle_deg); + EXPECT_EQ(20, properties.touch_major); + EXPECT_EQ(10, properties.touch_minor); + EXPECT_NEAR(M_PI_2, properties.orientation, 0.001); + } + { + PointerProperties properties; + float radius_x = 10; + float radius_y = 5; + float rotation_angle_deg = 90; + properties.SetAxesAndOrientation(radius_x, radius_y, rotation_angle_deg); + EXPECT_EQ(20, properties.touch_major); + EXPECT_EQ(10, properties.touch_minor); + EXPECT_NEAR(0, properties.orientation, 0.001); + } +} + TEST(MotionEventGenericTest, ToString) { base::TimeTicks event_time = base::TimeTicks::Now(); base::TimeTicks historical_event_time0 = diff --git a/ui/events/gestures/motion_event_aura.cc b/ui/events/gestures/motion_event_aura.cc index 01df3f6..8c345f8 100644 --- a/ui/events/gestures/motion_event_aura.cc +++ b/ui/events/gestures/motion_event_aura.cc @@ -2,13 +2,8 @@ // 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 "ui/events/gestures/motion_event_aura.h" -#include - #include "base/logging.h" #include "ui/events/gesture_detection/gesture_configuration.h" @@ -25,35 +20,8 @@ PointerProperties GetPointerPropertiesFromTouchEvent(const TouchEvent& touch) { pointer_properties.pressure = touch.force(); pointer_properties.source_device_id = touch.source_device_id(); - float radius_x = touch.radius_x(); - float radius_y = touch.radius_y(); - float rotation_angle_rad = touch.rotation_angle() * M_PI / 180.f; - - DCHECK_GE(radius_x, 0) << "Unexpected x-radius < 0"; - DCHECK_GE(radius_y, 0) << "Unexpected y-radius < 0"; - DCHECK(0 <= rotation_angle_rad && rotation_angle_rad < M_PI) - << "Unexpected touch rotation angle"; - - // Make the angle acute to ease subsequent logic. The angle range effectively - // changes from [0, pi) to [0, pi/2). - if (rotation_angle_rad >= M_PI_2) { - rotation_angle_rad -= static_cast(M_PI_2); - std::swap(radius_x, radius_y); - } - - if (radius_x > radius_y) { - // The case radius_x == radius_y 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. - pointer_properties.touch_major = 2.f * radius_x; - pointer_properties.touch_minor = 2.f * radius_y; - pointer_properties.orientation = rotation_angle_rad - M_PI_2; - } else { - pointer_properties.touch_major = 2.f * radius_y; - pointer_properties.touch_minor = 2.f * radius_x; - pointer_properties.orientation = rotation_angle_rad; - } - + pointer_properties.SetAxesAndOrientation(touch.radius_x(), touch.radius_y(), + touch.rotation_angle()); if (!pointer_properties.touch_major) { pointer_properties.touch_major = 2.f * GestureConfiguration::GetInstance()->default_radius(); -- cgit v1.1