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(NULL, 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 if (!enabled_.val_) {
36 next_->SyncInterpret(hwstate, timeout);
37 return;
38 }
39
40 RemoveMissingIdsFromMap(&previous_input_[0], *hwstate);
41 RemoveMissingIdsFromMap(&previous_input_[1], *hwstate);
42 RemoveMissingIdsFromSet(&first_flag_[0], *hwstate);
43 RemoveMissingIdsFromSet(&first_flag_[1], *hwstate);
44 RemoveMissingIdsFromSet(&first_flag_[2], *hwstate);
45 RemoveMissingIdsFromSet(&first_flag_[3], *hwstate);
46
47 std::map<short, FingerState> current_input;
48
49 for (size_t i = 0; i < hwstate->finger_cnt; i++)
50 current_input[hwstate->fingers[i].tracking_id] = hwstate->fingers[i];
51
52 for (size_t i = 0; i < hwstate->finger_cnt; i++) {
53 short tracking_id = hwstate->fingers[i].tracking_id;
54 if (!MapContainsKey(previous_input_[1], tracking_id) ||
55 !MapContainsKey(previous_input_[0], tracking_id))
56 continue;
57 FingerState* fs[] = {
58 &hwstate->fingers[i], // newest
59 &previous_input_[0][tracking_id],
60 &previous_input_[1][tracking_id], // oldest
61 };
62 float FingerState::* const fields[] = { &FingerState::position_x,
63 &FingerState::position_y,
64 &FingerState::position_x,
65 &FingerState::position_y };
66
67 unsigned warp[] = { GESTURES_FINGER_WARP_X_NON_MOVE,
68 GESTURES_FINGER_WARP_Y_NON_MOVE,
69 GESTURES_FINGER_WARP_X_MOVE,
70 GESTURES_FINGER_WARP_Y_MOVE };
71
72 for (size_t f_idx = 0; f_idx < arraysize(fields); f_idx++) {
73 float FingerState::* const field = fields[f_idx];
74 const float val[] = {
75 fs[0]->*field, // newest
76 fs[1]->*field,
77 fs[2]->*field, // oldest
78 };
79 const float delta[] = {
80 val[0] - val[1], // newer
81 val[1] - val[2], // older
82 };
83
84 bool warp_move = (warp[f_idx] == GESTURES_FINGER_WARP_X_MOVE ||
85 warp[f_idx] == GESTURES_FINGER_WARP_Y_MOVE);
86 float min_warp_dist = warp_move ? min_warp_dist_move_.val_ :
87 min_warp_dist_non_move_.val_;
88 float max_warp_dist = warp_move ? max_warp_dist_move_.val_ :
89 max_warp_dist_non_move_.val_;
90 float similar_multiplier = warp_move ? similar_multiplier_move_.val_ :
91 similar_multiplier_non_move_.val_;
92
93 const float kAllowableChange = fabsf(delta[1] * similar_multiplier);
94
95 bool should_warp = false;
96 bool should_store_flag = false;
97 if (delta[0] * delta[1] < 0.0) {
98 // switched direction
99 // Don't mark direction change with small delta with WARP_*_MOVE.
100 if (!warp_move || !(fabsf(delta[0]) < no_warp_min_dist_move_.val_ &&
101 fabsf(delta[1]) < no_warp_min_dist_move_.val_))
102 should_store_flag = should_warp = true;
103 } else if (fabsf(delta[0]) < min_warp_dist ||
104 fabsf(delta[0]) > max_warp_dist) {
105 // acceptable movement
106 } else if (fabsf(delta[0] - delta[1]) <= kAllowableChange) {
107 if (SetContainsValue(first_flag_[f_idx], tracking_id)) {
108 // Was flagged last time. Flag one more time
109 should_warp = true;
110 }
111 } else {
112 should_store_flag = should_warp = true;
113 }
114 if (should_warp) {
115 fs[0]->flags |= (warp[f_idx] | GESTURES_FINGER_WARP_TELEPORTATION);
116 // Warping moves here get tap warped, too
117 if (warp_move) {
118 fs[0]->flags |= warp[f_idx] == GESTURES_FINGER_WARP_X_MOVE ?
119 GESTURES_FINGER_WARP_X_TAP_MOVE : GESTURES_FINGER_WARP_Y_TAP_MOVE;
120 }
121 }
122 if (should_store_flag)
123 first_flag_[f_idx].insert(tracking_id);
124 else
125 first_flag_[f_idx].erase(tracking_id);
126 }
127 }
128
129 // Update previous input/output state
130 previous_input_[1] = previous_input_[0];
131 previous_input_[0] = current_input;
132
133 next_->SyncInterpret(hwstate, timeout);
134 }
135
136 } // namespace gestures
137