| Index: ui/events/ozone/evdev/touch_noise/single_position_touch_noise_filter.cc
|
| diff --git a/ui/events/ozone/evdev/touch_noise/single_position_touch_noise_filter.cc b/ui/events/ozone/evdev/touch_noise/single_position_touch_noise_filter.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b5e14823e98ceff1eb9ef240e9485608e81bebd9
|
| --- /dev/null
|
| +++ b/ui/events/ozone/evdev/touch_noise/single_position_touch_noise_filter.cc
|
| @@ -0,0 +1,144 @@
|
| +// 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.
|
| +
|
| +#include "ui/events/ozone/evdev/touch_noise/single_position_touch_noise_filter.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/strings/stringprintf.h"
|
| +
|
| +namespace ui {
|
| +
|
| +namespace {
|
| +
|
| +// Max squared distance between fingers for the fingers to be considered in the
|
| +// same position.
|
| +const int kSamePositionMaxDistance2 = 2 * 2;
|
| +
|
| +// Max squared movement of a finger before it's no longer considered noise.
|
| +const int kNoiseMaxMovement2 = 2 * 2;
|
| +
|
| +// Min duration in milliseconds after which touches in the same position are
|
| +// considered noise.
|
| +const int kMinDurationMs = 2000;
|
| +
|
| +// Max duration in milliseconds to check for common positions with previous
|
| +// touches.
|
| +const int kMaxDurationMs = 4000;
|
| +
|
| +// Returns the squared distance between |p1| and |p2|.
|
| +int Distance2(const gfx::PointF& p1, const gfx::PointF& p2) {
|
| + gfx::Vector2dF offset = p2 - p1;
|
| + return offset.x() * offset.x() + offset.y() * offset.y();
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +SinglePositionTouchNoiseFilter::SinglePositionTouchNoiseFilter()
|
| + : touches_start_(0), touches_end_(0) {
|
| + for (size_t i = 0; i < kNumSlots; i++)
|
| + tracked_slots_[i] = kNumTrackedTouches;
|
| +}
|
| +
|
| +void SinglePositionTouchNoiseFilter::FilterFrame(Frame* previous,
|
| + Frame* current) {
|
| + // Forget old touches which will no longer be considered for overlap.
|
| + base::TimeDelta touch_cutoff =
|
| + current->timestamp - base::TimeDelta::FromMilliseconds(kMaxDurationMs);
|
| + for (size_t i = touches_start_; i != touches_end_;
|
| + i = (i + 1) % kNumTrackedTouches) {
|
| + if (!tracked_touches_[i].valid)
|
| + continue;
|
| + if (tracked_touches_[i].end < touch_cutoff)
|
| + StopTrackingTouch(i);
|
| + }
|
| +
|
| + for (size_t slot = 0; slot < kNumSlots; ++slot) {
|
| + Finger* cur = ¤t->fingers[slot];
|
| + Finger* prev = &previous->fingers[slot];
|
| +
|
| + bool arrived = prev->tracking_id == -1 && cur->tracking_id >= 0;
|
| + bool departed = prev->tracking_id >= 0 && cur->tracking_id == -1;
|
| + if (departed)
|
| + tracked_slots_[slot] = kNumTrackedTouches;
|
| + if (cur->tracking_id == -1)
|
| + continue;
|
| +
|
| + // Track all new touches until they move too far.
|
| + if (arrived)
|
| + TrackTouch(slot, current);
|
| +
|
| + size_t t_ind = tracked_slots_[slot];
|
| + if (t_ind != kNumTrackedTouches) {
|
| + tracked_touches_[t_ind].end = current->timestamp;
|
| + // Stop tracking if touch moves more than sqrt(kNoiseMaxMovement2).
|
| + if (Distance2(cur->location, tracked_touches_[t_ind].location) >
|
| + kNoiseMaxMovement2) {
|
| + StopTrackingTouch(t_ind);
|
| + } else {
|
| + // Determine duration over which touches have been occuring in this
|
| + // position.
|
| + base::TimeDelta max_duration;
|
| + for (size_t i = touches_start_; i != touches_end_;
|
| + i = (i + 1) % kNumTrackedTouches) {
|
| + Touch* touch = &tracked_touches_[i];
|
| + if (!touch->valid)
|
| + continue;
|
| + if (Distance2(cur->location, touch->location) <=
|
| + kSamePositionMaxDistance2) {
|
| + base::TimeDelta duration = current->timestamp - touch->begin;
|
| + if (duration > max_duration)
|
| + max_duration = duration;
|
| + }
|
| + }
|
| +
|
| + if (max_duration.InMilliseconds() > kMinDurationMs) {
|
| + VLOG(2) << base::StringPrintf(
|
| + "Cancel tracking id %d, in position occurring for %ldms",
|
| + cur->tracking_id, max_duration.InMilliseconds());
|
| + cur->canceled = true;
|
| + }
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +void SinglePositionTouchNoiseFilter::StopTrackingTouch(size_t index) {
|
| + size_t slot = tracked_touches_[index].slot;
|
| + if (tracked_slots_[slot] == index)
|
| + tracked_slots_[slot] = kNumTrackedTouches;
|
| + tracked_touches_[index].valid = false;
|
| +
|
| + // If first touch is canceled, remove all dead touches.
|
| + if (index == touches_start_) {
|
| + while (!tracked_touches_[touches_start_].valid &&
|
| + touches_start_ != touches_end_) {
|
| + touches_start_ = (touches_start_ + 1) % kNumTrackedTouches;
|
| + }
|
| + }
|
| +}
|
| +
|
| +void SinglePositionTouchNoiseFilter::TrackTouch(size_t slot, Frame* frame) {
|
| + size_t index = (touches_end_ + 1) % kNumTrackedTouches;
|
| + // If we would reach the start touch index, we cannot track any more touches.
|
| + if (index == touches_start_)
|
| + return;
|
| +
|
| + touches_end_ = index;
|
| + tracked_touches_[index].valid = true;
|
| + tracked_touches_[index].location = frame->fingers[slot].location;
|
| + tracked_touches_[index].begin = frame->timestamp;
|
| + tracked_touches_[index].end = frame->timestamp;
|
| + tracked_touches_[index].slot = slot;
|
| + tracked_slots_[slot] = index;
|
| +}
|
| +
|
| +SinglePositionTouchNoiseFilter::SinglePositionTouchNoiseFilter::Touch::Touch()
|
| + : valid(false), slot(0) {
|
| +}
|
| +
|
| +SinglePositionTouchNoiseFilter::SinglePositionTouchNoiseFilter::Touch::
|
| + ~Touch() {
|
| +}
|
| +
|
| +} // namespace ui
|
|
|