Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 14a288da authored by Jeff Brown's avatar Jeff Brown Committed by Android (Google) Code Review
Browse files

Merge "Add suuport for splitting touch events across windows." into gingerbread

parents 524ae7dd 01ce2e9e
Loading
Loading
Loading
Loading
+0 −61
Original line number Diff line number Diff line
@@ -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;
    }
+13 −0
Original line number Diff line number Diff line
@@ -584,6 +584,19 @@ public interface WindowManager extends ViewManager {
         */
        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
         * in the future we just make this the default behavior.
+34 −0
Original line number Diff line number Diff line
@@ -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;
    
@@ -564,6 +565,36 @@ public class PopupWindow {
        mClippingEnabled = enabled;
    }

    /**
     * <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
@@ -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;
    }
    
+11 −48
Original line number Diff line number Diff line
@@ -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,22 +7625,10 @@ 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.
@@ -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.
         */
+8 −0
Original line number Diff line number Diff line
@@ -40,9 +40,17 @@ enum {

/*
 * Maximum number of pointers supported per motion event.
 * Smallest number of pointers is 1.
 */
#define MAX_POINTERS 10

/*
 * Maximum pointer id value supported in a motion event.
 * Smallest pointer id is 0.
 * (This is limited by our use of BitSet32 to track pointer assignments.)
 */
#define MAX_POINTER_ID 31

/*
 * Declare a concrete type for the NDK's input event forward declaration.
 */
Loading