• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/fling_stop_filter_interpreter.h"
6 
7 #include "include/util.h"
8 
9 namespace gestures {
10 
FlingStopFilterInterpreter(PropRegistry * prop_reg,Interpreter * next,Tracer * tracer,GestureInterpreterDeviceClass devclass)11 FlingStopFilterInterpreter::FlingStopFilterInterpreter(
12     PropRegistry* prop_reg, Interpreter* next, Tracer* tracer,
13     GestureInterpreterDeviceClass devclass)
14     : FilterInterpreter(NULL, next, tracer, false),
15       already_extended_(false),
16       prev_touch_cnt_(0),
17       prev_gesture_type_(kGestureTypeNull),
18       fling_stop_already_sent_(false),
19       fling_stop_deadline_(NO_DEADLINE),
20       devclass_(devclass),
21       fling_stop_timeout_(prop_reg, "Fling Stop Timeout", 0.03),
22       fling_stop_extra_delay_(prop_reg, "Fling Stop Extra Delay", 0.055) {
23   InitName();
24 }
25 
SyncInterpretImpl(HardwareState * hwstate,stime_t * timeout)26 void FlingStopFilterInterpreter::SyncInterpretImpl(HardwareState* hwstate,
27                                                    stime_t* timeout) {
28   fingers_of_last_hwstate_.clear();
29   for (int i = 0; i < hwstate->finger_cnt; i++)
30     fingers_of_last_hwstate_.insert(hwstate->fingers[i].tracking_id);
31 
32   UpdateFlingStopDeadline(*hwstate);
33 
34   stime_t next_timeout = NO_DEADLINE;
35   if (fling_stop_deadline_ != NO_DEADLINE) {
36     if (!already_extended_ && NeedsExtraTime(*hwstate)) {
37       fling_stop_deadline_ += fling_stop_extra_delay_.val_;
38       already_extended_ = true;
39     }
40     if (hwstate->timestamp > fling_stop_deadline_) {
41       // sub in a fling before processing other interpreters
42       ProduceGesture(Gesture(kGestureFling, prev_timestamp_,
43                              hwstate->timestamp, 0.0, 0.0,
44                              GESTURES_FLING_TAP_DOWN));
45       fling_stop_already_sent_ = true;
46       fling_stop_deadline_ = NO_DEADLINE;
47     }
48   }
49   next_->SyncInterpret(hwstate, &next_timeout);
50   *timeout = SetNextDeadlineAndReturnTimeoutVal(hwstate->timestamp,
51                                                 fling_stop_deadline_,
52                                                 next_timeout);
53 }
54 
NeedsExtraTime(const HardwareState & hwstate) const55 bool FlingStopFilterInterpreter::NeedsExtraTime(
56     const HardwareState& hwstate) const {
57   int num_new_fingers = 0;
58   for (int i = 0; i < hwstate.finger_cnt; i++) {
59     const short id = hwstate.fingers[i].tracking_id;
60     if (!SetContainsValue(fingers_present_for_last_fling_, id)) {
61       num_new_fingers++;
62     }
63   }
64 
65   return (num_new_fingers >= 2);
66 }
67 
FlingStopNeeded(const Gesture & gesture) const68 bool FlingStopFilterInterpreter::FlingStopNeeded(const Gesture& gesture) const {
69   if (fling_stop_already_sent_ || gesture.type == prev_gesture_type_)
70     return false;
71 
72   if (devclass_ == GESTURES_DEVCLASS_MULTITOUCH_MOUSE &&
73       gesture.type == kGestureTypeMove)
74     return false;
75 
76   return (gesture.type != kGestureTypeFling &&
77           gesture.type != kGestureTypeSwipeLift &&
78           gesture.type != kGestureTypeFourFingerSwipeLift);
79 }
80 
ConsumeGesture(const Gesture & gesture)81 void FlingStopFilterInterpreter::ConsumeGesture(const Gesture& gesture) {
82   if (gesture.type == kGestureTypeFling) {
83     fingers_present_for_last_fling_ = fingers_of_last_hwstate_;
84     already_extended_ = false;
85   }
86 
87   if (FlingStopNeeded(gesture)) {
88     // sub in a fling before a new gesture
89     ProduceGesture(Gesture(kGestureFling, gesture.start_time,
90                            gesture.start_time, 0.0, 0.0,
91                            GESTURES_FLING_TAP_DOWN));
92   }
93   ProduceGesture(gesture);
94   fling_stop_deadline_ = NO_DEADLINE;
95   prev_gesture_type_ = gesture.type;
96   fling_stop_already_sent_ = false;
97 }
98 
UpdateFlingStopDeadline(const HardwareState & hwstate)99 void FlingStopFilterInterpreter::UpdateFlingStopDeadline(
100     const HardwareState& hwstate) {
101   if (fling_stop_timeout_.val_ <= 0.0)
102     return;
103 
104   stime_t now = hwstate.timestamp;
105   bool finger_added = hwstate.touch_cnt > prev_touch_cnt_;
106 
107   if (finger_added && fling_stop_deadline_ == NO_DEADLINE) {
108     // first finger added in a while. Note it.
109     fling_stop_deadline_ = now + fling_stop_timeout_.val_;
110     return;
111   }
112 
113   prev_timestamp_ = now;
114   prev_touch_cnt_ = hwstate.touch_cnt;
115 }
116 
HandleTimerImpl(stime_t now,stime_t * timeout)117 void FlingStopFilterInterpreter::HandleTimerImpl(stime_t now,
118                                                      stime_t* timeout) {
119   if (!ShouldCallNextTimer(fling_stop_deadline_)) {
120     if (fling_stop_deadline_ > now) {
121       Err("Spurious callback. now: %f, fs deadline: %f, next deadline: %f",
122           now, fling_stop_deadline_, next_timer_deadline_);
123       return;
124     }
125     fling_stop_deadline_ = NO_DEADLINE;
126     ProduceGesture(Gesture(kGestureFling, prev_timestamp_,
127                            now, 0.0, 0.0,
128                            GESTURES_FLING_TAP_DOWN));
129     fling_stop_already_sent_ = true;
130     stime_t next_timeout =
131       next_timer_deadline_ == NO_DEADLINE || next_timer_deadline_ <= now ?
132       NO_DEADLINE : next_timer_deadline_ - now;
133     *timeout = SetNextDeadlineAndReturnTimeoutVal(now, fling_stop_deadline_,
134                                                   next_timeout);
135     return;
136   }
137   // Call next_
138   if (next_timer_deadline_ > now) {
139     Err("Spurious callback. now: %f, fs deadline: %f, next deadline: %f",
140         now, fling_stop_deadline_, next_timer_deadline_);
141     return;
142   }
143   stime_t next_timeout = NO_DEADLINE;
144   next_->HandleTimer(now, &next_timeout);
145   *timeout = SetNextDeadlineAndReturnTimeoutVal(now, fling_stop_deadline_,
146                                                 next_timeout);
147 }
148 
149 }  // namespace gestures
150