Fix issue #3222014: Dragging items around home screen is unresponsive
Also make the dim fade duration configurable, with a configured value
that more closely matches what UX wants.
Change-Id: Id32e2de14a2a2003d8fade6331377d8d723ac397
diff --git a/api/current.xml b/api/current.xml
index 2d190b5..403e3d0 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -12904,6 +12904,23 @@
>
</field>
</class>
+<class name="R.fraction"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="R.fraction"
+ type="android.R.fraction"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+</class>
<class name="R.id"
extends="java.lang.Object"
abstract="false"
@@ -248607,7 +248624,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
</parameter>
</method>
</interface>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4f077b6..642a588 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -70,6 +70,12 @@
<integer name="config_activityShortDur">150</integer>
<integer name="config_activityDefaultDur">220</integer>
+ <!-- Duration for the dim animation behind a dialog. This may be either
+ a percentage, which is relative to the duration of the enter/open
+ animation of the window being shown that is dimming behind, or it may
+ be an integer for a constant duration. -->
+ <fraction name="config_dimBehindFadeDuration">100%</fraction>
+
<!-- The duration (in milliseconds) that the radio will scan for a signal
when there's no network connection. If the scan doesn't timeout, use zero -->
<integer name="config_radioScanningTimeout">0</integer>
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index a91574e..b3ea836 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -59,6 +59,7 @@
import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
@@ -200,10 +201,6 @@
*/
static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
- /** Adjustment to time to perform a dim, to make it more dramatic.
- */
- static final int DIM_DURATION_MULTIPLIER = 6;
-
// Maximum number of milliseconds to wait for input event injection.
// FIXME is this value reasonable?
private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
@@ -6627,6 +6624,7 @@
final Rect mContainingFrame = new Rect();
final Rect mDisplayFrame = new Rect();
final Rect mContentFrame = new Rect();
+ final Rect mParentFrame = new Rect();
final Rect mVisibleFrame = new Rect();
boolean mContentChanged;
@@ -6832,8 +6830,12 @@
h = mAttrs.height== mAttrs.MATCH_PARENT ? ph : mRequestedHeight;
}
+ if (!mParentFrame.equals(pf)) {
+ mParentFrame.set(pf);
+ mContentChanged = true;
+ }
+
final Rect content = mContentFrame;
- mContentChanged |= !content.equals(cf);
content.set(cf);
final Rect visible = mVisibleFrame;
@@ -7699,6 +7701,21 @@
&& !mDrawPending && !mCommitDrawPending;
}
+ /**
+ * Return whether this window is wanting to have a translation
+ * animation applied to it for an in-progress move. (Only makes
+ * sense to call from performLayoutAndPlaceSurfacesLockedInner().)
+ */
+ boolean shouldAnimateMove() {
+ return mContentChanged && !mAnimating && !mLastHidden && !mDisplayFrozen
+ && (mFrame.top != mLastFrame.top
+ || mFrame.left != mLastFrame.left)
+ && (mAttachedWindow == null
+ || (mAttachedWindow.mAnimation == null
+ && !mAttachedWindow.shouldAnimateMove()))
+ && mPolicy.isScreenOn();
+ }
+
boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
return
// only if the application is requesting compatible window
@@ -7925,6 +7942,8 @@
pw.println();
pw.print(prefix); pw.print("mContainingFrame=");
mContainingFrame.printShortString(pw);
+ pw.print(" mParentFrame=");
+ mParentFrame.printShortString(pw);
pw.print(" mDisplayFrame=");
mDisplayFrame.printShortString(pw);
pw.println();
@@ -9157,11 +9176,11 @@
|| win.mAttachedHidden
|| win.mExiting || win.mDestroying;
- if (!win.mLayoutAttached) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "First pass " + win
+ if (DEBUG_LAYOUT && !win.mLayoutAttached) {
+ Slog.v(TAG, "First pass " + win
+ ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
+ " mLayoutAttached=" + win.mLayoutAttached);
- if (DEBUG_LAYOUT && gone) Slog.v(TAG, " (mViewVisibility="
+ if (gone) Slog.v(TAG, " (mViewVisibility="
+ win.mViewVisibility + " mRelayoutCalled="
+ win.mRelayoutCalled + " hidden="
+ win.mRootToken.hidden + " hiddenRequested="
@@ -9198,16 +9217,16 @@
for (i = topAttached; i >= 0; i--) {
WindowState win = mWindows.get(i);
- // If this view is GONE, then skip it -- keep the current
- // frame, and let the caller know so they can ignore it
- // if they want. (We do the normal layout for INVISIBLE
- // windows, since that means "perform layout as normal,
- // just don't display").
if (win.mLayoutAttached) {
if (DEBUG_LAYOUT) Slog.v(TAG, "Second pass " + win
+ " mHaveFrame=" + win.mHaveFrame
+ " mViewVisibility=" + win.mViewVisibility
+ " mRelayoutCalled=" + win.mRelayoutCalled);
+ // If this view is GONE, then skip it -- keep the current
+ // frame, and let the caller know so they can ignore it
+ // if they want. (We do the normal layout for INVISIBLE
+ // windows, since that means "perform layout as normal,
+ // just don't display").
if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
|| !win.mHaveFrame) {
if (initial) {
@@ -9390,10 +9409,7 @@
// content frame changing, then we'd like to animate
// it. The checks here are ordered by what is least
// likely to be true first.
- if (w.mContentChanged && !wasAnimating && !w.mLastHidden && !mDisplayFrozen
- && (w.mFrame.top != w.mLastFrame.top
- || w.mFrame.left != w.mLastFrame.left)
- && mPolicy.isScreenOn()) {
+ if (w.shouldAnimateMove()) {
// Frame has moved, containing content frame
// has also moved, and we're not currently animating...
// let's do something.
@@ -9402,6 +9418,7 @@
w.setAnimation(a);
animDw = w.mLastFrame.left - w.mFrame.left;
animDh = w.mLastFrame.top - w.mFrame.top;
+ w.mContentChanged = false;
}
// Execute animation.
@@ -10265,7 +10282,8 @@
mDimAnimator = new DimAnimator(mFxSession);
}
mDimAnimator.show(dw, dh);
- mDimAnimator.updateParameters(w, currentTime);
+ mDimAnimator.updateParameters(mContext.getResources(),
+ w, currentTime);
}
}
if ((attrFlags&FLAG_BLUR_BEHIND) != 0) {
@@ -11327,7 +11345,7 @@
* Set's the dim surface's layer and update dim parameters that will be used in
* {@link updateSurface} after all windows are examined.
*/
- void updateParameters(WindowState w, long currentTime) {
+ void updateParameters(Resources res, WindowState w, long currentTime) {
mDimSurface.setLayer(w.mAnimLayer-1);
final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
@@ -11341,11 +11359,15 @@
? w.mAnimation.computeDurationHint()
: DEFAULT_DIM_DURATION;
if (target > mDimTargetAlpha) {
- // This is happening behind the activity UI,
- // so we can make it run a little longer to
- // give a stronger impression without disrupting
- // the user.
- duration *= DIM_DURATION_MULTIPLIER;
+ TypedValue tv = new TypedValue();
+ res.getValue(com.android.internal.R.fraction.config_dimBehindFadeDuration,
+ tv, true);
+ if (tv.type == TypedValue.TYPE_FRACTION) {
+ duration = (long)tv.getFraction((float)duration, (float)duration);
+ } else if (tv.type >= TypedValue.TYPE_FIRST_INT
+ && tv.type <= TypedValue.TYPE_LAST_INT) {
+ duration = tv.data;
+ }
}
if (duration < 1) {
// Don't divide by zero