Merge "Fix 6547012: ignore events outside the home/back/recent navigation area" into jb-dev

This commit is contained in:
Jim Miller
2012-05-24 17:51:10 -07:00
committed by Android (Google) Code Review
5 changed files with 113 additions and 59 deletions

View File

@@ -476,19 +476,12 @@ public class MultiWaveView extends View {
/**
* Dispatches a trigger event to listener. Ignored if a listener is not set.
* @param whichHandle the handle that triggered the event.
* @param whichTarget the target that was triggered.
*/
private void dispatchTriggerEvent(int whichHandle) {
private void dispatchTriggerEvent(int whichTarget) {
vibrate();
if (mOnTriggerListener != null) {
mOnTriggerListener.onTrigger(this, whichHandle);
}
}
private void dispatchGrabbedEvent(int whichHandler) {
vibrate();
if (mOnTriggerListener != null) {
mOnTriggerListener.onGrabbed(this, whichHandler);
mOnTriggerListener.onTrigger(this, whichTarget);
}
}
@@ -514,7 +507,7 @@ public class MultiWaveView extends View {
// Inform listener of any active targets. Typically only one will be active.
if (DEBUG) Log.v(TAG, "Finish with target hit = " + targetHit);
dispatchTriggerEvent(mActiveTarget);
dispatchTriggerEvent(activeTarget);
}
// Animate handle back to the center based on current state.
@@ -791,7 +784,7 @@ public class MultiWaveView extends View {
}
private void handleDown(MotionEvent event) {
if (!trySwitchToFirstTouchState(event.getX(), event.getY())) {
if (!trySwitchToFirstTouchState(event.getX(), event.getY())) {
mDragging = false;
mTargetAnimations.cancel();
ping();
@@ -903,7 +896,6 @@ public class MultiWaveView extends View {
if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
target.setState(TargetDrawable.STATE_FOCUSED);
}
dispatchGrabbedEvent(activeTarget);
if (AccessibilityManager.getInstance(mContext).isEnabled()) {
String targetContentDescription = getTargetDescription(activeTarget);
announceText(targetContentDescription);
@@ -950,7 +942,7 @@ public class MultiWaveView extends View {
} else {
mOnTriggerListener.onGrabbed(this, OnTriggerListener.CENTER_HANDLE);
}
mOnTriggerListener.onGrabbedStateChange(this, mGrabbedState);
mOnTriggerListener.onGrabbedStateChange(this, newState);
}
}
}

View File

@@ -129,7 +129,7 @@ public class SearchPanelView extends FrameLayout implements
}
public void onGrabbedStateChange(View v, int handle) {
if (OnTriggerListener.NO_HANDLE == handle) {
if (mTarget == -1 && OnTriggerListener.NO_HANDLE == handle) {
mBar.hideSearchPanel();
}
}
@@ -147,8 +147,8 @@ public class SearchPanelView extends FrameLayout implements
startAssistActivity();
break;
}
mBar.hideSearchPanel();
}
mBar.hideSearchPanel();
}
};

View File

