diff options
author | mariakhomenko@chromium.org <mariakhomenko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-15 15:13:11 +0000 |
---|---|---|
committer | mariakhomenko@chromium.org <mariakhomenko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-15 15:13:11 +0000 |
commit | bd38a51821150cb872b6a3d5e01e25ff15c4f12b (patch) | |
tree | ec5afe000d81abdc06f054aec220f3a72d2fa546 /content | |
parent | 151905a7ff1135a90bfa191529797bc8e7795d87 (diff) | |
download | chromium_src-bd38a51821150cb872b6a3d5e01e25ff15c4f12b.zip chromium_src-bd38a51821150cb872b6a3d5e01e25ff15c4f12b.tar.gz chromium_src-bd38a51821150cb872b6a3d5e01e25ff15c4f12b.tar.bz2 |
Fix stuck state when long press on a button is performed.
This makes sure that when a tap becomes a long press, we keep
SHOW_PRESSED_STATE until either it becomes a LONG_TAP (finger is lifted),
or SCROLL, or window focus is lost (a context menu has been opened). At
which point we will send SHOW_PRESS_CANCEL.
BUG=285712
Review URL: https://chromiumcodereview.appspot.com/23444068
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@223283 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
4 files changed, 81 insertions, 6 deletions
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentView.java b/content/public/android/java/src/org/chromium/content/browser/ContentView.java index b047909..dd2847cd 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentView.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentView.java @@ -449,6 +449,12 @@ public class ContentView extends FrameLayout } @Override + public void onWindowFocusChanged(boolean hasWindowFocus) { + super.onWindowFocusChanged(hasWindowFocus); + mContentViewCore.onWindowFocusChanged(hasWindowFocus); + } + + @Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mContentViewCore.onKeyUp(keyCode, event); } diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java index a55cebe..edbc53f 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java @@ -63,8 +63,8 @@ import org.chromium.content.browser.accessibility.BrowserAccessibilityManager; import org.chromium.content.browser.input.AdapterInputConnection; import org.chromium.content.browser.input.HandleView; import org.chromium.content.browser.input.ImeAdapter; -import org.chromium.content.browser.input.InputMethodManagerWrapper; import org.chromium.content.browser.input.ImeAdapter.AdapterInputConnectionFactory; +import org.chromium.content.browser.input.InputMethodManagerWrapper; import org.chromium.content.browser.input.InsertionHandleController; import org.chromium.content.browser.input.SelectPopupDialog; import org.chromium.content.browser.input.SelectionHandleController; @@ -76,7 +76,6 @@ import org.chromium.ui.gfx.DeviceDisplayInfo; import java.lang.annotation.Annotation; import java.lang.reflect.Field; -import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -1682,6 +1681,15 @@ import java.util.Map; mScrolledAndZoomedFocusedEditableNode = false; } + /** + * @see View#onWindowFocusChanged(boolean) + */ + public void onWindowFocusChanged(boolean hasWindowFocus) { + if (!hasWindowFocus) { + mContentViewGestureHandler.onWindowFocusLost(); + } + } + public void onFocusChanged(boolean gainFocus) { if (!gainFocus) getContentViewClient().onImeStateChangeRequested(false); if (mNativeContentViewCore != 0) nativeSetFocus(mNativeContentViewCore, gainFocus); diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java index 1cb1276..6912bcc 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java @@ -164,6 +164,10 @@ class ContentViewGestureHandler implements LongPressDelegate { // confirmTouchEvent(), from either itself or onTouchEvent(). private int mTouchEventHandlingStackDepth; + // Keeps track of the last long press event, if we end up opening a context menu, we would need + // to potentially use the event to send GESUTRE_SHOW_PRESS_CANCEL to remove ::active styling + private MotionEvent mLastLongPressEvent; + static final int GESTURE_SHOW_PRESSED_STATE = 0; static final int GESTURE_DOUBLE_TAP = 1; static final int GESTURE_SINGLE_TAP_UP = 2; @@ -366,9 +370,9 @@ class ContentViewGestureHandler implements LongPressDelegate { void setTestDependencies( LongPressDetector longPressDetector, GestureDetector gestureDetector, OnGestureListener listener) { - mLongPressDetector = longPressDetector; - mGestureDetector = gestureDetector; - mListener = listener; + if (longPressDetector != null) mLongPressDetector = longPressDetector; + if (gestureDetector != null) mGestureDetector = gestureDetector; + if (listener != null) mListener = listener; } private void initGestureDetectors(final Context context) { @@ -608,7 +612,7 @@ class ContentViewGestureHandler implements LongPressDelegate { if (!mZoomManager.isScaleGestureDetectionInProgress() && (mDoubleTapDragMode == DOUBLE_TAP_DRAG_MODE_NONE || isDoubleTapDragDisabled())) { - sendShowPressCancelIfNecessary(e); + mLastLongPressEvent = e; sendMotionEventAsGesture(GESTURE_LONG_PRESS, e, null); } } @@ -858,6 +862,15 @@ class ContentViewGestureHandler implements LongPressDelegate { } } + /** + * Handle content view losing focus -- ensure that any remaining active state is removed. + */ + void onWindowFocusLost() { + if (mLongPressDetector.isInLongPress() && mLastLongPressEvent != null) { + sendShowPressCancelIfNecessary(mLastLongPressEvent); + } + } + private MotionEvent obtainActionCancelMotionEvent() { return MotionEvent.obtain( SystemClock.uptimeMillis(), @@ -1161,6 +1174,7 @@ class ContentViewGestureHandler implements LongPressDelegate { if (sendMotionEventAsGesture(GESTURE_SHOW_PRESS_CANCEL, e, null)) { mShowPressIsCalled = false; + mLastLongPressEvent = null; } } diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewGestureHandlerTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewGestureHandlerTest.java index 15e1b25f..e05fcb5 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewGestureHandlerTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewGestureHandlerTest.java @@ -656,6 +656,53 @@ public class ContentViewGestureHandlerTest extends InstrumentationTestCase { } /** + * Verify that a show pressed state gesture followed by a long press followed by the focus + * loss in the window due to context menu cancels show pressed. + * @throws Exception + */ + @SmallTest + @Feature({"Gestures"}) + public void testShowPressCancelOnWindowFocusLost() throws Exception { + final long time = SystemClock.uptimeMillis(); + GestureRecordingMotionEventDelegate mockDelegate = + new GestureRecordingMotionEventDelegate(); + mGestureHandler = new ContentViewGestureHandler( + getInstrumentation().getTargetContext(), mockDelegate, mMockZoomManager, + ContentViewCore.INPUT_EVENTS_DELIVERED_AT_VSYNC); + mLongPressDetector = new LongPressDetector( + getInstrumentation().getTargetContext(), mGestureHandler); + mGestureHandler.setTestDependencies(mLongPressDetector, null, null); + + MotionEvent event = motionEvent(MotionEvent.ACTION_DOWN, time, time); + mGestureHandler.onTouchEvent(event); + + mGestureHandler.sendShowPressedStateGestureForTesting(); + assertEquals("A show pressed state event should have been sent", + ContentViewGestureHandler.GESTURE_SHOW_PRESSED_STATE, + mockDelegate.mMostRecentGestureEvent.mType); + assertEquals("Only showPressedState should have been sent", + 1, mockDelegate.mGestureTypeList.size()); + + mLongPressDetector.startLongPressTimerIfNeeded(event); + mLongPressDetector.sendLongPressGestureForTest(); + + assertEquals("Only should have sent only LONG_PRESS event", + 2, mockDelegate.mGestureTypeList.size()); + assertEquals("Should have a long press event next", + ContentViewGestureHandler.GESTURE_LONG_PRESS, + mockDelegate.mGestureTypeList.get(1).intValue()); + + // The long press triggers window focus loss by opening a context menu + mGestureHandler.onWindowFocusLost(); + + assertEquals("Only should have sent only GESTURE_SHOW_PRESS_CANCEL event", + 3, mockDelegate.mGestureTypeList.size()); + assertEquals("Should have a long press event next", + ContentViewGestureHandler.GESTURE_SHOW_PRESS_CANCEL, + mockDelegate.mGestureTypeList.get(2).intValue()); + } + + /** * Verify that a recent show pressed state gesture is canceled when scrolling begins. * @throws Exception */ |