Move Right-click handling into UserInputHandler.
am: dbcccd65da
Change-Id: Ib28acfd62081f74d92c2a45b780f0b51763867ea
diff --git a/src/com/android/documentsui/dirlist/ListeningGestureDetector.java b/src/com/android/documentsui/dirlist/ListeningGestureDetector.java
index 85ff6ed..7a23d00 100644
--- a/src/com/android/documentsui/dirlist/ListeningGestureDetector.java
+++ b/src/com/android/documentsui/dirlist/ListeningGestureDetector.java
@@ -46,20 +46,13 @@
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
- // TODO: If possible, move this into UserInputHandler.
- if (e.getAction() == MotionEvent.ACTION_DOWN && Events.isMouseEvent(e)) {
- mInputHandler.setLastButtonState(e.getButtonState());
- }
-
// Detect drag events. When a drag is detected, intercept the rest of the gesture.
View itemView = rv.findChildViewUnder(e.getX(), e.getY());
if (itemView != null && mDragHelper.onTouch(itemView, e)) {
return true;
}
// Forward unhandled events to the GestureDetector.
- onTouchEvent(e);
-
- return false;
+ return onTouchEvent(e);
}
@Override
@@ -79,7 +72,7 @@
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getButtonState() == MotionEvent.BUTTON_SECONDARY) {
- return mInputHandler.onSingleRightClickUp(event);
+ return mInputHandler.onRightClick(event);
}
return false;
}
diff --git a/src/com/android/documentsui/dirlist/UserInputHandler.java b/src/com/android/documentsui/dirlist/UserInputHandler.java
index bd0cbf1..7324695 100644
--- a/src/com/android/documentsui/dirlist/UserInputHandler.java
+++ b/src/com/android/documentsui/dirlist/UserInputHandler.java
@@ -76,6 +76,20 @@
}
@Override
+ public boolean onDown(MotionEvent e) {
+ try (T event = mEventConverter.apply(e)) {
+ return onDown(event);
+ }
+ }
+
+ @VisibleForTesting
+ boolean onDown(T event) {
+ return event.isMouseEvent()
+ ? mMouseDelegate.onDown(event)
+ : mTouchDelegate.onDown(event);
+ }
+
+ @Override
public boolean onSingleTapUp(MotionEvent e) {
try (T event = mEventConverter.apply(e)) {
return onSingleTapUp(event);
@@ -132,9 +146,12 @@
mTouchDelegate.onLongPress(event);
}
- public boolean onSingleRightClickUp(MotionEvent e) {
+ // Only events from RecyclerView are fed into UserInputHandler#onDown.
+ // ListeningGestureDetector#onTouch directly calls this method to support context menu in empty
+ // view
+ boolean onRightClick(MotionEvent e) {
try (T event = mEventConverter.apply(e)) {
- return mMouseDelegate.onSingleRightClickUp(event);
+ return mMouseDelegate.onRightClick(event);
}
}
@@ -143,11 +160,6 @@
return mKeyListener.onKey(doc, keyCode, event);
}
- // TODO: Isolate this hack...see if we can't get this solved at the platform level.
- public void setLastButtonState(int state) {
- mMouseDelegate.setLastButtonState(state);
- }
-
private boolean activateDocument(DocumentDetails doc) {
return mActivateHandler.accept(doc);
}
@@ -169,6 +181,10 @@
private final class TouchInputDelegate {
+ boolean onDown(T event) {
+ return false;
+ }
+
boolean onSingleTapUp(T event) {
if (!event.isOverItem()) {
if (DEBUG) Log.d(TAG, "Tap on non-item. Clearing selection.");
@@ -220,25 +236,28 @@
}
private final class MouseInputDelegate {
-
- // From the RecyclerView, we get two events sent to
- // ListeningGestureDetector#onInterceptTouchEvent on a mouse click; we first get an
- // ACTION_DOWN Event for clicking on the mouse, and then an ACTION_UP event from releasing
- // the mouse click. ACTION_UP event doesn't have information regarding the button (primary
- // vs. secondary), so we have to save that somewhere first from ACTION_DOWN, and then reuse
- // it later. The ACTION_DOWN event doesn't get forwarded to UserInputListener,
- // so we have open up a public set method to set it.
- private int mLastButtonState = -1;
-
- // true when the previous event has consumed a right click motion event
- private boolean mAteRightClick;
-
// The event has been handled in onSingleTapUp
private boolean mHandledTapUp;
+ // true when the previous event has consumed a right click motion event
+ private boolean mHandledOnDown;
+
+ boolean onDown(T event) {
+ if (event.isSecondaryButtonPressed()) {
+ assert(!mHandledOnDown);
+ mHandledOnDown = true;
+ return onRightClick(event);
+ }
+ return false;
+ }
boolean onSingleTapUp(T event) {
- if (eatRightClick()) {
- return onSingleRightClickUp(event);
+
+ // See b/27377794. Since we don't get a button state back from UP events, we have to
+ // explicitly save this state to know whether something was previously handled by
+ // DOWN events or not.
+ if (mHandledOnDown) {
+ mHandledOnDown = false;
+ return false;
}
if (!event.isOverItem()) {
@@ -272,10 +291,6 @@
}
boolean onSingleTapConfirmed(T event) {
- if (mAteRightClick) {
- mAteRightClick = false;
- return false;
- }
if (mHandledTapUp) {
mHandledTapUp = false;
return false;
@@ -316,23 +331,9 @@
}
}
- private boolean onSingleRightClickUp(T event) {
+ private boolean onRightClick(T event) {
return mRightClickHandler.apply(event);
}
-
- // hack alert from here through end of class.
- private void setLastButtonState(int state) {
- mLastButtonState = state;
- }
-
- private boolean eatRightClick() {
- if (mLastButtonState == MotionEvent.BUTTON_SECONDARY) {
- mLastButtonState = -1;
- mAteRightClick = true;
- return true;
- }
- return false;
- }
}
private final class KeyInputHandler {
diff --git a/tests/src/com/android/documentsui/TestInputEvent.java b/tests/src/com/android/documentsui/TestInputEvent.java
index e6936d6..5cd6514 100644
--- a/tests/src/com/android/documentsui/TestInputEvent.java
+++ b/tests/src/com/android/documentsui/TestInputEvent.java
@@ -105,6 +105,13 @@
return e;
}
+ public static TestInputEvent rightClick(int position) {
+ TestInputEvent e = new TestInputEvent(position);
+ e.mouseEvent = true;
+ e.secondaryButtonPressed = true;
+ return e;
+ }
+
public static TestInputEvent shiftClick(int position) {
TestInputEvent e = new TestInputEvent(position);
e.mouseEvent = true;
diff --git a/tests/src/com/android/documentsui/dirlist/UserInputHandler_MouseTest.java b/tests/src/com/android/documentsui/dirlist/UserInputHandler_MouseTest.java
index 4e7997f..c459830 100644
--- a/tests/src/com/android/documentsui/dirlist/UserInputHandler_MouseTest.java
+++ b/tests/src/com/android/documentsui/dirlist/UserInputHandler_MouseTest.java
@@ -87,6 +87,12 @@
}
@Test
+ public void testRightClickDown_StartsContextMenu() {
+ mInputHandler.onDown(mEvent.secondary().build());
+ mRightClickHandler.assertLastArgument(mEvent.secondary().build());
+ }
+
+ @Test
public void testUnconfirmedClick_AddsToExistingSelection() {
mInputHandler.onSingleTapConfirmed(mEvent.at(7).build());
diff --git a/tests/src/com/android/documentsui/testing/TestEvent.java b/tests/src/com/android/documentsui/testing/TestEvent.java
index e59a603..f56118e 100644
--- a/tests/src/com/android/documentsui/testing/TestEvent.java
+++ b/tests/src/com/android/documentsui/testing/TestEvent.java
@@ -125,6 +125,11 @@
return this;
}
+ public Builder secondary() {
+ mState.secondaryButtonPressed = true;
+ return this;
+ }
+
public TestEvent build() {
// Return a copy, so nobody can mess w/ our internal state.
TestEvent e = new TestEvent();
@@ -132,6 +137,7 @@
e.modelId = mState.modelId;
e.shiftKeyDow = mState.shiftKeyDow;
e.mouseEvent = mState.mouseEvent;
+ e.secondaryButtonPressed = mState.secondaryButtonPressed;
return e;
}
}