Discrete modes for touch or key traversal

Change-Id: I19e0258a6312409a5fe493c9ada68f55038e335d
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index e0c58d3..d3ad04c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -136,7 +136,9 @@
             if (action.equals(Recents.ACTION_HIDE_RECENTS_ACTIVITY)) {
                 if (intent.getBooleanExtra(Recents.EXTRA_TRIGGERED_FROM_ALT_TAB, false)) {
                     // If we are hiding from releasing Alt-Tab, dismiss Recents to the focused app
-                    dismissRecentsToFocusedTaskOrHome(false);
+                    if (!mRecentsView.hasBeenTouched()) {
+                        dismissRecentsToFocusedTaskOrHome(false);
+                    }
                 } else if (intent.getBooleanExtra(Recents.EXTRA_TRIGGERED_FROM_HOME_KEY, false)) {
                     // Otherwise, dismiss Recents to Home
                     dismissRecentsToHomeRaw(true);
@@ -547,6 +549,12 @@
                     mRecentsView.focusNextTask(!backward);
                     mLastTabKeyEventTime = SystemClock.elapsedRealtime();
                 }
+
+                // In the case of another ALT event, ignore the previous touches.
+                final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
+                if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
+                    mRecentsView.resetHasBeenTouched();
+                }
                 return true;
             }
             case KeyEvent.KEYCODE_DPAD_UP: {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index ae437b7..73f3ac9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -517,6 +517,22 @@
         cancelLaunchedTaskWindowTransitionWithDelay(task, 0);
     }
 
+    public void resetHasBeenTouched() {
+        List<TaskStackView> stackViews = getTaskStackViews();
+        if (!stackViews.isEmpty()) {
+            stackViews.get(0).resetHasBeenTouched();
+        }
+    }
+
+    public boolean hasBeenTouched() {
+        List<TaskStackView> stackViews = getTaskStackViews();
+        if (!stackViews.isEmpty()) {
+            return stackViews.get(0).hasBeenTouched();
+        }
+
+        return false;
+    }
+
     @Override
     public void onTaskViewClicked(final TaskStackView stackView, final TaskView tv,
                                   final TaskStack stack, final Task task, final boolean lockToTask) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index b4bdebe..e6f44bb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -1091,6 +1091,14 @@
         }
     }
 
+    public void resetHasBeenTouched() {
+        mTouchHandler.resetHasBeenTouched();
+    }
+
+    public boolean hasBeenTouched() {
+        return mTouchHandler.hasBeenTouched();
+    }
+
     /**** TaskStackCallbacks Implementation ****/
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 9d8b25a..506a02d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -58,6 +58,7 @@
     // Used to calculate when a tap is outside a task view rectangle.
     final int mWindowTouchSlop;
     boolean mIsTouching;
+    boolean mHasBeenTouched;
 
     SwipeHelper mSwipeHelper;
     boolean mInterceptedBySwipeHelper;
@@ -151,6 +152,7 @@
             case MotionEvent.ACTION_DOWN: {
                 // Save the touch down info
                 mIsTouching = true;
+                mHasBeenTouched = true;
                 mInitialMotionX = mLastMotionX = (int) ev.getX();
                 mInitialMotionY = mLastMotionY = (int) ev.getY();
                 mInitialP = mLastP = mSv.mLayoutAlgorithm.screenYToCurveProgress(mLastMotionY);
@@ -260,6 +262,7 @@
             case MotionEvent.ACTION_DOWN: {
                 // Save the touch down info
                 mIsTouching = true;
+                mHasBeenTouched = true;
                 mInitialMotionX = mLastMotionX = (int) ev.getX();
                 mInitialMotionY = mLastMotionY = (int) ev.getY();
                 mInitialP = mLastP = mSv.mLayoutAlgorithm.screenYToCurveProgress(mLastMotionY);
@@ -455,6 +458,7 @@
     @Override
     public void onBeginDrag(View v) {
         mIsTouching = true;
+        mHasBeenTouched = true;
 
         TaskView tv = (TaskView) v;
         // Disable clipping with the stack while we are swiping
@@ -513,7 +517,16 @@
         return mIsTouching;
     }
 
+    public void resetHasBeenTouched() {
+        mHasBeenTouched = false;
+    }
+
+    public boolean hasBeenTouched() {
+        return mHasBeenTouched;
+    }
+
     public void reset() {
         mIsTouching = false;
+        mHasBeenTouched = false;
     }
 }