diff options
9 files changed, 142 insertions, 67 deletions
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index ba42ff5181bd..1164649a3f5e 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -669,7 +669,7 @@ public final class WebViewCore { int x, int y); private native boolean nativeMouseClick(int nativeClass); - private native boolean nativeHandleTouchEvent(int nativeClass, int action, + private native int nativeHandleTouchEvent(int nativeClass, int action, int[] idArray, int[] xArray, int[] yArray, int count, int actionIndex, int metaState); @@ -968,6 +968,9 @@ public final class WebViewCore { static final int ACTION_LONGPRESS = 0x100; static final int ACTION_DOUBLETAP = 0x200; + private static final int TOUCH_FLAG_HIT_HANDLER = 0x1; + private static final int TOUCH_FLAG_PREVENT_DEFAULT = 0x2; + static class TouchEventData { int mAction; int[] mIds; // Ids of the touch points @@ -1784,7 +1787,8 @@ public final class WebViewCore { } @Override - public boolean dispatchWebKitEvent(MotionEvent event, int eventType, int flags) { + public boolean dispatchWebKitEvent(WebViewInputDispatcher dispatcher, + MotionEvent event, int eventType, int flags) { if (mNativeClass == 0) { return false; } @@ -1811,10 +1815,16 @@ public final class WebViewCore { xArray[i] = (int) event.getX(i); yArray[i] = (int) event.getY(i); } - return nativeHandleTouchEvent(mNativeClass, + int touchFlags = nativeHandleTouchEvent(mNativeClass, event.getActionMasked(), idArray, xArray, yArray, count, event.getActionIndex(), event.getMetaState()); + if (touchFlags == 0 + && event.getActionMasked() != MotionEvent.ACTION_CANCEL + && (flags & WebViewInputDispatcher.FLAG_PRIVATE) == 0) { + dispatcher.skipWebkitForRemainingTouchStream(); + } + return (touchFlags & TOUCH_FLAG_PREVENT_DEFAULT) > 0; } default: diff --git a/core/java/android/webkit/WebViewInputDispatcher.java b/core/java/android/webkit/WebViewInputDispatcher.java index feff16ec0443..d8065e951681 100644 --- a/core/java/android/webkit/WebViewInputDispatcher.java +++ b/core/java/android/webkit/WebViewInputDispatcher.java @@ -686,7 +686,7 @@ final class WebViewInputDispatcher { + ", eventType=" + eventType + ", flags=" + flags); } boolean preventDefault = mWebKitCallbacks.dispatchWebKitEvent( - event, eventType, flags); + this, event, eventType, flags); if (DEBUG) { Log.d(TAG, "dispatchWebKitEvent: preventDefault=" + preventDefault); } @@ -710,6 +710,12 @@ final class WebViewInputDispatcher { mWebKitDispatchEventQueue.mHead = d; } + // Called by WebKit when it doesn't care about the rest of the touch stream + public void skipWebkitForRemainingTouchStream() { + // Just treat this like a timeout + handleWebKitTimeout(); + } + // Runs on UI thread in response to the web kit thread appearing to be unresponsive. private void handleWebKitTimeout() { synchronized (mLock) { @@ -1081,12 +1087,14 @@ final class WebViewInputDispatcher { /** * Dispatches an event to web kit. + * @param dispatcher The WebViewInputDispatcher sending the event * @param event The event. * @param eventType The event type. * @param flags The event's dispatch flags. * @return True if web kit wants to prevent default event handling. */ - public boolean dispatchWebKitEvent(MotionEvent event, int eventType, int flags); + public boolean dispatchWebKitEvent(WebViewInputDispatcher dispatcher, + MotionEvent event, int eventType, int flags); } // Runs on UI thread. diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java index d6fb84747575..8cd63efd414f 100644 --- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java +++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java @@ -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); } } } diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java index 28283ef41807..90f94fc1fdc4 100644 --- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java @@ -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(); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java index a90192e842c7..96afbb602a68 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java @@ -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]; + mDelegateView.getLocationOnScreen(mTempPoint); + final float delegateX = mTempPoint[0]; + final float delegateY = mTempPoint[1]; - event.offsetLocation(deltaX, deltaY); - mDelegateView.dispatchTouchEvent(event); - event.offsetLocation(-deltaX, -deltaY); - } - return false; + 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; + } }
\ No newline at end of file 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 4bb2d1d4036f..9c773a58623d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -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; @@ -113,6 +114,14 @@ public class NavigationBarView extends LinearLayout { } @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); @@ -330,6 +340,12 @@ public class NavigationBarView extends LinearLayout { } @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( "onSizeChanged: (%dx%d) old: (%dx%d)", w, h, oldw, oldh)); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java index 25fdf07fffdf..30d49ca86d84 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java @@ -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); } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 4ee0d2535c7b..a99ae269e2d9 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -3506,6 +3506,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { } if (screenOnListener != null) { if (mKeyguardMediator != null) { + try { + mWindowManager.setEventDispatching(true); + } catch (RemoteException unhandled) { + } mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() { @Override public void onShown(IBinder windowToken) { if (windowToken != null) { diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index d9e0ec6976d0..b1612a159af7 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -6621,15 +6621,14 @@ public class WindowManagerService extends IWindowManager.Stub public void setEventDispatching(boolean enabled) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "resumeKeyDispatching()")) { + "setEventDispatching()")) { throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); } synchronized (mWindowMap) { mInputMonitor.setEventDispatchingLw(enabled); + sendScreenStatusToClientsLocked(); } - - sendScreenStatusToClients(); } public IBinder getFocusedWindowClientToken() { @@ -6735,7 +6734,7 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.systemReady(); } - private void sendScreenStatusToClients() { + private void sendScreenStatusToClientsLocked() { final ArrayList<WindowState> windows = mWindows; final int count = windows.size(); boolean on = mPowerManager.isScreenOn(); |