@@ -16,9 +16,8 @@
package com.android.systemui.statusbar;
import android.util.Slog;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import com.android.systemui.R;
@@ -29,8 +28,12 @@ public class DelegateViewHelper {
private BaseStatusBar mBar;
private int[] mTempPoint = new int[2];
private float[] mDownPoint = new float[2];
private int mOrientation;
private float mTriggerThreshhold;
private boolean mPanelShowing;
RectF mInitialTouch = new RectF();
private boolean mStarted;
private boolean mSwapXY = false;
public DelegateViewHelper(View sourceView) {
setSourceView(sourceView);
@@ -44,49 +47,53 @@ public class DelegateViewHelper {
mBar = phoneStatusBar;
}
public void setOrientation(int orientation) {
mOrientation = orientation;
}
public boolean onInterceptTouchEvent(MotionEvent event) {
if (mBar.shouldDisableNavbarGestures()) {
if (mSourceView == null || mDelegateView == null || mBar.shouldDisableNavbarGestures()) {
return false;
}
mSourceView.getLocationOnScreen(mTempPoint);
final float sourceX = mTempPoint[0];
final float sourceY = mTempPoint[1];
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mPanelShowing = mDelegateView.getVisibility() == View.VISIBLE;
mDownPoint[0] = event.getX();
mDownPoint[1] = event.getY();
mStarted = mInitialTouch.contains(mDownPoint[0] + sourceX, mDownPoint[1] + sourceY);
break;
}
if (mDelegateView != null) {
if (mDelegateView.getVisibility() != View.VISIBLE
&& event.getAction() != MotionEvent.ACTION_CANCEL) {
final boolean isVertical = (mOrientation == Surface.ROTATION_90
|| mOrientation == Surface.ROTATION_270);
final int historySize = event.getHistorySize();
for (int k = 0; k < historySize + 1; k++) {
float x = k < historySize ? event.getHistoricalX(k) : event.getX();
float y = k < historySize ? event.getHistoricalY(k) : event.getY();
final float distance = isVertical ? (mDownPoint[0] - x) : (mDownPoint[1] - y);
if (distance > mTriggerThreshhold) {
mBar.showSearchPanel();
break;
}
if (!mStarted) {
return false;
}
if (!mPanelShowing && event.getAction() == MotionEvent.ACTION_MOVE) {
final int historySize = event.getHistorySize();
for (int k = 0; k < historySize + 1; k++) {
float x = k < historySize ? event.getHistoricalX(k) : event.getX();
float y = k < historySize ? event.getHistoricalY(k) : event.getY();
final float distance = mSwapXY ? (mDownPoint[0] - x) : (mDownPoint[1] - y);
if (distance > mTriggerThreshhold) {
mBar.showSearchPanel();
mPanelShowing = true;
break;
}
}
mSourceView.getLocationOnScreen(mTempPoint);
float deltaX = mTempPoint[0];
float deltaY = mTempPoint[1];
mDelegateView.getLocationOnScreen(mTempPoint);
deltaX -= mTempPoint[0];
deltaY -= mTempPoint[1];
event.offsetLocation(deltaX, deltaY);
mDelegateView.dispatchTouchEvent(event);
event.offsetLocation(-deltaX, -deltaY);
}
return false;
mDelegateView.getLocationOnScreen(mTempPoint);
final float delegateX = mTempPoint[0];
final float delegateY = mTempPoint[1];
float deltaX = sourceX - delegateX;
float deltaY = sourceY - delegateY;
event.offsetLocation(deltaX, deltaY);
mDelegateView.dispatchTouchEvent(event);
event.offsetLocation(-deltaX, -deltaY);
return mPanelShowing;
}
public void setSourceView(View view) {
@@ -96,4 +103,35 @@ public class DelegateViewHelper {
.getDimension(R.dimen.navbar_search_up_threshhold);
}
}
/**
* Selects the initial touch region based on a list of views. This is meant to be called by
* a container widget on children over which the initial touch should be detected. Note this
* will compute a minimum bound that contains all specified views.
*
* @param views
*/
public void setInitialTouchRegion(View ... views) {
RectF bounds = new RectF();
int p[] = new int[2];
for (int i = 0; i < views.length; i++) {
View view = views[i];
if (view == null) continue;
view.getLocationOnScreen(p);
if (i == 0) {
bounds.set(p[0], p[1], p[0] + view.getWidth(), p[1] + view.getHeight());
} else {
bounds.union(p[0], p[1], p[0] + view.getWidth(), p[1] + view.getHeight());
}
}
mInitialTouch.set(bounds);
}
/**
* When rotation is set to NO_SENSOR, then this allows swapping x/y for gesture detection
* @param swap
*/
public void setSwapXY(boolean swap) {
mSwapXY = swap;
}
}

View File

@@ -23,6 +23,7 @@ import android.app.StatusBarManager;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
@@ -112,6 +113,14 @@ public class NavigationBarView extends LinearLayout {
mDelegateHelper.setBar(phoneStatusBar);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mDelegateHelper != null) {
mDelegateHelper.onInterceptTouchEvent(event);
}
return true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
return mDelegateHelper.onInterceptTouchEvent(event);
@@ -292,6 +301,7 @@ public class NavigationBarView extends LinearLayout {
setLowProfile(false);
}
@Override
public void onFinishInflate() {
mRotatedViews[Surface.ROTATION_0] =
mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
@@ -329,6 +339,12 @@ public class NavigationBarView extends LinearLayout {
setNavigationIconHints(mNavigationIconHints, true);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mDelegateHelper.setInitialTouchRegion(getHomeButton(), getBackButton(), getRecentsButton());
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (DEBUG) Slog.d(TAG, String.format(

View File

@@ -55,17 +55,25 @@ public class TabletStatusBarView extends FrameLayout {
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
public boolean onTouchEvent(MotionEvent event) {
if (mDelegateHelper != null) {
mDelegateHelper.onInterceptTouchEvent(event);
}
return true;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
// Find the view we wish to grab events from in order to detect search gesture.
// Depending on the device, this will be one of the id's listed below.
// If we don't find one, we'll use the view provided in the constructor above (this view).
View view = null;
if ((view = findViewById(R.id.navigationArea)) != null) {
mDelegateHelper.setSourceView(view);
} else if ((view = findViewById(R.id.nav_buttons)) != null) {
mDelegateHelper.setSourceView(view);
View view = findViewById(R.id.navigationArea);
if (view == null) {
view = findViewById(R.id.nav_buttons);
}
mDelegateHelper.setSourceView(view);
mDelegateHelper.setInitialTouchRegion(view);
}
@Override
@@ -100,8 +108,8 @@ public class TabletStatusBarView extends FrameLayout {
if (TabletStatusBar.DEBUG) {
Slog.d(TabletStatusBar.TAG, "TabletStatusBarView not intercepting event");
}
if (mDelegateHelper != null) {
return mDelegateHelper.onInterceptTouchEvent(ev);
if (mDelegateHelper != null && mDelegateHelper.onInterceptTouchEvent(ev)) {
return true;
}
return super.onInterceptTouchEvent(ev);
}