immediate_interpreter: Fixed tap to drag behavior. Introduced delay before accepting drag.

In the SubsequentTabBegan state we used to accept any movement as a drag.
This is no longer the case, the finger has to stay in the same position for a short
period of time before it can be moved. This way tap to drag is not longer confused with tap to click and then move.

BUG=chromium-os:24172
TEST=Unit tests and manual testing on target machine. Test repeated by adlr.

Change-Id: I504271205229b17d87dbfe4c87f81846fb8fcac0
Reviewed-on: https://gerrit.chromium.org/gerrit/20748
Reviewed-by: Andrew de los Reyes <adlr@chromium.org>
Commit-Ready: Dennis Kempin <denniskempin@chromium.org>
Tested-by: Dennis Kempin <denniskempin@chromium.org>
diff --git a/include/immediate_interpreter.h b/include/immediate_interpreter.h
index 9b942e5..a60287b 100644
--- a/include/immediate_interpreter.h
+++ b/include/immediate_interpreter.h
@@ -342,6 +342,8 @@
   DoubleProperty tap_timeout_;
   // General time limit [s] for time between taps.
   DoubleProperty inter_tap_timeout_;
+  // Time [s] before a tap gets recognized as a drag.
+  DoubleProperty tap_drag_delay_;
   // Time [s] it takes to stop dragging when you let go of the touchpad
   DoubleProperty tap_drag_timeout_;
   // True if drag lock is enabled
diff --git a/src/immediate_interpreter.cc b/src/immediate_interpreter.cc
index f08268b..4d44a1a 100644
--- a/src/immediate_interpreter.cc
+++ b/src/immediate_interpreter.cc
@@ -235,7 +235,8 @@
       scroll_buffer_(3),
       tap_enable_(prop_reg, "Tap Enable", false),
       tap_timeout_(prop_reg, "Tap Timeout", 0.2),
-      inter_tap_timeout_(prop_reg, "Inter-Tap Timeout", 0.1),
+      inter_tap_timeout_(prop_reg, "Inter-Tap Timeout", 0.15),
+      tap_drag_delay_(prop_reg, "Tap Drag Delay", 0.1),
       tap_drag_timeout_(prop_reg, "Tap Drag Timeout", 0.7),
       drag_lock_enable_(prop_reg, "Tap Drag Lock Enable", 0),
       tap_move_dist_(prop_reg, "Tap Move Distance", 2.0),
@@ -913,14 +914,16 @@
   //       ↓
   //    [Idle**] <----------------------------------------------------------,
   //       ↓ added finger(s)                                                |
-  //    [FirstTapBegan] -<right click: send right click, timeout/movement>->|
-  //       ↓ released all fingers                                           |
+  //  ,>[FirstTapBegan] -<right click: send right click, timeout/movement>->|
+  //  |    ↓ released all fingers                                           |
   // ,->[TapComplete*] --<timeout: send click>----------------------------->|
-  // |     ↓ add finger(s): send button down                                |
-  // |  [SubsequentTapBegan] --<timeout/move(non-drag): send btn up>------->|
-  // |     | | released all fingers: send button up                         |
+  // ||    | | two finger touching: send left click.                        |
+  // |'----+-'                                                              |
+  // |     ↓ add finger(s)                                                  |
+  // |  [SubsequentTapBegan] --<timeout/move w/o delay: send click>------->|
+  // |     | | released all fingers send button click                       |
   // |<----+-'                                                              |
-  // |     ↓ timeout/movement (that looks like drag)                        |
+  // |     ↓ timeout/movement with delay: send button down                  |
   // | ,->[Drag] --<detect 2 finger gesture: send button up>--------------->|
   // | |   ↓ release all fingers                                            |
   // | |  [DragRelease*]  --<timeout: send button up>---------------------->|
