Fixing some bugs in Recents keyboard behaviour.
- Ensuring that we don't allow meta-tab to trigger Recents (since meta is a system key now)
- Adding dpad keys support to traverse stack
- Adding workaround for cases where tasks wouldn't be focused depending on how you launch Recents
Change-Id: I4101ced7e47e0d1659d5fa236214be5697c00560
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 95edd1c..4c52b24 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -147,7 +147,9 @@
}
} else if (action.equals(RecentsService.ACTION_START_ENTER_ANIMATION)) {
// Try and start the enter animation (or restart it on configuration changed)
- mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(mFullScreenOverlayView));
+ ReferenceCountedTrigger t = new ReferenceCountedTrigger(context, null, null, null);
+ mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(
+ mFullScreenOverlayView, t));
// Call our callback
onEnterAnimationTriggered();
}
@@ -392,7 +394,9 @@
void onConfigurationChange() {
// Try and start the enter animation (or restart it on configuration changed)
- mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(mFullScreenOverlayView));
+ ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
+ mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(
+ mFullScreenOverlayView, t));
// Call our callback
onEnterAnimationTriggered();
}
@@ -536,6 +540,12 @@
final boolean backward = event.isShiftPressed();
mRecentsView.focusNextTask(!backward);
return true;
+ } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
+ mRecentsView.focusNextTask(true);
+ return true;
+ } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
+ mRecentsView.focusNextTask(false);
+ return true;
}
// Pass through the debug trigger
mDebugTrigger.onKeyEvent(keyCode);
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 e7eac67..b5b9cb5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -186,6 +186,10 @@
/** Requests all task stacks to start their enter-recents animation */
public void startEnterRecentsAnimation(ViewAnimation.TaskViewEnterContext ctx) {
+ // Handle the case when there are no views by incrementing and decrementing after all
+ // animations are started.
+ ctx.postAnimationTrigger.increment();
+
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
@@ -194,6 +198,10 @@
stackView.startEnterRecentsAnimation(ctx);
}
}
+
+ // Handle the case when there are no views by incrementing and decrementing after all
+ // animations are started.
+ ctx.postAnimationTrigger.decrement();
}
/** Requests all task stacks to start their exit-recents animation */
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 29eaa9e..2c05daa 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -747,9 +747,6 @@
// Mark that we have completely the first layout
mAwaitingFirstLayout = false;
- // Start dozing
- mUIDozeTrigger.startDozing();
-
// Prepare the first view for its enter animation
int offsetTopAlign = -mStackAlgorithm.mTaskRect.top;
int offscreenY = mStackAlgorithm.mRect.bottom -
@@ -770,7 +767,11 @@
// Update the focused task index to be the next item to the top task
if (mConfig.launchedWithAltTab) {
+ // When alt-tabbing, we focus the next previous task
focusTask(Math.max(0, mStack.getTaskCount() - 2), false);
+ } else {
+ // Normally we just focus the front task
+ focusTask(Math.max(0, mStack.getTaskCount() - 1), false);
}
}
}
@@ -799,6 +800,15 @@
mStack.indexOfTask(tv.getTask()), getStackScroll());
tv.startEnterRecentsAnimation(ctx);
}
+
+ // Add a runnable to the post animation ref counter to clear all the views
+ ctx.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
+ @Override
+ public void run() {
+ // Start dozing
+ mUIDozeTrigger.startDozing();
+ }
+ });
}
/** Requests this task stacks to start it's exit-recents animation. */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index b1fc700..c6bacbd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -16,6 +16,8 @@
package com.android.systemui.recents.views;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
@@ -296,7 +298,7 @@
}
/** Animates this task view as it enters recents */
- public void startEnterRecentsAnimation(ViewAnimation.TaskViewEnterContext ctx) {
+ public void startEnterRecentsAnimation(final ViewAnimation.TaskViewEnterContext ctx) {
TaskViewTransform transform = ctx.transform;
if (mConfig.launchedFromAppWithScreenshot) {
@@ -308,6 +310,8 @@
// Animate the task bar of the first task view
mBarView.startEnterRecentsAnimation(0, mEnableThumbnailClip);
setVisibility(View.VISIBLE);
+ // Decrement the post animation trigger
+ ctx.postAnimationTrigger.decrement();
}
});
} else {
@@ -321,9 +325,17 @@
.setInterpolator(mConfig.linearOutSlowInInterpolator)
.setDuration(475)
.withLayer()
- .withEndAction(mEnableThumbnailClip)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mEnableThumbnailClip.run();
+ // Decrement the post animation trigger
+ ctx.postAnimationTrigger.decrement();
+ }
+ })
.start();
}
+ ctx.postAnimationTrigger.increment();
} else if (mConfig.launchedFromAppWithThumbnail) {
if (ctx.isFrontMost) {
@@ -335,7 +347,15 @@
anim.setStartDelay(mConfig.taskBarEnterAnimDelay);
anim.setDuration(mConfig.taskBarEnterAnimDuration);
anim.setInterpolator(mConfig.fastOutLinearInInterpolator);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ // Decrement the post animation trigger
+ ctx.postAnimationTrigger.decrement();
+ }
+ });
anim.start();
+ ctx.postAnimationTrigger.increment();
} else {
mEnableThumbnailClip.run();
}
@@ -355,8 +375,16 @@
.setInterpolator(mConfig.quintOutInterpolator)
.setDuration(mConfig.taskViewEnterFromHomeDuration)
.withLayer()
- .withEndAction(mEnableThumbnailClip)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mEnableThumbnailClip.run();
+ // Decrement the post animation trigger
+ ctx.postAnimationTrigger.decrement();
+ }
+ })
.start();
+ ctx.postAnimationTrigger.increment();
}
}
@@ -518,7 +546,12 @@
*/
public void setFocusedTask() {
mIsFocused = true;
+ // Workaround, we don't always want it focusable in touch mode, but we want the first task
+ // to be focused after the enter-recents animation, which can be triggered from either touch
+ // or keyboard
+ setFocusableInTouchMode(true);
requestFocus();
+ setFocusableInTouchMode(false);
invalidate();
mCb.onTaskFocused(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java b/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
index 13407aa..fa97d2c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
@@ -38,9 +38,13 @@
int stackViewCount;
// Whether this is the front most task view
boolean isFrontMost;
+ // A trigger to run some logic when all the animations complete. This works around the fact
+ // that it is difficult to coordinate ViewPropertyAnimators
+ ReferenceCountedTrigger postAnimationTrigger;
- public TaskViewEnterContext(FullscreenTransitionOverlayView fss) {
+ public TaskViewEnterContext(FullscreenTransitionOverlayView fss, ReferenceCountedTrigger t) {
fullScreenshot = fss;
+ postAnimationTrigger = t;
}
}