diff options
author | Jeff Brown <jeffbrown@google.com> | 2010-09-26 22:20:12 -0700 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2010-09-26 22:20:12 -0700 |
commit | 01ce2e9eee41cc0c24b0d16465710a28ea337d5d (patch) | |
tree | 08e45a8ec47e63760655a1770dac367258511538 /core | |
parent | 37cedce14bc0e68e8bf27c2cecb181728226e6ed (diff) | |
download | frameworks_base-01ce2e9eee41cc0c24b0d16465710a28ea337d5d.zip frameworks_base-01ce2e9eee41cc0c24b0d16465710a28ea337d5d.tar.gz frameworks_base-01ce2e9eee41cc0c24b0d16465710a28ea337d5d.tar.bz2 |
Add suuport for splitting touch events across windows.
This feature is currently used to enable dragging the start and end
selection handles of a TextView at the same time. Could be used for
other things later.
Deleted some dead code in ArrowKeyMovementMethod and CursorControllers.
Change-Id: I930accd97ca1ca1917aab8a807db2c950fc7b409
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/text/method/ArrowKeyMovementMethod.java | 61 | ||||
-rw-r--r-- | core/java/android/view/WindowManager.java | 13 | ||||
-rw-r--r-- | core/java/android/widget/PopupWindow.java | 34 | ||||
-rw-r--r-- | core/java/android/widget/TextView.java | 59 |
4 files changed, 58 insertions, 109 deletions
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java index 733b535..220e023 100644 --- a/core/java/android/text/method/ArrowKeyMovementMethod.java +++ b/core/java/android/text/method/ArrowKeyMovementMethod.java @@ -23,19 +23,12 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.widget.TextView; -import android.widget.TextView.CursorController; // XXX this doesn't extend MetaKeyKeyListener because the signatures // don't match. Need to figure that out. Meanwhile the meta keys // won't work in fields that don't take input. public class ArrowKeyMovementMethod implements MovementMethod { - /** - * An optional controller for the cursor. - * Use {@link #setCursorController(CursorController)} to set this field. - */ - private CursorController mCursorController; - private boolean isCap(Spannable buffer) { return ((MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) || (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0)); @@ -192,21 +185,10 @@ public class ArrowKeyMovementMethod implements MovementMethod { } public boolean onTrackballEvent(TextView widget, Spannable text, MotionEvent event) { - if (mCursorController != null) { - mCursorController.hide(); - } return false; } public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { - if (mCursorController != null) { - return onTouchEventCursor(widget, buffer, event); - } else { - return onTouchEventStandard(widget, buffer, event); - } - } - - private boolean onTouchEventStandard(TextView widget, Spannable buffer, MotionEvent event) { int initialScrollX = -1, initialScrollY = -1; if (event.getAction() == MotionEvent.ACTION_UP) { initialScrollX = Touch.getInitialScrollX(widget, buffer); @@ -278,49 +260,6 @@ public class ArrowKeyMovementMethod implements MovementMethod { return handled; } - private boolean onTouchEventCursor(TextView widget, Spannable buffer, MotionEvent event) { - if (widget.isFocused() && !widget.didTouchFocusSelect()) { - switch (event.getActionMasked()) { - case MotionEvent.ACTION_MOVE: - widget.cancelLongPress(); - - // Offset the current touch position (from controller to cursor) - final float x = event.getX() + mCursorController.getOffsetX(); - final float y = event.getY() + mCursorController.getOffsetY(); - mCursorController.updatePosition((int) x, (int) y); - return true; - - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - mCursorController = null; - return true; - } - } - return false; - } - - /** - * Defines the cursor controller. - * - * When set, this object can be used to handle touch events, that can be translated into cursor - * updates. - * - * {@link MotionEvent#ACTION_MOVE} events will call back the - * {@link CursorController#updatePosition(int, int)} controller's method, passing the current - * finger coordinates (offset by {@link CursorController#getOffsetX()} and - * {@link CursorController#getOffsetY()}) as parameters. - * - * When the gesture is finished (on a {@link MotionEvent#ACTION_UP} or - * {@link MotionEvent#ACTION_CANCEL} event), the controller is reset to null. - * - * @param cursorController A cursor controller implementation - * - * @hide - */ - public void setCursorController(CursorController cursorController) { - mCursorController = cursorController; - } - public boolean canSelectArbitrarily() { return true; } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index eebbc93..9c4aefe 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -583,6 +583,19 @@ public interface WindowManager extends ViewManager { * also been set. */ public static final int FLAG_DISMISS_KEYGUARD = 0x00400000; + + /** Window flag: when set the window will accept for touch events + * outside of its bounds to be sent to other windows that also + * support split touch. When this flag is not set, the first pointer + * that goes down determines the window to which all subsequent touches + * go until all pointers go up. When this flag is set, each pointer + * (not necessarily the first) that goes down determines the window + * to which all subsequent touches of that pointer will go until that + * pointer goes up thereby enabling touches with multiple pointers + * to be split across multiple windows. + * + * {@hide} */ + public static final int FLAG_SPLIT_TOUCH = 0x00800000; /** Window flag: *sigh* The lock screen wants to continue running its * animation while it is fading. A kind-of hack to allow this. Maybe diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index a10d647..7fe6190 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -85,6 +85,7 @@ public class PopupWindow { private boolean mTouchable = true; private boolean mOutsideTouchable = false; private boolean mClippingEnabled = true; + private boolean mSplitTouchEnabled; private OnTouchListener mTouchInterceptor; @@ -565,6 +566,36 @@ public class PopupWindow { } /** + * <p>Indicates whether the popup window supports splitting touches.</p> + * + * @return true if the touch splitting is enabled, false otherwise + * + * @see #setSplitTouchEnabled(boolean) + * @hide + */ + public boolean isSplitTouchEnabled() { + return mSplitTouchEnabled; + } + + /** + * <p>Allows the popup window to split touches across other windows that also + * support split touch. When this flag is not set, the first pointer + * that goes down determines the window to which all subsequent touches + * go until all pointers go up. When this flag is set, each pointer + * (not necessarily the first) that goes down determines the window + * to which all subsequent touches of that pointer will go until that + * pointer goes up thereby enabling touches with multiple pointers + * to be split across multiple windows.</p> + * + * @param enabled true if the split touches should be enabled, false otherwise + * @see #isSplitTouchEnabled() + * @hide + */ + public void setSplitTouchEnabled(boolean enabled) { + mSplitTouchEnabled = enabled; + } + + /** * <p>Change the width and height measure specs that are given to the * window manager by the popup. By default these are 0, meaning that * the current width or height is requested as an explicit size from @@ -889,6 +920,9 @@ public class PopupWindow { if (!mClippingEnabled) { curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; } + if (mSplitTouchEnabled) { + curFlags |= WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; + } return curFlags; } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 034c617..6278192 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -7601,16 +7601,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener /** * A CursorController instance can be used to control a cursor in the text. - * - * It can be passed to an {@link ArrowKeyMovementMethod} which can intercepts events - * and send them to this object instead of the cursor. - * + * It is not used outside of {@link TextView}. * @hide */ - public interface CursorController { - /* Cursor fade-out animation duration, in milliseconds. */ - static final int FADE_OUT_DURATION = 400; - + private interface CursorController { /** * Makes the cursor controller visible on screen. Will be drawn by {@link #draw(Canvas)}. * See also {@link #hide()}. @@ -7631,23 +7625,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener /** * Update the controller's position. */ - public void updatePosition(int x, int y); + public void updatePosition(HandleView handle, int x, int y); public void updatePosition(); /** - * The controller and the cursor's positions can be link by a fixed offset, - * computed when the controller is touched, and then maintained as it moves - * @return Horizontal offset between the controller and the cursor. - */ - public float getOffsetX(); - - /** - * @return Vertical offset between the controller and the cursor. - */ - public float getOffsetY(); - - /** * This method is called by {@link #onTouchEvent(MotionEvent)} and gives the controller * a chance to become active and/or visible. * @param event The touch event @@ -7670,6 +7652,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mDrawable = handle; mContainer = new PopupWindow(TextView.this.mContext, null, com.android.internal.R.attr.textSelectHandleWindowStyle); + mContainer.setSplitTouchEnabled(true); } @Override @@ -7768,7 +7751,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener TextView.this.getLocationOnScreen(coords); final int x = (int) (rawX - coords[0] + 0.5f); final int y = (int) (rawY - coords[1] + 0.5f); - mController.updatePosition(x, y); + mController.updatePosition(this, x, y); break; case MotionEvent.ACTION_UP: @@ -7802,13 +7785,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - class InsertionPointCursorController implements CursorController { + private class InsertionPointCursorController implements CursorController { private static final int DELAY_BEFORE_FADE_OUT = 4100; // The cursor controller image private final HandleView mHandle; - // Offset between finger hot point on cursor controller and actual cursor - private float mOffsetX, mOffsetY; private final Runnable mHider = new Runnable() { public void run() { @@ -7841,7 +7822,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return mHandle.isShowing(); } - public void updatePosition(int x, int y) { + public void updatePosition(HandleView handle, int x, int y) { final int previousOffset = getSelectionStart(); int offset = getHysteresisOffset(x, y, previousOffset); @@ -7865,24 +7846,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mHandle.positionAtCursor(offset, true); } - public float getOffsetX() { - return mOffsetX; - } - - public float getOffsetY() { - return mOffsetY; - } - public boolean onTouchEvent(MotionEvent ev) { return false; } } - class SelectionModifierCursorController implements CursorController { + private class SelectionModifierCursorController implements CursorController { // The cursor controller images private HandleView mStartHandle, mEndHandle; - // Offset between finger hot point on active cursor controller and actual cursor - private float mOffsetX, mOffsetY; // The offsets of that last touch down event. Remembered to start selection there. private int mMinTouchOffset, mMaxTouchOffset; // Whether selection anchors are active @@ -7916,15 +7887,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener hide(); } - public void updatePosition(int x, int y) { + public void updatePosition(HandleView handle, int x, int y) { int selectionStart = getSelectionStart(); int selectionEnd = getSelectionEnd(); - final int previousOffset = mStartHandle.isDragging() ? selectionStart : selectionEnd; + final int previousOffset = handle == mStartHandle ? selectionStart : selectionEnd; int offset = getHysteresisOffset(x, y, previousOffset); // Handle the case where start and end are swapped, making sure start <= end - if (mStartHandle.isDragging()) { + if (handle == mStartHandle) { if (offset <= selectionEnd) { if (selectionStart == offset) { return; // no change, no need to redraw; @@ -8021,14 +7992,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return mMaxTouchOffset; } - public float getOffsetX() { - return mOffsetX; - } - - public float getOffsetY() { - return mOffsetY; - } - /** * @return true iff this controller is currently used to move the selection start. */ |