@@ -988,15 +991,20 @@
       break;
     case kTtcTapComplete:
       if (!added_fingers.empty()) {
-        // Generate a button event for the tap type that got us into
-        // kTtcTapComplete state, after which we'll repurpose
-        // tap_record_ to record the next tap.
-        *buttons_down = tap_record_.TapType();
+
         tap_record_.Clear();
         tap_record_.Update(
             *hwstate, prev_state_, added_fingers, removed_fingers,
             dead_fingers);
-        SetTapToClickState(kTtcSubsequentTapBegan, now);
+
+        // If more than one finger is touching: Send click
+        // and return to FirstTapBegan state.
+        if (tap_record_.TapType() != GESTURES_BUTTON_LEFT) {
+          *buttons_down = *buttons_up = GESTURES_BUTTON_LEFT;
+          SetTapToClickState(kTtcFirstTapBegan, now);
+        } else {
+          SetTapToClickState(kTtcSubsequentTapBegan, now);
+        }
       } else if (is_timeout) {
         *buttons_down = *buttons_up =
             tap_record_.MinTapPressureMet() ? tap_record_.TapType() : 0;
@@ -1014,15 +1022,31 @@
             dead_fingers);
       if (is_timeout || tap_record_.Moving(*hwstate, tap_move_dist_.val_)) {
         if (tap_record_.TapType() == GESTURES_BUTTON_LEFT) {
-          SetTapToClickState(kTtcDrag, now);
-        } else {
-          *buttons_up = GESTURES_BUTTON_LEFT;
+          if (is_timeout) {
+            // moving with just one finger. Start dragging.
+            *buttons_down = GESTURES_BUTTON_LEFT;
+            SetTapToClickState(kTtcDrag, now);
+          } else {
+            bool drag_delay_met = (now - tap_to_click_state_entered_
+                > tap_drag_delay_.val_);
+            if (drag_delay_met) {
+              *buttons_down = GESTURES_BUTTON_LEFT;
+              SetTapToClickState(kTtcDrag, now);
+            } else {
+              *buttons_down = GESTURES_BUTTON_LEFT;
+              *buttons_up = GESTURES_BUTTON_LEFT;
+              SetTapToClickState(kTtcIdle, now);
+            }
+          }
+        } else if(!tap_record_.TapComplete()) {
+          // not just one finger. Send button click and go to idle.
+          *buttons_down = *buttons_up = GESTURES_BUTTON_LEFT;
           SetTapToClickState(kTtcIdle, now);
         }
         break;
       }
       if (tap_record_.TapComplete()) {
-        *buttons_up = GESTURES_BUTTON_LEFT;
+        *buttons_down = *buttons_up = GESTURES_BUTTON_LEFT;
         SetTapToClickState(kTtcTapComplete, now);
         Log("Subsequent left tap complete");
       }
