| Index: ui/base/x/events_x.cc
|
| diff --git a/ui/base/x/events_x.cc b/ui/base/x/events_x.cc
|
| index 06adb00c37d2620caf5889573d236d70dd6e08fa..355fa3fab4b9dd90e43cb4e09878269dd5e6c005 100644
|
| --- a/ui/base/x/events_x.cc
|
| +++ b/ui/base/x/events_x.cc
|
| @@ -256,8 +256,31 @@ gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) {
|
| case GenericEvent: {
|
| XIDeviceEvent* xievent =
|
| static_cast<XIDeviceEvent*>(native_event->xcookie.data);
|
| - return gfx::Point(static_cast<int>(xievent->event_x),
|
| - static_cast<int>(xievent->event_y));
|
| +
|
| + if (xievent->sourceid == xievent->deviceid) {
|
| + // This event is coming from a slave device. Read the position from the
|
| + // valuators, because the events reported for a slave device seems to be
|
| + // behind the master device by one event. See more on crbug.com/103981.
|
| + // The position in the valuators is in the global screen coordinates.
|
| + // But it is necessary to convert it into the window's coordinates. If
|
| + // the valuator is not set, that means the value hasn't changed, and so
|
| + // we can use the value from event_x/event_y (which are in the window's
|
| + // coordinates).
|
| + double* valuators = xievent->valuators.values;
|
| +
|
| + double x = xievent->event_x;
|
| + if (XIMaskIsSet(xievent->valuators.mask, 0))
|
| + x = *valuators++ - (xievent->root_x - xievent->event_x);
|
| +
|
| + double y = xievent->event_y;
|
| + if (XIMaskIsSet(xievent->valuators.mask, 1))
|
| + y = *valuators++ - (xievent->root_y - xievent->event_y);
|
| +
|
| + return gfx::Point(static_cast<int>(x), static_cast<int>(y));
|
| + } else {
|
| + return gfx::Point(static_cast<int>(xievent->event_x),
|
| + static_cast<int>(xievent->event_y));
|
| + }
|
| }
|
| }
|
| return gfx::Point();
|
|
|