summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarry Cutts <hcutts@google.com>2023-01-13 16:36:24 +0000
committerHarry Cutts <hcutts@google.com>2023-01-13 16:43:24 +0000
commit0d4e0160efa20717934a23323805f5817d224032 (patch)
tree0b1f87b9b1633009765c1f27d7f2a0000c84eada
parent681529d6c173bd072287ac3b7e9e25dc2540fbb2 (diff)
parent10ca30a7497231a1c978264f4220c863f5d35727 (diff)
downloadlibchrome-gestures-0d4e0160efa20717934a23323805f5817d224032.tar.gz
Merge remote-tracking branch 'aosp/upstream-main' into gestures-updateplatform-tools-34.0.0platform-tools-33.0.4main-16k-with-phones
The main change we need here is the addition of the "Invert Scrolling" property. The other changes are documentation and test coverage fixes. Bug: 251196347 Test: Treehugger Change-Id: Ifde19527eb0ff0322aa0bd988333d449f992789a
-rw-r--r--METADATA.android4
-rw-r--r--Makefile4
-rw-r--r--docs/gesture_properties.md9
-rw-r--r--include/finger_merge_filter_interpreter.h1
-rw-r--r--include/gestures.h51
-rw-r--r--include/haptic_button_generator_filter_interpreter.h5
-rw-r--r--include/immediate_interpreter.h2
-rw-r--r--include/metrics_filter_interpreter.h4
-rw-r--r--include/palm_classifying_filter_interpreter.h3
-rw-r--r--include/scaling_filter_interpreter.h7
-rw-r--r--include/stationary_wiggle_filter_interpreter.h3
-rw-r--r--include/trace_marker.h3
-rw-r--r--include/trend_classifying_filter_interpreter.h1
-rw-r--r--src/finger_merge_filter_interpreter_unittest.cc136
-rw-r--r--src/haptic_button_generator_filter_interpreter.cc21
-rw-r--r--src/haptic_button_generator_filter_interpreter_unittest.cc65
-rw-r--r--src/immediate_interpreter_unittest.cc13
-rw-r--r--src/lookahead_filter_interpreter.cc20
-rw-r--r--src/metrics_filter_interpreter_unittest.cc230
-rw-r--r--src/palm_classifying_filter_interpreter.cc7
-rw-r--r--src/palm_classifying_filter_interpreter_unittest.cc10
-rw-r--r--src/prop_registry_unittest.cc147
-rw-r--r--src/scaling_filter_interpreter.cc16
-rw-r--r--src/stationary_wiggle_filter_interpreter_unittest.cc152
-rw-r--r--src/trace_marker_unittest.cc7
-rw-r--r--src/trend_classifying_filter_interpreter_unittest.cc120
26 files changed, 996 insertions, 45 deletions
diff --git a/METADATA.android b/METADATA.android
index 6759c17..8df3226 100644
--- a/METADATA.android
+++ b/METADATA.android
@@ -6,7 +6,7 @@ third_party {
type: GIT
value: "https://chromium.googlesource.com/chromiumos/platform/gestures/"
}
- version: "c7054fe1a0729f9d84c5e6441a385bf362d7a6e7"
- last_upgrade_date { year: 2022 month: 11 day: 23 }
+ version: "10ca30a7497231a1c978264f4220c863f5d35727"
+ last_upgrade_date { year: 2023 month: 01 day: 13 }
license_type: NOTICE
}
diff --git a/Makefile b/Makefile
index b0e4c75..c6165e9 100644
--- a/Makefile
+++ b/Makefile
@@ -51,6 +51,7 @@ TEST_OBJECTS=\
$(OBJDIR)/click_wiggle_filter_interpreter_unittest.o \
$(OBJDIR)/command_line.o \
$(OBJDIR)/filter_interpreter_unittest.o \
+ $(OBJDIR)/finger_merge_filter_interpreter_unittest.o \
$(OBJDIR)/finger_metrics_unittest.o \
$(OBJDIR)/fling_stop_filter_interpreter_unittest.o \
$(OBJDIR)/gestures_unittest.o \
@@ -63,6 +64,7 @@ TEST_OBJECTS=\
$(OBJDIR)/logging_filter_interpreter_unittest.o \
$(OBJDIR)/lookahead_filter_interpreter_unittest.o \
$(OBJDIR)/non_linearity_filter_interpreter_unittest.o \
+ $(OBJDIR)/metrics_filter_interpreter_unittest.o \
$(OBJDIR)/mouse_interpreter_unittest.o \
$(OBJDIR)/multitouch_mouse_interpreter_unittest.o \
$(OBJDIR)/palm_classifying_filter_interpreter_unittest.o \
@@ -70,12 +72,14 @@ TEST_OBJECTS=\
$(OBJDIR)/scaling_filter_interpreter_unittest.o \
$(OBJDIR)/sensor_jump_filter_interpreter_unittest.o \
$(OBJDIR)/split_correcting_filter_interpreter_unittest.o \
+ $(OBJDIR)/stationary_wiggle_filter_interpreter_unittest.o \
$(OBJDIR)/string_util_unittest.o \
$(OBJDIR)/stuck_button_inhibitor_filter_interpreter_unittest.o \
$(OBJDIR)/t5r2_correcting_filter_interpreter_unittest.o \
$(OBJDIR)/timestamp_filter_interpreter_unittest.o \
$(OBJDIR)/trace_marker_unittest.o \
$(OBJDIR)/tracer_unittest.o \
+ $(OBJDIR)/trend_classifying_filter_interpreter_unittest.o \
$(OBJDIR)/unittest_util.o \
$(OBJDIR)/util_unittest.o \
$(OBJDIR)/vector_unittest.o
diff --git a/docs/gesture_properties.md b/docs/gesture_properties.md
index 813601c..28eda53 100644
--- a/docs/gesture_properties.md
+++ b/docs/gesture_properties.md
@@ -18,9 +18,12 @@ such as "Scroll Accel Curve", "Mouse Reverse Scrolling", or "Palm Pressure".
Each property has a type (integer, double, boolean, or string), and a size,
which is the number of values of that type that it stores. (For strings, the
-size is always 1.) Some properties are read-only, which normally means that
-modifying them wouldn't make sense (for example, the "Device Vendor ID"
-property, which reflects a hardware ID).
+size is always 1.)
+
+Chromium creates some read-only properties, which normally means that modifying
+them wouldn't make sense (for example, the "Device Vendor ID" property, which
+reflects a hardware ID). However, the Gestures library itself does not do this,
+so other clients don't need to support them.
## Changing properties without recompiling
diff --git a/include/finger_merge_filter_interpreter.h b/include/finger_merge_filter_interpreter.h
index e8d8ef7..44abd23 100644
--- a/include/finger_merge_filter_interpreter.h
+++ b/include/finger_merge_filter_interpreter.h
@@ -24,6 +24,7 @@ namespace gestures {
// merging/merged finger(s).
class FingerMergeFilterInterpreter : public FilterInterpreter {
+ FRIEND_TEST(FingerMergeFilterInterpreterTest, SimpleTest);
public:
FingerMergeFilterInterpreter(PropRegistry* prop_reg, Interpreter* next,
diff --git a/include/gestures.h b/include/gestures.h
index 07e4306..5a1acc9 100644
--- a/include/gestures.h
+++ b/include/gestures.h
@@ -160,6 +160,7 @@ struct HardwareProperties {
// skip the flag so that we can have the option to use the not-that-accurate
// positions.
#define GESTURES_FINGER_WARP_TELEPORTATION (1 << 19)
+#define GESTURES_FINGER_LARGE_PALM (1 << 20)
#define GESTURES_FINGER_WARP_X (GESTURES_FINGER_WARP_X_NON_MOVE | \
GESTURES_FINGER_WARP_X_MOVE)
@@ -343,21 +344,38 @@ typedef struct {
float data[2];
} GestureMetrics;
+// Describes the type of gesture that is being reported.
enum GestureType {
#ifdef GESTURES_INTERNAL
kGestureTypeNull = -1, // internal to Gestures library only
#endif // GESTURES_INTERNAL
+ // No longer used.
kGestureTypeContactInitiated = 0,
+ // For touchpads, a movement of a single finger on the pad. For mice, a
+ // movement of the whole mouse.
kGestureTypeMove,
+ // A two-finger scroll gesture on a touchpad. (See kGestureTypeMouseWheel for
+ // the mouse equivalent.)
kGestureTypeScroll,
+ // A change in the buttons that are currently pressed on the device.
kGestureTypeButtonsChange,
+ // The start or end of a fling motion, where scrolling should continue after
+ // the user's fingers have left the touchpad.
kGestureTypeFling,
+ // A movement of three fingers on a touchpad.
kGestureTypeSwipe,
+ // A movement of two fingers on a touchpad that are primarily moving closer to
+ // or further from each other.
kGestureTypePinch,
+ // The end of a movement of three fingers on a touchpad.
kGestureTypeSwipeLift,
+ // Used to report metrics to the client.
kGestureTypeMetrics,
+ // A movement of four fingers on a touchpad.
kGestureTypeFourFingerSwipe,
+ // The end of a movement of four fingers on a touchpad.
kGestureTypeFourFingerSwipeLift,
+ // The movement of a scroll wheel on a mouse.
kGestureTypeMouseWheel,
};
@@ -522,8 +540,10 @@ typedef unsigned char GesturesPropBool;
// These functions create a named property of given type.
// data - data used by PropProvider
-// loc - location of a variable to be updated by PropProvider.
-// Set to NULL to create a ReadOnly property
+// loc - location of a variable to be updated by PropProvider
+// (Chromium calls its own GesturesPropCreate... functions with loc set
+// to null to create read-only properties, but the Gestures library
+// itself doesn't, so other clients don't need to support them.)
// init - initial value for the property.
// If the PropProvider has an alternate configuration source, it may
// override this initial value, in which case *loc returns the
@@ -532,9 +552,9 @@ typedef GesturesProp* (*GesturesPropCreateInt)(void* data, const char* name,
int* loc, size_t count,
const int* init);
-typedef GesturesProp* (*GesturesPropCreateShort)(void* data, const char* name,
- short* loc, size_t count,
- const short* init);
+// Deprecated: the gestures library no longer uses short gesture properties.
+typedef GesturesProp* (*GesturesPropCreateShort_Deprecated)(
+ void*, const char*, short*, size_t, const short*);
typedef GesturesProp* (*GesturesPropCreateBool)(void* data, const char* name,
GesturesPropBool* loc,
@@ -558,12 +578,17 @@ typedef GesturesPropBool (*GesturesPropGetHandler)(void* handler_data);
// |handler_data| is a local context pointer that can be used by the handler.
typedef void (*GesturesPropSetHandler)(void* handler_data);
-// Register handlers to be called when a GesturesProp is accessed.
-// The get handler, if not NULL, is called immediately before the property's
-// value is to be read. This gives the library a chance to update its value.
-// The set handler, if not NULL, is called immediately after the property's
-// value is updated. This can be used to create a property that is used to
-// trigger an action, or to force an update to multiple properties atomically.
+// Register handlers for the client to call when a GesturesProp is accessed.
+//
+// The get handler, if not NULL, should be called immediately before the
+// property's value is to be read. This gives the library a chance to update its
+// value.
+//
+// The set handler, if not NULL, should be called immediately after the
+// property's value is updated. This can be used to create a property that is
+// used to trigger an action, or to force an update to multiple properties
+// atomically.
+//
// Note: the handlers are called from non-signal/interrupt context
typedef void (*GesturesPropRegisterHandlers)(void* data, GesturesProp* prop,
void* handler_data,
@@ -575,7 +600,9 @@ typedef void (*GesturesPropFree)(void* data, GesturesProp* prop);
typedef struct GesturesPropProvider {
GesturesPropCreateInt create_int_fn;
- GesturesPropCreateShort create_short_fn;
+ // Deprecated: the library no longer uses short gesture properties, so this
+ // function pointer should be null.
+ GesturesPropCreateShort_Deprecated create_short_fn;
GesturesPropCreateBool create_bool_fn;
GesturesPropCreateString create_string_fn;
GesturesPropCreateReal create_real_fn;
diff --git a/include/haptic_button_generator_filter_interpreter.h b/include/haptic_button_generator_filter_interpreter.h
index c563104..22a4a92 100644
--- a/include/haptic_button_generator_filter_interpreter.h
+++ b/include/haptic_button_generator_filter_interpreter.h
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <gtest/gtest.h> // for FRIEND_TEST
+#include <set>
#include "include/filter_interpreter.h"
#include "include/gestures.h"
@@ -24,6 +25,7 @@ class HapticButtonGeneratorFilterInterpreter : public FilterInterpreter {
FRIEND_TEST(HapticButtonGeneratorFilterInterpreterTest,
GesturePreventsButtonDownTest);
FRIEND_TEST(HapticButtonGeneratorFilterInterpreterTest, DynamicThresholdTest);
+ FRIEND_TEST(HapticButtonGeneratorFilterInterpreterTest, PalmTest);
public:
// Takes ownership of |next|:
explicit HapticButtonGeneratorFilterInterpreter(PropRegistry* prop_reg,
@@ -42,6 +44,7 @@ class HapticButtonGeneratorFilterInterpreter : public FilterInterpreter {
void ConsumeGesture(const Gesture& gesture) override;
void HandleHardwareState(HardwareState* hwstate);
virtual void HandleTimerImpl(stime_t now, stime_t *timeout) override;
+ void UpdatePalmState(HardwareState* hwstate);
static const size_t kMaxSensitivitySettings = 5;
@@ -51,6 +54,8 @@ class HapticButtonGeneratorFilterInterpreter : public FilterInterpreter {
const double up_thresholds_[kMaxSensitivitySettings] =
{80.0, 95.0, 105.0, 120.0, 135.0};
+ std::set<short> palms_;
+
// Scaling factor for release force [0.0-1.0]
double release_suppress_factor_;
diff --git a/include/immediate_interpreter.h b/include/immediate_interpreter.h
index 09878e4..261b3b0 100644
--- a/include/immediate_interpreter.h
+++ b/include/immediate_interpreter.h
@@ -347,7 +347,7 @@ class ImmediateInterpreter : public Interpreter, public PropertyDelegate {
FRIEND_TEST(ImmediateInterpreterTest, PalmAtEdgeTest);
FRIEND_TEST(ImmediateInterpreterTest, PalmReevaluateTest);
FRIEND_TEST(ImmediateInterpreterTest, PalmTest);
- FRIEND_TEST(ImmediateInterpreterTest, DISABLED_PinchTests);
+ FRIEND_TEST(ImmediateInterpreterTest, PinchTests);
FRIEND_TEST(ImmediateInterpreterTest, ScrollResetTapTest);
FRIEND_TEST(ImmediateInterpreterTest, ScrollThenFalseTapTest);
FRIEND_TEST(ImmediateInterpreterTest, SemiMtActiveAreaTest);
diff --git a/include/metrics_filter_interpreter.h b/include/metrics_filter_interpreter.h
index d13ee93..60d5898 100644
--- a/include/metrics_filter_interpreter.h
+++ b/include/metrics_filter_interpreter.h
@@ -24,6 +24,10 @@ namespace gestures {
// metrics lib here because it might introduce the deadlock problem.
class MetricsFilterInterpreter : public FilterInterpreter {
+ FRIEND_TEST(MetricsFilterInterpreterTest, SimpleTestMultitouchMouse);
+ FRIEND_TEST(MetricsFilterInterpreterTest, SimpleTestPointingStick);
+ FRIEND_TEST(MetricsFilterInterpreterTest, SimpleTestTouchpad);
+
public:
// Takes ownership of |next|:
MetricsFilterInterpreter(PropRegistry* prop_reg,
diff --git a/include/palm_classifying_filter_interpreter.h b/include/palm_classifying_filter_interpreter.h
index 18cf3a7..8d5739b 100644
--- a/include/palm_classifying_filter_interpreter.h
+++ b/include/palm_classifying_filter_interpreter.h
@@ -97,6 +97,9 @@ class PalmClassifyingFilterInterpreter : public FilterInterpreter {
// Same fingers state. This state is accumulated as fingers remain the same
// and it's reset when fingers change.
std::set<short> palm_; // tracking ids of known palms
+ // These contacts are a subset of palms_ which are marked as palms because
+ // they have a large contact size.
+ std::set<short> large_palm_;
// These contacts have moved significantly and shouldn't be considered
// stationary palms:
std::set<short> non_stationary_palm_;
diff --git a/include/scaling_filter_interpreter.h b/include/scaling_filter_interpreter.h
index 749779f..25b4641 100644
--- a/include/scaling_filter_interpreter.h
+++ b/include/scaling_filter_interpreter.h
@@ -81,8 +81,11 @@ class ScalingFilterInterpreter : public FilterInterpreter {
HardwareProperties friendly_props_;
- // True if scrolling should be inverted
- BoolProperty australian_scrolling_;
+ // When set to true, scroll and swipe gesture directions are inverted.
+ BoolProperty invert_scrolling_and_swiping_;
+
+ // When set to true, only scroll gesture directions are inverted.
+ BoolProperty invert_scrolling_only_;
// Output surface area (sq. mm) =
// if surface_area_from_pressure_
diff --git a/include/stationary_wiggle_filter_interpreter.h b/include/stationary_wiggle_filter_interpreter.h
index 92c2cb2..60fb0c5 100644
--- a/include/stationary_wiggle_filter_interpreter.h
+++ b/include/stationary_wiggle_filter_interpreter.h
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <map>
+#include <gtest/gtest.h> // for FRIEND_TEST
#include "include/filter_interpreter.h"
#include "include/finger_metrics.h"
@@ -122,6 +123,8 @@ class FingerEnergyHistory {
};
class StationaryWiggleFilterInterpreter : public FilterInterpreter {
+ FRIEND_TEST(StationaryWiggleFilterInterpreterTest, SimpleTest);
+
public:
// Takes ownership of |next|:
StationaryWiggleFilterInterpreter(PropRegistry* prop_reg,
diff --git a/include/trace_marker.h b/include/trace_marker.h
index 73d61f6..d1fa9b2 100644
--- a/include/trace_marker.h
+++ b/include/trace_marker.h
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <gtest/gtest.h> // for FRIEND_TEST
#include <linux/limits.h>
#include "include/macros.h"
@@ -21,6 +22,8 @@ namespace gestures {
// debugfs/tracing/trace
class TraceMarker {
+ FRIEND_TEST(TraceMarkerTest, DeleteTraceMarkerTest);
+
public:
static void CreateTraceMarker();
static void DeleteTraceMarker();
diff --git a/include/trend_classifying_filter_interpreter.h b/include/trend_classifying_filter_interpreter.h
index f04e224..b2e8436 100644
--- a/include/trend_classifying_filter_interpreter.h
+++ b/include/trend_classifying_filter_interpreter.h
@@ -78,6 +78,7 @@ namespace gestures {
// thumbs.
class TrendClassifyingFilterInterpreter: public FilterInterpreter {
+ FRIEND_TEST(TrendClassifyingFilterInterpreterTest, SimpleTest);
public:
TrendClassifyingFilterInterpreter(PropRegistry* prop_reg, Interpreter* next,
diff --git a/src/finger_merge_filter_interpreter_unittest.cc b/src/finger_merge_filter_interpreter_unittest.cc
new file mode 100644
index 0000000..bd2d904
--- /dev/null
+++ b/src/finger_merge_filter_interpreter_unittest.cc
@@ -0,0 +1,136 @@
+// Copyright 2022 The ChromiumOS Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <gtest/gtest.h>
+
+#include "include/finger_merge_filter_interpreter.h"
+#include "include/unittest_util.h"
+
+namespace gestures {
+
+class FingerMergeFilterInterpreterTest : public ::testing::Test {};
+
+class FingerMergeFilterInterpreterTestInterpreter : public Interpreter {
+ public:
+ FingerMergeFilterInterpreterTestInterpreter()
+ : Interpreter(NULL, NULL, false),
+ handle_timer_called_(false) {}
+
+ virtual void SyncInterpret(HardwareState* hwstate, stime_t* timeout) {
+ EXPECT_NE(static_cast<HardwareState*>(NULL), hwstate);
+ EXPECT_EQ(2, hwstate->finger_cnt);
+ prev_ = hwstate->fingers[0];
+ }
+
+ virtual void HandleTimer(stime_t now, stime_t* timeout) {
+ handle_timer_called_ = true;
+ }
+
+ FingerState prev_;
+ bool handle_timer_called_;
+};
+
+
+TEST(FingerMergeFilterInterpreterTest, SimpleTest) {
+ FingerMergeFilterInterpreter::Start loc = {1.0, 1.0, 1.0};
+ FingerMergeFilterInterpreter::Start loc_eq = {1.0, 1.0, 1.0};
+ FingerMergeFilterInterpreter::Start loc_ne0 = {9.0, 1.0, 1.0};
+ FingerMergeFilterInterpreter::Start loc_ne1 = {1.0, 9.0, 1.0};
+ FingerMergeFilterInterpreter::Start loc_ne2 = {1.0, 1.0, 9.0};
+
+ EXPECT_EQ(loc, loc_eq);
+ EXPECT_NE(loc, loc_ne0);
+ EXPECT_NE(loc, loc_ne1);
+ EXPECT_NE(loc, loc_ne2);
+
+
+ FingerMergeFilterInterpreterTestInterpreter* base_interpreter =
+ new FingerMergeFilterInterpreterTestInterpreter;
+ FingerMergeFilterInterpreter interpreter(NULL, base_interpreter, NULL);
+
+ EXPECT_FALSE(interpreter.finger_merge_filter_enable_.val_);
+ interpreter.finger_merge_filter_enable_.val_ = true;
+
+ HardwareProperties hwprops = {
+ 0, 0, 100, 100, // left, top, right, bottom
+ 1, 1, // x res (pixels/mm), y res (pixels/mm)
+ 1, 1, // scrn DPI X, Y
+ -1, // orientation minimum
+ 2, // orientation maximum
+ 5, 5, // max fingers, max_touch,
+ 0, 0, 1, // t5r2, semi, button pad
+ 0, 0, // has wheel, vertical wheel is high resolution
+ 0, // haptic pad
+ };
+ TestInterpreterWrapper wrapper(&interpreter, &hwprops);
+
+ EXPECT_FALSE(base_interpreter->handle_timer_called_);
+ wrapper.HandleTimer(0.0, NULL);
+ EXPECT_TRUE(base_interpreter->handle_timer_called_);
+
+ FingerState finger_states[] = {
+ // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
+ // Consistent movement for 6 frames
+ {0, 0, 0, 0, 20, 0, 40, 20, 1, 0}, // 0
+ {0, 0, 0, 0, 20, 0, 42, 22, 2, 0},
+
+ {0, 0, 0, 0, 20, 0, 40, 25, 1, 0}, // 2
+ {0, 0, 0, 0, 20, 0, 42, 27, 2, 0},
+
+ {0, 0, 0, 0, 20, 0, 40, 30, 1, 0}, // 4
+ {0, 0, 0, 0, 20, 0, 42, 32, 2, 0},
+
+ {0, 0, 0, 0, 20, 0, 40, 35, 1, 0}, // 6
+ {0, 0, 0, 0, 20, 0, 42, 37, 2, 0},
+
+ {0, 0, 0, 0, 20, 0, 40, 40, 1, 0}, // 8
+ {0, 0, 0, 0, 20, 0, 42, 42, 2, 0},
+
+ {0, 0, 0, 0, 20, 0, 40, 45, 1, 0}, // 10
+ {0, 0, 0, 0, 20, 0, 42, 47, 2, 0},
+
+ {0, 0, 0, 0, 20, 0, 40, 50, 1, 0}, // 12
+ {0, 0, 0, 0, 20, 0, 42, 52, 2, 0},
+
+ {0, 0, 0, 0, 20, 0, 40, 55, 1, 0}, // 14
+ {0, 0, 0, 0, 20, 0, 42, 57, 2, 0},
+ };
+
+ HardwareState hardware_states[] = {
+ // time, buttons, finger count, touch count, finger states pointer
+ make_hwstate(1.00, 0, 2, 2, &finger_states[0]),
+ make_hwstate(1.01, 0, 2, 2, &finger_states[2]),
+ make_hwstate(1.02, 0, 2, 2, &finger_states[4]),
+ make_hwstate(1.03, 0, 2, 2, &finger_states[6]),
+ make_hwstate(1.04, 0, 2, 2, &finger_states[8]),
+ make_hwstate(1.05, 0, 2, 2, &finger_states[10]),
+ make_hwstate(1.06, 0, 2, 2, &finger_states[12]),
+ make_hwstate(1.07, 0, 2, 2, &finger_states[14]),
+ };
+
+ for (size_t i = 0; i < arraysize(hardware_states); i++) {
+ HardwareState *hwstate = &hardware_states[i];
+ wrapper.SyncInterpret(hwstate, NULL);
+ for (short j = 0; j < hwstate->finger_cnt; j++) {
+ FingerState *fs = hwstate->fingers;
+ EXPECT_TRUE(fs[j].flags & GESTURES_FINGER_MERGE);
+ }
+ }
+
+ EXPECT_TRUE(interpreter.finger_merge_filter_enable_.val_);
+ EXPECT_EQ(interpreter.merge_distance_threshold_.val_, 140.0);
+ EXPECT_EQ(interpreter.max_pressure_threshold_.val_, 83.0);
+ EXPECT_EQ(interpreter.min_pressure_threshold_.val_, 51.0);
+ EXPECT_EQ(interpreter.min_major_threshold_.val_, 280.0);
+ EXPECT_EQ(interpreter.merged_major_pressure_ratio_.val_, 5.0);
+ EXPECT_EQ(interpreter.merged_major_threshold_.val_, 380.0);
+ EXPECT_EQ(interpreter.x_jump_min_displacement_.val_, 6.0);
+ EXPECT_EQ(interpreter.x_jump_max_displacement_.val_, 9.0);
+ EXPECT_EQ(interpreter.suspicious_angle_min_displacement_.val_, 7.0);
+ EXPECT_EQ(interpreter.max_x_move_.val_, 180.0);
+ EXPECT_EQ(interpreter.max_y_move_.val_, 60.0);
+ EXPECT_EQ(interpreter.max_age_.val_, 0.35);
+}
+
+} // namespace gestures
diff --git a/src/haptic_button_generator_filter_interpreter.cc b/src/haptic_button_generator_filter_interpreter.cc
index 0fcbf9c..6d7fe52 100644
--- a/src/haptic_button_generator_filter_interpreter.cc
+++ b/src/haptic_button_generator_filter_interpreter.cc
@@ -10,6 +10,7 @@
#include "include/interpreter.h"
#include "include/logging.h"
#include "include/tracer.h"
+#include "include/util.h"
namespace gestures {
@@ -59,6 +60,7 @@ void HapticButtonGeneratorFilterInterpreter::SyncInterpretImpl(
HandleHardwareState(hwstate);
stime_t next_timeout = NO_DEADLINE;
next_->SyncInterpret(hwstate, &next_timeout);
+ UpdatePalmState(hwstate);
*timeout = SetNextDeadlineAndReturnTimeoutVal(
hwstate->timestamp, active_gesture_deadline_, next_timeout);
}
@@ -90,10 +92,13 @@ void HapticButtonGeneratorFilterInterpreter::HandleHardwareState(
up_threshold *= release_suppress_factor_;
- // Determine total force on touchpad in grams
+ // Determine maximum force on touchpad in grams
double force = 0.0;
for (short i = 0; i < hwstate->finger_cnt; i++) {
- force = fmax(force, hwstate->fingers[i].pressure);
+ FingerState* fs = &hwstate->fingers[i];
+ if (!SetContainsValue(palms_, fs->tracking_id)) {
+ force = fmax(force, fs->pressure);
+ }
}
force *= force_scale_.val_;
force += force_translate_.val_;
@@ -143,6 +148,18 @@ void HapticButtonGeneratorFilterInterpreter::HandleHardwareState(
release_suppress_factor_ = 1.0;
}
+void HapticButtonGeneratorFilterInterpreter::UpdatePalmState(
+ HardwareState* hwstate) {
+ RemoveMissingIdsFromSet(&palms_, *hwstate);
+ for (short i = 0; i < hwstate->finger_cnt; i++) {
+ FingerState* fs = &hwstate->fingers[i];
+ if (fs->flags & GESTURES_FINGER_LARGE_PALM) {
+ palms_.insert(fs->tracking_id);
+ }
+ }
+}
+
+
void HapticButtonGeneratorFilterInterpreter::HandleTimerImpl(
stime_t now, stime_t *timeout) {
stime_t next_timeout;
diff --git a/src/haptic_button_generator_filter_interpreter_unittest.cc b/src/haptic_button_generator_filter_interpreter_unittest.cc
index 798ab72..318a304 100644
--- a/src/haptic_button_generator_filter_interpreter_unittest.cc
+++ b/src/haptic_button_generator_filter_interpreter_unittest.cc
@@ -339,4 +339,69 @@ TEST(HapticButtonGeneratorFilterInterpreterTest, DynamicThresholdTest) {
}
}
+TEST(HapticButtonGeneratorFilterInterpreterTest, PalmTest) {
+ HapticButtonGeneratorFilterInterpreterTestInterpreter* base_interpreter =
+ new HapticButtonGeneratorFilterInterpreterTestInterpreter;
+ HapticButtonGeneratorFilterInterpreter interpreter(
+ NULL, base_interpreter, NULL);
+ HardwareProperties hwprops = {
+ 0, 0, 100, 100, // left, top, right, bottom
+ 10, // x res (pixels/mm)
+ 10, // y res (pixels/mm)
+ 133, 133, // scrn DPI X, Y
+ -1, // orientation minimum
+ 2, // orientation maximum
+ 2, 5, // max fingers, max_touch
+ 0, 0, 0, // t5r2, semi, button pad
+ 0, 0, // has wheel, vertical wheel is high resolution
+ 1, // haptic pad
+ };
+ TestInterpreterWrapper wrapper(&interpreter, &hwprops);
+
+ interpreter.enabled_.val_ = true;
+
+ FingerState fs[] = {
+ // TM, Tm, WM, Wm, pr, orient, x, y, id, flag
+ { 0, 0, 0, 0, 50, 0, 10, 1, 1, GESTURES_FINGER_LARGE_PALM },
+ { 0, 0, 0, 0, 160, 0, 10, 1, 1, GESTURES_FINGER_LARGE_PALM },
+ { 0, 0, 0, 0, 50, 0, 10, 1, 1, GESTURES_FINGER_LARGE_PALM },
+
+ { 0, 0, 0, 0, 50, 0, 10, 1, 1, GESTURES_FINGER_LARGE_PALM },
+ { 0, 0, 0, 0, 50, 0, 10, 1, 2, 0 },
+ { 0, 0, 0, 0, 160, 0, 10, 1, 1, GESTURES_FINGER_LARGE_PALM },
+ { 0, 0, 0, 0, 80, 0, 10, 1, 2, 0 },
+
+ { 0, 0, 0, 0, 160, 0, 10, 1, 1, GESTURES_FINGER_LARGE_PALM },
+ { 0, 0, 0, 0, 160, 0, 10, 1, 2, 0 },
+ };
+ HardwareState hs[] = {
+ // Expect not to set button down when a lone palm goes above 'down force
+ // threshold'
+ make_hwstate(2.01, 0, 1, 1, &fs[0]),
+ make_hwstate(2.03, 0, 1, 1, &fs[1]),
+ make_hwstate(2.05, 0, 1, 1, &fs[2]),
+
+ // Expect not to set button down when there are multiple fingers and only a
+ // palm goes above 'down force threshold'
+ make_hwstate(4.01, 0, 2, 2, &fs[3]),
+ make_hwstate(4.03, 0, 2, 2, &fs[5]),
+
+ // Expect to set button down when there are multiple fingers and a non-palm
+ // goes above 'down force threshold'
+ make_hwstate(4.05, 0, 2, 2, &fs[7]),
+ };
+
+ stime_t expected_buttons[] = {
+ 0, 0, 0,
+ 0, 0,
+ GESTURES_BUTTON_LEFT,
+ };
+
+ for (size_t i = 0; i < arraysize(hs); i++) {
+ stime_t timeout = NO_DEADLINE;
+ wrapper.SyncInterpret(&hs[i], &timeout);
+ EXPECT_EQ(hs[i].buttons_down, expected_buttons[i]);
+ }
+}
+
} // namespace gestures
diff --git a/src/immediate_interpreter_unittest.cc b/src/immediate_interpreter_unittest.cc
index 661541a..f5dd9a0 100644
--- a/src/immediate_interpreter_unittest.cc
+++ b/src/immediate_interpreter_unittest.cc
@@ -2879,7 +2879,8 @@ TEST(ImmediateInterpreterTest, ChangeTimeoutTest) {
enum PinchTestExpectedResult {
kPinch,
kNoPinch,
- kAny
+ kAny,
+ kNull
};
struct PinchTestInput {
@@ -2887,7 +2888,7 @@ struct PinchTestInput {
PinchTestExpectedResult expected_result;
};
-TEST(ImmediateInterpreterTest, DISABLED_PinchTests) {
+TEST(ImmediateInterpreterTest, PinchTests) {
ImmediateInterpreter ii(NULL, NULL);
ii.pinch_enable_.val_ = 1;
HardwareProperties hwprops = {
@@ -2976,8 +2977,8 @@ TEST(ImmediateInterpreterTest, DISABLED_PinchTests) {
{make_hwstate(1.08, 0, 2, 2, &finger_states[6]), kAny},
{make_hwstate(1.09, 0, 2, 2, &finger_states[8]), kAny},
{make_hwstate(1.10, 0, 2, 2, &finger_states[8]), kAny},
- {make_hwstate(1.11, 0, 2, 2, &finger_states[10]), kAny},
- {make_hwstate(1.12, 0, 2, 2, &finger_states[10]), kPinch},
+ {make_hwstate(1.11, 0, 2, 2, &finger_states[10]), kPinch},
+ {make_hwstate(1.12, 0, 2, 2, &finger_states[10]), kNull},
{make_hwstate(1.13, 0, 0, 0, NULL), kAny},
// single finger pinch
@@ -3019,6 +3020,10 @@ TEST(ImmediateInterpreterTest, DISABLED_PinchTests) {
EXPECT_NE(kGestureTypePinch, gs->type);
}
}
+ // assert if NULL is not given back
+ if (input_states[idx].expected_result == kNull) {
+ ASSERT_EQ(reinterpret_cast<Gesture*>(NULL), gs);
+ }
}
}
diff --git a/src/lookahead_filter_interpreter.cc b/src/lookahead_filter_interpreter.cc
index 280d396..f7abaf5 100644
--- a/src/lookahead_filter_interpreter.cc
+++ b/src/lookahead_filter_interpreter.cc
@@ -86,6 +86,14 @@ void LookaheadFilterInterpreter::SyncInterpretImpl(HardwareState* hwstate,
interpreter_due_ : interpreter_due_ + hwstate->timestamp,
hwstate->timestamp, timeout);
HandleTimerImpl(hwstate->timestamp, timeout);
+
+ // Copy finger flags for upstream filters.
+ QState* q_node = queue_.Head();
+ if (q_node->state_.SameFingersAs(*hwstate)) {
+ for (size_t i = 0; i < hwstate->finger_cnt; i++) {
+ hwstate->fingers[i].flags = q_node->state_.fingers[i].flags;
+ }
+ }
}
// Interpolates the two hardware states into out.
@@ -124,8 +132,13 @@ void LookaheadFilterInterpreter::AssignTrackingIds() {
// For semi-mt devices, drumrolls and quick moves are handled in
// SemiMtCorrectingFilterInterpreter already. We need to bypass the detection
// and tracking id reassignment here to make fast-scroll working correctly.
- if (hwprops_->support_semi_mt || !drumroll_suppression_enable_.val_)
+ // For haptic touchpads, we need to bypass tracking id reassignment so the
+ // haptic button filter can have the same tracking ids.
+ if (hwprops_->support_semi_mt ||
+ hwprops_->is_haptic_pad ||
+ !drumroll_suppression_enable_.val_) {
return;
+ }
if (queue_.size() < 2) {
// Always reassign trackingID on the very first hwstate so that
// the next hwstate can inherit the trackingID mapping.
@@ -464,6 +477,11 @@ void LookaheadFilterInterpreter::HandleTimerImpl(stime_t now,
// Mark current node completed. This should be the only completed
// node in the queue.
node->completed_ = true;
+
+ // Copy finger flags for upstream filters.
+ for (size_t i = 0; i < node->state_.finger_cnt; i++) {
+ node->state_.fingers[i].flags = hs_copy.fingers[i].flags;
+ }
}
UpdateInterpreterDue(next_timeout, now, timeout);
}
diff --git a/src/metrics_filter_interpreter_unittest.cc b/src/metrics_filter_interpreter_unittest.cc
new file mode 100644
index 0000000..83bf09d
--- /dev/null
+++ b/src/metrics_filter_interpreter_unittest.cc
@@ -0,0 +1,230 @@
+// Copyright 2022 The ChromiumOS Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <gtest/gtest.h>
+
+#include "include/metrics_filter_interpreter.h"
+#include "include/unittest_util.h"
+
+namespace gestures {
+
+class MetricsFilterInterpreterTest : public ::testing::Test {};
+
+class MetricsFilterInterpreterTestInterpreter : public Interpreter {
+ public:
+ MetricsFilterInterpreterTestInterpreter()
+ : Interpreter(NULL, NULL, false),
+ handle_timer_called_(false) {}
+
+ virtual void SyncInterpret(HardwareState* hwstate, stime_t* timeout) {
+ EXPECT_NE(static_cast<HardwareState*>(NULL), hwstate);
+ EXPECT_EQ(1, hwstate->finger_cnt);
+ prev_ = hwstate->fingers[0];
+ }
+
+ virtual void HandleTimer(stime_t now, stime_t* timeout) {
+ handle_timer_called_ = true;
+ }
+
+ FingerState prev_;
+ bool handle_timer_called_;
+};
+
+
+TEST(MetricsFilterInterpreterTest, SimpleTestTouchpad) {
+ MetricsFilterInterpreterTestInterpreter* base_interpreter =
+ new MetricsFilterInterpreterTestInterpreter;
+ MetricsFilterInterpreter interpreter(NULL, base_interpreter, NULL,
+ GESTURES_DEVCLASS_TOUCHPAD);
+
+ HardwareProperties hwprops = {
+ 0, 0, 100, 100, // left, top, right, bottom
+ 1, 1, // x res (pixels/mm), y res (pixels/mm)
+ 1, 1, // scrn DPI X, Y
+ -1, // orientation minimum
+ 2, // orientation maximum
+ 5, 5, // max fingers, max_touch,
+ 0, 0, 1, // t5r2, semi, button pad
+ 0, 0, // has wheel, vertical wheel is high resolution
+ 0, // haptic pad
+ };
+ TestInterpreterWrapper wrapper(&interpreter, &hwprops);
+
+ EXPECT_FALSE(base_interpreter->handle_timer_called_);
+ wrapper.HandleTimer(0.0, NULL);
+ EXPECT_TRUE(base_interpreter->handle_timer_called_);
+
+ FingerState finger_states[] = {
+ // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
+ // Consistent movement for 16 frames
+ {0, 0, 0, 0, 20, 0, 40, 20, 1, 0}, // 0
+ {0, 0, 0, 0, 20, 0, 40, 25, 1, 0}, // 1
+ {0, 0, 0, 0, 20, 0, 40, 30, 1, 0}, // 2
+ {0, 0, 0, 0, 20, 0, 40, 35, 1, 0}, // 3
+ {0, 0, 0, 0, 20, 0, 40, 40, 1, 0}, // 4
+ {0, 0, 0, 0, 20, 0, 40, 45, 1, 0}, // 5
+ {0, 0, 0, 0, 20, 0, 40, 50, 1, 0}, // 6
+ {0, 0, 0, 0, 20, 0, 40, 55, 1, 0}, // 7
+ {0, 0, 0, 0, 20, 0, 40, 60, 1, 0}, // 8
+ {0, 0, 0, 0, 20, 0, 40, 65, 1, 0}, // 9
+ {0, 0, 0, 0, 20, 0, 40, 70, 1, 0}, // 10
+ {0, 0, 0, 0, 20, 0, 40, 75, 1, 0}, // 11
+ {0, 0, 0, 0, 20, 0, 40, 80, 1, 0}, // 12
+ {0, 0, 0, 0, 20, 0, 40, 85, 1, 0}, // 13
+ {0, 0, 0, 0, 20, 0, 40, 90, 1, 0}, // 14
+ {0, 0, 0, 0, 20, 0, 40, 95, 1, 0}, // 15
+ };
+
+ HardwareState hardware_states[] = {
+ // time, buttons, finger count, touch count, finger states pointer
+ make_hwstate(1.00, 0, 1, 1, &finger_states[0]),
+ make_hwstate(1.01, 0, 1, 1, &finger_states[1]),
+ make_hwstate(1.02, 0, 1, 1, &finger_states[2]),
+ make_hwstate(1.03, 0, 1, 1, &finger_states[3]),
+ make_hwstate(1.04, 0, 1, 1, &finger_states[4]),
+ make_hwstate(1.05, 0, 1, 1, &finger_states[5]),
+ make_hwstate(1.06, 0, 1, 1, &finger_states[6]),
+ make_hwstate(1.07, 0, 1, 1, &finger_states[7]),
+ make_hwstate(1.08, 0, 1, 1, &finger_states[8]),
+ make_hwstate(1.09, 0, 1, 1, &finger_states[9]),
+ make_hwstate(1.10, 0, 1, 1, &finger_states[10]),
+ make_hwstate(1.11, 0, 1, 1, &finger_states[11]),
+ make_hwstate(1.12, 0, 1, 1, &finger_states[12]),
+ make_hwstate(1.13, 0, 1, 1, &finger_states[13]),
+ make_hwstate(1.14, 0, 1, 1, &finger_states[14]),
+ make_hwstate(1.15, 0, 1, 1, &finger_states[15]),
+ };
+
+ for (size_t i = 0; i < arraysize(hardware_states); i++) {
+ wrapper.SyncInterpret(&hardware_states[i], NULL);
+ }
+
+ EXPECT_EQ(interpreter.devclass_, GESTURES_DEVCLASS_TOUCHPAD);
+ EXPECT_EQ(interpreter.mouse_movement_session_index_, 0);
+ EXPECT_EQ(interpreter.mouse_movement_current_session_length, 0);
+ EXPECT_EQ(interpreter.mouse_movement_current_session_start, 0.0);
+ EXPECT_EQ(interpreter.mouse_movement_current_session_last, 0.0);
+ EXPECT_EQ(interpreter.mouse_movement_current_session_distance, 0.0);
+ EXPECT_EQ(interpreter.noisy_ground_distance_threshold_.val_, 10.0);
+ EXPECT_EQ(interpreter.noisy_ground_time_threshold_.val_, 0.1);
+ EXPECT_EQ(interpreter.mouse_moving_time_threshold_.val_, 0.05);
+ EXPECT_EQ(interpreter.mouse_control_warmup_sessions_.val_, 100);
+}
+
+TEST(MetricsFilterInterpreterTest, SimpleTestMultitouchMouse) {
+ MetricsFilterInterpreterTestInterpreter* base_interpreter =
+ new MetricsFilterInterpreterTestInterpreter;
+ MetricsFilterInterpreter interpreter(NULL, base_interpreter, NULL,
+ GESTURES_DEVCLASS_MULTITOUCH_MOUSE);
+
+ HardwareProperties hwprops = {
+ 0, 0, 100, 100, // left, top, right, bottom
+ 1, 1, // x res (pixels/mm), y res (pixels/mm)
+ 1, 1, // scrn DPI X, Y
+ -1, // orientation minimum
+ 2, // orientation maximum
+ 5, 5, // max fingers, max_touch,
+ 0, 0, 1, // t5r2, semi, button pad
+ 0, 0, // has wheel, vertical wheel is high resolution
+ 0, // haptic pad
+ };
+ TestInterpreterWrapper wrapper(&interpreter, &hwprops);
+
+ EXPECT_FALSE(base_interpreter->handle_timer_called_);
+ wrapper.HandleTimer(0.0, NULL);
+ EXPECT_TRUE(base_interpreter->handle_timer_called_);
+
+ FingerState finger_states[] = {
+ // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
+ // Consistent movement for 16 frames
+ {0, 0, 0, 0, 20, 0, 40, 20, 1, 0}, // 0
+ {0, 0, 0, 0, 20, 0, 40, 25, 1, 0}, // 1
+ {0, 0, 0, 0, 20, 0, 40, 30, 1, 0}, // 2
+ {0, 0, 0, 0, 20, 0, 40, 35, 1, 0}, // 3
+ {0, 0, 0, 0, 20, 0, 40, 40, 1, 0}, // 4
+ {0, 0, 0, 0, 20, 0, 40, 45, 1, 0}, // 5
+ {0, 0, 0, 0, 20, 0, 40, 50, 1, 0}, // 6
+ {0, 0, 0, 0, 20, 0, 40, 55, 1, 0}, // 7
+ {0, 0, 0, 0, 20, 0, 40, 60, 1, 0}, // 8
+ {0, 0, 0, 0, 20, 0, 40, 65, 1, 0}, // 9
+ {0, 0, 0, 0, 20, 0, 40, 70, 1, 0}, // 10
+ {0, 0, 0, 0, 20, 0, 40, 75, 1, 0}, // 11
+ {0, 0, 0, 0, 20, 0, 40, 80, 1, 0}, // 12
+ {0, 0, 0, 0, 20, 0, 40, 85, 1, 0}, // 13
+ {0, 0, 0, 0, 20, 0, 40, 90, 1, 0}, // 14
+ {0, 0, 0, 0, 20, 0, 40, 95, 1, 0}, // 15
+ };
+
+ HardwareState hardware_states[] = {
+ // time, buttons, finger count, touch count, finger states pointer
+ make_hwstate(1.00, 0, 1, 1, &finger_states[0]),
+ make_hwstate(1.01, 0, 1, 1, &finger_states[1]),
+ make_hwstate(1.02, 0, 1, 1, &finger_states[2]),
+ make_hwstate(1.03, 0, 1, 1, &finger_states[3]),
+ make_hwstate(1.04, 0, 1, 1, &finger_states[4]),
+ make_hwstate(1.05, 0, 1, 1, &finger_states[5]),
+ make_hwstate(1.06, 0, 1, 1, &finger_states[6]),
+ make_hwstate(1.07, 0, 1, 1, &finger_states[7]),
+ make_hwstate(1.08, 0, 1, 1, &finger_states[8]),
+ make_hwstate(1.09, 0, 1, 1, &finger_states[9]),
+ make_hwstate(1.10, 0, 1, 1, &finger_states[10]),
+ make_hwstate(1.11, 0, 1, 1, &finger_states[11]),
+ make_hwstate(1.12, 0, 1, 1, &finger_states[12]),
+ make_hwstate(1.13, 0, 1, 1, &finger_states[13]),
+ make_hwstate(1.14, 0, 1, 1, &finger_states[14]),
+ make_hwstate(1.15, 0, 1, 1, &finger_states[15]),
+ };
+
+ for (size_t i = 0; i < arraysize(hardware_states); i++) {
+ wrapper.SyncInterpret(&hardware_states[i], NULL);
+ }
+
+ EXPECT_EQ(interpreter.devclass_, GESTURES_DEVCLASS_MULTITOUCH_MOUSE);
+ EXPECT_EQ(interpreter.mouse_movement_session_index_, 0);
+ EXPECT_EQ(interpreter.mouse_movement_current_session_length, 0);
+ EXPECT_EQ(interpreter.mouse_movement_current_session_start, 0.0);
+ EXPECT_EQ(interpreter.mouse_movement_current_session_last, 0.0);
+ EXPECT_EQ(interpreter.mouse_movement_current_session_distance, 0.0);
+ EXPECT_EQ(interpreter.noisy_ground_distance_threshold_.val_, 10.0);
+ EXPECT_EQ(interpreter.noisy_ground_time_threshold_.val_, 0.1);
+ EXPECT_EQ(interpreter.mouse_moving_time_threshold_.val_, 0.05);
+ EXPECT_EQ(interpreter.mouse_control_warmup_sessions_.val_, 100);
+}
+
+TEST(MetricsFilterInterpreterTest, SimpleTestPointingStick) {
+ MetricsFilterInterpreterTestInterpreter* base_interpreter =
+ new MetricsFilterInterpreterTestInterpreter;
+ MetricsFilterInterpreter interpreter(NULL, base_interpreter, NULL,
+ GESTURES_DEVCLASS_POINTING_STICK);
+
+ HardwareProperties hwprops = {
+ 0, 0, 100, 100, // left, top, right, bottom
+ 1, 1, // x res (pixels/mm), y res (pixels/mm)
+ 1, 1, // scrn DPI X, Y
+ -1, // orientation minimum
+ 2, // orientation maximum
+ 5, 5, // max fingers, max_touch,
+ 0, 0, 1, // t5r2, semi, button pad
+ 0, 0, // has wheel, vertical wheel is high resolution
+ 0, // haptic pad
+ };
+ TestInterpreterWrapper wrapper(&interpreter, &hwprops);
+
+ EXPECT_FALSE(base_interpreter->handle_timer_called_);
+ wrapper.HandleTimer(0.0, NULL);
+ EXPECT_TRUE(base_interpreter->handle_timer_called_);
+
+ EXPECT_EQ(interpreter.devclass_, GESTURES_DEVCLASS_POINTING_STICK);
+ EXPECT_EQ(interpreter.mouse_movement_session_index_, 0);
+ EXPECT_EQ(interpreter.mouse_movement_current_session_length, 0);
+ EXPECT_EQ(interpreter.mouse_movement_current_session_start, 0.0);
+ EXPECT_EQ(interpreter.mouse_movement_current_session_last, 0.0);
+ EXPECT_EQ(interpreter.mouse_movement_current_session_distance, 0.0);
+ EXPECT_EQ(interpreter.noisy_ground_distance_threshold_.val_, 10.0);
+ EXPECT_EQ(interpreter.noisy_ground_time_threshold_.val_, 0.1);
+ EXPECT_EQ(interpreter.mouse_moving_time_threshold_.val_, 0.05);
+ EXPECT_EQ(interpreter.mouse_control_warmup_sessions_.val_, 100);
+}
+
+} // namespace gestures
diff --git a/src/palm_classifying_filter_interpreter.cc b/src/palm_classifying_filter_interpreter.cc
index 19a4f2f..7acbf58 100644
--- a/src/palm_classifying_filter_interpreter.cc
+++ b/src/palm_classifying_filter_interpreter.cc
@@ -164,6 +164,7 @@ bool PalmClassifyingFilterInterpreter::FingerInBottomArea(
void PalmClassifyingFilterInterpreter::UpdatePalmState(
const HardwareState& hwstate) {
RemoveMissingIdsFromSet(&palm_, hwstate);
+ RemoveMissingIdsFromSet(&large_palm_, hwstate);
RemoveMissingIdsFromMap(&pointing_, hwstate);
RemoveMissingIdsFromSet(&non_stationary_palm_, hwstate);
RemoveMissingIdsFromSet(&fingers_not_in_edge_, hwstate);
@@ -180,6 +181,7 @@ void PalmClassifyingFilterInterpreter::UpdatePalmState(
// Mark anything over the palm thresh as a palm
if (fs.pressure >= palm_pressure_.val_ ||
fs.touch_major >= multi_palm_width_.val_) {
+ large_palm_.insert(fs.tracking_id);
palm_.insert(fs.tracking_id);
pointing_.erase(fs.tracking_id);
continue;
@@ -188,6 +190,7 @@ void PalmClassifyingFilterInterpreter::UpdatePalmState(
if (hwstate.finger_cnt == 1 &&
hwstate.fingers[0].touch_major >= palm_width_.val_) {
+ large_palm_.insert(hwstate.fingers[0].tracking_id);
palm_.insert(hwstate.fingers[0].tracking_id);
pointing_.erase(hwstate.fingers[0].tracking_id);
}
@@ -214,6 +217,7 @@ void PalmClassifyingFilterInterpreter::UpdatePalmState(
if (max_pressure_[fs.tracking_id] <= kFatFingerMaxPressure &&
max_width_[fs.tracking_id] <= kFatFingerMaxWidth &&
dist_sq > kFatFingerMinDistSq) {
+ large_palm_.erase(fs.tracking_id);
palm_.erase(fs.tracking_id);
} else {
// Lock onto palm
@@ -288,6 +292,9 @@ void PalmClassifyingFilterInterpreter::UpdatePalmState(
void PalmClassifyingFilterInterpreter::UpdatePalmFlags(HardwareState* hwstate) {
for (short i = 0; i < hwstate->finger_cnt; i++) {
FingerState* fs = &hwstate->fingers[i];
+ if (SetContainsValue(large_palm_, fs->tracking_id)) {
+ fs->flags |= GESTURES_FINGER_LARGE_PALM;
+ }
if (SetContainsValue(palm_, fs->tracking_id)) {
fs->flags |= GESTURES_FINGER_PALM;
} else if (!MapContainsKey(pointing_, fs->tracking_id) &&
diff --git a/src/palm_classifying_filter_interpreter_unittest.cc b/src/palm_classifying_filter_interpreter_unittest.cc
index 57d95fb..b1cbee1 100644
--- a/src/palm_classifying_filter_interpreter_unittest.cc
+++ b/src/palm_classifying_filter_interpreter_unittest.cc
@@ -286,14 +286,17 @@ TEST(PalmClassifyingFilterInterpreterTest, PalmAtEdgeTest) {
break;
case 0: // fallthrough
case 1:
- case 4:
- case 5:
case 8:
case 9:
case 10:
case 12:
base_interpreter->expected_flags_ = GESTURES_FINGER_PALM;
break;
+ case 4:
+ case 5:
+ base_interpreter->expected_flags_ =
+ (GESTURES_FINGER_PALM | GESTURES_FINGER_LARGE_PALM);
+ break;
default:
ADD_FAILURE() << "Should be unreached.";
break;
@@ -659,7 +662,8 @@ TEST(PalmClassifyingFilterInterpreterTest, LargeTouchMajorTest) {
input.touch_major_, 0, 0, 0, input.pressure_, 0, input.x_, input.y_, 1, 0
};
HardwareState hs = make_hwstate(input.now_, 0, 1, 1, &fs);
- base_interpreter->expected_flags_ = GESTURES_FINGER_PALM;
+ base_interpreter->expected_flags_ =
+ (GESTURES_FINGER_PALM | GESTURES_FINGER_LARGE_PALM);
wrapper.SyncInterpret(&hs, NULL);
}
}
diff --git a/src/prop_registry_unittest.cc b/src/prop_registry_unittest.cc
index 2226d80..1b994fb 100644
--- a/src/prop_registry_unittest.cc
+++ b/src/prop_registry_unittest.cc
@@ -22,8 +22,13 @@ class PropRegistryTestDelegate : public PropertyDelegate {
public:
PropRegistryTestDelegate() : call_cnt_(0) {}
virtual void BoolWasWritten(BoolProperty* prop) { call_cnt_++; };
+ virtual void BoolArrayWasWritten(BoolArrayProperty* prop) { call_cnt_++; };
virtual void DoubleWasWritten(DoubleProperty* prop) { call_cnt_++; };
+ virtual void DoubleArrayWasWritten(DoubleArrayProperty* prop) {
+ call_cnt_++;
+ };
virtual void IntWasWritten(IntProperty* prop) { call_cnt_++; };
+ virtual void IntArrayWasWritten(IntArrayProperty* prop) { call_cnt_++; };
virtual void StringWasWritten(StringProperty* prop) { call_cnt_++; };
int call_cnt_;
@@ -82,6 +87,41 @@ TEST(PropRegistryTest, SimpleTest) {
EXPECT_TRUE(strstr(ValueForProperty(stp2).c_str(), "bar"));
stp2.HandleGesturesPropWritten();
EXPECT_EQ(expected_call_cnt, delegate.call_cnt_);
+
+
+ Json::Value my_bool_val = bp1.NewValue();
+ Json::Value my_int_val = ip1.NewValue();
+ Json::Value my_double_val = dp1.NewValue();
+ Json::Value my_str_val = stp1.NewValue();
+ EXPECT_TRUE(bp1.SetValue(my_bool_val));
+ EXPECT_FALSE(bp1.SetValue(my_int_val));
+ EXPECT_FALSE(bp1.SetValue(my_double_val));
+ EXPECT_FALSE(bp1.SetValue(my_str_val));
+
+ EXPECT_FALSE(ip1.SetValue(my_bool_val));
+ EXPECT_TRUE(ip1.SetValue(my_int_val));
+ EXPECT_FALSE(ip1.SetValue(my_double_val));
+ EXPECT_FALSE(ip1.SetValue(my_str_val));
+
+ EXPECT_FALSE(dp1.SetValue(my_bool_val));
+ EXPECT_TRUE(dp1.SetValue(my_int_val));
+ EXPECT_TRUE(dp1.SetValue(my_double_val));
+ EXPECT_FALSE(dp1.SetValue(my_str_val));
+
+ EXPECT_FALSE(stp1.SetValue(my_bool_val));
+ EXPECT_FALSE(stp1.SetValue(my_int_val));
+ EXPECT_FALSE(stp1.SetValue(my_double_val));
+ EXPECT_TRUE(stp1.SetValue(my_str_val));
+
+ // This code does not do anything but the code coverage
+ // hits for not covered areas due to not running the
+ // unused default virtual functions.
+ PropertyDelegate pd;
+
+ pd.BoolWasWritten(&bp1);
+ pd.DoubleWasWritten(&dp1);
+ pd.IntWasWritten(&ip1);
+ pd.StringWasWritten(&stp1);
}
TEST(PropRegistryTest, PropChangeTest) {
@@ -121,14 +161,6 @@ GesturesProp* MockGesturesPropCreateReal(void* data, const char* name,
return dummy;
}
-GesturesProp* MockGesturesPropCreateShort(void* data, const char* name,
- short* loc, size_t count,
- const short* init) {
- GesturesProp *dummy = new GesturesProp();
- *loc = 1;
- return dummy;
-}
-
GesturesProp* MockGesturesPropCreateString(void* data, const char* name,
const char** loc,
const char* const init) {
@@ -152,7 +184,7 @@ void MockGesturesPropFree(void* data, GesturesProp* prop) {
TEST(PropRegistryTest, SetAtCreateShouldNotifyTest) {
GesturesPropProvider mock_gestures_props_provider = {
MockGesturesPropCreateInt,
- MockGesturesPropCreateShort,
+ NULL,
MockGesturesPropCreateBool,
MockGesturesPropCreateString,
MockGesturesPropCreateReal,
@@ -184,4 +216,101 @@ TEST(PropRegistryTest, DoublePromoteIntTest) {
EXPECT_TRUE(my_double.SetValue(my_int_val));
EXPECT_TRUE(strstr(ValueForProperty(my_double).c_str(), "321"));
}
+
+TEST(PropRegistryTest, BoolArrayTest) {
+ PropRegistry reg;
+ PropRegistry reg_with_delegate;
+ PropRegistryTestDelegate delegate;
+
+ GesturesPropBool vals[] = { false, true };
+ BoolArrayProperty my_bool_array_w_delegate(
+ &reg, "MyBoolArray", vals, 2, &delegate);
+ EXPECT_EQ(0, delegate.call_cnt_);
+ my_bool_array_w_delegate.HandleGesturesPropWritten();
+ EXPECT_EQ(1, delegate.call_cnt_);
+ delegate.BoolArrayWasWritten(&my_bool_array_w_delegate);
+ EXPECT_EQ(2, delegate.call_cnt_);
+
+ IntProperty ip1(&reg, "hi", 567, &delegate);
+ StringProperty stp1(&reg, "hi", "foo", &delegate);
+ Json::Value my_bool_array_val = my_bool_array_w_delegate.NewValue();
+ Json::Value my_int_val = ip1.NewValue();
+ Json::Value my_str_val = stp1.NewValue();
+ EXPECT_FALSE(my_bool_array_w_delegate.SetValue(my_int_val));
+ EXPECT_FALSE(my_bool_array_w_delegate.SetValue(my_str_val));
+ EXPECT_TRUE(my_bool_array_w_delegate.SetValue(my_bool_array_val));
+
+ // This code does not do anything but the code coverage
+ // hits for not covered areas due to not running the
+ // unused default virtual functions.
+ PropertyDelegate pd;
+
+ BoolArrayProperty my_bool_array(&reg, "MyBoolArray", vals, 2);
+ pd.BoolArrayWasWritten(&my_bool_array);
+}
+
+TEST(PropRegistryTest, DoubleArrayTest) {
+ PropRegistry reg;
+ PropRegistry reg_with_delegate;
+ PropRegistryTestDelegate delegate;
+
+ double vals[] = { 0.0, 1.0 };
+ DoubleArrayProperty my_double_array_w_delegate(
+ &reg, "MyDoubleArray", vals, 2, &delegate);
+ EXPECT_EQ(0, delegate.call_cnt_);
+ my_double_array_w_delegate.HandleGesturesPropWritten();
+ EXPECT_EQ(1, delegate.call_cnt_);
+ delegate.DoubleArrayWasWritten(&my_double_array_w_delegate);
+ EXPECT_EQ(2, delegate.call_cnt_);
+
+ IntProperty ip1(&reg, "hi", 567, &delegate);
+ StringProperty stp1(&reg, "hi", "foo", &delegate);
+ Json::Value my_double_array_val = my_double_array_w_delegate.NewValue();
+ Json::Value my_int_val = ip1.NewValue();
+ Json::Value my_str_val = stp1.NewValue();
+ EXPECT_FALSE(my_double_array_w_delegate.SetValue(my_int_val));
+ EXPECT_FALSE(my_double_array_w_delegate.SetValue(my_str_val));
+ EXPECT_TRUE(my_double_array_w_delegate.SetValue(my_double_array_val));
+
+ // This code does not do anything but the code coverage
+ // hits for not covered areas due to not running the
+ // unused default virtual functions.
+ PropertyDelegate pd;
+
+ DoubleArrayProperty my_double_array(&reg, "MyDoubleArray", vals, 2);
+ pd.DoubleArrayWasWritten(&my_double_array);
+}
+
+TEST(PropRegistryTest, IntArrayTest) {
+ PropRegistry reg;
+ PropRegistry reg_with_delegate;
+ PropRegistryTestDelegate delegate;
+
+ int vals[] = { 0, 1 };
+ IntArrayProperty my_int_array_w_delegate(
+ &reg, "MyIntArray", vals, 2, &delegate);
+ EXPECT_EQ(0, delegate.call_cnt_);
+ my_int_array_w_delegate.HandleGesturesPropWritten();
+ EXPECT_EQ(1, delegate.call_cnt_);
+ delegate.IntArrayWasWritten(&my_int_array_w_delegate);
+ EXPECT_EQ(2, delegate.call_cnt_);
+
+ IntProperty ip1(&reg, "hi", 567, &delegate);
+ StringProperty stp1(&reg, "hi", "foo", &delegate);
+ Json::Value my_int_array_val = my_int_array_w_delegate.NewValue();
+ Json::Value my_int_val = ip1.NewValue();
+ Json::Value my_str_val = stp1.NewValue();
+ EXPECT_FALSE(my_int_array_w_delegate.SetValue(my_int_val));
+ EXPECT_FALSE(my_int_array_w_delegate.SetValue(my_str_val));
+ EXPECT_TRUE(my_int_array_w_delegate.SetValue(my_int_array_val));
+
+ // This code does not do anything but the code coverage
+ // hits for not covered areas due to not running the
+ // unused default virtual functions.
+ PropertyDelegate pd;
+
+ IntArrayProperty my_int_array(&reg, "MyIntArray", vals, 2);
+ pd.IntArrayWasWritten(&my_int_array);
+}
+
} // namespace gestures
diff --git a/src/scaling_filter_interpreter.cc b/src/scaling_filter_interpreter.cc
index 97bde2b..1094455 100644
--- a/src/scaling_filter_interpreter.cc
+++ b/src/scaling_filter_interpreter.cc
@@ -25,7 +25,8 @@ ScalingFilterInterpreter::ScalingFilterInterpreter(
screen_x_scale_(1.0),
screen_y_scale_(1.0),
orientation_scale_(1.0),
- australian_scrolling_(prop_reg, "Australian Scrolling", false),
+ invert_scrolling_and_swiping_(prop_reg, "Australian Scrolling", false),
+ invert_scrolling_only_(prop_reg, "Invert Scrolling", false),
surface_area_from_pressure_(prop_reg,
"Compute Surface Area from Pressure", true),
use_touch_size_for_haptic_pad_(
@@ -255,7 +256,8 @@ void ScalingFilterInterpreter::ConsumeGesture(const Gesture& gs) {
copy.details.scroll.ordinal_dx *= screen_x_scale_;
copy.details.scroll.ordinal_dy *= screen_y_scale_;
}
- if (!australian_scrolling_.val_) {
+ if (!(invert_scrolling_and_swiping_.val_ ||
+ invert_scrolling_only_.val_)) {
copy.details.scroll.dx *= -1;
copy.details.scroll.dy *= -1;
copy.details.scroll.ordinal_dx *= -1;
@@ -263,7 +265,8 @@ void ScalingFilterInterpreter::ConsumeGesture(const Gesture& gs) {
}
break;
case kGestureTypeMouseWheel:
- if (!australian_scrolling_.val_) {
+ if (!(invert_scrolling_and_swiping_.val_ ||
+ invert_scrolling_only_.val_)) {
copy.details.wheel.dx *= -1;
copy.details.wheel.dy *= -1;
copy.details.wheel.tick_120ths_dx *= -1;
@@ -275,7 +278,8 @@ void ScalingFilterInterpreter::ConsumeGesture(const Gesture& gs) {
copy.details.fling.vy *= screen_y_scale_;
copy.details.fling.ordinal_vx *= screen_x_scale_;
copy.details.fling.ordinal_vy *= screen_y_scale_;
- if (!australian_scrolling_.val_) {
+ if (!(invert_scrolling_and_swiping_.val_ ||
+ invert_scrolling_only_.val_)) {
copy.details.fling.vx *= -1;
copy.details.fling.vy *= -1;
copy.details.fling.ordinal_vx *= -1;
@@ -288,7 +292,7 @@ void ScalingFilterInterpreter::ConsumeGesture(const Gesture& gs) {
copy.details.swipe.dy *= screen_y_scale_;
copy.details.swipe.ordinal_dx *= screen_x_scale_;
copy.details.swipe.ordinal_dy *= screen_y_scale_;
- if (!australian_scrolling_.val_) {
+ if (!invert_scrolling_and_swiping_.val_) {
copy.details.swipe.dy *= -1;
copy.details.swipe.ordinal_dy *= -1;
}
@@ -299,7 +303,7 @@ void ScalingFilterInterpreter::ConsumeGesture(const Gesture& gs) {
copy.details.four_finger_swipe.dy *= screen_y_scale_;
copy.details.four_finger_swipe.ordinal_dx *= screen_x_scale_;
copy.details.four_finger_swipe.ordinal_dy *= screen_y_scale_;
- if (!australian_scrolling_.val_) {
+ if (!invert_scrolling_and_swiping_.val_) {
copy.details.four_finger_swipe.dy *= -1;
copy.details.four_finger_swipe.ordinal_dy *= -1;
}
diff --git a/src/stationary_wiggle_filter_interpreter_unittest.cc b/src/stationary_wiggle_filter_interpreter_unittest.cc
new file mode 100644
index 0000000..83c541c
--- /dev/null
+++ b/src/stationary_wiggle_filter_interpreter_unittest.cc
@@ -0,0 +1,152 @@
+// Copyright 2022 The ChromiumOS Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <gtest/gtest.h>
+
+#include "include/stationary_wiggle_filter_interpreter.h"
+#include "include/unittest_util.h"
+
+namespace gestures {
+
+class StationaryWiggleFilterInterpreterTest : public ::testing::Test {};
+
+class StationaryWiggleFilterInterpreterTestInterpreter : public Interpreter {
+ public:
+ StationaryWiggleFilterInterpreterTestInterpreter()
+ : Interpreter(NULL, NULL, false),
+ handle_timer_called_(false) {}
+
+ virtual void SyncInterpret(HardwareState* hwstate, stime_t* timeout) {
+ EXPECT_NE(static_cast<HardwareState*>(NULL), hwstate);
+ EXPECT_EQ(1, hwstate->finger_cnt);
+ prev_ = hwstate->fingers[0];
+ }
+
+ virtual void HandleTimer(stime_t now, stime_t* timeout) {
+ handle_timer_called_ = true;
+ }
+
+ FingerState prev_;
+ bool handle_timer_called_;
+};
+
+
+TEST(StationaryWiggleFilterInterpreterTest, SimpleTest) {
+ FingerEnergy fe = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
+ FingerEnergy fe_eq = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
+ FingerEnergy fe_ne0 = {9.0, 1.0, 1.0, 1.0, 1.0, 1.0};
+ FingerEnergy fe_ne1 = {1.0, 9.0, 1.0, 1.0, 1.0, 1.0};
+ FingerEnergy fe_ne2 = {1.0, 1.0, 9.0, 1.0, 1.0, 1.0};
+ FingerEnergy fe_ne3 = {1.0, 1.0, 1.0, 9.0, 1.0, 1.0};
+ FingerEnergy fe_ne4 = {1.0, 1.0, 1.0, 1.0, 9.0, 1.0};
+ FingerEnergy fe_ne5 = {1.0, 1.0, 1.0, 1.0, 1.0, 9.0};
+
+ EXPECT_EQ(fe, fe_eq);
+ EXPECT_NE(fe, fe_ne0);
+ EXPECT_NE(fe, fe_ne1);
+ EXPECT_NE(fe, fe_ne2);
+ EXPECT_NE(fe, fe_ne3);
+ EXPECT_NE(fe, fe_ne4);
+ EXPECT_NE(fe, fe_ne5);
+
+
+ StationaryWiggleFilterInterpreterTestInterpreter* base_interpreter =
+ new StationaryWiggleFilterInterpreterTestInterpreter;
+ StationaryWiggleFilterInterpreter interpreter(NULL, base_interpreter, NULL);
+
+ EXPECT_FALSE(interpreter.enabled_.val_);
+ interpreter.enabled_.val_ = true;
+
+ HardwareProperties hwprops = {
+ 0, 0, 100, 100, // left, top, right, bottom
+ 1, 1, // x res (pixels/mm), y res (pixels/mm)
+ 1, 1, // scrn DPI X, Y
+ -1, // orientation minimum
+ 2, // orientation maximum
+ 5, 5, // max fingers, max_touch,
+ 0, 0, 1, // t5r2, semi, button pad
+ 0, 0, // has wheel, vertical wheel is high resolution
+ 0, // haptic pad
+ };
+ TestInterpreterWrapper wrapper(&interpreter, &hwprops);
+
+ EXPECT_FALSE(base_interpreter->handle_timer_called_);
+ wrapper.HandleTimer(0.0, NULL);
+ EXPECT_TRUE(base_interpreter->handle_timer_called_);
+
+ FingerState finger_states[] = {
+ // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
+ // Consistent movement for 16 frames
+ {0, 0, 0, 0, 20, 0, 40, 20, 1, 0}, // 0
+ {0, 0, 0, 0, 20, 0, 40, 25, 1, 0}, // 1
+ {0, 0, 0, 0, 20, 0, 40, 30, 1, 0}, // 2
+ {0, 0, 0, 0, 20, 0, 40, 35, 1, 0}, // 3
+ {0, 0, 0, 0, 20, 0, 40, 40, 1, 0}, // 4
+ {0, 0, 0, 0, 20, 0, 40, 45, 1, 0}, // 5
+ {0, 0, 0, 0, 20, 0, 40, 50, 1, 0}, // 6
+ {0, 0, 0, 0, 20, 0, 40, 55, 1, 0}, // 7
+ {0, 0, 0, 0, 20, 0, 40, 60, 1, 0}, // 8
+ {0, 0, 0, 0, 20, 0, 40, 65, 1, 0}, // 9
+ {0, 0, 0, 0, 20, 0, 40, 70, 1, 0}, // 10
+ {0, 0, 0, 0, 20, 0, 40, 75, 1, 0}, // 11
+ {0, 0, 0, 0, 20, 0, 40, 80, 1, 0}, // 12
+ {0, 0, 0, 0, 20, 0, 40, 85, 1, 0}, // 13
+ {0, 0, 0, 0, 20, 0, 40, 90, 1, 0}, // 14
+ {0, 0, 0, 0, 20, 0, 40, 95, 1, 0}, // 15
+ };
+
+ HardwareState hardware_states[] = {
+ // time, buttons, finger count, touch count, finger states pointer
+ make_hwstate(1.00, 0, 1, 1, &finger_states[0]),
+ make_hwstate(1.01, 0, 1, 1, &finger_states[1]),
+ make_hwstate(1.02, 0, 1, 1, &finger_states[2]),
+ make_hwstate(1.03, 0, 1, 1, &finger_states[3]),
+ make_hwstate(1.04, 0, 1, 1, &finger_states[4]),
+ make_hwstate(1.05, 0, 1, 1, &finger_states[5]),
+ make_hwstate(1.06, 0, 1, 1, &finger_states[6]),
+ make_hwstate(1.07, 0, 1, 1, &finger_states[7]),
+ make_hwstate(1.08, 0, 1, 1, &finger_states[8]),
+ make_hwstate(1.09, 0, 1, 1, &finger_states[9]),
+ make_hwstate(1.10, 0, 1, 1, &finger_states[10]),
+ make_hwstate(1.11, 0, 1, 1, &finger_states[11]),
+ make_hwstate(1.12, 0, 1, 1, &finger_states[12]),
+ make_hwstate(1.13, 0, 1, 1, &finger_states[13]),
+ make_hwstate(1.14, 0, 1, 1, &finger_states[14]),
+ make_hwstate(1.15, 0, 1, 1, &finger_states[15]),
+ };
+
+ unsigned expected[] = {
+ 0, 0, 0, 0,
+ GESTURES_FINGER_INSTANTANEOUS_MOVING,
+ GESTURES_FINGER_INSTANTANEOUS_MOVING,
+ GESTURES_FINGER_INSTANTANEOUS_MOVING,
+ GESTURES_FINGER_INSTANTANEOUS_MOVING,
+ GESTURES_FINGER_INSTANTANEOUS_MOVING,
+ GESTURES_FINGER_INSTANTANEOUS_MOVING,
+ GESTURES_FINGER_INSTANTANEOUS_MOVING,
+ GESTURES_FINGER_INSTANTANEOUS_MOVING,
+ GESTURES_FINGER_INSTANTANEOUS_MOVING,
+ GESTURES_FINGER_INSTANTANEOUS_MOVING,
+ GESTURES_FINGER_INSTANTANEOUS_MOVING,
+ GESTURES_FINGER_INSTANTANEOUS_MOVING,
+ };
+
+ for (size_t i = 0; i < arraysize(hardware_states); i++) {
+ HardwareState *hwstate = &hardware_states[i];
+ wrapper.SyncInterpret(hwstate, NULL);
+ for (int j = 0; j < hwstate->finger_cnt; ++j) {
+ FingerState *fs = &hwstate->fingers[j];
+ EXPECT_EQ(fs->flags & (GESTURES_FINGER_WARP_X |
+ GESTURES_FINGER_WARP_Y |
+ GESTURES_FINGER_INSTANTANEOUS_MOVING),
+ expected[i]);
+ }
+ }
+
+ EXPECT_TRUE(interpreter.enabled_.val_);
+ EXPECT_EQ(interpreter.threshold_.val_, 0.012);
+ EXPECT_EQ(interpreter.hysteresis_.val_, 0.006);
+}
+
+} // namespace gestures
diff --git a/src/trace_marker_unittest.cc b/src/trace_marker_unittest.cc
index 6b4a192..b7d1157 100644
--- a/src/trace_marker_unittest.cc
+++ b/src/trace_marker_unittest.cc
@@ -16,7 +16,14 @@ TEST(TraceMarkerTest, DeleteTraceMarkerTest) {
EXPECT_EQ(NULL, TraceMarker::GetTraceMarker());
TraceMarker::CreateTraceMarker();
EXPECT_TRUE(NULL != TraceMarker::GetTraceMarker());
+ TraceMarker::StaticTraceWrite("Test");
+ EXPECT_EQ(-1, TraceMarker::GetTraceMarker()->fd_);
+ EXPECT_EQ(1, TraceMarker::trace_marker_count_);
TraceMarker::DeleteTraceMarker();
EXPECT_EQ(NULL, TraceMarker::GetTraceMarker());
+ TraceMarker::StaticTraceWrite("Test");
+ EXPECT_EQ(0, TraceMarker::trace_marker_count_);
+ TraceMarker::DeleteTraceMarker();
+ EXPECT_EQ(0, TraceMarker::trace_marker_count_);
};
} // namespace gestures
diff --git a/src/trend_classifying_filter_interpreter_unittest.cc b/src/trend_classifying_filter_interpreter_unittest.cc
new file mode 100644
index 0000000..de45efe
--- /dev/null
+++ b/src/trend_classifying_filter_interpreter_unittest.cc
@@ -0,0 +1,120 @@
+// Copyright 2022 The ChromiumOS Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <gtest/gtest.h>
+
+#include "include/trend_classifying_filter_interpreter.h"
+#include "include/unittest_util.h"
+
+namespace gestures {
+
+class TrendClassifyingFilterInterpreterTest : public ::testing::Test {};
+
+class TrendClassifyingFilterInterpreterTestInterpreter : public Interpreter {
+ public:
+ TrendClassifyingFilterInterpreterTestInterpreter()
+ : Interpreter(NULL, NULL, false),
+ handle_timer_called_(false) {}
+
+ virtual void SyncInterpret(HardwareState* hwstate, stime_t* timeout) {
+ EXPECT_NE(static_cast<HardwareState*>(NULL), hwstate);
+ EXPECT_EQ(1, hwstate->finger_cnt);
+ prev_ = hwstate->fingers[0];
+ }
+
+ virtual void HandleTimer(stime_t now, stime_t* timeout) {
+ handle_timer_called_ = true;
+ }
+
+ FingerState prev_;
+ bool handle_timer_called_;
+};
+
+
+TEST(TrendClassifyingFilterInterpreterTest, SimpleTest) {
+ TrendClassifyingFilterInterpreterTestInterpreter* base_interpreter =
+ new TrendClassifyingFilterInterpreterTestInterpreter;
+ TrendClassifyingFilterInterpreter interpreter(NULL, base_interpreter, NULL);
+
+ EXPECT_TRUE(interpreter.trend_classifying_filter_enable_.val_);
+
+ EXPECT_FALSE(interpreter.second_order_enable_.val_);
+ interpreter.second_order_enable_.val_ = true;
+ EXPECT_TRUE(interpreter.second_order_enable_.val_);
+
+ HardwareProperties hwprops = {
+ 0, 0, 100, 100, // left, top, right, bottom
+ 1, 1, // x res (pixels/mm), y res (pixels/mm)
+ 1, 1, // scrn DPI X, Y
+ -1, // orientation minimum
+ 2, // orientation maximum
+ 5, 5, // max fingers, max_touch,
+ 0, 0, 1, // t5r2, semi, button pad
+ 0, 0, // has wheel, vertical wheel is high resolution
+ 0, // haptic pad
+ };
+ TestInterpreterWrapper wrapper(&interpreter, &hwprops);
+
+ EXPECT_FALSE(base_interpreter->handle_timer_called_);
+ wrapper.HandleTimer(0.0, NULL);
+ EXPECT_TRUE(base_interpreter->handle_timer_called_);
+
+ FingerState finger_states[] = {
+ // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
+ // Consistent movement for 16 frames
+ {0, 0, 0, 0, 20, 0, 40, 20, 1, 0}, // 0
+ {0, 0, 0, 0, 20, 0, 40, 25, 1, 0}, // 1
+ {0, 0, 0, 0, 20, 0, 40, 30, 1, 0}, // 2
+ {0, 0, 0, 0, 20, 0, 40, 35, 1, 0}, // 3
+ {0, 0, 0, 0, 20, 0, 40, 40, 1, 0}, // 4
+ {0, 0, 0, 0, 20, 0, 40, 45, 1, 0}, // 5
+ {0, 0, 0, 0, 20, 0, 40, 50, 1, 0}, // 6
+ {0, 0, 0, 0, 20, 0, 40, 55, 1, 0}, // 7
+ {0, 0, 0, 0, 20, 0, 40, 60, 1, 0}, // 8
+ {0, 0, 0, 0, 20, 0, 40, 65, 1, 0}, // 9
+ {0, 0, 0, 0, 20, 0, 40, 70, 1, 0}, // 10
+ {0, 0, 0, 0, 20, 0, 40, 75, 1, 0}, // 11
+ {0, 0, 0, 0, 20, 0, 40, 80, 1, 0}, // 12
+ {0, 0, 0, 0, 20, 0, 40, 85, 1, 0}, // 13
+ {0, 0, 0, 0, 20, 0, 40, 90, 1, 0}, // 14
+ {0, 0, 0, 0, 20, 0, 40, 95, 1, 0}, // 15
+ };
+
+ HardwareState hardware_states[] = {
+ // time, buttons, finger count, touch count, finger states pointer
+ make_hwstate(1.00, 0, 1, 1, &finger_states[0]),
+ make_hwstate(1.01, 0, 1, 1, &finger_states[1]),
+ make_hwstate(1.02, 0, 1, 1, &finger_states[2]),
+ make_hwstate(1.03, 0, 1, 1, &finger_states[3]),
+ make_hwstate(1.04, 0, 1, 1, &finger_states[4]),
+ make_hwstate(1.05, 0, 1, 1, &finger_states[5]),
+ make_hwstate(1.06, 0, 1, 1, &finger_states[6]),
+ make_hwstate(1.07, 0, 1, 1, &finger_states[7]),
+ make_hwstate(1.08, 0, 1, 1, &finger_states[8]),
+ make_hwstate(1.09, 0, 1, 1, &finger_states[9]),
+ make_hwstate(1.10, 0, 1, 1, &finger_states[10]),
+ make_hwstate(1.11, 0, 1, 1, &finger_states[11]),
+ make_hwstate(1.12, 0, 1, 1, &finger_states[12]),
+ make_hwstate(1.13, 0, 1, 1, &finger_states[13]),
+ make_hwstate(1.14, 0, 1, 1, &finger_states[14]),
+ make_hwstate(1.15, 0, 1, 1, &finger_states[15]),
+ };
+
+ for (size_t i = 0; i < arraysize(hardware_states); i++) {
+ HardwareState *hwstate = &hardware_states[i];
+ wrapper.SyncInterpret(hwstate, NULL);
+
+ for (short j = 0; i < hwstate->finger_cnt; i++) {
+ FingerState *fs = &hwstate->fingers[j];
+ EXPECT_EQ(fs->flags, 0);
+ }
+ }
+
+ EXPECT_TRUE(interpreter.trend_classifying_filter_enable_.val_);
+ EXPECT_TRUE(interpreter.second_order_enable_.val_);
+ EXPECT_EQ(interpreter.min_num_of_samples_.val_, 6);
+ EXPECT_EQ(interpreter.z_threshold_.val_, 2.5758293035489004);
+}
+
+} // namespace gestures