diff options
15 files changed, 464 insertions, 150 deletions
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index a78b56ab194c..4a1142f7204f 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -1333,9 +1333,9 @@ public interface WindowManagerPolicy { * Calculates the stable insets without running a layout. * * @param displayRotation the current display rotation - * @param outInsets the insets to return * @param displayWidth the current display width * @param displayHeight the current display height + * @param outInsets the insets to return */ public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight, Rect outInsets); diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java index fdf5f8419ba0..59a1e4a78299 100644 --- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java +++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java @@ -209,12 +209,8 @@ public class DividerSnapAlgorithm { } private void addMiddleTarget(boolean isHorizontalDivision) { - int start = isHorizontalDivision ? mInsets.top : mInsets.left; - int end = isHorizontalDivision - ? mDisplayHeight - mInsets.bottom - : mDisplayWidth - mInsets.right; - mTargets.add(new SnapTarget(start + (end - start) / 2 - mDividerSize / 2, - SnapTarget.FLAG_NONE)); + mTargets.add(new SnapTarget(DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision, + mInsets, mDisplayWidth, mDisplayHeight, mDividerSize), SnapTarget.FLAG_NONE)); } public SnapTarget getMiddleTarget() { diff --git a/core/java/com/android/internal/policy/DockedDividerUtils.java b/core/java/com/android/internal/policy/DockedDividerUtils.java index 25a060e0a0a7..d06e2bbb7722 100644 --- a/core/java/com/android/internal/policy/DockedDividerUtils.java +++ b/core/java/com/android/internal/policy/DockedDividerUtils.java @@ -19,6 +19,11 @@ package com.android.internal.policy; import android.graphics.Rect; import android.view.WindowManager; +import static android.view.WindowManager.DOCKED_BOTTOM; +import static android.view.WindowManager.DOCKED_LEFT; +import static android.view.WindowManager.DOCKED_RIGHT; +import static android.view.WindowManager.DOCKED_TOP; + /** * Utility functions for docked stack divider used by both window manager and System UI. * @@ -71,4 +76,45 @@ public class DockedDividerUtils { return 0; } } + + public static int calculateMiddlePosition(boolean isHorizontalDivision, Rect insets, + int displayWidth, int displayHeight, int dividerSize) { + int start = isHorizontalDivision ? insets.top : insets.left; + int end = isHorizontalDivision + ? displayHeight - insets.bottom + : displayWidth - insets.right; + return start + (end - start) / 2 - dividerSize / 2; + } + + public static int getDockSideFromCreatedMode(boolean dockOnTopOrLeft, + boolean isHorizontalDivision) { + if (dockOnTopOrLeft) { + if (isHorizontalDivision) { + return DOCKED_TOP; + } else { + return DOCKED_LEFT; + } + } else { + if (isHorizontalDivision) { + return DOCKED_BOTTOM; + } else { + return DOCKED_RIGHT; + } + } + } + + public static int invertDockSide(int dockSide) { + switch (dockSide) { + case WindowManager.DOCKED_LEFT: + return WindowManager.DOCKED_RIGHT; + case WindowManager.DOCKED_TOP: + return WindowManager.DOCKED_BOTTOM; + case WindowManager.DOCKED_RIGHT: + return WindowManager.DOCKED_LEFT; + case WindowManager.DOCKED_BOTTOM: + return WindowManager.DOCKED_TOP; + default: + return WindowManager.DOCKED_INVALID; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java index 67135d5621b4..61780f8bd8de 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java @@ -139,7 +139,7 @@ public class RecentsConfiguration { } else { // In portrait, the search bar appears on the top (which already has the inset) int top = searchBarBounds.isEmpty() ? topInset : 0; - taskStackBounds.set(windowBounds.left, searchBarBounds.bottom + top, + taskStackBounds.set(windowBounds.left, windowBounds.top + searchBarBounds.bottom + top, windowBounds.right - rightInset, windowBounds.bottom); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragDropTargetChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragDropTargetChangedEvent.java index 21321f297159..b85ddac62b19 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragDropTargetChangedEvent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragDropTargetChangedEvent.java @@ -25,6 +25,7 @@ import com.android.systemui.recents.views.DropTarget; */ public class DragDropTargetChangedEvent extends EventBus.Event { + // The task that is currently being dragged public final Task task; public final DropTarget dropTarget; diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index f9e825aaf064..e05a6f8f504f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -307,11 +307,12 @@ public class SystemServicesProxy { } /** Docks a task to the side of the screen and starts it. */ - public void startTaskInDockedMode(int taskId, int createMode) { + public void startTaskInDockedMode(Context context, int taskId, int createMode) { if (mIam == null) return; try { - final ActivityOptions options = ActivityOptions.makeBasic(); + // TODO: Determine what animation we want for the incoming task + final ActivityOptions options = ActivityOptions.makeCustomAnimation(context, 0, 0); options.setDockCreateMode(createMode); options.setLaunchStackId(DOCKED_STACK_ID); mIam.startActivityFromRecents(taskId, options.toBundle()); @@ -917,6 +918,18 @@ public class SystemServicesProxy { } } + /** + * Calculates the size of the dock divider in the current orientation. + */ + public int getDockedDividerSize(Context context) { + Resources res = context.getResources(); + int dividerWindowWidth = res.getDimensionPixelSize( + com.android.internal.R.dimen.docked_stack_divider_thickness); + int dividerInsets = res.getDimensionPixelSize( + com.android.internal.R.dimen.docked_stack_divider_insets); + return dividerWindowWidth - 2 * dividerInsets; + } + public void requestKeyboardShortcuts(Context context, KeyboardShortcutsReceiver receiver) { mWm.requestAppKeyboardShortcuts(receiver); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java index 2bf2ccba77c7..33f116ba4316 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java @@ -18,13 +18,43 @@ package com.android.systemui.recents.misc; import android.animation.Animator; import android.graphics.Color; +import android.graphics.Rect; import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.util.IntProperty; +import android.util.Property; import android.view.View; import android.view.ViewParent; /* Common code */ public class Utilities { + public static final Property<Drawable, Integer> DRAWABLE_ALPHA = + new IntProperty<Drawable>("drawableAlpha") { + @Override + public void setValue(Drawable object, int alpha) { + object.setAlpha(alpha); + } + + @Override + public Integer get(Drawable object) { + return object.getAlpha(); + } + }; + + public static final Property<Drawable, Rect> DRAWABLE_RECT = + new Property<Drawable, Rect>(Rect.class, "drawableBounds") { + @Override + public void set(Drawable object, Rect bounds) { + object.setBounds(bounds); + } + + @Override + public Rect get(Drawable object) { + return object.getBounds(); + } + }; + /** * @return the first parent walking up the view hierarchy that has the given class type. * diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java index 856200df6529..e97188b10af0 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java @@ -16,16 +16,25 @@ package com.android.systemui.recents.model; +import android.animation.Animator; +import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; +import android.animation.RectEvaluator; import android.content.ComponentName; import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; import android.graphics.Color; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.ColorDrawable; import android.util.SparseArray; +import android.view.animation.Interpolator; +import com.android.internal.policy.DockedDividerUtils; import com.android.systemui.R; import com.android.systemui.recents.Recents; +import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.RecentsDebugFlags; import com.android.systemui.recents.misc.NamedCounter; import com.android.systemui.recents.misc.SystemServicesProxy; @@ -44,6 +53,11 @@ import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIG import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; +import static android.view.WindowManager.DOCKED_LEFT; +import static android.view.WindowManager.DOCKED_RIGHT; +import static android.view.WindowManager.DOCKED_TOP; +import static android.view.WindowManager.DOCKED_BOTTOM; +import static android.view.WindowManager.DOCKED_INVALID; /** @@ -229,30 +243,36 @@ public class TaskStack { public static class DockState implements DropTarget { private static final int DOCK_AREA_ALPHA = 192; - public static final DockState NONE = new DockState(-1, 96, null, null); - public static final DockState LEFT = new DockState( + public static final DockState NONE = new DockState(DOCKED_INVALID, -1, 80, null, null, null); + public static final DockState LEFT = new DockState(DOCKED_LEFT, DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA, - new RectF(0, 0, 0.15f, 1), new RectF(0, 0, 0.15f, 1)); - public static final DockState TOP = new DockState( + new RectF(0, 0, 0.125f, 1), new RectF(0, 0, 0.125f, 1), + new RectF(0, 0, 0.5f, 1)); + public static final DockState TOP = new DockState(DOCKED_TOP, DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA, - new RectF(0, 0, 1, 0.15f), new RectF(0, 0, 1, 0.15f)); - public static final DockState RIGHT = new DockState( + new RectF(0, 0, 1, 0.125f), new RectF(0, 0, 1, 0.125f), + new RectF(0, 0, 1, 0.5f)); + public static final DockState RIGHT = new DockState(DOCKED_RIGHT, DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, DOCK_AREA_ALPHA, - new RectF(0.85f, 0, 1, 1), new RectF(0.85f, 0, 1, 1)); - public static final DockState BOTTOM = new DockState( + new RectF(0.875f, 0, 1, 1), new RectF(0.875f, 0, 1, 1), + new RectF(0.5f, 0, 1, 1)); + public static final DockState BOTTOM = new DockState(DOCKED_BOTTOM, DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT, DOCK_AREA_ALPHA, - new RectF(0, 0.85f, 1, 1), new RectF(0, 0.85f, 1, 1)); + new RectF(0, 0.875f, 1, 1), new RectF(0, 0.875f, 1, 1), + new RectF(0, 0.5f, 1, 1)); @Override - public boolean acceptsDrop(int x, int y, int width, int height) { - return touchAreaContainsPoint(width, height, x, y); + public boolean acceptsDrop(int x, int y, int width, int height, boolean isCurrentTarget) { + return isCurrentTarget + ? areaContainsPoint(expandedTouchDockArea, width, height, x, y) + : areaContainsPoint(touchArea, width, height, x, y); } // Represents the view state of this dock state public class ViewState { public final int dockAreaAlpha; public final ColorDrawable dockAreaOverlay; - private ObjectAnimator dockAreaOverlayAnimator; + private AnimatorSet dockAreaOverlayAnimator; private ViewState(int alpha) { dockAreaAlpha = alpha; @@ -261,56 +281,130 @@ public class TaskStack { } /** - * Creates a new alpha animation. + * Creates a new bounds and alpha animation. */ - public void startAlphaAnimation(int alpha, int duration) { + public void startAnimation(Rect bounds, int alpha, int duration, + Interpolator interpolator, boolean animateAlpha, boolean animateBounds) { + if (dockAreaOverlayAnimator != null) { + dockAreaOverlayAnimator.cancel(); + } + + ArrayList<Animator> animators = new ArrayList<>(); if (dockAreaOverlay.getAlpha() != alpha) { - if (dockAreaOverlayAnimator != null) { - dockAreaOverlayAnimator.cancel(); + if (animateAlpha) { + animators.add(ObjectAnimator.ofInt(dockAreaOverlay, + Utilities.DRAWABLE_ALPHA, dockAreaOverlay.getAlpha(), alpha)); + } else { + dockAreaOverlay.setAlpha(alpha); } - dockAreaOverlayAnimator = ObjectAnimator.ofInt(dockAreaOverlay, "alpha", alpha); + } + if (bounds != null && !dockAreaOverlay.getBounds().equals(bounds)) { + if (animateBounds) { + PropertyValuesHolder prop = PropertyValuesHolder.ofObject( + Utilities.DRAWABLE_RECT, new RectEvaluator(new Rect()), + dockAreaOverlay.getBounds(), bounds); + animators.add(ObjectAnimator.ofPropertyValuesHolder(dockAreaOverlay, prop)); + } else { + dockAreaOverlay.setBounds(bounds); + } + } + if (!animators.isEmpty()) { + dockAreaOverlayAnimator = new AnimatorSet(); + dockAreaOverlayAnimator.playTogether(animators); dockAreaOverlayAnimator.setDuration(duration); + dockAreaOverlayAnimator.setInterpolator(interpolator); dockAreaOverlayAnimator.start(); } } } + public final int dockSide; public final int createMode; public final ViewState viewState; - private final RectF dockArea; private final RectF touchArea; + private final RectF dockArea; + private final RectF expandedTouchDockArea; /** * @param createMode used to pass to ActivityManager to dock the task * @param touchArea the area in which touch will initiate this dock state * @param dockArea the visible dock area + * @param expandedTouchDockArea the areain which touch will continue to dock after entering + * the initial touch area. This is also the new dock area to + * draw. */ - DockState(int createMode, int dockAreaAlpha, RectF touchArea, RectF dockArea) { + DockState(int dockSide, int createMode, int dockAreaAlpha, RectF touchArea, RectF dockArea, + RectF expandedTouchDockArea) { + this.dockSide = dockSide; this.createMode = createMode; this.viewState = new ViewState(dockAreaAlpha); this.dockArea = dockArea; this.touchArea = touchArea; + this.expandedTouchDockArea = expandedTouchDockArea; } /** - * Returns whether {@param x} and {@param y} are contained in the touch area scaled to the + * Returns whether {@param x} and {@param y} are contained in the area scaled to the * given {@param width} and {@param height}. */ - public boolean touchAreaContainsPoint(int width, int height, float x, float y) { - int left = (int) (touchArea.left * width); - int top = (int) (touchArea.top * height); - int right = (int) (touchArea.right * width); - int bottom = (int) (touchArea.bottom * height); + public boolean areaContainsPoint(RectF area, int width, int height, float x, float y) { + int left = (int) (area.left * width); + int top = (int) (area.top * height); + int right = (int) (area.right * width); + int bottom = (int) (area.bottom * height); return x >= left && y >= top && x <= right && y <= bottom; } /** * Returns the docked task bounds with the given {@param width} and {@param height}. */ - public Rect getDockedBounds(int width, int height) { + public Rect getPreDockedBounds(int width, int height) { return new Rect((int) (dockArea.left * width), (int) (dockArea.top * height), (int) (dockArea.right * width), (int) (dockArea.bottom * height)); } + + /** + * Returns the expanded docked task bounds with the given {@param width} and + * {@param height}. + */ + public Rect getDockedBounds(int width, int height, int dividerSize, Rect insets, + Resources res) { + // Calculate the docked task bounds + boolean isHorizontalDivision = + res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; + int position = DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision, + insets, width, height, dividerSize); + Rect newWindowBounds = new Rect(); + DockedDividerUtils.calculateBoundsForPosition(position, dockSide, newWindowBounds, + width, height, dividerSize); + return newWindowBounds; + } + + /** + * Returns the task stack bounds with the given {@param width} and + * {@param height}. + */ + public Rect getDockedTaskStackBounds(int width, int height, int dividerSize, Rect insets, + Resources res) { + RecentsConfiguration config = Recents.getConfiguration(); + + // Calculate the inverse docked task bounds + boolean isHorizontalDivision = + res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; + int position = DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision, + insets, width, height, dividerSize); + Rect newWindowBounds = new Rect(); + DockedDividerUtils.calculateBoundsForPosition(position, + DockedDividerUtils.invertDockSide(dockSide), newWindowBounds, width, height, + dividerSize); + + // Calculate the task stack bounds from the new window bounds + Rect searchBarSpaceBounds = new Rect(); + Rect taskStackBounds = new Rect(); + config.getTaskStackBounds(newWindowBounds, insets.top, insets.right, + searchBarSpaceBounds, taskStackBounds); + return taskStackBounds; + } } // A comparator that sorts tasks by their last active time @@ -446,6 +540,7 @@ public class TaskStack { mCb.onHistoryTaskRemoved(this, t); } } + mRawTaskList.remove(t); } /** diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/DropTarget.java b/packages/SystemUI/src/com/android/systemui/recents/views/DropTarget.java index 8ae00a7eae82..3ad368cbf60a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/DropTarget.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/DropTarget.java @@ -25,5 +25,5 @@ public interface DropTarget { * Returns whether this target can accept this drop. The x,y are relative to the top level * RecentsView, and the width/height are of the RecentsView. */ - boolean acceptsDrop(int x, int y, int width, int height); + boolean acceptsDrop(int x, int y, int width, int height, boolean isCurrentTarget); } 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 e28e2b383aba..d71bdbeb569f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -19,6 +19,7 @@ package com.android.systemui.recents.views; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.content.Context; +import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; @@ -63,6 +64,7 @@ import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskStack; import com.android.systemui.stackdivider.WindowManagerProxy; import com.android.systemui.statusbar.FlingAnimationUtils; +import com.android.systemui.statusbar.phone.PhoneStatusBar; import java.util.ArrayList; import java.util.Collections; @@ -76,8 +78,7 @@ import static android.app.ActivityManager.StackId.INVALID_STACK_ID; */ public class RecentsView extends FrameLayout { - private static final String TAG = "RecentsView"; - private static final boolean DEBUG = false; + private static final int DOCK_AREA_OVERLAY_TRANSITION_DURATION = 135; private final Handler mHandler; @@ -89,6 +90,7 @@ public class RecentsView extends FrameLayout { private boolean mAwaitingFirstLayout = true; private boolean mLastTaskLaunchedWasFreeform; private Rect mSystemInsets = new Rect(); + private int mDividerSize; private RecentsTransitionHelper mTransitionHelper; private RecentsViewTouchHandler mTouchHandler; @@ -118,12 +120,15 @@ public class RecentsView extends FrameLayout { public RecentsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); setWillNotDraw(false); + + SystemServicesProxy ssp = Recents.getSystemServices(); mHandler = new Handler(); mTransitionHelper = new RecentsTransitionHelper(getContext(), mHandler); mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, com.android.internal.R.interpolator.fast_out_slow_in); mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context, com.android.internal.R.interpolator.fast_out_linear_in); + mDividerSize = ssp.getDockedDividerSize(context); mTouchHandler = new RecentsViewTouchHandler(this); mFlingAnimationUtils = new FlingAnimationUtils(context, 0.3f); @@ -470,52 +475,77 @@ public class RecentsView extends FrameLayout { public final void onBusEvent(DragStartEvent event) { updateVisibleDockRegions(mTouchHandler.getDockStatesForCurrentOrientation(), - TaskStack.DockState.NONE.viewState.dockAreaAlpha); + true /* isDefaultDockState */, TaskStack.DockState.NONE.viewState.dockAreaAlpha, + true /* animateAlpha */, false /* animateBounds */); } public final void onBusEvent(DragDropTargetChangedEvent event) { if (event.dropTarget == null || !(event.dropTarget instanceof TaskStack.DockState)) { updateVisibleDockRegions(mTouchHandler.getDockStatesForCurrentOrientation(), - TaskStack.DockState.NONE.viewState.dockAreaAlpha); + true /* isDefaultDockState */, TaskStack.DockState.NONE.viewState.dockAreaAlpha, + true /* animateAlpha */, true /* animateBounds */); } else { final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget; - updateVisibleDockRegions(new TaskStack.DockState[] {dockState}, -1); + updateVisibleDockRegions(new TaskStack.DockState[] {dockState}, + false /* isDefaultDockState */, -1, true /* animateAlpha */, + true /* animateBounds */); } } public final void onBusEvent(final DragEndEvent event) { - // Animate the overlay alpha back to 0 - updateVisibleDockRegions(null, -1); - // Handle the case where we drop onto a dock region if (event.dropTarget instanceof TaskStack.DockState) { - TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget; + final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget; + + // Hide the dock region + updateVisibleDockRegions(null, false /* isDefaultDockState */, -1, + false /* animateAlpha */, false /* animateBounds */); + TaskStackLayoutAlgorithm stackLayout = mTaskStackView.getStackAlgorithm(); TaskStackViewScroller stackScroller = mTaskStackView.getScroller(); TaskViewTransform tmpTransform = new TaskViewTransform(); + // We translated the view but we need to animate it back from the current layout-space + // rect to its final layout-space rect + int x = (int) event.taskView.getTranslationX(); + int y = (int) event.taskView.getTranslationY(); + Rect taskViewRect = new Rect(event.taskView.getLeft(), event.taskView.getTop(), + event.taskView.getRight(), event.taskView.getBottom()); + taskViewRect.offset(x, y); + event.taskView.setTranslationX(0); + event.taskView.setTranslationY(0); + event.taskView.setLeftTopRightBottom(taskViewRect.left, taskViewRect.top, + taskViewRect.right, taskViewRect.bottom); + // Remove the task view after it is docked + mTaskStackView.updateLayout(false /* boundScroll */); stackLayout.getStackTransform(event.task, stackScroller.getStackScroll(), tmpTransform, null); - tmpTransform.scale = event.taskView.getScaleX(); - tmpTransform.rect.offset(event.taskView.getTranslationX(), - event.taskView.getTranslationY()); + tmpTransform.alpha = 0; + tmpTransform.scale = 1f; + tmpTransform.rect.set(taskViewRect); mTaskStackView.updateTaskViewToTransform(event.taskView, tmpTransform, - new TaskViewAnimation(150, mFastOutLinearInInterpolator, + new TaskViewAnimation(125, PhoneStatusBar.ALPHA_OUT, new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { + // Dock the task and launch it + SystemServicesProxy ssp = Recents.getSystemServices(); + ssp.startTaskInDockedMode(getContext(), event.task.key.id, + dockState.createMode); + launchTask(event.task, null, INVALID_STACK_ID); + mTaskStackView.getStack().removeTask(event.task); } })); - // Dock the task and launch it - SystemServicesProxy ssp = Recents.getSystemServices(); - ssp.startTaskInDockedMode(event.task.key.id, dockState.createMode); - launchTask(event.task, null, INVALID_STACK_ID); MetricsLogger.action(mContext, MetricsLogger.ACTION_WINDOW_DOCK_DRAG_DROP); + } else { + // Animate the overlay alpha back to 0 + updateVisibleDockRegions(null, true /* isDefaultDockState */, -1, + true /* animateAlpha */, false /* animateBounds */); } } @@ -638,7 +668,9 @@ public class RecentsView extends FrameLayout { /** * Updates the dock region to match the specified dock state. */ - private void updateVisibleDockRegions(TaskStack.DockState[] newDockStates, int overrideAlpha) { + private void updateVisibleDockRegions(TaskStack.DockState[] newDockStates, + boolean isDefaultDockState, int overrideAlpha, boolean animateAlpha, + boolean animateBounds) { ArraySet<TaskStack.DockState> newDockStatesSet = new ArraySet<>(); if (newDockStates != null) { Collections.addAll(newDockStatesSet, newDockStates); @@ -647,14 +679,21 @@ public class RecentsView extends FrameLayout { TaskStack.DockState.ViewState viewState = dockState.viewState; if (newDockStates == null || !newDockStatesSet.contains(dockState)) { // This is no longer visible, so hide it - viewState.startAlphaAnimation(0, 150); + viewState.startAnimation(null, 0, DOCK_AREA_OVERLAY_TRANSITION_DURATION, + PhoneStatusBar.ALPHA_OUT, animateAlpha, animateBounds); } else { // This state is now visible, update the bounds and show it int alpha = (overrideAlpha != -1 ? overrideAlpha : viewState.dockAreaAlpha); - viewState.dockAreaOverlay.setBounds( - dockState.getDockedBounds(getMeasuredWidth(), getMeasuredHeight())); - viewState.dockAreaOverlay.setCallback(this); - viewState.startAlphaAnimation(alpha, 150); + Rect bounds = isDefaultDockState + ? dockState.getPreDockedBounds(getMeasuredWidth(), getMeasuredHeight()) + : dockState.getDockedBounds(getMeasuredWidth(), getMeasuredHeight(), + mDividerSize, mSystemInsets, getResources()); + if (viewState.dockAreaOverlay.getCallback() != this) { + viewState.dockAreaOverlay.setCallback(this); + viewState.dockAreaOverlay.setBounds(bounds); + } + viewState.startAnimation(bounds, alpha, DOCK_AREA_OVERLAY_TRANSITION_DURATION, + PhoneStatusBar.ALPHA_IN, animateAlpha, animateBounds); } } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java index 473334b40d8d..0ca46a020999 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java @@ -19,6 +19,7 @@ package com.android.systemui.recents.views; import android.content.res.Configuration; import android.graphics.Point; import android.view.MotionEvent; +import android.view.ViewConfiguration; import com.android.systemui.recents.Recents; import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.events.EventBus; @@ -64,13 +65,16 @@ public class RecentsViewTouchHandler { private Point mTaskViewOffset = new Point(); private Point mDownPos = new Point(); - private boolean mDragging; + private boolean mDragRequested; + private boolean mIsDragging; + private float mDragSlop; private DropTarget mLastDropTarget; private ArrayList<DropTarget> mDropTargets = new ArrayList<>(); public RecentsViewTouchHandler(RecentsView rv) { mRv = rv; + mDragSlop = ViewConfiguration.get(rv.getContext()).getScaledTouchSlop(); } /** @@ -96,13 +100,13 @@ public class RecentsViewTouchHandler { /** Touch preprocessing for handling below */ public boolean onInterceptTouchEvent(MotionEvent ev) { handleTouchEvent(ev); - return mDragging; + return mDragRequested; } /** Handles touch events once we have intercepted them */ public boolean onTouchEvent(MotionEvent ev) { handleTouchEvent(ev); - return mDragging; + return mDragRequested; } /**** Events ****/ @@ -110,7 +114,9 @@ public class RecentsViewTouchHandler { public final void onBusEvent(DragStartEvent event) { SystemServicesProxy ssp = Recents.getSystemServices(); mRv.getParent().requestDisallowInterceptTouchEvent(true); - mDragging = true; + mDragRequested = true; + // We defer starting the actual drag handling until the user moves past the drag slop + mIsDragging = false; mDragTask = event.task; mTaskView = event.taskView; mDropTargets.clear(); @@ -137,7 +143,7 @@ public class RecentsViewTouchHandler { } public final void onBusEvent(DragEndEvent event) { - mDragging = false; + mDragRequested = false; mDragTask = null; mTaskView = null; mLastDropTarget = null; @@ -153,25 +159,45 @@ public class RecentsViewTouchHandler { mDownPos.set((int) ev.getX(), (int) ev.getY()); break; case MotionEvent.ACTION_MOVE: { - if (mDragging) { - int width = mRv.getMeasuredWidth(); - int height = mRv.getMeasuredHeight(); - float evX = ev.getX(); - float evY = ev.getY(); - float x = evX - mTaskViewOffset.x; - float y = evY - mTaskViewOffset.y; - - DropTarget currentDropTarget = null; - for (DropTarget target : mDropTargets) { - if (target.acceptsDrop((int) evX, (int) evY, width, height)) { - currentDropTarget = target; - break; - } + float evX = ev.getX(); + float evY = ev.getY(); + float x = evX - mTaskViewOffset.x; + float y = evY - mTaskViewOffset.y; + + if (mDragRequested) { + if (!mIsDragging) { + mIsDragging = Math.hypot(evX - mDownPos.x, evY - mDownPos.y) > mDragSlop; } - if (mLastDropTarget != currentDropTarget) { - mLastDropTarget = currentDropTarget; - EventBus.getDefault().send(new DragDropTargetChangedEvent(mDragTask, - currentDropTarget)); + if (mIsDragging) { + int width = mRv.getMeasuredWidth(); + int height = mRv.getMeasuredHeight(); + + DropTarget currentDropTarget = null; + + // Give priority to the current drop target to retain the touch handling + if (mLastDropTarget != null) { + if (mLastDropTarget.acceptsDrop((int) evX, (int) evY, width, height, + true /* isCurrentTarget */)) { + currentDropTarget = mLastDropTarget; + } + } + + // Otherwise, find the next target to handle this event + if (currentDropTarget == null) { + for (DropTarget target : mDropTargets) { + if (target.acceptsDrop((int) evX, (int) evY, width, height, + false /* isCurrentTarget */)) { + currentDropTarget = target; + break; + } + } + } + if (mLastDropTarget != currentDropTarget) { + mLastDropTarget = currentDropTarget; + EventBus.getDefault().send(new DragDropTargetChangedEvent(mDragTask, + currentDropTarget)); + } + } mTaskView.setTranslationX(x); @@ -181,7 +207,7 @@ public class RecentsViewTouchHandler { } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: { - if (mDragging) { + if (mDragRequested) { EventBus.getDefault().send(new DragEndEvent(mDragTask, mTaskView, mLastDropTarget)); break; diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java index c2bb74567599..e908e537438b 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java @@ -37,7 +37,9 @@ import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskStack; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; /** * Used to describe a visible range that can be normalized to [0, 1]. @@ -373,7 +375,7 @@ public class TaskStackLayoutAlgorithm { * Computes the minimum and maximum scroll progress values and the progress values for each task * in the stack. */ - void update(TaskStack stack) { + void update(TaskStack stack, HashSet<Task> ignoreTasksSet) { SystemServicesProxy ssp = Recents.getSystemServices(); // Clear the progress map @@ -393,6 +395,9 @@ public class TaskStackLayoutAlgorithm { ArrayList<Task> stackTasks = new ArrayList<>(); for (int i = 0; i < tasks.size(); i++) { Task task = tasks.get(i); + if (ignoreTasksSet.contains(task)) { + continue; + } if (task.isFreeformTask()) { freeformTasks.add(task); } else { 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 ceab9c73eb1b..582698cb60c7 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -28,8 +28,6 @@ import android.graphics.drawable.GradientDrawable; import android.os.Bundle; import android.os.Parcelable; import android.provider.Settings; -import android.util.IntProperty; -import android.util.Property; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -77,6 +75,7 @@ import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskStack; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -105,19 +104,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal private static final int DRAG_SCALE_DURATION = 175; private static final float DRAG_SCALE_FACTOR = 1.05f; - public static final Property<Drawable, Integer> DRAWABLE_ALPHA = - new IntProperty<Drawable>("drawableAlpha") { - @Override - public void setValue(Drawable object, int alpha) { - object.setAlpha(alpha); - } - - @Override - public Integer get(Drawable object) { - return object.getAlpha(); - } - }; - TaskStack mStack; TaskStackLayoutAlgorithm mLayoutAlgorithm; TaskStackViewScroller mStackScroller; @@ -136,6 +122,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal Task mFocusedTask; int mTaskCornerRadiusPx; + private int mDividerSize; boolean mTaskViewsClipDirty = true; boolean mAwaitingFirstLayout = true; @@ -143,10 +130,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal boolean mTouchExplorationEnabled; boolean mScreenPinningEnabled; - Rect mTaskStackBounds = new Rect(); + // The stable stack bounds are the full bounds that we were measured with from RecentsView + Rect mStableStackBounds = new Rect(); + // The current stack bounds are dynamic and may change as the user drags and drops + Rect mStackBounds = new Rect(); int[] mTmpVisibleRange = new int[2]; Rect mTmpRect = new Rect(); HashMap<Task, TaskView> mTmpTaskViewMap = new HashMap<>(); + HashSet<Task> mTmpTaskSet = new HashSet<>(); List<TaskView> mTmpTaskViews = new ArrayList<>(); TaskViewTransform mTmpTransform = new TaskViewTransform(); LayoutInflater mInflater; @@ -166,15 +157,25 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // The drop targets for a task drag private DropTarget mFreeformWorkspaceDropTarget = new DropTarget() { @Override - public boolean acceptsDrop(int x, int y, int width, int height) { - return mLayoutAlgorithm.mFreeformRect.contains(x, y); + public boolean acceptsDrop(int x, int y, int width, int height, boolean isCurrentTarget) { + // This drop target has a fixed bounds and should be checked last, so just fall through + // if it is the current target + if (!isCurrentTarget) { + return mLayoutAlgorithm.mFreeformRect.contains(x, y); + } + return false; } }; private DropTarget mStackDropTarget = new DropTarget() { @Override - public boolean acceptsDrop(int x, int y, int width, int height) { - return mLayoutAlgorithm.mStackRect.contains(x, y); + public boolean acceptsDrop(int x, int y, int width, int height, boolean isCurrentTarget) { + // This drop target has a fixed bounds and should be checked last, so just fall through + // if it is the current target + if (!isCurrentTarget) { + return mLayoutAlgorithm.mStackRect.contains(x, y); + } + return false; } }; @@ -196,6 +197,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal com.android.internal.R.interpolator.fast_out_slow_in); mTaskCornerRadiusPx = res.getDimensionPixelSize( R.dimen.recents_task_view_rounded_corners_radius); + mDividerSize = ssp.getDockedDividerSize(context); int taskBarDismissDozeDelaySeconds = getResources().getInteger( R.integer.recents_task_bar_dismiss_delay_seconds); @@ -347,9 +349,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * This call ignores freeform tasks. */ private boolean updateStackTransforms(ArrayList<TaskViewTransform> taskTransforms, - ArrayList<Task> tasks, - float stackScroll, - int[] visibleRangeOut) { + ArrayList<Task> tasks, float stackScroll, + int[] visibleRangeOut, HashSet<Task> ignoreTasksSet) { int taskTransformCount = taskTransforms.size(); int taskCount = tasks.size(); int frontMostVisibleIndex = -1; @@ -370,6 +371,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal TaskViewTransform frontTransform = null; for (int i = taskCount - 1; i >= 0; i--) { Task task = tasks.get(i); + if (ignoreTasksSet.contains(task)) { + continue; + } + TaskViewTransform transform = mLayoutAlgorithm.getStackTransform(task, stackScroll, taskTransforms.get(i), frontTransform); @@ -410,14 +415,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * they are initially picked up from the pool, when they will be placed in a suitable initial * position. */ - private void bindTaskViewsWithStack() { + private void bindTaskViewsWithStack(HashSet<Task> ignoreTasksSet) { final float stackScroll = mStackScroller.getStackScroll(); final int[] visibleStackRange = mTmpVisibleRange; // Get all the task transforms final ArrayList<Task> tasks = mStack.getStackTasks(); - final boolean isValidVisibleStackRange = updateStackTransforms(mCurrentTaskTransforms, tasks, - stackScroll, visibleStackRange); + final boolean isValidVisibleStackRange = updateStackTransforms(mCurrentTaskTransforms, + tasks, stackScroll, visibleStackRange, ignoreTasksSet); // Return all the invisible children to the pool mTmpTaskViewMap.clear(); @@ -429,6 +434,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal final Task task = tv.getTask(); final int taskIndex = mStack.indexOfStackTask(task); + // Skip ignored tasks + if (ignoreTasksSet.contains(task)) { + continue; + } + if (task.isFreeformTask() || visibleStackRange[1] <= taskIndex && taskIndex <= visibleStackRange[0]) { mTmpTaskViewMap.put(task, tv); @@ -447,6 +457,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal final Task task = tasks.get(i); final TaskViewTransform transform = mCurrentTaskTransforms.get(i); + // Skip ignored tasks + if (ignoreTasksSet.contains(task)) { + continue; + } + // Skip the invisible non-freeform stack tasks if (i > visibleStackRange[0] && !task.isFreeformTask()) { continue; @@ -496,8 +511,15 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal /** * Cancels any existing {@link TaskView} animations, and updates each {@link TaskView} to its * current position as defined by the {@link TaskStackLayoutAlgorithm}. + * + * @param ignoreTasks the set of tasks to ignore in the relayout */ - private void updateTaskViewsToLayout(TaskViewAnimation animation) { + private void updateTaskViewsToLayout(TaskViewAnimation animation, Task... ignoreTasks) { + // Keep track of the ignore tasks + HashSet<Task> ignoreTasksSet = mTmpTaskSet; + ignoreTasksSet.clear(); + Collections.addAll(ignoreTasksSet, ignoreTasks); + // If we had a deferred animation, cancel that mDeferredTaskViewUpdateAnimation = null; @@ -505,7 +527,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal cancelAllTaskViewAnimations(); // Fetch the current set of TaskViews - bindTaskViewsWithStack(); + bindTaskViewsWithStack(ignoreTasksSet); // Animate them to their final transforms with the given animation List<TaskView> taskViews = getTaskViews(); @@ -515,6 +537,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal final int taskIndex = mStack.indexOfStackTask(tv.getTask()); final TaskViewTransform transform = mCurrentTaskTransforms.get(taskIndex); + if (ignoreTasksSet.contains(tv.getTask())) { + continue; + } + updateTaskViewToTransform(tv, transform, animation); } } @@ -542,8 +568,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal */ private void cancelAllTaskViewAnimations() { List<TaskView> taskViews = getTaskViews(); - int taskViewCount = taskViews.size(); - for (int i = 0; i < taskViewCount; i++) { + for (int i = taskViews.size() - 1; i >= 0; i--) { final TaskView tv = taskViews.get(i); tv.cancelTransformAnimation(); } @@ -594,10 +619,19 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal mTaskViewsClipDirty = false; } - /** Updates the min and max virtual scroll bounds */ - void updateLayout(boolean boundScrollToNewMinMax) { + /** + * Updates the min and max virtual scroll bounds. + * + * @param ignoreTasks the set of tasks to ignore in the relayout + */ + void updateLayout(boolean boundScrollToNewMinMax, Task... ignoreTasks) { + // Keep track of the ingore tasks + HashSet<Task> ignoreTasksSet = mTmpTaskSet; + ignoreTasksSet.clear(); + Collections.addAll(ignoreTasksSet, ignoreTasks); + // Compute the min and max scroll values - mLayoutAlgorithm.update(mStack); + mLayoutAlgorithm.update(mStack, ignoreTasksSet); // Update the freeform workspace SystemServicesProxy ssp = Recents.getSystemServices(); @@ -918,14 +952,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } } - /** Computes the stack and task rects */ - public void computeRects(Rect taskStackBounds) { + /** + * Computes the stack and task rects. + * + * @param ignoreTasks the set of tasks to ignore in the relayout + */ + public void computeRects(Rect taskStackBounds, boolean boundScroll, Task... ignoreTasks) { // Compute the rects in the stack algorithm mLayoutAlgorithm.initialize(taskStackBounds, TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack)); // Update the scroll bounds - updateLayout(false); + updateLayout(boundScroll, ignoreTasks); } /** @@ -945,9 +983,19 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal return mLayoutAlgorithm.computeStackVisibilityReport(mStack.getStackTasks()); } + /** + * Updates the expected task stack bounds for this stack view. + */ public void setTaskStackBounds(Rect taskStackBounds, Rect systemInsets) { - mTaskStackBounds.set(taskStackBounds); + // We can get spurious measure passes with the old bounds when docking, and since we are + // using the current stack bounds during drag and drop, don't overwrite them until we + // actually get new bounds + if (!taskStackBounds.equals(mStableStackBounds)) { + mStableStackBounds.set(taskStackBounds); + mStackBounds.set(taskStackBounds); + } mLayoutAlgorithm.setSystemInsets(systemInsets); + requestLayout(); } /** @@ -960,14 +1008,15 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal int height = MeasureSpec.getSize(heightMeasureSpec); // Compute our stack/task rects - computeRects(mTaskStackBounds); + computeRects(mStackBounds, false); // If this is the first layout, then scroll to the front of the stack, then update the // TaskViews with the stack so that we can lay them out if (mAwaitingFirstLayout) { mStackScroller.setStackScrollToInitialState(); } - bindTaskViewsWithStack(); + mTmpTaskSet.clear(); + bindTaskViewsWithStack(mTmpTaskSet); // Measure each of the TaskViews mTmpTaskViews.clear(); @@ -1407,6 +1456,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal mLayoutAlgorithm.getStackTransform(event.task, getScroller().getStackScroll(), mTmpTransform, null); mTmpTransform.scale = finalScale; + mTmpTransform.translationZ = mLayoutAlgorithm.mMaxTranslationZ + 1; updateTaskViewToTransform(event.taskView, mTmpTransform, new TaskViewAnimation(DRAG_SCALE_DURATION, mFastOutSlowInInterpolator)); } @@ -1420,7 +1470,23 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } public final void onBusEvent(DragDropTargetChangedEvent event) { - // TODO: Animate the freeform workspace background etc. + if (event.dropTarget instanceof TaskStack.DockState) { + // Calculate the new task stack bounds that matches the window size that Recents will + // have after the drop + final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget; + mStackBounds.set(dockState.getDockedTaskStackBounds(getMeasuredWidth(), + getMeasuredHeight(), mDividerSize, mLayoutAlgorithm.mSystemInsets, + getResources())); + computeRects(mStackBounds, true /* boundScroll */, event.task /* ignoreTask */); + updateTaskViewsToLayout(new TaskViewAnimation(250, mFastOutSlowInInterpolator), + event.task /* ignoreTask */); + } else { + // Restore the pre-drag task stack bounds + mStackBounds.set(mStableStackBounds); + computeRects(mStackBounds, true /* boundScroll */); + updateTaskViewsToLayout(new TaskViewAnimation(250, mFastOutSlowInInterpolator), + event.task /* ignoreTask */); + } } public final void onBusEvent(final DragEndEvent event) { @@ -1564,7 +1630,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal Utilities.cancelAnimationWithoutCallbacks(mFreeformWorkspaceBackgroundAnimator); mFreeformWorkspaceBackgroundAnimator = ObjectAnimator.ofInt(mFreeformWorkspaceBackground, - DRAWABLE_ALPHA, mFreeformWorkspaceBackground.getAlpha(), targetAlpha); + Utilities.DRAWABLE_ALPHA, mFreeformWorkspaceBackground.getAlpha(), targetAlpha); mFreeformWorkspaceBackgroundAnimator.setDuration(duration); mFreeformWorkspaceBackgroundAnimator.setInterpolator(interpolator); mFreeformWorkspaceBackgroundAnimator.start(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java index 00d64feb451e..96dadff7b077 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java @@ -136,6 +136,10 @@ public class TaskViewHeader extends FrameLayout float mDimAlpha; Drawable mLightDismissDrawable; Drawable mDarkDismissDrawable; + Drawable mLightFreeformIcon; + Drawable mDarkFreeformIcon; + Drawable mLightFullscreenIcon; + Drawable mDarkFullscreenIcon; int mTaskBarViewLightTextColor; int mTaskBarViewDarkTextColor; String mDismissContentDescription; @@ -179,6 +183,11 @@ public class TaskViewHeader extends FrameLayout mHighlightHeight = res.getDimensionPixelSize(R.dimen.recents_task_view_highlight); mTaskBarViewLightTextColor = context.getColor(R.color.recents_task_bar_light_text_color); mTaskBarViewDarkTextColor = context.getColor(R.color.recents_task_bar_dark_text_color); + mLightFreeformIcon = context.getDrawable(R.drawable.recents_move_task_freeform_light); + mDarkFreeformIcon = context.getDrawable(R.drawable.recents_move_task_freeform_dark); + mLightFullscreenIcon = context.getDrawable(R.drawable.recents_move_task_fullscreen_light); + mDarkFullscreenIcon = context.getDrawable(R.drawable.recents_move_task_fullscreen_dark); + mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, com.android.internal.R.interpolator.fast_out_slow_in); mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context, @@ -223,7 +232,9 @@ public class TaskViewHeader extends FrameLayout mTaskViewRect.set(0, 0, width, height); boolean updateMoveTaskButton = mMoveTaskButton.getVisibility() != View.GONE; int appIconWidth = mIconView.getMeasuredWidth(); - int activityDescWidth = mTitleView.getMeasuredWidth(); + int activityDescWidth = (mTask != null) + ? (int) mTitleView.getPaint().measureText(mTask.title) + : mTitleView.getMeasuredWidth(); int dismissIconWidth = mDismissButton.getMeasuredWidth(); int moveTaskIconWidth = mMoveTaskButton.getVisibility() == View.VISIBLE ? mMoveTaskButton.getMeasuredWidth() @@ -360,14 +371,14 @@ public class TaskViewHeader extends FrameLayout if (ssp.hasFreeformWorkspaceSupport()) { if (t.isFreeformTask()) { mMoveTaskTargetStackId = FULLSCREEN_WORKSPACE_STACK_ID; - mMoveTaskButton.setImageResource(t.useLightOnPrimaryColor - ? R.drawable.recents_move_task_fullscreen_light - : R.drawable.recents_move_task_fullscreen_dark); + mMoveTaskButton.setImageDrawable(t.useLightOnPrimaryColor + ? mLightFullscreenIcon + : mDarkFullscreenIcon); } else { mMoveTaskTargetStackId = FREEFORM_WORKSPACE_STACK_ID; - mMoveTaskButton.setImageResource(t.useLightOnPrimaryColor - ? R.drawable.recents_move_task_freeform_light - : R.drawable.recents_move_task_freeform_dark); + mMoveTaskButton.setImageDrawable(t.useLightOnPrimaryColor + ? mLightFreeformIcon + : mDarkFreeformIcon); } if (mMoveTaskButton.getVisibility() != View.VISIBLE) { mMoveTaskButton.setVisibility(View.VISIBLE); diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 824d10a3aa19..c16703e86a10 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -363,21 +363,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, return mStartPosition + touchY - mStartY; } - private int invertDockSide(int dockSide) { - switch (dockSide) { - case WindowManager.DOCKED_LEFT: - return WindowManager.DOCKED_RIGHT; - case WindowManager.DOCKED_TOP: - return WindowManager.DOCKED_BOTTOM; - case WindowManager.DOCKED_RIGHT: - return WindowManager.DOCKED_LEFT; - case WindowManager.DOCKED_BOTTOM: - return WindowManager.DOCKED_TOP; - default: - return WindowManager.DOCKED_INVALID; - } - } - private void alignTopLeft(Rect containingRect, Rect rect) { int width = rect.width(); int height = rect.height(); @@ -409,8 +394,9 @@ public class DividerView extends FrameLayout implements OnTouchListener, mLastResizeRect.set(mDockedRect); if (taskPosition != TASK_POSITION_SAME) { - calculateBoundsForPosition(position, invertDockSide(mDockSide), mOtherRect); - int dockSideInverted = invertDockSide(mDockSide); + calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide), + mOtherRect); + int dockSideInverted = DockedDividerUtils.invertDockSide(mDockSide); int taskPositionDocked = restrictDismissingTaskPosition(taskPosition, mDockSide, taskSnapTarget); int taskPositionOther = |