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
This commit is contained in:
Winson Chung
2014-06-30 18:04:55 -07:00
parent ca5be9a8fb
commit c6011deffc
6 changed files with 75 additions and 12 deletions

View File

@ -147,7 +147,9 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
} 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 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
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 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
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);

View File

@ -186,6 +186,10 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
/** 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 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
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 */

View File

@ -747,9 +747,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// 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 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// 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 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
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. */

View File

@ -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 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
}
/** 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 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
// 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 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
.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 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
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 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
.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 class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
*/
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);
}

View File

@ -38,9 +38,13 @@ public class ViewAnimation {
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;
}
}

View File

@ -2380,9 +2380,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
if (mRecentAppsHeldModifiers == 0 && !keyguardOn) {
final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)
|| KeyEvent.metaStateHasModifiers(
shiftlessModifiers, KeyEvent.META_META_ON)) {
if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
mRecentAppsHeldModifiers = shiftlessModifiers;
showRecentApps(true);
return -1;