1 // Copyright 2012 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "include/sensor_jump_filter_interpreter.h"
6
7 #include "include/tracer.h"
8 #include "include/util.h"
9
10 namespace gestures {
11
SensorJumpFilterInterpreter(PropRegistry * prop_reg,Interpreter * next,Tracer * tracer)12 SensorJumpFilterInterpreter::SensorJumpFilterInterpreter(PropRegistry* prop_reg,
13 Interpreter* next,
14 Tracer* tracer)
15 : FilterInterpreter(nullptr, next, tracer, false),
16 enabled_(prop_reg, "Sensor Jump Filter Enable", false),
17 min_warp_dist_non_move_(prop_reg, "Sensor Jump Min Dist Non-Move", 0.9),
18 max_warp_dist_non_move_(prop_reg, "Sensor Jump Max Dist Non-Move", 7.5),
19 similar_multiplier_non_move_(prop_reg,
20 "Sensor Jump Similar Multiplier Non-Move",
21 0.9),
22 min_warp_dist_move_(prop_reg, "Sensor Jump Min Dist Move", 0.9),
23 max_warp_dist_move_(prop_reg, "Sensor Jump Max Dist Move", 7.5),
24 similar_multiplier_move_(prop_reg,
25 "Sensor Jump Similar Multiplier Move",
26 0.9),
27 no_warp_min_dist_move_(prop_reg,
28 "Sensor Jump No Warp Min Dist Move",
29 0.21) {
30 InitName();
31 }
32
SyncInterpretImpl(HardwareState & hwstate,stime_t * timeout)33 void SensorJumpFilterInterpreter::SyncInterpretImpl(HardwareState& hwstate,
34 stime_t* timeout) {
35 const char name[] = "SensorJumpFilterInterpreter::SyncInterpretImpl";
36 LogHardwareStatePre(name, hwstate);
37
38 if (!enabled_.val_) {
39 next_->SyncInterpret(hwstate, timeout);
40 return;
41 }
42
43 RemoveMissingIdsFromMap(&previous_input_[0], hwstate);
44 RemoveMissingIdsFromMap(&previous_input_[1], hwstate);
45 RemoveMissingIdsFromSet(&first_flag_[0], hwstate);
46 RemoveMissingIdsFromSet(&first_flag_[1], hwstate);
47 RemoveMissingIdsFromSet(&first_flag_[2], hwstate);
48 RemoveMissingIdsFromSet(&first_flag_[3], hwstate);
49
50 std::map<short, FingerState> current_input;
51
52 for (size_t i = 0; i < hwstate.finger_cnt; i++)
53 current_input[hwstate.fingers[i].tracking_id] = hwstate.fingers[i];
54
55 for (size_t i = 0; i < hwstate.finger_cnt; i++) {
56 short tracking_id = hwstate.fingers[i].tracking_id;
57 if (!MapContainsKey(previous_input_[1], tracking_id) ||
58 !MapContainsKey(previous_input_[0], tracking_id))
59 continue;
60 FingerState* fs[] = {
61 &hwstate.fingers[i], // newest
62 &previous_input_[0][tracking_id],
63 &previous_input_[1][tracking_id], // oldest
64 };
65 float FingerState::* const fields[] = { &FingerState::position_x,
66 &FingerState::position_y,
67 &FingerState::position_x,
68 &FingerState::position_y };
69
70 unsigned warp[] = { GESTURES_FINGER_WARP_X_NON_MOVE,
71 GESTURES_FINGER_WARP_Y_NON_MOVE,
72 GESTURES_FINGER_WARP_X_MOVE,
73 GESTURES_FINGER_WARP_Y_MOVE };
74
75 for (size_t f_idx = 0; f_idx < arraysize(fields); f_idx++) {
76 float FingerState::* const field = fields[f_idx];
77 const float val[] = {
78 fs[0]->*field, // newest
79 fs[1]->*field,
80 fs[2]->*field, // oldest
81 };
82 const float delta[] = {
83 val[0] - val[1], // newer
84 val[1] - val[2], // older
85 };
86
87 bool warp_move = (warp[f_idx] == GESTURES_FINGER_WARP_X_MOVE ||
88 warp[f_idx] == GESTURES_FINGER_WARP_Y_MOVE);
89 float min_warp_dist = warp_move ? min_warp_dist_move_.val_ :
90 min_warp_dist_non_move_.val_;
91 float max_warp_dist = warp_move ? max_warp_dist_move_.val_ :
92 max_warp_dist_non_move_.val_;
93 float similar_multiplier = warp_move ? similar_multiplier_move_.val_ :
94 similar_multiplier_non_move_.val_;
95
96 const float kAllowableChange = fabsf(delta[1] * similar_multiplier);
97
98 bool should_warp = false;
99 bool should_store_flag = false;
100 if (delta[0] * delta[1] < 0.0) {
101 // switched direction
102 // Don't mark direction change with small delta with WARP_*_MOVE.
103 if (!warp_move || !(fabsf(delta[0]) < no_warp_min_dist_move_.val_ &&
104 fabsf(delta[1]) < no_warp_min_dist_move_.val_))
105 should_store_flag = should_warp = true;
106 } else if (fabsf(delta[0]) < min_warp_dist ||
107 fabsf(delta[0]) > max_warp_dist) {
108 // acceptable movement
109 } else if (fabsf(delta[0] - delta[1]) <= kAllowableChange) {
110 if (SetContainsValue(first_flag_[f_idx], tracking_id)) {
111 // Was flagged last time. Flag one more time
112 should_warp = true;
113 }
114 } else {
115 should_store_flag = should_warp = true;
116 }
117 if (should_warp) {
118 fs[0]->flags |= (warp[f_idx] | GESTURES_FINGER_WARP_TELEPORTATION);
119 // Warping moves here get tap warped, too
120 if (warp_move) {
121 fs[0]->flags |= warp[f_idx] == GESTURES_FINGER_WARP_X_MOVE ?
122 GESTURES_FINGER_WARP_X_TAP_MOVE : GESTURES_FINGER_WARP_Y_TAP_MOVE;
123 }
124 }
125 if (should_store_flag)
126 first_flag_[f_idx].insert(tracking_id);
127 else
128 first_flag_[f_idx].erase(tracking_id);
129 }
130 }
131
132 // Update previous input/output state
133 previous_input_[1] = previous_input_[0];
134 previous_input_[0] = current_input;
135
136 LogHardwareStatePost(name, hwstate);
137 next_->SyncInterpret(hwstate, timeout);
138 }
139
140 } // namespace gestures
141