blob: de884fc9dc6453fc2bc4745fbf0f535faffc64b8 [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <algorithm>
#include <memory>
#include <gtest/gtest.h> // For FRIEND_TEST
#include "gestures/include/filter_interpreter.h"
#include "gestures/include/finger_metrics.h"
#include "gestures/include/gestures.h"
#include "gestures/include/list.h"
#include "gestures/include/map.h"
#include "gestures/include/prop_registry.h"
#include "gestures/include/tracer.h"
#ifndef GESTURES_LOOKAHEAD_FILTER_INTERPRETER_H_
#define GESTURES_LOOKAHEAD_FILTER_INTERPRETER_H_
namespace gestures {
class LookaheadFilterInterpreter : public FilterInterpreter {
FRIEND_TEST(LookaheadFilterInterpreterTest, CyapaQuickTwoFingerMoveTest);
FRIEND_TEST(LookaheadFilterInterpreterTest, DrumrollTest);
FRIEND_TEST(LookaheadFilterInterpreterTest, InterpolateHwStateTest);
FRIEND_TEST(LookaheadFilterInterpreterTest, InterpolateTest);
FRIEND_TEST(LookaheadFilterInterpreterTest, InterpolationOverdueTest);
FRIEND_TEST(LookaheadFilterInterpreterTest, NoTapSetTest);
FRIEND_TEST(LookaheadFilterInterpreterTest, QuickMoveTest);
FRIEND_TEST(LookaheadFilterInterpreterTest, QuickSwipeTest);
FRIEND_TEST(LookaheadFilterInterpreterTest, SemiMtNoTrackingIdAssignmentTest);
FRIEND_TEST(LookaheadFilterInterpreterTest, SimpleTest);
FRIEND_TEST(LookaheadFilterInterpreterTest, SpuriousCallbackTest);
FRIEND_TEST(LookaheadFilterInterpreterTest, VariableDelayTest);
public:
LookaheadFilterInterpreter(PropRegistry* prop_reg, Interpreter* next,
Tracer* tracer);
virtual ~LookaheadFilterInterpreter() {}
protected:
virtual void SyncInterpretImpl(HardwareState* hwstate,
stime_t* timeout);
virtual void HandleTimerImpl(stime_t now, stime_t* timeout);
virtual void Initialize(const HardwareProperties* hwprops,
Metrics* metrics, MetricsProperties* mprops,
GestureConsumer* consumer);
private:
struct QState {
QState();
explicit QState(unsigned short max_fingers);
// Deep copy of new_state to state_
void set_state(const HardwareState& new_state);
HardwareState state_;
unsigned short max_fingers_;
std::unique_ptr<FingerState[]> fs_;
map<short, short, kMaxFingers> output_ids_; // input tracking ids -> output
stime_t due_;
bool completed_;
QState* next_;
QState* prev_;
};
void LogVectors();
// Produces a tapdown fling gesture if we just got a new hardware state
// with a finger missing from the previous, or a null gesture otherwise.
void TapDownOccurringGesture(stime_t now);
// Looks at the most recent 2 states in the queue (one of which may have
// already completed), and if they are separated by split_min_period_ time,
// tries to insert an interpolated event in the middle.
void AttemptInterpolation();
// Reassigns tracking IDs, assigning them in such a way to avoid problems
// of drumroll.
void AssignTrackingIds();
// For drumroll. Edits a QState node's fingerstate to have a new tracking id.
void SeparateFinger(QState* node, FingerState* fs, short input_id);
// Looks for a finger possibly lifting off the pad. If found, returns true.
bool LiftoffJumpStarting(const HardwareState& hs,
const HardwareState& prev_hs,
const HardwareState& prev2_hs) const;
// Returns a new tracking id for a contact.
short NextTrackingId();
// Interpolates first and second, storing the result into out.
// first and second must have the same the same number of fingers and
// have the same tracking_ids for all fingers.
static void Interpolate(const HardwareState& first,
const HardwareState& second,
HardwareState* out);
void UpdateInterpreterDue(stime_t new_interpreter_due,
stime_t now,
stime_t* timeout);
void ConsumeGesture(const Gesture& gesture);
stime_t ExtraVariableDelay() const;
List<QState> queue_;
List<QState> free_list_;
// The last id assigned to a contact (part of drumroll suppression)
short last_id_;
unsigned short max_fingers_per_hwstate_;
stime_t interpreter_due_;
// We want to present time to next_ in a monotonically increasing manner,
// so this keeps track of the most recent timestamp we've given next_.
stime_t last_interpreted_time_;
Gesture result_;
DoubleProperty min_nonsuppress_speed_;
DoubleProperty min_delay_;
// On some platforms, min_delay_ is very small, and sometimes we would like
// temporary extra delay to avoid problems, so we can in those cases add
// a delay specified by max_delay_. It's okay for max_delay_ to be less
// than min_delay_. In that case, it simply has no effect.
DoubleProperty max_delay_;
// If this much time passes between consecutive events, interpolate.
DoubleProperty split_min_period_;
// If set to false, tracking IDs are not reassigned
BoolProperty drumroll_suppression_enable_;
// If a contact appears to move faster than this, the drumroll detector may
// consider it a new contact.
DoubleProperty drumroll_speed_thresh_;
// If one contact's speed is more than drumroll_max_speed_ratio_ times the
// previous speed, the drumroll detector may consider it a new contact.
DoubleProperty drumroll_max_speed_ratio_;
// If during 3 consecutive HardwareState, one contact moves more than
// quick_move_thresh_ distance along the same direction on either x or y
// axis, both between the 1st and 2nd HardwareState, and the 2nd and 3rd
// HardwareState, it is considered to be a quick move and the tracking ID
// reassignment due to drumroll detection may get corrected.
DoubleProperty quick_move_thresh_;
// If we're going to drumroll-suppress a finger that is moving too much,
// we abort said suppression if it's moving less than co_move_ratio_ *
// distance of another non-drumroll-suppressed finger.
DoubleProperty co_move_ratio_;
// Temporary property to turn on/off the generation of TapDown gestures
// (i.e., stop flinging gestures).
BoolProperty suppress_immediate_tapdown_;
// If we should add extra delay when we think a finger may be lifting off.
BoolProperty delay_on_possible_liftoff_;
// If looking for a possible liftoff-move, the speed a finger is moving
// relative to the previous speed, such that it's a possible leave.
DoubleProperty liftoff_speed_increase_threshold_;
};
} // namespace gestures
#endif // GESTURES_LOOKAHEAD_FILTER_INTERPRETER_H_