Index: ui/events/ozone/evdev/touch_event_converter_evdev.cc |
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev.cc b/ui/events/ozone/evdev/touch_event_converter_evdev.cc |
index e0c9d2d2fa6a656c34ad10f7a2f0ab12df913874..f98da649211003c6b9c9026e6afb931e3dfc2998 100644 |
--- a/ui/events/ozone/evdev/touch_event_converter_evdev.cc |
+++ b/ui/events/ozone/evdev/touch_event_converter_evdev.cc |
@@ -31,6 +31,7 @@ |
#include "ui/events/event_switches.h" |
#include "ui/events/event_utils.h" |
#include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h" |
+#include "ui/events/ozone/evdev/palm_suppression_filter.h" |
#include "ui/events/ozone/evdev/touch_evdev_types.h" |
#include "ui/events/ozone/evdev/touch_noise/touch_noise_finder.h" |
#include "ui/ozone/public/input_controller.h" |
@@ -113,7 +114,8 @@ TouchEventConverterEvdev::TouchEventConverterEvdev( |
devinfo.name(), |
devinfo.vendor_id(), |
devinfo.product_id()), |
- dispatcher_(dispatcher) { |
+ dispatcher_(dispatcher), |
+ palm_filter_(nullptr) { |
if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
switches::kExtraTouchNoiseFiltering)) { |
touch_noise_finder_.reset(new TouchNoiseFinder); |
@@ -126,6 +128,7 @@ TouchEventConverterEvdev::~TouchEventConverterEvdev() { |
void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) { |
has_mt_ = info.HasMultitouch(); |
+ has_pen_ = info.HasKeyEvent(BTN_TOOL_PEN); |
if (has_mt_) { |
pressure_min_ = info.GetAbsMinimum(ABS_MT_PRESSURE); |
@@ -136,6 +139,7 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) { |
y_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_Y) - y_min_tuxels_ + 1; |
touch_points_ = |
std::min<int>(info.GetAbsMaximum(ABS_MT_SLOT) + 1, kNumTouchEvdevSlots); |
+ major_max_ = info.GetAbsMaximum(ABS_MT_TOUCH_MAJOR); |
current_slot_ = info.GetAbsValue(ABS_MT_SLOT); |
} else { |
pressure_min_ = info.GetAbsMinimum(ABS_PRESSURE); |
@@ -144,6 +148,7 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) { |
x_num_tuxels_ = info.GetAbsMaximum(ABS_X) - x_min_tuxels_ + 1; |
y_min_tuxels_ = info.GetAbsMinimum(ABS_Y); |
y_num_tuxels_ = info.GetAbsMaximum(ABS_Y) - y_min_tuxels_ + 1; |
+ major_max_ = std::numeric_limits<int>::max(); |
touch_points_ = 1; |
current_slot_ = 0; |
} |
@@ -185,12 +190,14 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) { |
events_[i].altered = true; |
// Optional bits. |
- events_[i].radius_x = |
- info.GetAbsMtSlotValueWithDefault(ABS_MT_TOUCH_MAJOR, i, 0) / 2.0f; |
+ int touch_major = |
+ info.GetAbsMtSlotValueWithDefault(ABS_MT_TOUCH_MAJOR, i, 0); |
+ events_[i].radius_x = touch_major / 2.0f; |
events_[i].radius_y = |
info.GetAbsMtSlotValueWithDefault(ABS_MT_TOUCH_MINOR, i, 0) / 2.0f; |
events_[i].pressure = ScalePressure( |
info.GetAbsMtSlotValueWithDefault(ABS_MT_PRESSURE, i, 0)); |
+ events_[i].is_palm = (touch_major == major_max_); |
spang
2016/08/23 23:32:29
Are we confident all MT drivers have the touch maj
denniskempin
2016/08/25 23:27:45
Of course we shouldn't rely on this. I should have
|
} |
} else { |
// TODO(spang): Add key state to EventDeviceInfo to allow initial contact. |
@@ -204,7 +211,11 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) { |
events_[0].radius_y = 0; |
events_[0].pressure = 0; |
events_[0].tool_code = 0; |
+ events_[0].is_palm = false; |
} |
+ |
+ if (palm_filter_) |
+ palm_filter_->Reset(); |
spang
2016/08/23 23:32:29
Why should losing sync cancel suppression? Dropped
denniskempin
2016/08/25 23:27:45
Done.
|
} |
void TouchEventConverterEvdev::Reinitialize() { |
@@ -224,6 +235,10 @@ bool TouchEventConverterEvdev::HasTouchscreen() const { |
return true; |
} |
+bool TouchEventConverterEvdev::HasPen() const { |
+ return has_pen_; |
+} |
+ |
gfx::Size TouchEventConverterEvdev::GetTouchscreenSize() const { |
return gfx::Size(x_num_tuxels_, y_num_tuxels_); |
} |
@@ -239,6 +254,8 @@ void TouchEventConverterEvdev::OnEnabled() { |
void TouchEventConverterEvdev::OnDisabled() { |
ReleaseTouches(); |
ReleaseButtons(); |
+ if (palm_filter_) |
+ palm_filter_->Reset(); |
} |
void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { |
@@ -281,6 +298,11 @@ void TouchEventConverterEvdev::SetTouchEventLoggingEnabled(bool enabled) { |
touch_logging_enabled_ = enabled; |
} |
+void TouchEventConverterEvdev::SetPalmSuppressionFilter( |
+ PalmSuppressionFilter* palm_filter) { |
+ palm_filter_ = palm_filter; |
+} |
+ |
void TouchEventConverterEvdev::ProcessMultitouchEvent( |
const input_event& input) { |
if (touch_logging_enabled_) |
@@ -352,6 +374,7 @@ void TouchEventConverterEvdev::ProcessKey(const input_event& input) { |
} else { |
events_[current_slot_].tool_code = 0; |
} |
+ events_[current_slot_].altered = true; |
break; |
default: |
NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code; |
@@ -365,6 +388,10 @@ void TouchEventConverterEvdev::ProcessAbs(const input_event& input) { |
// 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; |
+ |
+ // The MT protocol cannot communicate cancelled touches, so some kernel |
+ // drivers will identify palms by setting touch major to max. |
+ events_[current_slot_].is_palm = (input.value == major_max_); |
break; |
case ABS_MT_TOUCH_MINOR: |
events_[current_slot_].radius_y = input.value / 2.0f; |
@@ -417,6 +444,12 @@ EventType TouchEventConverterEvdev::GetEventTypeForTouch( |
if (touch.cancelled) |
return ET_UNKNOWN; |
+ if (touch.is_palm) { |
+ if (touch.touching && !touch.was_touching) |
+ return ET_UNKNOWN; |
+ return ET_TOUCH_CANCELLED; |
+ } |
+ |
if (touch_noise_finder_ && touch_noise_finder_->SlotHasNoise(touch.slot)) { |
if (touch.touching && !touch.was_touching) |
return ET_UNKNOWN; |
@@ -432,9 +465,11 @@ void TouchEventConverterEvdev::ReportTouchEvent( |
const InProgressTouchEvdev& event, |
EventType event_type, |
base::TimeTicks timestamp) { |
- dispatcher_->DispatchTouchEvent(TouchEventParams( |
- input_device_.id, event.slot, event_type, gfx::PointF(event.x, event.y), |
- GetEventPointerDetails(event), timestamp)); |
+ TouchEventParams params(input_device_.id, event.slot, event_type, |
+ gfx::PointF(event.x, event.y), |
+ GetEventPointerDetails(event), timestamp); |
+ if (!palm_filter_ || palm_filter_->FilterTouch(params)) |
spang
2016/08/23 23:32:29
I'm nervous about putting filtering this late beca
|
+ dispatcher_->DispatchTouchEvent(params); |
} |
void TouchEventConverterEvdev::ReportStylusEvent( |
@@ -475,6 +510,10 @@ void TouchEventConverterEvdev::ReportEvents(base::TimeTicks timestamp) { |
if (!event->altered) |
continue; |
+ if (has_pen_ && palm_filter_) { |
+ palm_filter_->EnableSuppression(event->tool_code > 0, timestamp); |
+ } |
+ |
if (event->tool_code > 0) { |
ReportStylusEvent(*event, timestamp); |
} else { |