Commit e7f0416c authored by Jingkui Wang's avatar Jingkui Wang Committed by Commit Bot

Ozone: Use resolution to scale touch_major and touch_minor

The units of touch_major and abs_mt_position_x could be different. We
have to scale the values from touch_major/touch_minor before we map the
value to radius (pixels).

Bug: 771374
Change-Id: Ic5ca2424ff72e475e7146ff7a42725445d2fb250
Reviewed-on: https://chromium-review.googlesource.com/702758Reviewed-by: default avatarMichael Spang <spang@chromium.org>
Commit-Queue: Jingkui Wang <jkwang@google.com>
Cr-Commit-Position: refs/heads/master@{#506859}
parent ba6e1195
......@@ -173,6 +173,44 @@ const DeviceCapabilities kiBuffaloGamepad = {
arraysize(kiBuffaloGamepadAbsAxes),
};
// Captured from Pixelbook.
const DeviceAbsoluteAxis kEveTouchScreenAbsAxes[] = {
{ABS_X, {4624, 0, 10368, 0, 0, 40}},
{ABS_Y, {2177, 0, 6912, 0, 0, 40}},
{ABS_PRESSURE, {0, 0, 255, 0, 0, 0}},
{ABS_MT_SLOT, {0, 0, 9, 0, 0, 0}},
{ABS_MT_TOUCH_MAJOR, {0, 0, 255, 0, 0, 1}},
{ABS_MT_TOUCH_MINOR, {0, 0, 255, 0, 0, 1}},
{ABS_MT_ORIENTATION, {0, 0, 1, 0, 0, 0}},
{ABS_MT_POSITION_X, {0, 0, 10368, 0, 0, 40}},
{ABS_MT_POSITION_Y, {0, 0, 6912, 0, 0, 40}},
{ABS_MT_TOOL_TYPE, {0, 0, 2, 0, 0}},
{ABS_MT_PRESSURE, {0, 0, 255, 0, 0, 0}}};
const DeviceCapabilities kEveTouchScreen = {
/* path */
"/sys/devices/pci0000:00/0000:00:15.0/i2c_designware.0/i2c-6/"
"i2c-WCOM50C1:00/0018:2D1F:5143.0001/input/input4/event4",
/* name */ "WCOM50C1:00 2D1F:5143",
/* phys */ "i2c-WCOM50C1:00",
/* uniq */ "",
/* bustype */ "0018",
/* vendor */ "2d1f",
/* product */ "5143",
/* version */ "0100",
/* prop */ "2",
/* ev */ "1b",
/* key */ "400 0 0 0 0 0",
/* rel */ "0",
/* abs */ "6f3800001000003",
/* msc */ "20",
/* sw */ "0",
/* led */ "0",
/* ff */ "0",
kEveTouchScreenAbsAxes,
arraysize(kEveTouchScreenAbsAxes),
};
// Captured from Chromebook Pixel.
const DeviceCapabilities kLinkKeyboard = {
/* path */ "/sys/devices/platform/i8042/serio0/input/input6/event6",
......
......@@ -62,6 +62,7 @@ bool CapabilitiesToDeviceInfo(const DeviceCapabilities& capabilities,
extern const DeviceCapabilities kXboxGamepad;
extern const DeviceCapabilities kHJCGamepad;
extern const DeviceCapabilities kiBuffaloGamepad;
extern const DeviceCapabilities kEveTouchScreen;
extern const DeviceCapabilities kLinkKeyboard;
extern const DeviceCapabilities kLinkTouchscreen;
extern const DeviceCapabilities kLinkWithToolTypeTouchscreen;
......
......@@ -94,6 +94,20 @@ ui::EventPointerType GetEventPointerType(int tool_code) {
}
}
// This function calculate the touch_major_scale_ and touch_minor_scale_ from
// resolution.
float GetFingerSizeScale(int32_t finger_size_res, int32_t screen_size_res) {
// If there is no resolution for both events, we assume they are consistent.
// Though this is not guaranteed by kernel, we don't have any info to guess.
// If there is a resolution (units/mm) for touch_major/minor, but not a
// resolution for screen size. We could not get the scale either as we don't
// have the dpi.
if (!finger_size_res || !screen_size_res) {
return 1.0f;
}
return static_cast<float>(screen_size_res) / finger_size_res;
}
const int kTrackingIdForUnusedSlot = -1;
} // namespace
......@@ -125,14 +139,23 @@ TouchEventConverterEvdev::~TouchEventConverterEvdev() {
void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) {
has_mt_ = info.HasMultitouch();
has_pen_ = info.HasKeyEvent(BTN_TOOL_PEN);
int32_t touch_major_res =
info.GetAbsInfoByCode(ABS_MT_TOUCH_MAJOR).resolution;
int32_t touch_minor_res =
info.GetAbsInfoByCode(ABS_MT_TOUCH_MINOR).resolution;
int32_t x_res;
int32_t y_res;
if (has_mt_) {
pressure_min_ = info.GetAbsMinimum(ABS_MT_PRESSURE);
pressure_max_ = info.GetAbsMaximum(ABS_MT_PRESSURE);
x_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_X);
x_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_X) - x_min_tuxels_ + 1;
x_res = info.GetAbsInfoByCode(ABS_MT_POSITION_X).resolution;
y_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_Y);
y_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_Y) - y_min_tuxels_ + 1;
y_res = info.GetAbsInfoByCode(ABS_MT_POSITION_Y).resolution;
touch_points_ =
std::min<int>(info.GetAbsMaximum(ABS_MT_SLOT) + 1, kNumTouchEvdevSlots);
major_max_ = info.GetAbsMaximum(ABS_MT_TOUCH_MAJOR);
......@@ -142,8 +165,10 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) {
pressure_max_ = info.GetAbsMaximum(ABS_PRESSURE);
x_min_tuxels_ = info.GetAbsMinimum(ABS_X);
x_num_tuxels_ = info.GetAbsMaximum(ABS_X) - x_min_tuxels_ + 1;
x_res = info.GetAbsInfoByCode(ABS_X).resolution;
y_min_tuxels_ = info.GetAbsMinimum(ABS_Y);
y_num_tuxels_ = info.GetAbsMaximum(ABS_Y) - y_min_tuxels_ + 1;
y_res = info.GetAbsInfoByCode(ABS_Y).resolution;
tilt_x_min_ = info.GetAbsMinimum(ABS_TILT_X);
tilt_y_min_ = info.GetAbsMinimum(ABS_TILT_Y);
tilt_x_range_ = info.GetAbsMaximum(ABS_TILT_X) - tilt_x_min_ + 1;
......@@ -154,6 +179,9 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) {
current_slot_ = 0;
}
touch_major_scale_ = GetFingerSizeScale(touch_major_res, x_res);
touch_minor_scale_ = GetFingerSizeScale(touch_minor_res, y_res);
quirk_left_mouse_button_ =
!has_mt_ && !info.HasKeyEvent(BTN_TOUCH) && info.HasKeyEvent(BTN_LEFT);
......@@ -191,9 +219,10 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) {
// Optional bits.
int touch_major =
info.GetAbsMtSlotValueWithDefault(ABS_MT_TOUCH_MAJOR, i, 0);
events_[i].radius_x = touch_major / 2.0f;
events_[i].radius_x = touch_major * touch_major_scale_ / 2.0f;
events_[i].radius_y =
info.GetAbsMtSlotValueWithDefault(ABS_MT_TOUCH_MINOR, i, 0) / 2.0f;
info.GetAbsMtSlotValueWithDefault(ABS_MT_TOUCH_MINOR, i, 0) *
touch_minor_scale_ / 2.0f;
events_[i].pressure = ScalePressure(
info.GetAbsMtSlotValueWithDefault(ABS_MT_PRESSURE, i, 0));
int tool_type = info.GetAbsMtSlotValueWithDefault(ABS_MT_TOOL_TYPE, i,
......@@ -392,7 +421,7 @@ void TouchEventConverterEvdev::ProcessAbs(const input_event& input) {
// TODO(spang): If we have all of major, minor, and orientation,
// we can scale the ellipse correctly. However on the Pixel we get
// neither minor nor orientation, so this is all we can do.
events_[current_slot_].radius_x = input.value / 2.0f;
events_[current_slot_].radius_x = input.value * touch_major_scale_ / 2.0f;
// The MT protocol communicates that there is palm on the surface
// by either sending ABS_MT_TOOL_TYPE/MT_TOOL_PALM, or by setting
......@@ -401,7 +430,7 @@ void TouchEventConverterEvdev::ProcessAbs(const input_event& input) {
events_[current_slot_].cancelled = true;
break;
case ABS_MT_TOUCH_MINOR:
events_[current_slot_].radius_y = input.value / 2.0f;
events_[current_slot_].radius_y = input.value * touch_major_scale_ / 2.0f;
break;
case ABS_MT_POSITION_X:
events_[current_slot_].x = input.value;
......
......@@ -133,6 +133,12 @@ class EVENTS_OZONE_EVDEV_EXPORT TouchEventConverterEvdev
float y_min_tuxels_;
float y_num_tuxels_;
// The resolution of ABS_MT_TOUCH_MAJOR/MINOR might be different from the
// resolution of ABS_MT_POSITION_X/Y. As we use the (position range, display
// pixels) to resize touch event radius, we have to scale major/minor.
float touch_major_scale_ = 1.0f;
float touch_minor_scale_ = 1.0f;
// Number of touch points reported by driver
int touch_points_ = 0;
......
......@@ -1347,4 +1347,45 @@ TEST_F(TouchEventConverterEvdevTest, ActiveStylusBarrelButton) {
up_event.pointer_details.pointer_type);
}
// crbug.com/771374
TEST_F(TouchEventConverterEvdevTest, FingerSizeWithResolution) {
ui::MockTouchEventConverterEvdev* dev = device();
EventDeviceInfo devinfo;
EXPECT_TRUE(CapabilitiesToDeviceInfo(kEveTouchScreen, &devinfo));
dev->Initialize(devinfo);
// Captured from Pixelbook (Eve).
timeval time;
time = {1507226211, 483601};
struct input_event mock_kernel_queue[] = {
{time, EV_ABS, ABS_MT_TRACKING_ID, 461},
{time, EV_ABS, ABS_MT_POSITION_X, 1795},
{time, EV_ABS, ABS_MT_POSITION_Y, 5559},
{time, EV_ABS, ABS_MT_PRESSURE, 217},
{time, EV_ABS, ABS_MT_TOUCH_MAJOR, 14},
{time, EV_ABS, ABS_MT_TOUCH_MINOR, 14},
{time, EV_KEY, BTN_TOUCH, 1},
{time, EV_ABS, ABS_X, 1795},
{time, EV_ABS, ABS_Y, 5559},
{time, EV_ABS, ABS_PRESSURE, 217},
{time, EV_MSC, MSC_TIMESTAMP, 0},
{time, EV_SYN, SYN_REPORT, 0},
};
// Finger pressed with major/minor reported.
dev->ConfigureReadMock(mock_kernel_queue, arraysize(mock_kernel_queue), 0);
dev->ReadNow();
EXPECT_EQ(1u, size());
ui::TouchEventParams event = dispatched_touch_event(0);
EXPECT_EQ(ui::ET_TOUCH_PRESSED, event.type);
EXPECT_EQ(ToTestTimeTicks(1507226211483601), event.timestamp);
EXPECT_EQ(1795, event.location.x());
EXPECT_EQ(5559, event.location.y());
EXPECT_EQ(0, event.slot);
EXPECT_EQ(EventPointerType::POINTER_TYPE_TOUCH,
event.pointer_details.pointer_type);
EXPECT_FLOAT_EQ(280.f, event.pointer_details.radius_x);
EXPECT_FLOAT_EQ(0.8509804f, event.pointer_details.force);
}
} // namespace ui
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment