diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
index 67e13eb7af960..fbbd7e5f76509 100644
--- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
@@ -143,8 +143,13 @@
@@ -269,8 +274,13 @@
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index d41040d13f2e7..33b5dbb7b52e8 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -147,8 +147,13 @@
@@ -276,9 +281,14 @@
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 48fb21f76dffb..047570f088987 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -35,5 +35,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1cd7904d0ffd7..333757333d9af 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -72,5 +72,9 @@
90
+
+
+ 333
+ 333
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 94465e2f38907..0d7cdb1656508 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -63,6 +63,8 @@
12dp
+
+ 32dp
@*android:dimen/status_bar_icon_size
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 33973b6ec7c2f..dcc2e570aa72e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -45,13 +45,12 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.R;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.DelegateViewHelper;
+import com.android.systemui.statusbar.policy.DeadZone;
public class NavigationBarView extends LinearLayout {
final static boolean DEBUG = false;
final static String TAG = "PhoneStatusBar/NavigationBarView";
- final static boolean DEBUG_DEADZONE = false;
-
final static boolean NAVBAR_ALWAYS_AT_RIGHT = true;
final static boolean ANIMATE_HIDE_TRANSITION = false; // turned off because it introduces unsightly delay when videos goes to full screen
@@ -71,6 +70,7 @@ public class NavigationBarView extends LinearLayout {
private Drawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
private DelegateViewHelper mDelegateHelper;
+ private DeadZone mDeadZone;
// workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288)
final static boolean WORKAROUND_INVALID_LAYOUT = true;
@@ -109,10 +109,14 @@ public class NavigationBarView extends LinearLayout {
@Override
public boolean onTouchEvent(MotionEvent event) {
- if (mDelegateHelper != null) {
- mDelegateHelper.onInterceptTouchEvent(event);
+ if (mDeadZone != null && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
+ mDeadZone.poke(event);
}
- return true;
+ if (mDelegateHelper != null) {
+ boolean ret = mDelegateHelper.onInterceptTouchEvent(event);
+ if (ret) return true;
+ }
+ return super.onTouchEvent(event);
}
@Override
@@ -335,15 +339,13 @@ public class NavigationBarView extends LinearLayout {
mCurrentView = mRotatedViews[rot];
mCurrentView.setVisibility(View.VISIBLE);
+ mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
+
// force the low profile & disabled states into compliance
setLowProfile(mLowProfile, false, true /* force */);
setDisabledFlags(mDisabledFlags, true /* force */);
setMenuVisibility(mShowMenu, true /* force */);
- if (DEBUG_DEADZONE) {
- mCurrentView.findViewById(R.id.deadzone).setBackgroundColor(0x808080FF);
- }
-
if (DEBUG) {
Slog.d(TAG, "reorient(): rot=" + mDisplay.getRotation());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 9d2678a7b1cb3..9b4ee38f9e381 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -639,6 +639,7 @@ public class PhoneStatusBar extends BaseStatusBar {
| WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
PixelFormat.OPAQUE);
// this will allow the navbar to run in an overlay on devices that support this
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
index 19fbe9636c0d5..6ffca2a9f0ad3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
@@ -16,26 +16,145 @@
package com.android.systemui.statusbar.policy;
+import android.animation.ObjectAnimator;
import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.os.SystemClock;
import android.util.AttributeSet;
+import android.util.Slog;
import android.view.MotionEvent;
import android.view.View;
import com.android.systemui.R;
public class DeadZone extends View {
+ public static final String TAG = "DeadZone";
+
+ public static final boolean DEBUG = false;
+ public static final int HORIZONTAL = 0;
+ public static final int VERTICAL = 1;
+
+ private boolean mShouldFlash;
+ private float mFlashFrac = 0f;
+
+ private int mSizeMax;
+ private int mSizeMin;
+ // Upon activity elsewhere in the UI, the dead zone will hold steady for
+ // mHold ms, then move back over the course of mDecay ms
+ private int mHold, mDecay;
+ private boolean mVertical;
+ private long mLastPokeTime;
+
+ private final Runnable mDebugFlash = new Runnable() {
+ @Override
+ public void run() {
+ ObjectAnimator.ofFloat(DeadZone.this, "flash", 1f, 0f).setDuration(150).start();
+ }
+ };
+
public DeadZone(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DeadZone(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DeadZone,
+ defStyle, 0);
+
+ mHold = a.getInteger(R.styleable.DeadZone_holdTime, 0);
+ mDecay = a.getInteger(R.styleable.DeadZone_decayTime, 0);
+
+ mSizeMin = a.getDimensionPixelSize(R.styleable.DeadZone_minSize, 0);
+ mSizeMax = a.getDimensionPixelSize(R.styleable.DeadZone_maxSize, 0);
+
+ int index = a.getInt(R.styleable.DeadZone_orientation, -1);
+ mVertical = (index == VERTICAL);
+
+ if (DEBUG)
+ Slog.v(TAG, this + " size=[" + mSizeMin + "-" + mSizeMax + "] hold=" + mHold
+ + (mVertical ? " vertical" : " horizontal"));
+
+ setFlashOnTouchCapture(true);
+ }
+
+ static float lerp(float a, float b, float f) {
+ return (b - a) * f + a;
+ }
+
+ private float getSize(long now) {
+ if (mSizeMax == 0)
+ return 0;
+ long dt = (now - mLastPokeTime);
+ if (dt > mHold + mDecay)
+ return mSizeMin;
+ if (dt < mHold)
+ return mSizeMax;
+ return (int) lerp(mSizeMax, mSizeMin, (float) (dt - mHold) / mDecay);
+ }
+
+ public void setFlashOnTouchCapture(boolean dbg) {
+ mShouldFlash = dbg;
+ mFlashFrac = 0f;
+ postInvalidate();
}
// I made you a touch event
@Override
- public boolean onTouchEvent (MotionEvent event) {
- return true; // but I eated it
+ public boolean onTouchEvent(MotionEvent event) {
+ if (DEBUG)
+ Slog.v(TAG, this + " onTouch: " + MotionEvent.actionToString(event.getAction()));
+
+ final int action = event.getAction();
+ if (action == MotionEvent.ACTION_OUTSIDE) {
+ poke(event);
+ } else if (action == MotionEvent.ACTION_DOWN) {
+ if (DEBUG)
+ Slog.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY());
+ int size = (int) getSize(event.getEventTime());
+ if ((mVertical && event.getX() < size) || event.getY() < size) {
+ if (DEBUG)
+ Slog.v(TAG, "eating click!");
+ if (mShouldFlash) {
+ post(mDebugFlash);
+ postInvalidate();
+ }
+ return true; // but I eated it
+ }
+ }
+ return false;
+ }
+
+ public void poke(MotionEvent event) {
+ mLastPokeTime = event.getEventTime();
+ if (DEBUG)
+ Slog.v(TAG, "poked! size=" + getSize(mLastPokeTime));
+ postInvalidate();
+ }
+
+ public void setFlash(float f) {
+ mFlashFrac = f;
+ postInvalidate();
+ }
+
+ public float getFlash() {
+ return mFlashFrac;
+ }
+
+ @Override
+ public void onDraw(Canvas can) {
+ if (!mShouldFlash || mFlashFrac <= 0f) {
+ return;
+ }
+
+ final int size = (int) getSize(SystemClock.uptimeMillis());
+ can.clipRect(0, 0, mVertical ? size : can.getWidth(), mVertical ? can.getHeight() : size);
+ final float frac = DEBUG ? (mFlashFrac - 0.5f) + 0.5f : mFlashFrac;
+ can.drawARGB((int) (frac * 0xFF), 0xDD, 0xEE, 0xAA);
+
+ if (DEBUG && size > mSizeMin)
+ // crazy aggressive redrawing here, for debugging only
+ postInvalidateDelayed(100);
}
}
-