diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-03-14 01:07:36 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-03-14 01:07:36 +0000 |
commit | f576ac91fd5a71fb0f25833369b36faf00b3d272 (patch) | |
tree | 80174cb1645877863c3d48298a5683a8adc109a0 | |
parent | 8e529b2b20adc94b770a32f7cce9193811c59d27 (diff) | |
parent | 6ec93b19a1b8ed00a228299db08c33fbed268d7e (diff) | |
download | libchrome-gestures-sdk-release.tar.gz |
Snap for 11573087 from 6ec93b19a1b8ed00a228299db08c33fbed268d7e to sdk-releaseplatform-tools-35.0.1sdk-release
Change-Id: Ibdb5c16beaa21c2865095ff879477e4aa60ef831
-rw-r--r-- | METADATA | 4 | ||||
-rw-r--r-- | Makefile | 12 | ||||
-rw-r--r-- | include/finger_metrics.h | 6 | ||||
-rw-r--r-- | include/immediate_interpreter.h | 1 | ||||
-rw-r--r-- | include/mouse_interpreter.h | 17 | ||||
-rw-r--r-- | include/string_util.h | 33 | ||||
-rw-r--r-- | include/util.h | 11 | ||||
-rw-r--r-- | src/activity_log.cc | 2 | ||||
-rw-r--r-- | src/activity_replay_unittest.cc | 36 | ||||
-rw-r--r-- | src/command_line.cc | 4 | ||||
-rw-r--r-- | src/finger_metrics.cc | 26 | ||||
-rw-r--r-- | src/gestures.cc | 7 | ||||
-rw-r--r-- | src/gestures_unittest.cc | 13 | ||||
-rw-r--r-- | src/iir_filter_interpreter.cc | 12 | ||||
-rw-r--r-- | src/immediate_interpreter.cc | 205 | ||||
-rw-r--r-- | src/immediate_interpreter_unittest.cc | 22 | ||||
-rw-r--r-- | src/interpreter_unittest.cc | 162 | ||||
-rw-r--r-- | src/lookahead_filter_interpreter.cc | 6 | ||||
-rw-r--r-- | src/mouse_interpreter.cc | 72 | ||||
-rw-r--r-- | src/mouse_interpreter_unittest.cc | 3 | ||||
-rw-r--r-- | src/non_linearity_filter_interpreter.cc | 8 | ||||
-rw-r--r-- | src/prop_registry.cc | 24 | ||||
-rw-r--r-- | src/string_util.cc | 81 | ||||
-rw-r--r-- | src/string_util_unittest.cc | 23 | ||||
-rw-r--r-- | tools/touchtests-report.json | 7 |
25 files changed, 402 insertions, 395 deletions
@@ -6,7 +6,7 @@ third_party { type: GIT value: "https://chromium.googlesource.com/chromiumos/platform/gestures/" } - version: "b31ef0adcaff61c045e95158cb9720543b42b531" - last_upgrade_date { year: 2023 month: 12 day: 13 } + version: "b824af1e782a4e741fbfe4b0c311de3bc161e2fc" + last_upgrade_date { year: 2024 month: 3 day: 13 } license_type: NOTICE } @@ -129,6 +129,15 @@ CXXFLAGS+=\ -DGESTURES_INTERNAL=1 \ -I. +ifeq (yes,$(SANITIZE_GESTURES)) +CXXFLAGS+=\ + -fsanitize=address,undefined \ + -fno-sanitize-recover=all +LINK_FLAGS+=\ + -fsanitize=address,undefined \ + -fno-sanitize-recover=all +endif + # Local compilation needs these flags, esp for code coverage testing ifeq (g++,$(CXX)) CXXFLAGS+=\ @@ -138,9 +147,6 @@ CXXFLAGS+=\ -ftest-coverage \ -fprofile-arcs LINK_FLAGS+=-lgcov -else -CXXFLAGS+=\ - -DXLOGGING endif PKG_CONFIG ?= pkg-config diff --git a/include/finger_metrics.h b/include/finger_metrics.h index 1773a94..c1f33dd 100644 --- a/include/finger_metrics.h +++ b/include/finger_metrics.h @@ -6,10 +6,10 @@ #define GESTURES_FINGER_METRICS_H_ #include <cmath> +#include <vector> #include "include/gestures.h" #include "include/prop_registry.h" -#include "include/vector.h" namespace gestures { @@ -130,7 +130,7 @@ class Metrics { // A collection of FingerMetrics describing the current hardware state. // The collection is sorted to yield the oldest finger first. - vector<FingerMetrics, kMaxFingers>& fingers() { return fingers_; } + std::vector<FingerMetrics>& fingers() { return fingers_; } // Find a FingerMetrics instance by it's tracking id. // Returns nullptr if not found. @@ -156,7 +156,7 @@ class Metrics { void SetFingerOriginTimestampForTesting(short tracking_id, stime_t time); private: - vector<FingerMetrics, kMaxFingers> fingers_; + std::vector<FingerMetrics> fingers_; MetricsProperties* properties_; std::unique_ptr<MetricsProperties> own_properties_; diff --git a/include/immediate_interpreter.h b/include/immediate_interpreter.h index 1be420e..7f2aa52 100644 --- a/include/immediate_interpreter.h +++ b/include/immediate_interpreter.h @@ -13,6 +13,7 @@ #include "include/macros.h" #include "include/prop_registry.h" #include "include/tracer.h" +#include "include/vector.h" #ifndef GESTURES_IMMEDIATE_INTERPRETER_H_ #define GESTURES_IMMEDIATE_INTERPRETER_H_ diff --git a/include/mouse_interpreter.h b/include/mouse_interpreter.h index e56be37..d1e12a3 100644 --- a/include/mouse_interpreter.h +++ b/include/mouse_interpreter.h @@ -45,9 +45,9 @@ class MouseInterpreter : public Interpreter, public PropertyDelegate { bool EmulateScrollWheel(const HardwareState& hwstate); private: struct WheelRecord { - WheelRecord(float v, stime_t t): value(v), timestamp(t) {} - WheelRecord(): value(0), timestamp(0) {} - float value; + WheelRecord(float v, stime_t t): change(v), timestamp(t) {} + WheelRecord(): change(0), timestamp(0) {} + float change; stime_t timestamp; }; @@ -60,8 +60,8 @@ class MouseInterpreter : public Interpreter, public PropertyDelegate { HardwareState prev_state_; - // Records last scroll wheel event. - WheelRecord last_wheel_, last_hwheel_; + // Records last scroll wheel events. + std::vector<WheelRecord> last_vertical_wheels_, last_horizontal_wheels_; // Accumulators to measure scroll distance while doing scroll wheel emulation double wheel_emulation_accu_x_; @@ -85,6 +85,13 @@ class MouseInterpreter : public Interpreter, public PropertyDelegate { // Enable high-resolution scrolling. BoolProperty hi_res_scrolling_; + // When calculating scroll velocity for the purpose of acceleration, we + // use the average of this many events in the same direction. This is to avoid + // over-accelerating if we receive batched events with timestamps that are + // artificially close. If we don't have enough events, we won't accelerate at + // all. + IntProperty scroll_velocity_buffer_size_; + // We use normal CDF to simulate scroll wheel acceleration curve. Use the // following method to generate the coefficients of a degree-4 polynomial // regression for a specific normal cdf in Python. diff --git a/include/string_util.h b/include/string_util.h index 6e1a4ba..67fda6c 100644 --- a/include/string_util.h +++ b/include/string_util.h @@ -21,36 +21,9 @@ std::string StringPrintf(const char* format, ...) void StringAppendV(std::string* dst, const char* format, va_list ap) PRINTF_FORMAT(2, 0); -// Trims any whitespace from either end of the input string. Returns where -// whitespace was found. -// The non-wide version has two functions: -// * TrimWhitespaceASCII() -// This function is for ASCII strings and only looks for ASCII whitespace; -// Please choose the best one according to your usage. -// NOTE: Safe to use the same variable for both input and output. -enum TrimPositions { - TRIM_NONE = 0, - TRIM_LEADING = 1 << 0, - TRIM_TRAILING = 1 << 1, - TRIM_ALL = TRIM_LEADING | TRIM_TRAILING, -}; -TrimPositions TrimWhitespaceASCII(const std::string& input, - TrimPositions positions, - std::string* output); - -// Returns true if str starts with search, or false otherwise. -bool StartsWithASCII(const std::string& str, - const std::string& search, - bool case_sensitive); - -// |str| should not be in a multi-byte encoding like Shift-JIS or GBK in which -// the trailing byte of a multi-byte character can be in the ASCII range. -// UTF-8, and other single/multi-byte ASCII-compatible encodings are OK. -// Note: |c| must be in the ASCII range. -void SplitString(const std::string& str, - char c, - std::vector<std::string>* r); - +// Trims whitespace from the start and end of the input string. This function +// is for ASCII strings and only looks for ASCII whitespace. +std::string TrimWhitespaceASCII(const std::string& input); } // namespace gestures diff --git a/include/util.h b/include/util.h index f0c2a39..9371327 100644 --- a/include/util.h +++ b/include/util.h @@ -8,6 +8,7 @@ #include <list> #include <map> #include <set> +#include <vector> #include <math.h> @@ -78,14 +79,14 @@ void RemoveMissingIdsFromMap(std::map<short, Data>* the_map, static inline void RemoveMissingIdsFromSet(std::set<short>* the_set, const HardwareState& hs) { - short old_ids[the_set->size() + 1]; - size_t old_ids_len = 0; + std::vector<short> old_ids; + old_ids.reserve(the_set->size() + 1); for (typename std::set<short>::const_iterator it = the_set->begin(); it != the_set->end(); ++it) if (!hs.GetFingerState(*it)) - old_ids[old_ids_len++] = *it; - for (size_t i = 0; i < old_ids_len; i++) - the_set->erase(old_ids[i]); + old_ids.push_back(*it); + for (auto id : old_ids) + the_set->erase(id); } template<typename Set, typename Elt> diff --git a/src/activity_log.cc b/src/activity_log.cc index 9e6bfbf..d668f9c 100644 --- a/src/activity_log.cc +++ b/src/activity_log.cc @@ -579,7 +579,7 @@ void ActivityLog::AddEncodeInfo(Json::Value* root) { string gestures_version = VCSID; // Strip tailing whitespace. - TrimWhitespaceASCII(gestures_version, TRIM_ALL, &gestures_version); + gestures_version = TrimWhitespaceASCII(gestures_version); (*root)["gesturesVersion"] = Json::Value(gestures_version); (*root)[kKeyProperties] = EncodePropRegistry(); } diff --git a/src/activity_replay_unittest.cc b/src/activity_replay_unittest.cc index ef75491..0dd2879 100644 --- a/src/activity_replay_unittest.cc +++ b/src/activity_replay_unittest.cc @@ -20,6 +20,42 @@ using std::string; namespace gestures { +namespace { + +template <typename STR> +void SplitStringT(const STR& str, + const typename STR::value_type s, + bool trim_whitespace, + std::vector<STR>* r) { + r->clear(); + size_t last = 0; + size_t c = str.size(); + for (size_t i = 0; i <= c; ++i) { + if (i == c || str[i] == s) { + STR tmp(str, last, i - last); + if (trim_whitespace) + tmp = TrimWhitespaceASCII(tmp); + // Avoid converting an empty or all-whitespace source string into a vector + // of one empty string. + if (i != c || !r->empty() || !tmp.empty()) + r->push_back(tmp); + last = i + 1; + } + } +} + +// |str| should not be in a multi-byte encoding like Shift-JIS or GBK in which +// the trailing byte of a multi-byte character can be in the ASCII range. +// UTF-8, and other single/multi-byte ASCII-compatible encodings are OK. +// Note: |c| must be in the ASCII range. +void SplitString(const std::string& str, + char c, + std::vector<std::string>* r) { + SplitStringT(str, c, true, r); +} + +} // namespace + class ActivityReplayTest : public ::testing::Test {}; // This test reads a log file and replays it. This test should be enabled for a diff --git a/src/command_line.cc b/src/command_line.cc index 7f309a2..2779b13 100644 --- a/src/command_line.cc +++ b/src/command_line.cc @@ -59,7 +59,7 @@ void AppendSwitchesAndArguments(CommandLine& command_line, bool parse_switches = true; for (size_t i = 1; i < argv.size(); ++i) { std::string arg = argv[i]; - TrimWhitespaceASCII(arg, TRIM_ALL, &arg); + arg = TrimWhitespaceASCII(arg); std::string switch_string; std::string switch_value; @@ -131,7 +131,7 @@ std::string CommandLine::GetProgram() const { } void CommandLine::SetProgram(const std::string& program) { - TrimWhitespaceASCII(program, TRIM_ALL, &argv_[0]); + argv_[0] = TrimWhitespaceASCII(program); } bool CommandLine::HasSwitch(const std::string& switch_string) const { diff --git a/src/finger_metrics.cc b/src/finger_metrics.cc index a79ea10..4215196 100644 --- a/src/finger_metrics.cc +++ b/src/finger_metrics.cc @@ -76,14 +76,17 @@ bool Metrics::CloseEnoughToGesture(const Vector2& pos_a, < vert_axis_sq * horiz_axis_sq; } -Metrics::Metrics(MetricsProperties* properties) : properties_(properties) {} +Metrics::Metrics(MetricsProperties* properties) : properties_(properties) { + fingers_.reserve(kMaxFingers); +} const FingerMetrics* Metrics::GetFinger(short tracking_id) const { - auto iter = fingers_.find(FingerMetrics(tracking_id)); - if (iter != fingers_.end()) - return iter; - else - return nullptr; + for (auto iter = fingers_.cbegin(); iter != fingers_.cend(); ++iter) { + if(iter->tracking_id() == tracking_id) { + return &(*iter); + } + } + return nullptr; } const FingerMetrics* Metrics::GetFinger(const FingerState& state) const { @@ -98,8 +101,7 @@ void Metrics::Update(const HardwareState& hwstate) { // create metrics for new fingers for (int i=0; i<hwstate.finger_cnt; ++i) { const FingerState& state = hwstate.fingers[i]; - auto iter = fingers_.find(FingerMetrics(state.tracking_id)); - if (iter == fingers_.end()) { + if (GetFinger(state.tracking_id) == nullptr) { fingers_.push_back(FingerMetrics(state, hwstate.timestamp)); ++new_count; @@ -138,9 +140,11 @@ void Metrics::Clear() { void Metrics::SetFingerOriginTimestampForTesting(short tracking_id, stime_t time) { - if (auto iter = fingers_.find(FingerMetrics(tracking_id)); - iter != fingers_.end()) { - fingers_.erase(iter); + for (auto iter = fingers_.begin(); iter != fingers_.end(); ++iter) { + if(iter->tracking_id() == tracking_id) { + fingers_.erase(iter); + break; + } } fingers_.push_back(FingerMetrics(tracking_id, time)); } diff --git a/src/gestures.cc b/src/gestures.cc index b4d5271..cd49c68 100644 --- a/src/gestures.cc +++ b/src/gestures.cc @@ -42,7 +42,6 @@ using std::string; using std::min; using gestures::StringPrintf; -using gestures::StartsWithASCII; // C API: @@ -135,9 +134,9 @@ string FingerState::FlagsString(unsigned flags) { if (flags) { // prepend remaining number ret = StringPrintf("%u%s", flags, ret.c_str()); - } else if (StartsWithASCII(ret, kPipeSeparator, false)) { + } else if (ret.rfind(kPipeSeparator, 0) == 0) { // strip extra pipe - ret = string(ret.c_str() + strlen(kPipeSeparator)); + ret = ret.substr(strlen(kPipeSeparator)); } else { ret = "0"; } @@ -507,7 +506,7 @@ void GestureInterpreter::SetTimerProvider(GesturesTimerProvider* tp, interpret_timer_ = nullptr; } if (interpret_timer_) - Log("How was interpret_timer_ not null?!"); + Err("How was interpret_timer_ not null?!"); timer_provider_ = tp; timer_provider_data_ = data; if (timer_provider_) diff --git a/src/gestures_unittest.cc b/src/gestures_unittest.cc index 6b00902..b11a339 100644 --- a/src/gestures_unittest.cc +++ b/src/gestures_unittest.cc @@ -411,6 +411,19 @@ TEST(GesturesTest, StimeFromTimespecTest) { EXPECT_DOUBLE_EQ(2000000000.999999999, StimeFromTimespec(&tv)); } +TEST(GesturesTest, FingerStateFlagsStringTest) { + EXPECT_EQ("0", FingerState::FlagsString(0)); + EXPECT_EQ("GESTURES_FINGER_PALM", + FingerState::FlagsString(GESTURES_FINGER_PALM)); + EXPECT_EQ("GESTURES_FINGER_PALM | GESTURES_FINGER_WARP_X_MOVE", + FingerState::FlagsString( + GESTURES_FINGER_PALM | GESTURES_FINGER_WARP_X_MOVE)); + // 1 << 31 probably won't be used as a finger flag value anytime soon, so use + // it to test prepending the remaining number. + EXPECT_EQ("2147483648 | GESTURES_FINGER_PALM", + FingerState::FlagsString(GESTURES_FINGER_PALM | (1 << 31))); +} + TEST(GesturesTest, HardwareStateGetFingerStateTest) { FingerState fs[] = { { 0, 0, 0, 0, 1, 0, 150, 4000, 4, 0 }, diff --git a/src/iir_filter_interpreter.cc b/src/iir_filter_interpreter.cc index 5ea513d..84a1faf 100644 --- a/src/iir_filter_interpreter.cc +++ b/src/iir_filter_interpreter.cc @@ -5,6 +5,7 @@ #include "include/iir_filter_interpreter.h" #include <utility> +#include <vector> namespace gestures { @@ -57,14 +58,15 @@ void IirFilterInterpreter::SyncInterpretImpl(HardwareState& hwstate, LogHardwareStatePre(name, hwstate); // Delete old entries from map - short dead_ids[histories_.size() + 1]; - size_t dead_ids_len = 0; + std::vector<short> dead_ids; + dead_ids.reserve(histories_.size()); + for (std::map<short, IoHistory>::iterator it = histories_.begin(), e = histories_.end(); it != e; ++it) if (!hwstate.GetFingerState((*it).first)) - dead_ids[dead_ids_len++] = (*it).first; - for (size_t i = 0; i < dead_ids_len; ++i) - histories_.erase(dead_ids[i]); + dead_ids.push_back((*it).first); + for (auto dead_id : dead_ids) + histories_.erase(dead_id); // Modify current hwstate for (size_t i = 0; i < hwstate.finger_cnt; i++) { diff --git a/src/immediate_interpreter.cc b/src/immediate_interpreter.cc index c1aa568..9f63427 100644 --- a/src/immediate_interpreter.cc +++ b/src/immediate_interpreter.cc @@ -11,6 +11,7 @@ #include <functional> #include <limits> #include <tuple> +#include <vector> #include "include/gestures.h" #include "include/logging.h" @@ -61,9 +62,7 @@ void TapRecord::NoteTouch(short the_id, const FingerState& fs) { // New finger must be close enough to an existing finger if (!touched_.empty()) { bool reject_new_finger = true; - for (std::map<short, FingerState>::const_iterator it = - touched_.begin(), e = touched_.end(); it != e; ++it) { - const FingerState& existing_fs = (*it).second; + for (const auto& [tracking_id, existing_fs] : touched_) { if (immediate_interpreter_->metrics_->CloseEnoughToGesture( Vector2(existing_fs), Vector2(fs))) { @@ -113,28 +112,26 @@ void TapRecord::Update(const HardwareState& hwstate, else if (diff < 0) t5r2_released_size_ += -diff; } - for (std::set<short>::const_iterator it = added.begin(), - e = added.end(); it != e; ++it) - Log("TapRecord::Update: Added: %d", *it); - for (std::set<short>::const_iterator it = removed.begin(), - e = removed.end(); it != e; ++it) - Log("TapRecord::Update: Removed: %d", *it); - for (std::set<short>::const_iterator it = dead.begin(), - e = dead.end(); it != e; ++it) - Log("TapRecord::Update: Dead: %d", *it); + for (short tracking_id : added) { + Log("TapRecord::Update: Added: %d", tracking_id); + } + for (short tracking_id: removed) { + Log("TapRecord::Update: Removed: %d", tracking_id); + } + for (short tracking_id : dead) { + Log("TapRecord::Update: Dead: %d", tracking_id); + } for_each(dead.begin(), dead.end(), bind(&TapRecord::Remove, this, std::placeholders::_1)); - for (std::set<short>::const_iterator it = added.begin(), - e = added.end(); it != e; ++it) - NoteTouch(*it, *hwstate.GetFingerState(*it)); + for (short tracking_id : added) { + NoteTouch(tracking_id, *hwstate.GetFingerState(tracking_id)); + } for_each(removed.begin(), removed.end(), bind(&TapRecord::NoteRelease, this, std::placeholders::_1)); // Check if min tap/cotap pressure met yet const float cotap_min_pressure = CotapMinPressure(); - for (std::map<short, FingerState>::iterator it = - touched_.begin(), e = touched_.end(); - it != e; ++it) { - const FingerState* fs = hwstate.GetFingerState((*it).first); + for (auto& [tracking_id, existing_fs] : touched_) { + const FingerState* fs = hwstate.GetFingerState(tracking_id); if (fs) { if (fs->pressure >= immediate_interpreter_->tap_min_pressure() || !immediate_interpreter_->device_reports_pressure()) @@ -142,11 +139,11 @@ void TapRecord::Update(const HardwareState& hwstate, if (fs->pressure >= cotap_min_pressure || !immediate_interpreter_->device_reports_pressure()) { min_cotap_pressure_met_.insert(fs->tracking_id); - if ((*it).second.pressure < cotap_min_pressure && + if (existing_fs.pressure < cotap_min_pressure && immediate_interpreter_->device_reports_pressure()) { // Update existing record, since the old one hadn't met the cotap // pressure - (*it).second = *fs; + existing_fs = *fs; } } stime_t finger_age = hwstate.timestamp - @@ -171,20 +168,19 @@ void TapRecord::Clear() { bool TapRecord::Moving(const HardwareState& hwstate, const float dist_max) const { const float cotap_min_pressure = CotapMinPressure(); - for (std::map<short, FingerState>::const_iterator it = - touched_.begin(), e = touched_.end(); it != e; ++it) { - const FingerState* fs = hwstate.GetFingerState((*it).first); + for (const auto& [tracking_id, existing_fs] : touched_) { + const FingerState* fs = hwstate.GetFingerState(tracking_id); if (!fs) continue; // Only look for moving when current frame meets cotap pressure and // our history contains a contact that's met cotap pressure. if ((fs->pressure < cotap_min_pressure || - (*it).second.pressure < cotap_min_pressure) && + existing_fs.pressure < cotap_min_pressure) && immediate_interpreter_->device_reports_pressure()) continue; // Compute distance moved - float dist_x = fs->position_x - (*it).second.position_x; - float dist_y = fs->position_y - (*it).second.position_y; + float dist_x = fs->position_x - existing_fs.position_x; + float dist_y = fs->position_y - existing_fs.position_y; // Respect WARP flags if (fs->flags & GESTURES_FINGER_WARP_X_TAP_MOVE) dist_x = 0.0; @@ -202,10 +198,9 @@ bool TapRecord::Moving(const HardwareState& hwstate, bool TapRecord::Motionless(const HardwareState& hwstate, const HardwareState& prev_hwstate, const float max_speed) const { const float cotap_min_pressure = CotapMinPressure(); - for (std::map<short, FingerState>::const_iterator it = - touched_.begin(), e = touched_.end(); it != e; ++it) { - const FingerState* fs = hwstate.GetFingerState((*it).first); - const FingerState* prev_fs = prev_hwstate.GetFingerState((*it).first); + for (const auto& [tracking_id, _] : touched_) { + const FingerState* fs = hwstate.GetFingerState(tracking_id); + const FingerState* prev_fs = prev_hwstate.GetFingerState(tracking_id); if (!fs || !prev_fs) continue; // Only look for moving when current frame meets cotap pressure and @@ -233,12 +228,12 @@ bool TapRecord::TapComplete() const { ret = t5r2_touched_size_ && t5r2_touched_size_ == t5r2_released_size_; else ret = !touched_.empty() && (touched_.size() == released_.size()); - for (std::map<short, FingerState>::const_iterator - it = touched_.begin(), e = touched_.end(); it != e; ++it) - Log("TapRecord::TapComplete: touched_: %d", (*it).first); - for (std::set<short>::const_iterator it = released_.begin(), - e = released_.end(); it != e; ++it) - Log("TapRecord::TapComplete: released_: %d", *it); + for (const auto& [tracking_id, finger_state] : touched_) { + Log("TapRecord::TapComplete: touched_: %d", tracking_id); + } + for (short tracking_id : released_) { + Log("TapRecord::TapComplete: released_: %d", tracking_id); + } return ret; } @@ -457,10 +452,9 @@ bool ScrollManager::FillResultScroll( float dy = 0.0; bool stationary = true; bool pressure_changing = false; - for (FingerMap::const_iterator it = - gs_fingers.begin(), e = gs_fingers.end(); it != e; ++it) { - const FingerState* fs = state_buffer.Get(0).GetFingerState(*it); - const FingerState* prev = state_buffer.Get(1).GetFingerState(*it); + for (short tracking_id : gs_fingers) { + const FingerState* fs = state_buffer.Get(0).GetFingerState(tracking_id); + const FingerState* prev = state_buffer.Get(1).GetFingerState(tracking_id); if (!prev) return false; const stime_t dt = @@ -1687,9 +1681,9 @@ void ImmediateInterpreter::UpdateThumbState(const HardwareState& hwstate) { thumb_eval_timer_[fs.tracking_id] = thumb_eval_timeout_.val_; } } - for (std::map<short, stime_t>::const_iterator it = thumb_.begin(); - it != thumb_.end(); ++it) - pointing_.erase((*it).first); + for (const auto& [tracking_id, _] : thumb_) { + pointing_.erase(tracking_id); + } } void ImmediateInterpreter::UpdateNonGsFingers(const HardwareState& hwstate) { @@ -1733,7 +1727,7 @@ FingerMap ImmediateInterpreter::GetGesturingFingers( return {}; } - const FingerState* fs[hwstate.finger_cnt]; + std::vector<FingerState*> fs(hwstate.finger_cnt); for (size_t i = 0; i < hwstate.finger_cnt; ++i) fs[i] = &hwstate.fingers[i]; @@ -1743,11 +1737,12 @@ FingerMap ImmediateInterpreter::GetGesturingFingers( FingerMap ret; size_t sorted_cnt; if (hwstate.finger_cnt > kMaxGesturingFingers) { - std::partial_sort(fs, fs + kMaxGesturingFingers, fs + hwstate.finger_cnt, + std::partial_sort(fs.begin(), fs.begin() + kMaxGesturingFingers, + fs.end(), compare); sorted_cnt = kMaxGesturingFingers; } else { - std::sort(fs, fs + hwstate.finger_cnt, compare); + std::sort(fs.begin(), fs.end(), compare); sorted_cnt = hwstate.finger_cnt; } for (size_t i = 0; i < sorted_cnt; i++) @@ -1883,9 +1878,7 @@ void ImmediateInterpreter::UpdateCurrentGestureType( } if (current_gesture_type_ != kGestureTypeNull) { active_gs_fingers->clear(); - for (vector<short, kMaxGesturingFingers>::const_iterator it = - sorted_ids.begin(), e = sorted_ids.end(); it != e; ++it) - active_gs_fingers->insert(*it); + active_gs_fingers->insert(sorted_ids.begin(), sorted_ids.end()); break; } } @@ -1975,8 +1968,10 @@ void ImmediateInterpreter::SortFingersByProximity( // that until we have enough points size_t dist_sq_capacity = (finger_ids.size() * (finger_ids.size() - 1)) / 2; - DistSqElt dist_sq[dist_sq_capacity]; - size_t dist_sq_len = 0; + + std::vector<DistSqElt> dist_sq; + dist_sq.reserve(dist_sq_capacity); + for (size_t i = 0; i < hwstate.finger_cnt; i++) { const FingerState& fs1 = hwstate.fingers[i]; if (!SetContainsValue(finger_ids, fs1.tracking_id)) @@ -1989,24 +1984,20 @@ void ImmediateInterpreter::SortFingersByProximity( DistSq(fs1, fs2), { fs1.tracking_id, fs2.tracking_id } }; - if (dist_sq_len >= dist_sq_capacity) { - Err("%s: Array overrun", __func__); - break; - } - dist_sq[dist_sq_len++] = elt; + dist_sq.push_back(elt); } } DistSqCompare distSqCompare; - std::sort(dist_sq, dist_sq + dist_sq_len, distSqCompare); + std::sort(dist_sq.begin(), dist_sq.end(), distSqCompare); if (out_sorted_ids == nullptr) { Err("out_sorted_ids became null"); return; } - for (size_t i = 0; i < dist_sq_len; i++) { - short id1 = dist_sq[i].tracking_id[0]; - short id2 = dist_sq[i].tracking_id[1]; + for (auto const & d: dist_sq) { + short id1 = d.tracking_id[0]; + short id2 = d.tracking_id[1]; bool contains1 = out_sorted_ids->find(id1) != out_sorted_ids->end(); bool contains2 = out_sorted_ids->find(id2) != out_sorted_ids->end(); if (contains1 == contains2 && !out_sorted_ids->empty()) { @@ -2222,9 +2213,8 @@ bool ImmediateInterpreter::PalmIsArrivingOrDeparting( bool ImmediateInterpreter::IsTooCloseToThumb(const FingerState& finger) const { const float kMin2fDistThreshSq = tapping_finger_min_separation_.val_ * tapping_finger_min_separation_.val_; - for (std::map<short, stime_t>::const_iterator it = thumb_.begin(); - it != thumb_.end(); ++it) { - const FingerState* thumb = state_buffer_.Get(0).GetFingerState(it->first); + for (const auto& [tracking_id, _] : thumb_) { + const FingerState* thumb = state_buffer_.Get(0).GetFingerState(tracking_id); float xdist = fabsf(finger.position_x - thumb->position_x); float ydist = fabsf(finger.position_y - thumb->position_y); if (xdist * xdist + ydist * ydist < kMin2fDistThreshSq) @@ -2463,8 +2453,10 @@ GestureType ImmediateInterpreter::GetMultiFingerGestureType( return kGestureTypeNull; } - const FingerState* x_fingers[num_fingers]; - const FingerState* y_fingers[num_fingers]; + assert(num_fingers <= (int) kMaxGesturingFingers); + + const FingerState* x_fingers[kMaxGesturingFingers]; + const FingerState* y_fingers[kMaxGesturingFingers]; for (int i = 0; i < num_fingers; i++) { x_fingers[i] = fingers[i]; y_fingers[i] = fingers[i]; @@ -2478,13 +2470,13 @@ GestureType ImmediateInterpreter::GetMultiFingerGestureType( bool horizontal = (x_fingers[num_fingers - 1]->position_x - x_fingers[0]->position_x) >= (y_fingers[num_fingers -1]->position_y - y_fingers[0]->position_y); - const FingerState* sorted_fingers[num_fingers]; + const FingerState* sorted_fingers[4]; for (int i = 0; i < num_fingers; i++) { sorted_fingers[i] = horizontal ? x_fingers[i] : y_fingers[i]; } - float dx[num_fingers]; - float dy[num_fingers]; + float dx[kMaxGesturingFingers]; + float dy[kMaxGesturingFingers]; float dy_sum = 0; float dx_sum = 0; for (int i = 0; i < num_fingers; i++) { @@ -2548,7 +2540,7 @@ stime_t ImmediateInterpreter::TimeoutForTtcState(TapToClickState state) { case kTtcDragRelease: return tap_drag_timeout_.val_; case kTtcDragRetouch: return tap_timeout_.val_; default: - Log("Unknown state!"); + Err("Unknown TapToClickState %u!", state); return 0.0; } } @@ -2606,14 +2598,13 @@ void ImmediateInterpreter::UpdateTapState( (GESTURES_FINGER_NO_TAP | GESTURES_FINGER_MERGE)) cancel_tapping = true; } - for (FingerMap::const_iterator it = - gs_fingers.begin(), e = gs_fingers.end(); it != e; ++it) { - const FingerState* fs = hwstate->GetFingerState(*it); + for (short tracking_id : gs_fingers) { + const FingerState* fs = hwstate->GetFingerState(tracking_id); if (!fs) { Err("Missing finger state?!"); continue; } - tap_gs_fingers.insert(*it); + tap_gs_fingers.insert(tracking_id); } } std::set<short> added_fingers; @@ -2638,40 +2629,37 @@ void ImmediateInterpreter::UpdateTapState( if (hwstate && (!same_fingers || prev_tap_gs_fingers_ != tap_gs_fingers)) { // See if fingers were added - for (FingerMap::const_iterator it = - tap_gs_fingers.begin(), e = tap_gs_fingers.end(); it != e; ++it) { + for (short tracking_id : tap_gs_fingers) { // If the finger was marked as a thumb before, it is not new. - if (hwstate->timestamp - finger_origin_timestamp(*it) > + if (hwstate->timestamp - finger_origin_timestamp(tracking_id) > thumb_click_prevention_timeout_.val_) continue; - if (!SetContainsValue(prev_tap_gs_fingers_, *it)) { + if (!SetContainsValue(prev_tap_gs_fingers_, tracking_id)) { // Gesturing finger wasn't in prev state. It's new. - const FingerState* fs = hwstate->GetFingerState(*it); + const FingerState* fs = hwstate->GetFingerState(tracking_id); if (FingerTooCloseToTap(*hwstate, *fs) || FingerTooCloseToTap(state_buffer_.Get(1), *fs) || SetContainsValue(tap_dead_fingers_, fs->tracking_id)) continue; - added_fingers.insert(*it); - Log("TTC: Added %d", *it); + added_fingers.insert(tracking_id); + Log("TTC: Added %d", tracking_id); } } // See if fingers were removed or are now non-gesturing (dead) - for (FingerMap::const_iterator it = - prev_tap_gs_fingers_.begin(), e = prev_tap_gs_fingers_.end(); - it != e; ++it) { - if (tap_gs_fingers.find(*it) != tap_gs_fingers.end()) + for (short tracking_id : prev_tap_gs_fingers_) { + if (tap_gs_fingers.find(tracking_id) != tap_gs_fingers.end()) // still gesturing; neither removed nor dead continue; - if (!hwstate->GetFingerState(*it)) { + if (!hwstate->GetFingerState(tracking_id)) { // Previously gesturing finger isn't in current state. It's gone. - removed_fingers.insert(*it); - Log("TTC: Removed %d", *it); + removed_fingers.insert(tracking_id); + Log("TTC: Removed %d", tracking_id); } else { // Previously gesturing finger is in current state. It's dead. - dead_fingers.insert(*it); - Log("TTC: Dead %d", *it); + dead_fingers.insert(tracking_id); + Log("TTC: Dead %d", tracking_id); } } } @@ -2747,7 +2735,7 @@ void ImmediateInterpreter::UpdateTapState( break; } if (!hwstate) { - Log("hwstate is null but no timeout?!"); + Err("hwstate is null but not a timeout?!"); break; } tap_record_.Update( @@ -2797,7 +2785,7 @@ void ImmediateInterpreter::UpdateTapState( break; case kTtcSubsequentTapBegan: if (!is_timeout && !hwstate) { - Log("hwstate is null but not a timeout?!"); + Err("hwstate is null but not a timeout?!"); break; } if (hwstate) @@ -2901,7 +2889,7 @@ void ImmediateInterpreter::UpdateTapState( break; } if (!hwstate) { - Log("not timeout but hwstate is null?!"); + Err("hwstate is null but not a timeout?!"); break; } if (tap_record_.Moving(*hwstate, tap_move_dist_.val_)) @@ -3038,15 +3026,15 @@ void ImmediateInterpreter::UpdateStartedMovingTime( const FingerMap& gs_fingers, const FingerMap& newly_moving_fingers) { // Update started moving time if any gesturing finger is newly moving. - for (auto it = gs_fingers.begin(), e = gs_fingers.end(); it != e; ++it) { - if (SetContainsValue(newly_moving_fingers, *it)) { + for (short gs_tracking_id : gs_fingers) { + if (SetContainsValue(newly_moving_fingers, gs_tracking_id)) { started_moving_time_ = now; // Extend the thumb evaluation period for any finger that is still under // evaluation as there is a new moving finger. - for (std::map<short, stime_t>::iterator it = thumb_.begin(); - it != thumb_.end(); ++it) - if ((*it).second < thumb_eval_timeout_.val_ && (*it).second > 0.0) - (*it).second = thumb_eval_timeout_.val_; + for (auto& [_, time] : thumb_) { + if (time < thumb_eval_timeout_.val_ && time > 0.0) + time = thumb_eval_timeout_.val_; + } return; } } @@ -3168,9 +3156,8 @@ void ImmediateInterpreter::FillResultGesture( const HardwareState& prev_hs = state_buffer_.Get(1); if (!current) { float curr_dist_sq = -1; - for (FingerMap::const_iterator it = - fingers.begin(), e = fingers.end(); it != e; ++it) { - const FingerState* fs = hwstate.GetFingerState(*it); + for (short tracking_id : fingers) { + const FingerState* fs = hwstate.GetFingerState(tracking_id); const FingerState* prev_fs = prev_hs.GetFingerState(fs->tracking_id); if (!prev_fs) break; @@ -3277,9 +3264,8 @@ void ImmediateInterpreter::FillResultGesture( float finger_cnt[] = { 0.0, 0.0 }; float FingerState::*fields[] = { &FingerState::position_x, &FingerState::position_y }; - for (FingerMap::const_iterator it = - fingers.begin(), e = fingers.end(); it != e; ++it) { - if (!state_buffer_.Get(1).GetFingerState(*it)) { + for (short tracking_id : fingers) { + if (!state_buffer_.Get(1).GetFingerState(tracking_id)) { Err("missing prev state?"); continue; } @@ -3290,8 +3276,8 @@ void ImmediateInterpreter::FillResultGesture( if (!valid[i] || !correct_axis) continue; float FingerState::*field = fields[i]; - float delta = hwstate.GetFingerState(*it)->*field - - state_buffer_.Get(1).GetFingerState(*it)->*field; + float delta = hwstate.GetFingerState(tracking_id)->*field - + state_buffer_.Get(1).GetFingerState(tracking_id)->*field; // The multiply is to see if they have the same sign: if (sum_delta[i] == 0.0 || sum_delta[i] * delta > 0) { sum_delta[i] += delta; @@ -3430,9 +3416,8 @@ void ImmediateInterpreter::Initialize(const HardwareProperties* hwprops, bool AnyGesturingFingerLeft(const HardwareState& state, const FingerMap& prev_gs_fingers) { - for (FingerMap::const_iterator it = prev_gs_fingers.begin(), - e = prev_gs_fingers.end(); it != e; ++it) { - if (!state.GetFingerState(*it)) { + for (short tracking_id : prev_gs_fingers) { + if (!state.GetFingerState(tracking_id)) { return true; } } diff --git a/src/immediate_interpreter_unittest.cc b/src/immediate_interpreter_unittest.cc index c7c6db2..994b11c 100644 --- a/src/immediate_interpreter_unittest.cc +++ b/src/immediate_interpreter_unittest.cc @@ -28,31 +28,31 @@ TEST(ImmediateInterpreterTest, ScrollEventTest) { EXPECT_EQ(22.0, ev3.dy); EXPECT_EQ(33.0, ev3.dt); - ScrollEventBuffer* evbuf = new ScrollEventBuffer(2); - evbuf->Insert(1.0, 2.0, 3.0); - ev1 = evbuf->Get(0); + ScrollEventBuffer evbuf(2); + evbuf.Insert(1.0, 2.0, 3.0); + ev1 = evbuf.Get(0); EXPECT_EQ(1.0, ev1.dx); EXPECT_EQ(2.0, ev1.dy); EXPECT_EQ(3.0, ev1.dt); - ev1 = evbuf->Get(3); + ev1 = evbuf.Get(3); EXPECT_EQ(0.0, ev1.dx); EXPECT_EQ(0.0, ev1.dy); EXPECT_EQ(0.0, ev1.dt); } TEST(ImmediateInterpreterTest, HardwareStateBufferTest) { - HardwareStateBuffer* hsb = new HardwareStateBuffer(10); - hsb->Reset(0); - EXPECT_EQ(hsb->Size(), 10); + HardwareStateBuffer hsb(10); + hsb.Reset(0); + EXPECT_EQ(hsb.Size(), 10); } TEST(ImmediateInterpreterTest, ScrollManagerTest) { - PropRegistry* my_prop_reg = new PropRegistry(); - ScrollManager* sm = new ScrollManager(my_prop_reg); - ScrollEventBuffer* scroll_buffer = new ScrollEventBuffer(2); + PropRegistry my_prop_reg; + ScrollManager sm(&my_prop_reg); + ScrollEventBuffer scroll_buffer(2); ScrollEvent ev; - sm->RegressScrollVelocity(*scroll_buffer, 1, &ev); + sm.RegressScrollVelocity(scroll_buffer, 1, &ev); EXPECT_EQ(0.0, ev.dx); EXPECT_EQ(0.0, ev.dy); EXPECT_EQ(1.0, ev.dt); diff --git a/src/interpreter_unittest.cc b/src/interpreter_unittest.cc index e0d1cff..ff5e785 100644 --- a/src/interpreter_unittest.cc +++ b/src/interpreter_unittest.cc @@ -75,9 +75,8 @@ class InterpreterTestInterpreter : public Interpreter { TEST(InterpreterTest, SimpleTest) { PropRegistry prop_reg; - InterpreterTestInterpreter* base_interpreter = - new InterpreterTestInterpreter(&prop_reg); - base_interpreter->SetEventLoggingEnabled(true); + InterpreterTestInterpreter base_interpreter(&prop_reg); + base_interpreter.SetEventLoggingEnabled(true); MetricsProperties mprops(&prop_reg); HardwareProperties hwprops = { @@ -94,19 +93,19 @@ TEST(InterpreterTest, SimpleTest) { .is_haptic_pad = 0, }; - TestInterpreterWrapper wrapper(base_interpreter, &hwprops); + TestInterpreterWrapper wrapper(&base_interpreter, &hwprops); - base_interpreter->bool_prop_.val_ = 1; - base_interpreter->double_prop_.val_ = 1; - base_interpreter->int_prop_.val_ = 1; - base_interpreter->string_prop_.val_ = "x"; + base_interpreter.bool_prop_.val_ = 1; + base_interpreter.double_prop_.val_ = 1; + base_interpreter.int_prop_.val_ = 1; + base_interpreter.string_prop_.val_ = "x"; //if (prop_reg) - // prop_reg->set_activity_log(&(base_interpreter->log_)); + // prop_reg->set_activity_log(&(base_interpreter.log_)); char interpreter_name[] = "InterpreterTestInterpreter"; - base_interpreter->expected_interpreter_name_ = interpreter_name; - base_interpreter->return_value_ = Gesture(kGestureMove, + base_interpreter.expected_interpreter_name_ = interpreter_name; + base_interpreter.return_value_ = Gesture(kGestureMove, 0, // start time 1, // end time -4, // dx @@ -119,39 +118,38 @@ TEST(InterpreterTest, SimpleTest) { HardwareState hardware_state = make_hwstate(200000, 0, 1, 1, &finger_state); stime_t timeout = NO_DEADLINE; - base_interpreter->expected_hwstate_ = &hardware_state; + base_interpreter.expected_hwstate_ = &hardware_state; Gesture* result = wrapper.SyncInterpret(hardware_state, &timeout); - EXPECT_TRUE(base_interpreter->return_value_ == *result); + EXPECT_TRUE(base_interpreter.return_value_ == *result); ASSERT_GT(timeout, 0); stime_t now = hardware_state.timestamp + timeout; timeout = NO_DEADLINE; result = wrapper.HandleTimer(now, &timeout); - EXPECT_TRUE(base_interpreter->return_value_ == *result); + EXPECT_TRUE(base_interpreter.return_value_ == *result); ASSERT_LT(timeout, 0); - EXPECT_EQ(1, base_interpreter->interpret_call_count_); - EXPECT_EQ(1, base_interpreter->handle_timer_call_count_); + EXPECT_EQ(1, base_interpreter.interpret_call_count_); + EXPECT_EQ(1, base_interpreter.handle_timer_call_count_); // Now, get the log - string initial_log = base_interpreter->Encode(); + string initial_log = base_interpreter.Encode(); // Make a new interpreter and push the log through it PropRegistry prop_reg2; - InterpreterTestInterpreter* base_interpreter2 = - new InterpreterTestInterpreter(&prop_reg2); - base_interpreter2->SetEventLoggingEnabled(true); - base_interpreter2->return_value_ = base_interpreter->return_value_; - base_interpreter2->expected_interpreter_name_ = interpreter_name; + InterpreterTestInterpreter base_interpreter2(&prop_reg2); + base_interpreter2.SetEventLoggingEnabled(true); + base_interpreter2.return_value_ = base_interpreter.return_value_; + base_interpreter2.expected_interpreter_name_ = interpreter_name; MetricsProperties mprops2(&prop_reg2); ActivityReplay replay(&prop_reg2); replay.Parse(initial_log); - base_interpreter2->expected_hwstate_ = &hardware_state; + base_interpreter2.expected_hwstate_ = &hardware_state; - replay.Replay(base_interpreter2, &mprops2); - string final_log = base_interpreter2->Encode(); + replay.Replay(&base_interpreter2, &mprops2); + string final_log = base_interpreter2.Encode(); EXPECT_EQ(initial_log, final_log); - EXPECT_EQ(1, base_interpreter2->interpret_call_count_); - EXPECT_EQ(1, base_interpreter2->handle_timer_call_count_); + EXPECT_EQ(1, base_interpreter2.interpret_call_count_); + EXPECT_EQ(1, base_interpreter2.handle_timer_call_count_); } class InterpreterResetLogTestInterpreter : public Interpreter { @@ -168,10 +166,9 @@ class InterpreterResetLogTestInterpreter : public Interpreter { TEST(InterpreterTest, ResetLogTest) { PropRegistry prop_reg; - InterpreterResetLogTestInterpreter* base_interpreter = - new InterpreterResetLogTestInterpreter(); - base_interpreter->SetEventLoggingEnabled(true); - TestInterpreterWrapper wrapper(base_interpreter); + InterpreterResetLogTestInterpreter base_interpreter; + base_interpreter.SetEventLoggingEnabled(true); + TestInterpreterWrapper wrapper(&base_interpreter); FingerState finger_state = { // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID @@ -180,24 +177,23 @@ TEST(InterpreterTest, ResetLogTest) { HardwareState hardware_state = make_hwstate(200000, 0, 1, 1, &finger_state); stime_t timeout = NO_DEADLINE; wrapper.SyncInterpret(hardware_state, &timeout); - EXPECT_EQ(base_interpreter->log_->size(), 1); + EXPECT_EQ(base_interpreter.log_->size(), 1); wrapper.SyncInterpret(hardware_state, &timeout); - EXPECT_EQ(base_interpreter->log_->size(), 2); + EXPECT_EQ(base_interpreter.log_->size(), 2); // Assume the ResetLog property is set. - base_interpreter->Clear(); - EXPECT_EQ(base_interpreter->log_->size(), 0); + base_interpreter.Clear(); + EXPECT_EQ(base_interpreter.log_->size(), 0); wrapper.SyncInterpret(hardware_state, &timeout); - EXPECT_EQ(base_interpreter->log_->size(), 1); + EXPECT_EQ(base_interpreter.log_->size(), 1); } TEST(InterpreterTest, LoggingDisabledByDefault) { PropRegistry prop_reg; - InterpreterResetLogTestInterpreter* base_interpreter = - new InterpreterResetLogTestInterpreter(); - TestInterpreterWrapper wrapper(base_interpreter); + InterpreterResetLogTestInterpreter base_interpreter; + TestInterpreterWrapper wrapper(&base_interpreter); FingerState finger_state = { // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID @@ -206,102 +202,98 @@ TEST(InterpreterTest, LoggingDisabledByDefault) { HardwareState hardware_state = make_hwstate(200000, 0, 1, 1, &finger_state); stime_t timeout = NO_DEADLINE; wrapper.SyncInterpret(hardware_state, &timeout); - EXPECT_EQ(base_interpreter->log_->size(), 0); + EXPECT_EQ(base_interpreter.log_->size(), 0); wrapper.SyncInterpret(hardware_state, &timeout); - EXPECT_EQ(base_interpreter->log_->size(), 0); + EXPECT_EQ(base_interpreter.log_->size(), 0); } TEST(InterpreterTest, EventDebugLoggingEnableTest) { - InterpreterResetLogTestInterpreter* base_interpreter = - new InterpreterResetLogTestInterpreter(); + InterpreterResetLogTestInterpreter base_interpreter; - base_interpreter->SetEventDebugLoggingEnabled(0); - EXPECT_EQ(base_interpreter->GetEventDebugLoggingEnabled(), 0); + base_interpreter.SetEventDebugLoggingEnabled(0); + EXPECT_EQ(base_interpreter.GetEventDebugLoggingEnabled(), 0); using EventDebug = ActivityLog::EventDebug; - base_interpreter->EventDebugLoggingEnable(EventDebug::HardwareState); - EXPECT_EQ(base_interpreter->GetEventDebugLoggingEnabled(), + base_interpreter.EventDebugLoggingEnable(EventDebug::HardwareState); + EXPECT_EQ(base_interpreter.GetEventDebugLoggingEnabled(), 1 << static_cast<int>(EventDebug::HardwareState)); - base_interpreter->EventDebugLoggingDisable(EventDebug::HardwareState); - EXPECT_EQ(base_interpreter->GetEventDebugLoggingEnabled(), 0); + base_interpreter.EventDebugLoggingDisable(EventDebug::HardwareState); + EXPECT_EQ(base_interpreter.GetEventDebugLoggingEnabled(), 0); } TEST(InterpreterTest, LogHardwareStateTest) { PropRegistry prop_reg; - InterpreterResetLogTestInterpreter* base_interpreter = - new InterpreterResetLogTestInterpreter(); + InterpreterResetLogTestInterpreter base_interpreter; FingerState fs = { 0.0, 0.0, 0.0, 0.0, 9.0, 0.0, 3.0, 4.0, 22, 0 }; HardwareState hs = make_hwstate(1.0, 0, 1, 1, &fs); - base_interpreter->SetEventLoggingEnabled(false); - base_interpreter->SetEventDebugLoggingEnabled(0); + base_interpreter.SetEventLoggingEnabled(false); + base_interpreter.SetEventDebugLoggingEnabled(0); - base_interpreter->LogHardwareStatePre( + base_interpreter.LogHardwareStatePre( "InterpreterTest_LogHardwareStateTest", hs); - EXPECT_EQ(base_interpreter->log_->size(), 0); + EXPECT_EQ(base_interpreter.log_->size(), 0); - base_interpreter->LogHardwareStatePost( + base_interpreter.LogHardwareStatePost( "InterpreterTest_LogHardwareStateTest", hs); - EXPECT_EQ(base_interpreter->log_->size(), 0); + EXPECT_EQ(base_interpreter.log_->size(), 0); using EventDebug = ActivityLog::EventDebug; - base_interpreter->SetEventLoggingEnabled(true); - base_interpreter->EventDebugLoggingEnable(EventDebug::HardwareState); + base_interpreter.SetEventLoggingEnabled(true); + base_interpreter.EventDebugLoggingEnable(EventDebug::HardwareState); - base_interpreter->LogHardwareStatePre( + base_interpreter.LogHardwareStatePre( "InterpreterTest_LogHardwareStateTest", hs); - EXPECT_EQ(base_interpreter->log_->size(), 1); + EXPECT_EQ(base_interpreter.log_->size(), 1); - base_interpreter->LogHardwareStatePost( + base_interpreter.LogHardwareStatePost( "InterpreterTest_LogHardwareStateTest", hs); - EXPECT_EQ(base_interpreter->log_->size(), 2); + EXPECT_EQ(base_interpreter.log_->size(), 2); } TEST(InterpreterTest, LogGestureTest) { PropRegistry prop_reg; - InterpreterResetLogTestInterpreter* base_interpreter = - new InterpreterResetLogTestInterpreter(); + InterpreterResetLogTestInterpreter base_interpreter; Gesture move(kGestureMove, 1.0, 2.0, 773, 4.0); - base_interpreter->SetEventLoggingEnabled(false); - base_interpreter->SetEventDebugLoggingEnabled(0); - base_interpreter->LogGestureConsume("InterpreterTest_LogGestureTest", move); - EXPECT_EQ(base_interpreter->log_->size(), 0); - base_interpreter->LogGestureProduce("InterpreterTest_LogGestureTest", move); - EXPECT_EQ(base_interpreter->log_->size(), 0); + base_interpreter.SetEventLoggingEnabled(false); + base_interpreter.SetEventDebugLoggingEnabled(0); + base_interpreter.LogGestureConsume("InterpreterTest_LogGestureTest", move); + EXPECT_EQ(base_interpreter.log_->size(), 0); + base_interpreter.LogGestureProduce("InterpreterTest_LogGestureTest", move); + EXPECT_EQ(base_interpreter.log_->size(), 0); using EventDebug = ActivityLog::EventDebug; - base_interpreter->SetEventLoggingEnabled(true); - base_interpreter->EventDebugLoggingEnable(EventDebug::Gesture); - base_interpreter->LogGestureConsume("InterpreterTest_LogGestureTest", move); - EXPECT_EQ(base_interpreter->log_->size(), 1); - base_interpreter->LogGestureProduce("InterpreterTest_LogGestureTest", move); - EXPECT_EQ(base_interpreter->log_->size(), 2); + base_interpreter.SetEventLoggingEnabled(true); + base_interpreter.EventDebugLoggingEnable(EventDebug::Gesture); + base_interpreter.LogGestureConsume("InterpreterTest_LogGestureTest", move); + EXPECT_EQ(base_interpreter.log_->size(), 1); + base_interpreter.LogGestureProduce("InterpreterTest_LogGestureTest", move); + EXPECT_EQ(base_interpreter.log_->size(), 2); } TEST(InterpreterTest, LogHandleTimerTest) { PropRegistry prop_reg; - InterpreterResetLogTestInterpreter* base_interpreter = - new InterpreterResetLogTestInterpreter(); + InterpreterResetLogTestInterpreter base_interpreter; using EventDebug = ActivityLog::EventDebug; - base_interpreter->SetEventLoggingEnabled(true); - base_interpreter->EventDebugLoggingEnable(EventDebug::HandleTimer); + base_interpreter.SetEventLoggingEnabled(true); + base_interpreter.EventDebugLoggingEnable(EventDebug::HandleTimer); stime_t timeout = 10; - base_interpreter->LogHandleTimerPre("InterpreterTest_LogHandleTimerTest", + base_interpreter.LogHandleTimerPre("InterpreterTest_LogHandleTimerTest", 0, &timeout); - EXPECT_EQ(base_interpreter->log_->size(), 1); + EXPECT_EQ(base_interpreter.log_->size(), 1); - base_interpreter->LogHandleTimerPost("InterpreterTest_LogHandleTimerTest", + base_interpreter.LogHandleTimerPost("InterpreterTest_LogHandleTimerTest", 0, &timeout); - EXPECT_EQ(base_interpreter->log_->size(), 2); + EXPECT_EQ(base_interpreter.log_->size(), 2); } } // namespace gestures diff --git a/src/lookahead_filter_interpreter.cc b/src/lookahead_filter_interpreter.cc index 7a5c8fd..767f350 100644 --- a/src/lookahead_filter_interpreter.cc +++ b/src/lookahead_filter_interpreter.cc @@ -5,6 +5,7 @@ #include "include/lookahead_filter_interpreter.h" #include <algorithm> +#include <memory> #include <math.h> #include "include/tracer.h" @@ -472,7 +473,8 @@ void LookaheadFilterInterpreter::HandleTimerImpl(stime_t now, // SyncInterpret last_interpreted_time_ = node->state_.timestamp; const size_t finger_cnt = node->state_.finger_cnt; - FingerState fs_copy[std::max(finger_cnt,(size_t)1)]; + auto fs_copy = + std::make_unique<FingerState[]>(std::max(finger_cnt, (size_t)1)); std::copy(&node->state_.fingers[0], &node->state_.fingers[finger_cnt], &fs_copy[0]); @@ -481,7 +483,7 @@ void LookaheadFilterInterpreter::HandleTimerImpl(stime_t now, node->state_.buttons_down, node->state_.finger_cnt, node->state_.touch_cnt, - fs_copy, + fs_copy.get(), node->state_.rel_x, node->state_.rel_y, node->state_.rel_wheel, diff --git a/src/mouse_interpreter.cc b/src/mouse_interpreter.cc index 6ed44e7..a281a9a 100644 --- a/src/mouse_interpreter.cc +++ b/src/mouse_interpreter.cc @@ -31,6 +31,7 @@ MouseInterpreter::MouseInterpreter(PropRegistry* prop_reg, Tracer* tracer) scroll_sensitivity_(prop_reg,"Mouse Scroll Sensitivity", kMouseScrollSensitivityDefaultValue), hi_res_scrolling_(prop_reg, "Mouse High Resolution Scrolling", true), + scroll_velocity_buffer_size_(prop_reg, "Scroll Wheel Velocity Buffer", 3), scroll_accel_curve_prop_(prop_reg, "Mouse Scroll Accel Curve", scroll_accel_curve_, sizeof(scroll_accel_curve_) / sizeof(double)), scroll_max_allowed_input_speed_(prop_reg, @@ -49,8 +50,6 @@ MouseInterpreter::MouseInterpreter(PropRegistry* prop_reg, Tracer* tracer) "Output Mouse Wheel Gestures", false) { InitName(); memset(&prev_state_, 0, sizeof(prev_state_)); - memset(&last_wheel_, 0, sizeof(last_wheel_)); - memset(&last_hwheel_, 0, sizeof(last_hwheel_)); // Scroll acceleration curve coefficients. See the definition for more // details on how to generate them. scroll_accel_curve_[0] = 1.0374e+01; @@ -168,60 +167,81 @@ void MouseInterpreter::InterpretScrollWheelEvent(const HardwareState& hwstate, bool is_vertical) { const char name[] = "MouseInterpreter::InterpretScrollWheelEvent"; - const float scroll_wheel_event_time_delta_min = 0.008; + const size_t max_buffer_size = scroll_velocity_buffer_size_.val_; + const float scroll_wheel_event_time_delta_min = 0.008 * max_buffer_size; bool use_high_resolution = is_vertical && hwprops_->wheel_is_hi_res && hi_res_scrolling_.val_; // Vertical wheel or horizontal wheel. - float current_wheel_value = hwstate.rel_hwheel; - int ticks = hwstate.rel_hwheel * REL_WHEEL_HI_RES_UNITS_PER_NOTCH; - WheelRecord* last_wheel_record = &last_hwheel_; + WheelRecord current_wheel; + current_wheel.timestamp = hwstate.timestamp; + int ticks; + std::vector<WheelRecord>* last_wheels; if (is_vertical) { // Only vertical high-res scrolling is supported for now. if (use_high_resolution) { - current_wheel_value = hwstate.rel_wheel_hi_res + current_wheel.change = hwstate.rel_wheel_hi_res / REL_WHEEL_HI_RES_UNITS_PER_NOTCH; ticks = hwstate.rel_wheel_hi_res; } else { - current_wheel_value = hwstate.rel_wheel; + current_wheel.change = hwstate.rel_wheel; ticks = hwstate.rel_wheel * REL_WHEEL_HI_RES_UNITS_PER_NOTCH; } - last_wheel_record = &last_wheel_; + last_wheels = &last_vertical_wheels_; + } else { + last_wheels = &last_horizontal_wheels_; + current_wheel.change = hwstate.rel_hwheel; + ticks = hwstate.rel_hwheel * REL_WHEEL_HI_RES_UNITS_PER_NOTCH; } // Check if the wheel is scrolled. - if (current_wheel_value) { + if (current_wheel.change) { stime_t start_time, end_time = hwstate.timestamp; // Check if this scroll is in same direction as previous scroll event. - if ((current_wheel_value < 0 && last_wheel_record->value < 0) || - (current_wheel_value > 0 && last_wheel_record->value > 0)) { - start_time = last_wheel_record->timestamp; + if (!last_wheels->empty() && + ((current_wheel.change < 0 && last_wheels->back().change < 0) || + (current_wheel.change > 0 && last_wheels->back().change > 0))) { + start_time = last_wheels->begin()->timestamp; } else { + last_wheels->clear(); start_time = end_time; } - // If start_time == end_time, compute velocity using dt = 1 second. - // (this happens when the user initially starts scrolling) - stime_t dt = (end_time - start_time) ?: 1.0; - if (dt < scroll_wheel_event_time_delta_min) { - // the first packet received after BT wakeup may be delayed, causing the - // time delta between that and the subsequent packet to be very small. - // Prevent small time deltas from triggering large amounts of acceleration - // by enforcing a minimum time delta. - dt = scroll_wheel_event_time_delta_min; + // We will only accelerate scrolls if we have filled our buffer of scroll + // events all in the same direction. If the buffer is full, then calculate + // scroll velocity using the average velocity of the entire buffer. + float velocity; + if (last_wheels->size() < max_buffer_size) { + velocity = 0.0; + } else { + stime_t dt = end_time - last_wheels->back().timestamp; + if (dt < scroll_wheel_event_time_delta_min) { + // The first packets received after BT wakeup may be delayed, causing + // the time delta between that and the subsequent packets to be + // artificially very small. + // Prevent small time deltas from triggering large amounts of + // acceleration by enforcing a minimum time delta. + dt = scroll_wheel_event_time_delta_min; + } + + last_wheels->pop_back(); + float buffer_scroll_distance = current_wheel.change; + for (auto wheel : *last_wheels) { + buffer_scroll_distance += wheel.change; + } + + velocity = buffer_scroll_distance / dt; } + last_wheels->insert(last_wheels->begin(), current_wheel); // When scroll acceleration is off, the scroll factor does not relate to // scroll velocity. It's simply a constant multiplier to the wheel value. const double unaccel_scroll_factors[] = { 20.0, 36.0, 72.0, 112.0, 164.0 }; - float velocity = current_wheel_value / dt; - float offset = current_wheel_value * ( + float offset = current_wheel.change * ( scroll_acceleration_.val_? ComputeScrollAccelFactor(velocity) : unaccel_scroll_factors[scroll_sensitivity_.val_ - 1]); - last_wheel_record->timestamp = hwstate.timestamp; - last_wheel_record->value = current_wheel_value; if (is_vertical) { // For historical reasons the vertical wheel (REL_WHEEL) is inverted diff --git a/src/mouse_interpreter_unittest.cc b/src/mouse_interpreter_unittest.cc index 57267d8..520a455 100644 --- a/src/mouse_interpreter_unittest.cc +++ b/src/mouse_interpreter_unittest.cc @@ -103,6 +103,7 @@ TEST(MouseInterpreterTest, HighResolutionVerticalScrollTest) { mi.output_mouse_wheel_gestures_.val_ = true; mi.hi_res_scrolling_.val_ = 1; + mi.scroll_velocity_buffer_size_.val_ = 1; gs = wrapper.SyncInterpret(hwstates[0], nullptr); EXPECT_EQ(nullptr, gs); @@ -157,6 +158,7 @@ TEST(MouseInterpreterTest, ScrollAccelerationOnAndOffTest) { mi.scroll_acceleration_.val_ = true; mi.output_mouse_wheel_gestures_.val_ = true; mi.hi_res_scrolling_.val_ = false; + mi.scroll_velocity_buffer_size_.val_ = 1; gs = wrapper.SyncInterpret(hwstates[0], nullptr); EXPECT_EQ(nullptr, gs); @@ -212,6 +214,7 @@ TEST(MouseInterpreterTest, JankyScrollTest) { }; mi.output_mouse_wheel_gestures_.val_ = true; + mi.scroll_velocity_buffer_size_.val_ = 1; gs = wrapper.SyncInterpret(hwstates[0], nullptr); ASSERT_NE(nullptr, gs); diff --git a/src/non_linearity_filter_interpreter.cc b/src/non_linearity_filter_interpreter.cc index df0e765..4d5c1e4 100644 --- a/src/non_linearity_filter_interpreter.cc +++ b/src/non_linearity_filter_interpreter.cc @@ -4,6 +4,8 @@ #include "include/non_linearity_filter_interpreter.h" +#include <cstring> + #include <linux/in.h> namespace { @@ -20,7 +22,7 @@ NonLinearityFilterInterpreter::NonLinearityFilterInterpreter( : FilterInterpreter(nullptr, next, tracer, false), x_range_len_(0), y_range_len_(0), p_range_len_(0), enabled_(prop_reg, "Enable non-linearity correction", false), - data_location_(prop_reg, "Non-linearity correction data file", "None") { + data_location_(prop_reg, "Non-linearity correction data file", "") { InitName(); LoadData(); } @@ -67,8 +69,12 @@ bool NonLinearityFilterInterpreter::LoadRange(std::unique_ptr<double[]>& arr, } void NonLinearityFilterInterpreter::LoadData() { + if (strlen(data_location_.val_) == 0) { + return; + } FILE* data_fd = fopen(data_location_.val_, "rb"); if (!data_fd) { + // TODO(b/329268257): make this an Err, not a Log. Log("Unable to open non-linearity filter data '%s'", data_location_.val_); return; } diff --git a/src/prop_registry.cc b/src/prop_registry.cc index 283db9d..d1aaf6e 100644 --- a/src/prop_registry.cc +++ b/src/prop_registry.cc @@ -106,22 +106,24 @@ void BoolProperty::HandleGesturesPropWritten() { } void BoolArrayProperty::CreatePropImpl() { - GesturesPropBool orig_vals[count_]; - memcpy(orig_vals, vals_, sizeof(orig_vals)); + auto orig_vals = std::make_unique<GesturesPropBool[]>(count_); + + memcpy(orig_vals.get(), vals_, count_ * sizeof(GesturesPropBool)); gprop_ = parent_->PropProvider()->create_bool_fn( parent_->PropProviderData(), name(), vals_, count_, vals_); - if (delegate_ && memcmp(orig_vals, vals_, sizeof(orig_vals))) + if (delegate_ && memcmp(orig_vals.get(), vals_, + count_ * sizeof(GesturesPropBool))) delegate_->BoolArrayWasWritten(this); } Json::Value BoolArrayProperty::NewValue() const { Json::Value list(Json::arrayValue); for (size_t i = 0; i < count_; i++) - list.append(new Json::Value(vals_[i] != 0)); + list.append(Json::Value(vals_[i] != 0)); return list; } @@ -182,15 +184,16 @@ void DoubleProperty::HandleGesturesPropWritten() { } void DoubleArrayProperty::CreatePropImpl() { - float orig_vals[count_]; - memcpy(orig_vals, vals_, sizeof(orig_vals)); + auto orig_vals = std::make_unique<float[]>(count_); + + memcpy(orig_vals.get(), vals_, count_ * sizeof(float)); gprop_ = parent_->PropProvider()->create_real_fn( parent_->PropProviderData(), name(), vals_, count_, vals_); - if (delegate_ && memcmp(orig_vals, vals_, sizeof(orig_vals))) + if (delegate_ && memcmp(orig_vals.get(), vals_, count_ * sizeof(float))) delegate_->DoubleArrayWasWritten(this); } @@ -263,15 +266,16 @@ void IntProperty::HandleGesturesPropWritten() { } void IntArrayProperty::CreatePropImpl() { - int orig_vals[count_]; - memcpy(orig_vals, vals_, sizeof(orig_vals)); + auto orig_vals = std::make_unique<int[]>(count_); + + memcpy(orig_vals.get(), vals_, count_ * sizeof(int)); gprop_ = parent_->PropProvider()->create_int_fn( parent_->PropProviderData(), name(), vals_, count_, vals_); - if (delegate_ && memcmp(orig_vals, vals_, sizeof(orig_vals))) + if (delegate_ && memcmp(orig_vals.get(), vals_, count_ * sizeof(int))) delegate_->IntArrayWasWritten(this); } diff --git a/src/string_util.cc b/src/string_util.cc index 3e5b896..863399c 100644 --- a/src/string_util.cc +++ b/src/string_util.cc @@ -85,58 +85,24 @@ static void StringAppendVT(std::string* dst, } } -template <typename STR> -void SplitStringT(const STR& str, - const typename STR::value_type s, - bool trim_whitespace, - std::vector<STR>* r) { - r->clear(); - size_t last = 0; - size_t c = str.size(); - for (size_t i = 0; i <= c; ++i) { - if (i == c || str[i] == s) { - STR tmp(str, last, i - last); - if (trim_whitespace) - TrimWhitespaceASCII(tmp, TRIM_ALL, &tmp); - // Avoid converting an empty or all-whitespace source string into a vector - // of one empty string. - if (i != c || !r->empty() || !tmp.empty()) - r->push_back(tmp); - last = i + 1; - } +template<typename STR> +STR TrimStringT(const STR& input, const typename STR::value_type trim_chars[]) { + if (input.empty()) { + return ""; } -} -template<typename STR> -TrimPositions TrimStringT(const STR& input, - const typename STR::value_type trim_chars[], - TrimPositions positions, - STR* output) { - // Find the edges of leading/trailing whitespace as desired. - const typename STR::size_type last_char = input.length() - 1; - const typename STR::size_type first_good_char = (positions & TRIM_LEADING) ? - input.find_first_not_of(trim_chars) : 0; - const typename STR::size_type last_good_char = (positions & TRIM_TRAILING) ? - input.find_last_not_of(trim_chars) : last_char; - - // When the string was all whitespace, report that we stripped off whitespace - // from whichever position the caller was interested in. For empty input, we - // stripped no whitespace, but we still need to clear |output|. - if (input.empty() || - (first_good_char == STR::npos) || (last_good_char == STR::npos)) { - bool input_was_empty = input.empty(); // in case output == &input - output->clear(); - return input_was_empty ? TRIM_NONE : positions; + // Find the edges of leading/trailing whitespace. + const typename STR::size_type first_good_char = + input.find_first_not_of(trim_chars); + const typename STR::size_type last_good_char = + input.find_last_not_of(trim_chars); + + if (first_good_char == STR::npos || last_good_char == STR::npos) { + return ""; } // Trim the whitespace. - *output = - input.substr(first_good_char, last_good_char - first_good_char + 1); - - // Return where we trimmed from. - return static_cast<TrimPositions>( - ((first_good_char == 0) ? TRIM_NONE : TRIM_LEADING) | - ((last_good_char == last_char) ? TRIM_NONE : TRIM_TRAILING)); + return input.substr(first_good_char, last_good_char - first_good_char + 1); } } // namespace @@ -154,25 +120,8 @@ std::string StringPrintf(const char* format, ...) { return result; } -bool StartsWithASCII(const std::string& str, - const std::string& search, - bool case_sensitive) { - if (case_sensitive) - return str.compare(0, search.length(), search) == 0; - else - return strncasecmp(str.c_str(), search.c_str(), search.length()) == 0; -} - -void SplitString(const std::string& str, - char c, - std::vector<std::string>* r) { - SplitStringT(str, c, true, r); -} - -TrimPositions TrimWhitespaceASCII(const std::string& input, - TrimPositions positions, - std::string* output) { - return TrimStringT(input, kWhitespaceASCII, positions, output); +std::string TrimWhitespaceASCII(const std::string& input) { + return TrimStringT(input, kWhitespaceASCII); } } // namespace gestures diff --git a/src/string_util_unittest.cc b/src/string_util_unittest.cc index 0ce0b0c..b1edda6 100644 --- a/src/string_util_unittest.cc +++ b/src/string_util_unittest.cc @@ -13,9 +13,7 @@ namespace gestures { class StringUtilTest : public ::testing::Test {}; -// This test adds code coverage to string_util. - -TEST(StringUtilTest, SimpleTest) { +TEST(StringUtilTest, StringPrintfTest) { const char *pstr = "0123456789012345678901234567890123456789012345678901234567890123456789"; std::string str = StringPrintf( @@ -26,17 +24,16 @@ TEST(StringUtilTest, SimpleTest) { ); int expected_length = (70*15)+15+1; EXPECT_EQ(str.size(), expected_length); +} - TrimPositions trimmed_from = TrimWhitespaceASCII(str, TRIM_ALL, &str); - EXPECT_EQ(trimmed_from, TRIM_ALL); - EXPECT_EQ(str.size(), expected_length-2); - - std::vector<std::string> split; - SplitString(str, ' ', &split); - EXPECT_EQ(split.size(), 15); - - bool matches = StartsWithASCII(split[0], pstr, true); - EXPECT_TRUE(matches); +TEST(StringUtilTest, TrimWhitespaceASCIITest) { + EXPECT_EQ(TrimWhitespaceASCII(""), ""); + EXPECT_EQ(TrimWhitespaceASCII(" x "), "x"); + EXPECT_EQ(TrimWhitespaceASCII("badger"), "badger"); + EXPECT_EQ(TrimWhitespaceASCII("badger "), "badger"); + EXPECT_EQ(TrimWhitespaceASCII(" badger"), "badger"); + EXPECT_EQ(TrimWhitespaceASCII(" \t \n\r "), ""); + EXPECT_EQ(TrimWhitespaceASCII(" Bees and ponies "), "Bees and ponies"); } } // namespace gestures diff --git a/tools/touchtests-report.json b/tools/touchtests-report.json index 8340e7b..145f6aa 100644 --- a/tools/touchtests-report.json +++ b/tools/touchtests-report.json @@ -1798,6 +1798,13 @@ "result": "success", "score": 1.0 }, + "logitech-m650-1.0/fast_initial_scroll": { + "description": "", + "disabled": false, + "error": "", + "result": "success", + "score": 1.0 + }, "logitech-t620/accidental_back_fling": { "description": "", "disabled": false, |