diff --git a/src/immediate_interpreter_unittest.cc b/src/immediate_interpreter_unittest.cc
index e8f099e..9cd43f3 100644
--- a/src/immediate_interpreter_unittest.cc
+++ b/src/immediate_interpreter_unittest.cc
@@ -1365,37 +1365,44 @@
     // Double 1-finger tap
     {S,{ 0.00, 0, 1, 1, &fs[0] }, -1,  MkSet(91),   0,   0, kFTB, false },
     {C,{ 0.01, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kTpC, true },
-    {C,{ 0.02, 0, 1, 1, &fs[2] }, -1,  MkSet(93), kBL,   0, kSTB, false },
-    {C,{ 0.03, 0, 0, 0, NULL   }, -1,  MkSet(),     0, kBL, kTpC, true },
+    {C,{ 0.02, 0, 1, 1, &fs[2] }, -1,  MkSet(93),   0,   0, kSTB, false },
+    {C,{ 0.03, 0, 0, 0, NULL   }, -1,  MkSet(),   kBL, kBL, kTpC, true },
     {C,{ 0.09, 0, 0, 0, NULL   }, .09, MkSet(),   kBL, kBL, kIdl, false },
     // Triple 1-finger tap
     {S,{ 0.00, 0, 1, 1, &fs[0] }, -1,  MkSet(91),   0,   0, kFTB, false },
     {C,{ 0.01, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kTpC, true },
-    {C,{ 0.02, 0, 1, 1, &fs[2] }, -1,  MkSet(93), kBL,   0, kSTB, false },
-    {C,{ 0.03, 0, 0, 0, NULL   }, -1,  MkSet(),     0, kBL, kTpC, true },
-    {C,{ 0.04, 0, 1, 1, &fs[3] }, -1,  MkSet(94), kBL,   0, kSTB, false },
-    {C,{ 0.05, 0, 0, 0, NULL   }, -1,  MkSet(),     0, kBL, kTpC, true },
+    {C,{ 0.02, 0, 1, 1, &fs[2] }, -1,  MkSet(93),   0,   0, kSTB, false },
+    {C,{ 0.03, 0, 0, 0, NULL   }, -1,  MkSet(),   kBL, kBL, kTpC, true },
+    {C,{ 0.04, 0, 1, 1, &fs[3] }, -1,  MkSet(94),   0,   0, kSTB, false },
+    {C,{ 0.05, 0, 0, 0, NULL   }, -1,  MkSet(),   kBL, kBL, kTpC, true },
     {C,{ 0.11, 0, 0, 0, NULL   }, .11, MkSet(),   kBL, kBL, kIdl, false },
+    // 1-finger tap + drag
+    {S,{ 0.00, 0, 1, 1, &fs[0] }, -1,  MkSet(91),   0,   0, kFTB, false },
+    {C,{ 0.01, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kTpC, true },
+    {C,{ 0.02, 0, 1, 1, &fs[4] }, -1,  MkSet(95),   0,   0, kSTB, false },
+    {C,{ 0.13, 0, 1, 1, &fs[5] }, -1,  MkSet(95), kBL,   0, kDrg, false },
+    {C,{ 0.14, 0, 1, 1, &fs[6] }, -1,  MkSet(95),   0,   0, kDrg, false },
+    {C,{ 0.15, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kDRl, true },
+    {C,{ 0.99 , 0, 0, 0, NULL   }, .99, MkSet(),    0, kBL, kIdl, false },
     // 1-finger tap + move
     {S,{ 0.00, 0, 1, 1, &fs[0] }, -1,  MkSet(91),   0,   0, kFTB, false },
     {C,{ 0.01, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kTpC, true },
-    {C,{ 0.02, 0, 1, 1, &fs[4] }, -1,  MkSet(95), kBL,   0, kSTB, false },
-    {C,{ 0.03, 0, 1, 1, &fs[5] }, -1,  MkSet(95),   0,   0, kDrg, false },
-    {C,{ 0.04, 0, 1, 1, &fs[6] }, -1,  MkSet(95),   0,   0, kDrg, false },
-    {C,{ 0.05, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kDRl, true },
-    {C,{ 0.11, 0, 0, 0, NULL   }, .11, MkSet(),     0, kBL, kIdl, false },
+    {C,{ 0.02, 0, 1, 1, &fs[4] }, -1,  MkSet(95),   0,   0, kSTB, false },
+    {C,{ 0.03, 0, 1, 1, &fs[5] }, -1,  MkSet(95), kBL, kBL, kIdl, false },
+    {C,{ 0.04, 0, 1, 1, &fs[6] }, -1,  MkSet(95),   0,   0, kIdl, false },
+    {C,{ 0.05, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kIdl, false },
     // 1-finger tap, move, release, move again (drag lock)
     {S,{ 0.00, 0, 1, 1, &fs[0] }, -1,  MkSet(91),   0,   0, kFTB, false },
     {C,{ 0.01, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kTpC, true },
-    {C,{ 0.02, 0, 1, 1, &fs[4] }, -1,  MkSet(95), kBL,   0, kSTB, false },
-    {C,{ 0.03, 0, 1, 1, &fs[5] }, -1,  MkSet(95),   0,   0, kDrg, false },
-    {C,{ 0.04, 0, 1, 1, &fs[6] }, -1,  MkSet(95),   0,   0, kDrg, false },
-    {C,{ 0.05, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kDRl, true },
-    {C,{ 0.06, 0, 1, 1, &fs[7] }, -1,  MkSet(96),   0,   0, kDRt, false },
-    {C,{ 0.07, 0, 1, 1, &fs[8] }, -1,  MkSet(96),   0,   0, kDrg, false },
-    {C,{ 0.08, 0, 1, 1, &fs[9] }, -1,  MkSet(96),   0,   0, kDrg, false },
-    {C,{ 0.09, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kDRl, true },
-    {C,{ 0.15, 0, 0, 0, NULL   }, .15, MkSet(),     0, kBL, kIdl, false },
+    {C,{ 0.02, 0, 1, 1, &fs[4] }, -1,  MkSet(95),   0,   0, kSTB, false },
+    {C,{ 0.13, 0, 1, 1, &fs[5] }, -1,  MkSet(95), kBL,   0, kDrg, false },
+    {C,{ 0.14, 0, 1, 1, &fs[6] }, -1,  MkSet(95),   0,   0, kDrg, false },
+    {C,{ 0.15, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kDRl, true },
+    {C,{ 0.16, 0, 1, 1, &fs[7] }, -1,  MkSet(96),   0,   0, kDRt, false },
+    {C,{ 0.17, 0, 1, 1, &fs[8] }, -1,  MkSet(96),   0,   0, kDrg, false },
+    {C,{ 0.18, 0, 1, 1, &fs[9] }, -1,  MkSet(96),   0,   0, kDrg, false },
+    {C,{ 0.19, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kDRl, true },
+    {C,{ 0.99, 0, 0, 0, NULL   }, .99, MkSet(),     0, kBL, kIdl, false },
     // 1-finger long press
     {S,{ 0.00, 0, 1, 1, &fs[0] }, -1, MkSet(91),   0,   0, kFTB, false },
     {C,{ 0.02, 0, 1, 1, &fs[0] }, -1, MkSet(91),   0,   0, kFTB, false },
@@ -1405,12 +1412,12 @@
     // 1-finger tap then long press
     {S,{ 0.00, 0, 1, 1, &fs[0] }, -1,  MkSet(91),   0,   0, kFTB, false },
     {C,{ 0.01, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kTpC, true },
-    {C,{ 0.02, 0, 1, 1, &fs[4] }, -1,  MkSet(95), kBL,   0, kSTB, false },
-    {C,{ 0.04, 0, 1, 1, &fs[4] }, -1,  MkSet(95),   0,   0, kSTB, false },
-    {C,{ 0.06, 0, 1, 1, &fs[4] }, -1,  MkSet(95),   0,   0, kSTB, false },
-    {C,{ 0.08, 0, 1, 1, &fs[4] }, -1,  MkSet(95),   0,   0, kDrg, false },
-    {C,{ 0.09, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kDRl, true },
-    {C,{ 0.15, 0, 0, 0, NULL   }, .15, MkSet(),     0, kBL, kIdl, false },
+    {C,{ 0.02, 0, 1, 1, &fs[4] }, -1,  MkSet(95),   0,   0, kSTB, false },
+    {C,{ 0.14, 0, 1, 1, &fs[4] }, -1,  MkSet(95), kBL,   0, kDrg, false },
+    {C,{ 0.16, 0, 1, 1, &fs[4] }, -1,  MkSet(95),   0,   0, kDrg, false },
+    {C,{ 0.18, 0, 1, 1, &fs[4] }, -1,  MkSet(95),   0,   0, kDrg, false },
+    {C,{ 0.19, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kDRl, true },
+    {C,{ 0.99, 0, 0, 0, NULL   }, .99, MkSet(),     0, kBL, kIdl, false },
     // 2-finger tap (right click)
     {S,{ 0.00, 0, 2, 2, &fs[10] }, -1,  MkSet(97, 98), 0, 0, kFTB, false },
     {C,{ 0.01, 0, 0, 0, NULL    }, -1,  MkSet(),       kBR, kBR, kIdl, false },
@@ -1425,17 +1432,17 @@
     {C,{ 0.02, 0, 2, 2, &fs[14] }, -1, MkSet(97, 98),   0,   0, kIdl, false },
     {C,{ 0.03, 0, 0, 0, NULL    }, -1, MkSet(),         0,   0, kIdl, false },
     // left tap, right tap
-    {S,{ 0.00, 0, 1, 1, &fs[0] },  -1,  MkSet(91),     0, 0, kFTB, false },
+    {S,{ 0.00, 0, 1, 1, &fs[0] },  -1,  MkSet(91),       0, 0, kFTB, false },
     {C,{ 0.01, 0, 0, 0, NULL   },  -1,  MkSet(),         0,   0, kTpC, true },
-    {C,{ 0.02, 0, 2, 2, &fs[10] }, -1,  MkSet(97, 98), kBL,   0, kSTB, false },
-    {C,{ 0.03, 0, 0, 0, NULL   },  -1,  MkSet(),         0, kBL, kTpC, true },
-    {C,{ 0.09, 0, 0, 0, NULL    }, .09, MkSet(),       kBR, kBR, kIdl, false },
+    {C,{ 0.02, 0, 2, 2, &fs[10] }, -1,  MkSet(97, 98), kBL, kBL, kFTB, false },
+    {C,{ 0.03, 0, 0, 0, NULL   },  -1,  MkSet(),       kBR, kBR, kIdl, false },
+    {C,{ 0.09, 0, 0, 0, NULL    }, .09, MkSet(),         0,   0, kIdl, false },
     // left tap, multi-frame right tap
     {S,{ 0.00, 0, 1, 1, &fs[0] },  -1,  MkSet(91),   0,   0, kFTB, false },
     {C,{ 0.01, 0, 0, 0, NULL   },  -1,  MkSet(),     0,   0, kTpC, true },
-    {C,{ 0.02, 0, 1, 1, &fs[10] }, -1,  MkSet(97), kBL,   0, kSTB, false },
+    {C,{ 0.02, 0, 1, 1, &fs[10] }, -1,  MkSet(97),   0,   0, kSTB, false },
     {C,{ 0.03, 0, 1, 1, &fs[11] }, -1,  MkSet(98),   0,   0, kSTB, false },
-    {C,{ 0.04, 0, 0, 0, NULL   },  -1,  MkSet(),     0, kBL, kTpC, true },
+    {C,{ 0.04, 0, 0, 0, NULL   },  -1,  MkSet(),   kBL, kBL, kTpC, true },
     {C,{ 0.10, 0, 0, 0, NULL    }, .10, MkSet(),   kBR, kBR, kIdl, false },
     // right tap, left tap
     {S,{ 0.00, 0, 2, 2, &fs[10] }, -1,  MkSet(97, 98),  0, 0, kFTB, false },
@@ -1452,17 +1459,25 @@
     // left tap, right-drag
     {S,{ 0.00, 0, 1, 1, &fs[0] },  -1, MkSet(91),       0, 0, kFTB, false },
     {C,{ 0.01, 0, 0, 0, NULL   },  -1, MkSet(),         0,   0, kTpC, true },
-    {C,{ 0.02, 0, 2, 2, &fs[10] }, -1, MkSet(97, 98), kBL,   0, kSTB, false },
-    {C,{ 0.03, 0, 2, 2, &fs[12] }, -1, MkSet(97, 98),   0, kBL, kIdl, false },
+    {C,{ 0.02, 0, 2, 2, &fs[10] }, -1, MkSet(97, 98), kBL, kBL, kFTB, false },
+    {C,{ 0.03, 0, 2, 2, &fs[12] }, -1, MkSet(97, 98),   0,   0, kIdl, false },
     {C,{ 0.04, 0, 2, 2, &fs[14] }, -1, MkSet(97, 98),   0,   0, kIdl, false },
     {C,{ 0.05, 0, 0, 0, NULL   },  -1, MkSet(),         0,   0, kIdl, false },
-    // left tap, right multi-frame join + drag
+    // left tap, right multi-frame drag
     {S,{ 0.00, 0, 1, 1, &fs[0] },  -1, MkSet(91),       0, 0, kFTB, false },
     {C,{ 0.01, 0, 0, 0, NULL   },  -1, MkSet(),         0,   0, kTpC, true },
-    {C,{ 0.02, 0, 1, 1, &fs[10] }, -1, MkSet(97),     kBL,   0, kSTB, false },
-    {C,{ 0.03, 0, 1, 1, &fs[12] }, -1, MkSet(97),       0,   0, kDrg, false },
-    {C,{ 0.04, 0, 2, 2, &fs[14] }, -1, MkSet(97, 98),   0, kBL, kIdl, false },
+    {C,{ 0.02, 0, 1, 1, &fs[10] }, -1, MkSet(97),       0,   0, kSTB, false },
+    {C,{ 0.03, 0, 2, 2, &fs[12] }, -1, MkSet(97, 98), kBL, kBL, kIdl, false },
+    {C,{ 0.04, 0, 2, 2, &fs[14] }, -1, MkSet(97, 98),   0,   0, kIdl, false },
     {C,{ 0.05, 0, 0, 0, NULL   },  -1, MkSet(),         0,   0, kIdl, false },
+    // left tap, drag + finger joined later
+    {S,{ 0.00, 0, 1, 1, &fs[0] },  -1, MkSet(91),       0, 0, kFTB, false },
+    {C,{ 0.01, 0, 0, 0, NULL   },  -1, MkSet(),         0,   0, kTpC, true },
+    {C,{ 0.02, 0, 1, 1, &fs[10] }, -1, MkSet(97),       0,   0, kSTB, false },
+    {C,{ 0.13, 0, 1, 1, &fs[10] }, -1, MkSet(97),     kBL,   0, kDrg, false },
+    {C,{ 0.14, 0, 2, 2, &fs[12] }, -1, MkSet(97, 98),   0, kBL, kIdl, false },
+    {C,{ 0.15, 0, 2, 2, &fs[14] }, -1, MkSet(97, 98),   0,   0, kIdl, false },
+    {C,{ 0.16, 0, 0, 0, NULL   },  -1, MkSet(),         0,   0, kIdl, false },
     // right tap, left-drag
     {S,{ 0.00, 0, 2, 2, &fs[14] }, -1, MkSet(97, 98),  0, 0, kFTB, false },
     {C,{ 0.01, 0, 0, 0, NULL   }, -1,  MkSet(),       kBR, kBR, kIdl, false },
@@ -1480,18 +1495,18 @@
     // drag then right-tap
     {S,{ 0.00, 0, 1, 1, &fs[0] }, -1,  MkSet(91),     0,  0, kFTB, false },
     {C,{ 0.01, 0, 0, 0, NULL   }, -1,  MkSet(),       0,   0, kTpC, true },
-    {C,{ 0.02, 0, 1, 1, &fs[4] }, -1,  MkSet(95),   kBL,   0, kSTB, false },
-    {C,{ 0.03, 0, 1, 1, &fs[5] }, -1,  MkSet(95),     0,   0, kDrg, false },
-    {C,{ 0.04, 0, 1, 1, &fs[6] }, -1,  MkSet(95),     0,   0, kDrg, false },
-    {C,{ 0.05, 0, 0, 0, NULL   }, -1,  MkSet(),       0,   0, kDRl, true },
-    {C,{ 0.06, 0, 2, 2, &fs[10] }, -1, MkSet(97, 98), 0,   0, kDRt, false },
-    {C,{ 0.07, 0, 0, 0, NULL   }, -1,  MkSet(),       0, kBL, kTpC, true },
-    {C,{ 0.13, 0, 0, 0, NULL   }, .13, MkSet(),     kBR, kBR, kIdl, false },
+    {C,{ 0.02, 0, 1, 1, &fs[4] }, -1,  MkSet(95),     0,   0, kSTB, false },
+    {C,{ 0.13, 0, 1, 1, &fs[5] }, -1,  MkSet(95),   kBL,   0, kDrg, false },
+    {C,{ 0.14, 0, 1, 1, &fs[6] }, -1,  MkSet(95),     0,   0, kDrg, false },
+    {C,{ 0.15, 0, 0, 0, NULL   }, -1,  MkSet(),       0,   0, kDRl, true },
+    {C,{ 0.16, 0, 2, 2, &fs[10] }, -1, MkSet(97, 98), 0,   0, kDRt, false },
+    {C,{ 0.17, 0, 0, 0, NULL   }, -1,  MkSet(),       0, kBL, kTpC, true },
+    {C,{ 0.99, 0, 0, 0, NULL   }, .99, MkSet(),     kBR, kBR, kIdl, false },
     // slow double tap
     {D,{ 0.00, 0, 1, 1, &fs[0] }, -1, MkSet(91),   0,   0, kFTB, false },
     {C,{ 0.10, 0, 0, 0, NULL   }, -1, MkSet(),     0,   0, kTpC, true },
-    {C,{ 0.12, 0, 1, 1, &fs[2] }, -1, MkSet(93), kBL,   0, kSTB, false },
-    {C,{ 0.22, 0, 0, 0, NULL   }, -1, MkSet(),     0, kBL, kTpC, true },
+    {C,{ 0.12, 0, 1, 1, &fs[2] }, -1, MkSet(93),   0,   0, kSTB, false },
+    {C,{ 0.22, 0, 0, 0, NULL   }, -1, MkSet(),   kBL, kBL, kTpC, true },
     {C,{ 0.90, 0, 0, 0, NULL   }, .9, MkSet(),   kBL, kBL, kIdl, false },
     // right tap, very close fingers - shouldn't tap
     {S,{ 0.00, 0, 2, 2, &fs[19] }, -1, MkSet(95, 96), 0, 0, kIdl, false },
@@ -1758,15 +1773,15 @@
     // 1-finger tap, move, release, move again (drag lock)
     {S,{ 0.00, 0, 1, 1, &fs[0] }, -1,  MkSet(91),   0,   0, kFTB, false },
     {C,{ 0.01, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kTpC, true },
-    {C,{ 0.02, 0, 1, 1, &fs[1] }, -1,  MkSet(92), kBL,   0, kSTB, false },
-    {C,{ 0.03, 0, 1, 1, &fs[2] }, -1,  MkSet(92),   0,   0, kDrg, false },
-    {C,{ 0.04, 0, 1, 1, &fs[3] }, -1,  MkSet(92),   0,   0, kDrg, false },
-    {C,{ 0.05, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kDRl, true },
-    {C,{ 0.06, 0, 1, 1, &fs[4] }, -1,  MkSet(93),   0,   0, kDRt, false },
-    {C,{ 0.07, 0, 1, 1, &fs[5] }, -1,  MkSet(93),   0,   0, kDrg, false },
-    {C,{ 0.08, 0, 1, 1, &fs[6] }, -1,  MkSet(93),   0,   0, kDrg, false },
-    {C,{ 0.09, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kDRl, true },
-    {C,{ 0.15, 0, 0, 0, NULL   }, .15, MkSet(),     0, kBL, kIdl, false }
+    {C,{ 0.02, 0, 1, 1, &fs[1] }, -1,  MkSet(92),   0,   0, kSTB, false },
+    {C,{ 0.13, 0, 1, 1, &fs[2] }, -1,  MkSet(92), kBL,   0, kDrg, false },
+    {C,{ 0.14, 0, 1, 1, &fs[3] }, -1,  MkSet(92),   0,   0, kDrg, false },
+    {C,{ 0.15, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kDRl, true },
+    {C,{ 0.16, 0, 1, 1, &fs[4] }, -1,  MkSet(93),   0,   0, kDRt, false },
+    {C,{ 0.17, 0, 1, 1, &fs[5] }, -1,  MkSet(93),   0,   0, kDrg, false },
+    {C,{ 0.18, 0, 1, 1, &fs[6] }, -1,  MkSet(93),   0,   0, kDrg, false },
+    {C,{ 0.19, 0, 0, 0, NULL   }, -1,  MkSet(),     0,   0, kDRl, true },
+    {C,{ 0.99, 0, 0, 0, NULL   }, .99, MkSet(),     0, kBL, kIdl, false }
   };
 
   for (int iter = 0; iter < 3; ++iter) {