Commit b42a277d authored by Sean O'Brien's avatar Sean O'Brien Committed by Commit Bot

ozone: Allow multiple delay filters for touchscreen

In order to allow more than one touch filter to delay the reporting of
touches, make the existing filter keep track of its own filter state.

BUG=b:69232663
TEST=manual testing with filters enabled

Change-Id: Idfc68fea22574becd920cdd599dd2e90e19bd04d
Reviewed-on: https://chromium-review.googlesource.com/1093584Reviewed-by: default avatarMichael Spang <spang@chromium.org>
Commit-Queue: Sean O'Brien <seobrien@chromium.org>
Cr-Commit-Position: refs/heads/master@{#567844}
parent fdf52c6c
......@@ -251,17 +251,7 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) {
if (cancelled_state)
CancelAllTouches();
bool touch_noise_filtering =
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kExtraTouchNoiseFiltering);
bool edge_touch_filtering =
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEdgeTouchFiltering);
if (touch_noise_filtering || edge_touch_filtering) {
false_touch_finder_.reset(new FalseTouchFinder(touch_noise_filtering,
edge_touch_filtering,
GetTouchscreenSize()));
}
false_touch_finder_ = FalseTouchFinder::Create(GetTouchscreenSize());
}
void TouchEventConverterEvdev::Reinitialize() {
......
......@@ -1201,12 +1201,12 @@ class TouchEventConverterEvdevTouchNoiseTest
~TouchEventConverterEvdevTouchNoiseTest() override {}
// Makes the FalseTouchFinder use |filter| and only |filter| to filter out
// touch noise. Also removes the edge touch filter.
// touch noise. Also removes any delay filters.
void SetTouchNoiseFilter(std::unique_ptr<TouchFilter> filter) {
FalseTouchFinder* finder = device()->false_touch_finder();
finder->noise_filters_.clear();
finder->noise_filters_.push_back(std::move(filter));
finder->edge_touch_filter_.reset();
finder->delay_filters_.clear();
}
// Returns the first of FalseTouchFinder's filters.
......
......@@ -33,6 +33,7 @@ bool IsNearBorder(const gfx::Point& point, gfx::Size touchscreen_size) {
EdgeTouchFilter::EdgeTouchFilter(gfx::Size& touchscreen_size)
: touchscreen_size_(touchscreen_size) {
}
EdgeTouchFilter::~EdgeTouchFilter() {}
void EdgeTouchFilter::Filter(
const std::vector<InProgressTouchEvdev>& touches,
......@@ -41,24 +42,24 @@ void EdgeTouchFilter::Filter(
for (const InProgressTouchEvdev& touch : touches) {
size_t slot = touch.slot;
gfx::Point& tracked_tap = tracked_taps_[slot];
gfx::Point touch_pos = gfx::Point(touch.x, touch.y);
bool should_delay = false;
if (!touch.touching && !touch.was_touching)
continue; // Only look at slots with active touches.
if (!touch.was_touching && IsNearBorder(touch_pos, touchscreen_size_)) {
should_delay = true; // Delay new contact near border.
tracked_taps_[slot] = touch_pos;
if (!touch.was_touching) {
// Track new contact and delay if near border.
bool near_border = IsNearBorder(touch_pos, touchscreen_size_);
slots_filtered_.set(slot, near_border);
if (near_border)
start_positions_[slot] = touch_pos;
}
if (slots_should_delay->test(slot) && touch_pos == tracked_tap) {
should_delay = true; // Continue delaying contacts that don't move.
}
slots_should_delay->set(slot, should_delay);
if (touch_pos != start_positions_[slot])
slots_filtered_.set(slot, false); // Stop delaying contacts that move.
}
(*slots_should_delay) |= slots_filtered_;
}
} // namespace ui
......@@ -15,7 +15,7 @@ namespace ui {
class EdgeTouchFilter : public TouchFilter {
public:
EdgeTouchFilter(gfx::Size& touchscreen_size);
~EdgeTouchFilter() override {}
~EdgeTouchFilter() override;
// TouchFilter:
void Filter(const std::vector<InProgressTouchEvdev>& touches,
......@@ -23,8 +23,9 @@ class EdgeTouchFilter : public TouchFilter {
std::bitset<kNumTouchEvdevSlots>* slots_should_delay) override;
private:
// Tracks in progress taps in slots.
gfx::Point tracked_taps_[kNumTouchEvdevSlots];
// Tracks in progress touches in slots.
gfx::Point start_positions_[kNumTouchEvdevSlots];
std::bitset<kNumTouchEvdevSlots> slots_filtered_;
gfx::Size touchscreen_size_;
......
......@@ -4,7 +4,10 @@
#include "ui/events/ozone/evdev/touch_filter/false_touch_finder.h"
#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "ui/events/event_switches.h"
#include "ui/events/event_utils.h"
#include "ui/events/ozone/evdev/touch_filter/edge_touch_filter.h"
#include "ui/events/ozone/evdev/touch_filter/far_apart_taps_touch_noise_filter.h"
......@@ -14,34 +17,28 @@
namespace ui {
FalseTouchFinder::FalseTouchFinder(
bool touch_noise_filtering,
bool edge_filtering,
gfx::Size touchscreen_size)
: last_noise_time_(ui::EventTimeForNow()) {
if (touch_noise_filtering) {
noise_filters_.push_back(std::make_unique<FarApartTapsTouchNoiseFilter>());
noise_filters_.push_back(
std::make_unique<HorizontallyAlignedTouchNoiseFilter>());
noise_filters_.push_back(
std::make_unique<SinglePositionTouchNoiseFilter>());
}
if (edge_filtering) {
edge_touch_filter_ = std::make_unique<EdgeTouchFilter>(touchscreen_size);
}
}
FalseTouchFinder::~FalseTouchFinder() {}
FalseTouchFinder::~FalseTouchFinder() {
std::unique_ptr<FalseTouchFinder> FalseTouchFinder::Create(
gfx::Size touchscreen_size) {
bool noise_filtering = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kExtraTouchNoiseFiltering);
bool edge_filtering = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEdgeTouchFiltering);
if (noise_filtering || edge_filtering) {
return base::WrapUnique(new FalseTouchFinder(
noise_filtering, edge_filtering, touchscreen_size));
}
return nullptr;
}
void FalseTouchFinder::HandleTouches(
const std::vector<InProgressTouchEvdev>& touches,
base::TimeTicks time) {
for (const InProgressTouchEvdev& touch : touches) {
if (!touch.was_touching) {
slots_should_delay_.set(touch.slot, false);
if (!touch.was_touching)
slots_with_noise_.set(touch.slot, false);
slots_should_delay_.set(touch.slot, false);
}
}
bool had_noise = slots_with_noise_.any();
......@@ -49,8 +46,8 @@ void FalseTouchFinder::HandleTouches(
for (const auto& filter : noise_filters_)
filter->Filter(touches, time, &slots_with_noise_);
if (edge_touch_filter_)
edge_touch_filter_->Filter(touches, time, &slots_should_delay_);
for (const auto& filter : delay_filters_)
filter->Filter(touches, time, &slots_should_delay_);
RecordUMA(had_noise, time);
}
......@@ -63,6 +60,23 @@ bool FalseTouchFinder::SlotShouldDelay(size_t slot) const {
return slots_should_delay_.test(slot);
}
FalseTouchFinder::FalseTouchFinder(bool noise_filtering,
bool edge_filtering,
gfx::Size touchscreen_size)
: last_noise_time_(ui::EventTimeForNow()) {
if (noise_filtering) {
noise_filters_.push_back(std::make_unique<FarApartTapsTouchNoiseFilter>());
noise_filters_.push_back(
std::make_unique<HorizontallyAlignedTouchNoiseFilter>());
noise_filters_.push_back(
std::make_unique<SinglePositionTouchNoiseFilter>());
}
if (edge_filtering) {
delay_filters_.push_back(
std::make_unique<EdgeTouchFilter>(touchscreen_size));
}
}
void FalseTouchFinder::RecordUMA(bool had_noise, base::TimeTicks time) {
if (slots_with_noise_.any()) {
if (!had_noise) {
......
......@@ -24,11 +24,10 @@ class TouchFilter;
// Finds touches which are should be filtered.
class EVENTS_OZONE_EVDEV_EXPORT FalseTouchFinder {
public:
FalseTouchFinder(bool touch_noise_filtering,
bool edge_filtering,
gfx::Size touchscreen_size);
~FalseTouchFinder();
static std::unique_ptr<FalseTouchFinder> Create(gfx::Size touchscreen_size);
// Updates which ABS_MT_SLOTs should be filtered. |touches| should contain
// all of the in-progress touches at |time| (including filtered touches).
// |touches| should have at most one entry per ABS_MT_SLOT.
......@@ -44,6 +43,10 @@ class EVENTS_OZONE_EVDEV_EXPORT FalseTouchFinder {
bool SlotShouldDelay(size_t slot) const;
private:
FalseTouchFinder(bool touch_noise_filtering,
bool edge_filtering,
gfx::Size touchscreen_size);
// Records how frequently noisy touches occur to UMA.
void RecordUMA(bool had_noise, base::TimeTicks time);
......@@ -62,9 +65,9 @@ class EVENTS_OZONE_EVDEV_EXPORT FalseTouchFinder {
// cancelled by the touch converter.
std::vector<std::unique_ptr<TouchFilter>> noise_filters_;
// The edge filter detects taps on the edge. The edge filter should only
// filter slots which it is already filtering or which are new.
std::unique_ptr<TouchFilter> edge_touch_filter_;
// Delay filters may filter questionable new touches for an indefinite time,
// but should not start filtering a touch that it had previously allowed.
std::vector<std::unique_ptr<TouchFilter>> delay_filters_;
DISALLOW_COPY_AND_ASSIGN(FalseTouchFinder);
};
......
......@@ -9,10 +9,12 @@
#include <algorithm>
#include <memory>
#include "base/command_line.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/event_switches.h"
#include "ui/events/ozone/evdev/touch_evdev_types.h"
#include "ui/gfx/geometry/point_f.h"
......@@ -80,8 +82,11 @@ class FalseTouchFinderTest : public testing::Test {
private:
// testing::Test:
void SetUp() override {
false_touch_finder_.reset(
new FalseTouchFinder(true, true, touchscreen_size));
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kExtraTouchNoiseFiltering);
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEdgeTouchFiltering);
false_touch_finder_ = FalseTouchFinder::Create(touchscreen_size);
}
std::unique_ptr<FalseTouchFinder> false_touch_finder_;
......
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