summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rw-r--r--copy.bara.sky2
-rw-r--r--ui/events/ozone/evdev/touch_evdev_types.cc10
-rw-r--r--ui/events/ozone/evdev/touch_evdev_types.h2
-rw-r--r--ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc48
-rw-r--r--ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h25
-rw-r--r--ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.cc85
-rw-r--r--ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.h22
-rw-r--r--ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util_unittest.cc23
-rw-r--r--ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.cc25
-rw-r--r--ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.h3
11 files changed, 221 insertions, 25 deletions
diff --git a/Android.bp b/Android.bp
index f5e89dd..7211fd9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -24,6 +24,7 @@ cc_library_static {
"ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.cc",
"ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.cc",
"ui/events/ozone/evdev/touch_filter/palm_detection_filter.cc",
+ "ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.cc",
"ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.cc",
"ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.cc",
"ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.cc",
diff --git a/copy.bara.sky b/copy.bara.sky
index 292f008..c270d38 100644
--- a/copy.bara.sky
+++ b/copy.bara.sky
@@ -19,6 +19,7 @@ core.workflow(
"ui/events/ozone/evdev/touch_filter/palm_detection_filter.cc",
"ui/events/ozone/evdev/touch_filter/palm_model/**",
"ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.h",
+ "ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.cc",
"ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h",
"ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.cc",
"ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.h",
@@ -61,6 +62,7 @@ core.workflow(
"ui/events/ozone/evdev/touch_filter/palm_detection_filter.cc",
"ui/events/ozone/evdev/touch_filter/palm_model/**",
"ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.h",
+ "ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.cc",
"ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h",
"ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.cc",
"ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.h",
diff --git a/ui/events/ozone/evdev/touch_evdev_types.cc b/ui/events/ozone/evdev/touch_evdev_types.cc
index 39e598b..83ee59a 100644
--- a/ui/events/ozone/evdev/touch_evdev_types.cc
+++ b/ui/events/ozone/evdev/touch_evdev_types.cc
@@ -13,6 +13,16 @@ InProgressTouchEvdev::InProgressTouchEvdev(const InProgressTouchEvdev& other) =
InProgressTouchEvdev::~InProgressTouchEvdev() = default;
+std::ostream& operator<<(std::ostream& out, const InProgressTouchEvdev& touch) {
+ out << "InProgressTouchEvdev(x=" << touch.x << ", y=" << touch.y
+ << ", tracking_id=" << touch.tracking_id << ", slot=" << touch.slot
+ << ", pressure=" << touch.pressure << ", major=" << touch.major
+ << ", minor=" << touch.minor << ", tool_type=" << touch.tool_type
+ << ", altered=" << touch.altered << "was_touching=" << touch.was_touching
+ << ", touching=" << touch.touching << ")";
+ return out;
+}
+
InProgressStylusState::InProgressStylusState() = default;
InProgressStylusState::InProgressStylusState(
diff --git a/ui/events/ozone/evdev/touch_evdev_types.h b/ui/events/ozone/evdev/touch_evdev_types.h
index fee670a..37e0e0a 100644
--- a/ui/events/ozone/evdev/touch_evdev_types.h
+++ b/ui/events/ozone/evdev/touch_evdev_types.h
@@ -78,6 +78,8 @@ struct COMPONENT_EXPORT(EVDEV) InProgressTouchEvdev {
bool stylus_button = false;
};
+std::ostream& operator<<(std::ostream& out, const InProgressTouchEvdev& touch);
+
// Contains information about stylus event, the useful relate ddevice info and
// the timestamp.
struct COMPONENT_EXPORT(EVDEV) InProgressStylusState {
diff --git a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc
index e04c97c..1e5724c 100644
--- a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc
+++ b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc
@@ -161,8 +161,8 @@ void NeuralStylusPalmDetectionFilter::Filter(
DCHECK(strokes_.count(tracking_id) == 0)
<< " Tracking id " << tracking_id;
- strokes_.emplace(tracking_id, PalmFilterStroke(model_->config()));
- strokes_.find(tracking_id)->second.SetTrackingId(tracking_id);
+ strokes_.emplace(tracking_id,
+ PalmFilterStroke(model_->config(), tracking_id));
tracking_ids_[slot] = tracking_id;
is_palm_.set(slot, false);
is_delay_.set(slot, false);
@@ -244,7 +244,7 @@ void NeuralStylusPalmDetectionFilter::Filter(
LOG(DFATAL) << "Unable to find marked stroke.";
continue;
}
- auto& stroke = lookup->second;
+ const auto& stroke = lookup->second;
if (stroke.samples_seen() < model_->config().min_sample_count) {
// in very short strokes: we use a heuristic.
is_palm_.set(slot, IsHeuristicPalmStroke(stroke));
@@ -531,4 +531,46 @@ void NeuralStylusPalmDetectionFilter::EraseOldStrokes(base::TimeTicks time) {
}
previous_report_time_ = time;
}
+
+static std::string addLinePrefix(std::string str, const std::string& prefix) {
+ std::stringstream ss;
+ bool newLineStarted = true;
+ for (const auto& ch : str) {
+ if (newLineStarted) {
+ ss << prefix;
+ newLineStarted = false;
+ }
+ if (ch == '\n') {
+ newLineStarted = true;
+ }
+ ss << ch;
+ }
+ return ss.str();
+}
+
+std::ostream& operator<<(std::ostream& out,
+ const NeuralStylusPalmDetectionFilter& filter) {
+ out << "NeuralStylusPalmDetectionFilter(\n";
+ out << " is_palm_ = " << filter.is_palm_ << "\n";
+ out << " is_delay_ = " << filter.is_delay_ << "\n";
+ out << " strokes_ =\n";
+ std::stringstream strokes;
+ strokes << filter.strokes_;
+ out << addLinePrefix(strokes.str(), " ") << "\n";
+ out << " previous_report_time_ = " << filter.previous_report_time_ << "\n";
+ out << " active_tracking_ids_ = " << filter.active_tracking_ids_ << "\n";
+ out << " tracking_ids_count_within_session_ = "
+ << filter.tracking_ids_count_within_session_ << "\n";
+ out << " tracking_ids = [";
+ for (int i = 0; i < kNumTouchEvdevSlots; i++) {
+ out << filter.tracking_ids_[i] << ", ";
+ }
+ out << "]\n";
+
+ out << " palm_filter_dev_info_ = " << filter.palm_filter_dev_info_ << "\n";
+ out << ")\n";
+
+ return out;
+}
+
} // namespace ui
diff --git a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h
index fa8b2fa..bab332e 100644
--- a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h
+++ b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h
@@ -31,6 +31,24 @@ namespace ui {
const base::TimeDelta kResamplePeriod = base::Milliseconds(8);
#endif
+template <typename K, typename V>
+std::ostream& operator<<(std::ostream& out, const std::map<K, V>& map) {
+ for (const auto& [k, v] : map) {
+ out << k << " : " << v << "\n";
+ }
+ return out;
+}
+
+template <typename T>
+std::ostream& operator<<(std::ostream& out, const std::unordered_set<T>& set) {
+ out << "{";
+ for (const auto& entry : set) {
+ out << entry << ", ";
+ }
+ out << "}";
+ return out;
+}
+
// An implementation of PalmDetectionFilter that relies on a DNN implementation
// to decide on palm detection. Requires a configured model as an argument.
// Heuristics are added for handling short strokes
@@ -108,8 +126,15 @@ class COMPONENT_EXPORT(EVDEV) NeuralStylusPalmDetectionFilter
int tracking_ids_[kNumTouchEvdevSlots];
const PalmFilterDeviceInfo palm_filter_dev_info_;
std::unique_ptr<NeuralStylusPalmDetectionFilterModel> model_;
+
+ friend std::ostream& operator<<(
+ std::ostream& out,
+ const NeuralStylusPalmDetectionFilter& filter);
};
+std::ostream& operator<<(std::ostream& out,
+ const NeuralStylusPalmDetectionFilter& filter);
+
} // namespace ui
#endif // UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_NEURAL_STYLUS_PALM_DETECTION_FILTER_H_
diff --git a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.cc b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.cc
index 2874d50..d1813ef 100644
--- a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.cc
+++ b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.cc
@@ -142,17 +142,16 @@ PalmFilterSample CreatePalmFilterSample(
}
PalmFilterStroke::PalmFilterStroke(
- const NeuralStylusPalmDetectionFilterModelConfig& model_config)
- : max_sample_count_(model_config.max_sample_count),
+ const NeuralStylusPalmDetectionFilterModelConfig& model_config,
+ int tracking_id)
+ : tracking_id_(tracking_id),
+ max_sample_count_(model_config.max_sample_count),
resample_period_(model_config.resample_period) {}
PalmFilterStroke::PalmFilterStroke(const PalmFilterStroke& other) = default;
PalmFilterStroke::PalmFilterStroke(PalmFilterStroke&& other) = default;
PalmFilterStroke::~PalmFilterStroke() {}
void PalmFilterStroke::ProcessSample(const PalmFilterSample& sample) {
- if (samples_seen_ == 0) {
- tracking_id_ = sample.tracking_id;
- }
DCHECK_EQ(tracking_id_, sample.tracking_id);
if (resample_period_.has_value()) {
Resample(sample);
@@ -231,10 +230,6 @@ uint64_t PalmFilterStroke::samples_seen() const {
return samples_seen_;
}
-void PalmFilterStroke::SetTrackingId(int tracking_id) {
- tracking_id_ = tracking_id;
-}
-
float PalmFilterStroke::MaxMajorRadius() const {
float maximum = 0.0;
for (const auto& sample : samples_) {
@@ -257,4 +252,76 @@ float PalmFilterStroke::BiggestSize() const {
return biggest;
}
+static std::string addLinePrefix(std::string str, const std::string& prefix) {
+ std::stringstream ss;
+ bool newLineStarted = true;
+ for (const auto& ch : str) {
+ if (newLineStarted) {
+ ss << prefix;
+ newLineStarted = false;
+ }
+ if (ch == '\n') {
+ newLineStarted = true;
+ }
+ ss << ch;
+ }
+ return ss.str();
+}
+
+std::ostream& operator<<(std::ostream& out, const gfx::PointF& point) {
+ out << "PointF(" << point.x() << ", " << point.y() << ")";
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out, const gfx::Vector2dF& vec) {
+ out << "Vector2dF(" << vec.x() << ", " << vec.y() << ")";
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out, const PalmFilterDeviceInfo& info) {
+ out << "PalmFilterDeviceInfo(max_x=" << info.max_x;
+ out << ", max_y=" << info.max_y;
+ out << ", x_res=" << info.x_res;
+ out << ", y_res=" << info.y_res;
+ out << ", major_radius_res=" << info.major_radius_res;
+ out << ", minor_radius_res=" << info.minor_radius_res;
+ out << ", minor_radius_supported=" << info.minor_radius_supported;
+ out << ")";
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out, const PalmFilterSample& sample) {
+ out << "PalmFilterSample(major=" << sample.major_radius
+ << ", minor=" << sample.minor_radius << ", pressure=" << sample.pressure
+ << ", edge=" << sample.edge << ", tracking_id=" << sample.tracking_id
+ << ", point=" << sample.point << ", time=" << sample.time << ")";
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out, const PalmFilterStroke& stroke) {
+ out << "PalmFilterStroke(\n";
+ out << " GetCentroid() = " << stroke.GetCentroid() << "\n";
+ out << " BiggestSize() = " << stroke.BiggestSize() << "\n";
+ out << " MaxMajorRadius() = " << stroke.MaxMajorRadius() << "\n";
+ std::stringstream stream;
+ stream << stroke.samples();
+ out << " samples (" << stroke.samples().size() << " total): \n"
+ << addLinePrefix(stream.str(), " ") << "\n";
+ out << " samples_seen() = " << stroke.samples_seen() << "\n";
+ out << " tracking_id() = " << stroke.tracking_id() << "\n";
+ out << " max_sample_count_ = " << stroke.max_sample_count_ << "\n";
+ if (stroke.resample_period_) {
+ out << " resample_period_ = " << *(stroke.resample_period_) << "\n";
+ out << " last_sample_ = " << stroke.last_sample_ << "\n";
+ } else {
+ out << " resample_period_ = <not set>\n";
+ out << " last_sample_ = <not valid b/c resampling is off>\n";
+ }
+ out << " unscaled_centroid_ = " << stroke.unscaled_centroid_ << "\n";
+ out << " unscaled_centroid_sum_error_ = "
+ << stroke.unscaled_centroid_sum_error_ << "\n";
+ out << ")\n";
+ return out;
+}
+
} // namespace ui
diff --git a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.h b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.h
index e5e9419..47f0c33 100644
--- a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.h
+++ b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.h
@@ -37,6 +37,8 @@ struct COMPONENT_EXPORT(EVDEV) PalmFilterDeviceInfo {
#endif
};
+std::ostream& operator<<(std::ostream& out, const PalmFilterDeviceInfo& info);
+
#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__)
COMPONENT_EXPORT(EVDEV)
PalmFilterDeviceInfo CreatePalmFilterDeviceInfo(const EventDeviceInfo& devinfo);
@@ -60,6 +62,8 @@ struct COMPONENT_EXPORT(EVDEV) PalmFilterSample {
}
};
+std::ostream& operator<<(std::ostream& out, const PalmFilterSample& sample);
+
COMPONENT_EXPORT(EVDEV)
PalmFilterSample CreatePalmFilterSample(
const InProgressTouchEvdev& touch,
@@ -70,7 +74,8 @@ PalmFilterSample CreatePalmFilterSample(
class COMPONENT_EXPORT(EVDEV) PalmFilterStroke {
public:
explicit PalmFilterStroke(
- const NeuralStylusPalmDetectionFilterModelConfig& model_config);
+ const NeuralStylusPalmDetectionFilterModelConfig& model_config,
+ int tracking_id);
PalmFilterStroke(const PalmFilterStroke& other);
PalmFilterStroke(PalmFilterStroke&& other);
~PalmFilterStroke();
@@ -80,7 +85,6 @@ class COMPONENT_EXPORT(EVDEV) PalmFilterStroke {
float BiggestSize() const;
// If no elements in stroke, returns 0.0;
float MaxMajorRadius() const;
- void SetTrackingId(int tracking_id);
const std::deque<PalmFilterSample>& samples() const;
uint64_t samples_seen() const;
int tracking_id() const;
@@ -94,7 +98,7 @@ class COMPONENT_EXPORT(EVDEV) PalmFilterStroke {
void Resample(const PalmFilterSample& sample);
std::deque<PalmFilterSample> samples_;
- int tracking_id_ = 0;
+ const int tracking_id_;
/**
* How many total samples have been reported for this stroke. This is
* different from samples_.size() because samples_ will get pruned to only
@@ -117,8 +121,20 @@ class COMPONENT_EXPORT(EVDEV) PalmFilterStroke {
// Used in part of the kahan summation.
gfx::Vector2dF unscaled_centroid_sum_error_ =
gfx::PointF(0., 0.).OffsetFromOrigin();
+ friend std::ostream& operator<<(std::ostream& out,
+ const PalmFilterStroke& stroke);
};
+template <typename T>
+std::ostream& operator<<(std::ostream& out, const std::deque<T>& queue) {
+ for (const auto& entry : queue) {
+ out << entry << "\n";
+ }
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out, const PalmFilterStroke& filter);
+
} // namespace ui
#endif // UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_NEURAL_STYLUS_PALM_DETECTION_FILTER_UTIL_H_
diff --git a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util_unittest.cc b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util_unittest.cc
index 41364ae..ac3c841 100644
--- a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util_unittest.cc
+++ b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util_unittest.cc
@@ -234,8 +234,8 @@ TEST_P(NeuralStylusPalmDetectionFilterUtilTest, LinkTouchscreenSampleTest) {
}
TEST_P(NeuralStylusPalmDetectionFilterUtilTest, PalmFilterStrokeTest) {
- PalmFilterStroke stroke(model_config_);
- EXPECT_EQ(0, stroke.tracking_id());
+ PalmFilterStroke stroke(model_config_, /*tracking_id*/ 55);
+ touch_.tracking_id = 55;
// With no points, center is 0.
EXPECT_EQ(gfx::PointF(0., 0.), stroke.GetCentroid());
@@ -272,14 +272,13 @@ TEST_P(NeuralStylusPalmDetectionFilterUtilTest, PalmFilterStrokeTest) {
ASSERT_FLOAT_EQ(expected_centroid.x(), stroke.GetCentroid().x())
<< "failed at i " << i;
}
- stroke.SetTrackingId(55);
- EXPECT_EQ(55, stroke.tracking_id());
}
TEST_P(NeuralStylusPalmDetectionFilterUtilTest,
PalmFilterStrokeBiggestSizeTest) {
- PalmFilterStroke stroke(model_config_);
- PalmFilterStroke no_minor_stroke(model_config_);
+ PalmFilterStroke stroke(model_config_, /*tracking_id*/ 0);
+ PalmFilterStroke no_minor_stroke(model_config_, /*tracking_id*/ 0);
+ touch_.tracking_id = stroke.tracking_id();
EXPECT_EQ(0, stroke.BiggestSize());
base::TimeTicks time = base::TimeTicks() + base::Seconds(30);
@@ -327,7 +326,8 @@ TEST_P(NeuralStylusPalmDetectionFilterUtilTest, UnscaledMajorMinorResolution) {
}
TEST_P(NeuralStylusPalmDetectionFilterUtilTest, StrokeGetMaxMajorTest) {
- PalmFilterStroke stroke(model_config_);
+ PalmFilterStroke stroke(model_config_, /*tracking_id*/ 0);
+ touch_.tracking_id = stroke.tracking_id();
EXPECT_FLOAT_EQ(0, stroke.MaxMajorRadius());
base::TimeTicks time = base::TimeTicks::UnixEpoch() + base::Seconds(30);
const PalmFilterDeviceInfo nocturne_distilled =
@@ -377,7 +377,7 @@ TEST(PalmFilterStrokeTest, NumberOfResampledValues) {
model_config_.resample_period = base::Milliseconds(8);
base::TimeTicks down_time = base::TimeTicks::UnixEpoch() + base::Seconds(30);
- PalmFilterStroke stroke(model_config_);
+ PalmFilterStroke stroke(model_config_, /*tracking_id*/ 0);
const PalmFilterDeviceInfo device_info;
// Initially, no samples
@@ -386,6 +386,7 @@ TEST(PalmFilterStrokeTest, NumberOfResampledValues) {
// Add first sample at time = T
InProgressTouchEvdev touch_;
+ touch_.tracking_id = stroke.tracking_id();
PalmFilterSample sample =
CreatePalmFilterSample(touch_, down_time, model_config_, device_info);
stroke.ProcessSample(sample);
@@ -416,12 +417,13 @@ TEST(PalmFilterStrokeTest, ResamplingTest) {
model_config_.max_sample_count = 3;
model_config_.resample_period = base::Milliseconds(8);
- PalmFilterStroke stroke(model_config_);
+ PalmFilterStroke stroke(model_config_, /*tracking_id*/ 0);
PalmFilterDeviceInfo device_info;
device_info.minor_radius_supported = true;
// Add first sample at time = T
InProgressTouchEvdev touch_;
+ touch_.tracking_id = stroke.tracking_id();
touch_.x = 1;
touch_.y = 2;
touch_.major = 4;
@@ -471,12 +473,13 @@ TEST(PalmFilterStrokeTest, MultipleResampledValues) {
model_config_.max_sample_count = 3;
model_config_.resample_period = base::Milliseconds(8);
- PalmFilterStroke stroke(model_config_);
+ PalmFilterStroke stroke(model_config_, /*tracking_id*/ 0);
PalmFilterDeviceInfo device_info;
device_info.minor_radius_supported = true;
// Add first sample at time = T
InProgressTouchEvdev touch_;
+ touch_.tracking_id = stroke.tracking_id();
touch_.x = 0;
touch_.y = 10;
touch_.major = 200;
diff --git a/ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.cc b/ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.cc
new file mode 100644
index 0000000..7e843ba
--- /dev/null
+++ b/ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.cc
@@ -0,0 +1,25 @@
+// Copyright 2022 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_filter/shared_palm_detection_filter_state.h"
+
+namespace ui {
+
+std::ostream& operator<<(std::ostream& out,
+ const SharedPalmDetectionFilterState& state) {
+ base::TimeTicks now = base::TimeTicks::Now();
+ out << "SharedPalmDetectionFilterState(\n";
+ out << " latest_stylus_touch_time = " << state.latest_stylus_touch_time
+ << " (" << now - state.latest_stylus_touch_time << " from now)\n";
+ out << " latest_finger_touch_time = " << state.latest_finger_touch_time
+ << "\n";
+ out << " active_finger_touches = " << state.active_finger_touches << "\n";
+ out << " active_palm_touches = " << state.active_palm_touches << "\n";
+ out << " latest_palm_touch_time = " << state.latest_palm_touch_time << "\n";
+ out << " Now() = " << now << "\n";
+ out << ")";
+ return out;
+}
+
+} // namespace ui \ No newline at end of file
diff --git a/ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.h b/ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.h
index 942e6d2..bff9abb 100644
--- a/ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.h
+++ b/ui/events/ozone/evdev/touch_filter/shared_palm_detection_filter_state.h
@@ -29,6 +29,9 @@ struct SharedPalmDetectionFilterState {
base::TimeTicks latest_palm_touch_time = base::TimeTicks::UnixEpoch();
};
+std::ostream& operator<<(std::ostream& out,
+ const SharedPalmDetectionFilterState& state);
+
} // namespace ui
#endif // UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_SHARED_PALM_DETECTION_FILTER_STATE_H_ \ No newline at end of file