Guarantee that scroll/swipe end gestures are sent

If the previous gesture was a scroll or swipe and a different gesture is
detected, send the corresponding scroll/swipe end gesture instead of the
detected gesture.

BUG=b:67736270
TEST=Deploy to device, unable to reproduce bug and behavior is normal.
Also passes touchtest suite, including new test.

Change-Id: I2a3e6b6d6571aeeb69212fe83647a6404d8161e6
Reviewed-on: https://chromium-review.googlesource.com/726272
Commit-Ready: Sean O'Brien <seobrien@chromium.org>
Tested-by: Sean O'Brien <seobrien@chromium.org>
Reviewed-by: Andrew de los Reyes <adlr@chromium.org>
diff --git a/include/immediate_interpreter.h b/include/immediate_interpreter.h
index d13a17f..172af9c 100644
--- a/include/immediate_interpreter.h
+++ b/include/immediate_interpreter.h
@@ -480,6 +480,14 @@
                                 const FingerMap& gs_fingers,
                                 FingerMap* active_gs_fingers);
 
+  // Checks if gesture_type is one of kGestureTypeScroll, kGestureTypeSwipe, or
+  // kGestureTypeFourFingerSwipe
+  bool IsScrollOrSwipe(const GestureType gesture_type);
+
+  // Checks if a scroll or swipe has ended, and replaces current_gesture_type_
+  // with the appropriate finger lift gesture.
+  void GenerateFingerLiftGesture();
+
   // Sorts the fingers referred to in finger_ids (whose details are in hwstate)
   // according to prodimity and places the sorted range into out_sorted_ids.
   // The sort first finds the two closes points and includes them first.
@@ -706,8 +714,6 @@
   //     pinch_guess_ == true:  Guess there is a pinch
   //     pinch_guess_ == false: Guess there is no pinch
 
-  // Since the fingers changed, has a scroll or swipe gesture been detected?
-  bool these_fingers_scrolled_;
   // When guessing a pinch gesture. Do we guess pinch (true) or no-pinch?
   bool pinch_guess_;
   // Time when pinch guess was made. -1 if no guess has been made yet.
diff --git a/src/immediate_interpreter.cc b/src/immediate_interpreter.cc
index cb9c19c..25226dc 100644
--- a/src/immediate_interpreter.cc
+++ b/src/immediate_interpreter.cc
@@ -993,7 +993,6 @@
       current_gesture_type_(kGestureTypeNull),
       state_buffer_(8),
       scroll_buffer_(20),
-      these_fingers_scrolled_(false),
       pinch_guess_start_(-1.0),
       pinch_locked_(false),
       pinch_status_(GESTURES_ZOOM_START),
@@ -1194,6 +1193,7 @@
 
   FingerMap active_gs_fingers;
   UpdateCurrentGestureType(*hwstate, gs_fingers, &active_gs_fingers);
+  GenerateFingerLiftGesture();
   non_gs_fingers_ = SetSubtract(gs_fingers, active_gs_fingers);
   if (result_.type == kGestureTypeNull)
     FillResultGesture(*hwstate, active_gs_fingers);
@@ -1735,17 +1735,6 @@
     case kGestureTypeScroll:
     case kGestureTypeSwipe:
     case kGestureTypeFourFingerSwipe:
-      // Don't allow a pinch after a scroll or swipe gesture has been detected
-      these_fingers_scrolled_ = true;
-
-      // If a gesturing finger just left, do fling/lift
-      if (AnyGesturingFingerLeft(*state_buffer_.Get(0),
-                                 prev_gs_fingers_)) {
-        current_gesture_type_ = GetFingerLiftGesture(current_gesture_type_);
-        moving_.clear();
-        return;
-      }
-      // fallthrough
     case kGestureTypeSwipeLift:
     case kGestureTypeFourFingerSwipeLift:
     case kGestureTypeFling:
@@ -1862,7 +1851,7 @@
       if ((current_gesture_type_ == kGestureTypeMove ||
            current_gesture_type_ == kGestureTypeNull) &&
           (pinch_enable_.val_ && !hwprops_->support_semi_mt) &&
-          !these_fingers_scrolled_) {
+          !IsScrollOrSwipe(prev_gesture_type_)) {
         bool do_pinch = UpdatePinchState(hwstate, false, gs_fingers);
         if (do_pinch) {
           current_gesture_type_ = kGestureTypePinch;
@@ -1892,6 +1881,26 @@
   return;
 }
 
+bool ImmediateInterpreter::IsScrollOrSwipe(GestureType gesture_type) {
+  switch(gesture_type) {
+    case kGestureTypeScroll:
+    case kGestureTypeSwipe:
+    case kGestureTypeFourFingerSwipe:
+      return true;
+    default:
+      return false;
+  }
+}
+
+void ImmediateInterpreter::GenerateFingerLiftGesture() {
+  // If we have just finished scrolling, we set current_gesture_type_ to the
+  // appropriate lift gesture.
+  if (IsScrollOrSwipe(prev_gesture_type_) &&
+      current_gesture_type_ != prev_gesture_type_) {
+    current_gesture_type_ = GetFingerLiftGesture(prev_gesture_type_);
+  }
+}
+
 namespace {
 // Can't use tuple<float, short, short> b/c we want to make a variable
 // sized array of them on the stack
@@ -1983,7 +1992,6 @@
     pinch_guess_start_ = -1.0f;
     pinch_locked_ = false;
     pinch_prev_distance_sq_ = -1.0f;
-    these_fingers_scrolled_ = false;
     return false;
   }