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

Commit c0a1dc0e authored by Tadashi G. Takaoka's avatar Tadashi G. Takaoka Committed by Android (Google) Code Review
Browse files

Merge "Draw gesture trail that is above the keyboard" into jb-mr1-dev

parents 2aea34fb 157fe98f
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -826,7 +826,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
        }
        final int[] viewOrigin = new int[2];
        getLocationInWindow(viewOrigin);
        mPreviewPlacerView.setOrigin(viewOrigin[0], viewOrigin[1]);
        mPreviewPlacerView.setKeyboardViewGeometry(
                viewOrigin[0], viewOrigin[1], getWidth(), getHeight());
        final View rootView = getRootView();
        if (rootView == null) {
            Log.w(TAG, "Cannot find root view");
+15 −13
Original line number Diff line number Diff line
@@ -576,7 +576,8 @@ public class PointerTracker implements PointerTrackerQueue.Element {
        mDrawingProxy.showGesturePreviewTrail(this, isOldestTracker);
    }

    private void updateBatchInput(final long eventTime) {
    private void mayUpdateBatchInput(final long eventTime, final Key key) {
        if (key != null) {
            synchronized (sAggregratedPointers) {
                mGestureStrokeWithPreviewPoints.appendIncrementalBatchPoints(sAggregratedPointers);
                final int size = sAggregratedPointers.getPointerSize();
@@ -590,6 +591,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
                    mListener.onUpdateBatchInput(sAggregratedPointers);
                }
            }
        }
        final boolean isOldestTracker = sPointerTrackerQueue.getOldestElement() == this;
        mDrawingProxy.showGesturePreviewTrail(this, isOldestTracker);
    }
@@ -746,8 +748,8 @@ public class PointerTracker implements PointerTrackerQueue.Element {
        if (mIsDetectingGesture) {
            mGestureStrokeWithPreviewPoints.addPoint(x, y, gestureTime, isMajorEvent);
            mayStartBatchInput(key);
            if (sInGesture && key != null) {
                updateBatchInput(eventTime);
            if (sInGesture) {
                mayUpdateBatchInput(eventTime, key);
            }
        }
    }
+79 −32
Original line number Diff line number Diff line
@@ -40,6 +40,10 @@ import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;

public class PreviewPlacerView extends RelativeLayout {
    // The height of extra area above the keyboard to draw gesture trails.
    // Proportional to the keyboard height.
    private static final float EXTRA_GESTURE_TRAIL_AREA_ABOVE_KEYBOARD_RATIO = 0.25f;

    private final int mGestureFloatingPreviewTextColor;
    private final int mGestureFloatingPreviewTextOffset;
    private final int mGestureFloatingPreviewColor;
@@ -47,14 +51,17 @@ public class PreviewPlacerView extends RelativeLayout {
    private final float mGestureFloatingPreviewVerticalPadding;
    private final float mGestureFloatingPreviewRoundRadius;

    private int mXOrigin;
    private int mYOrigin;
    private int mKeyboardViewOriginX;
    private int mKeyboardViewOriginY;

    private final SparseArray<GesturePreviewTrail> mGesturePreviewTrails =
            CollectionUtils.newSparseArray();
    private final Params mGesturePreviewTrailParams;
    private final Paint mGesturePaint;
    private boolean mDrawsGesturePreviewTrail;
    private int mOffscreenWidth;
    private int mOffscreenHeight;
    private int mOffscreenOffsetY;
    private Bitmap mOffscreenBuffer;
    private final Canvas mOffscreenCanvas = new Canvas();
    private final Rect mOffscreenDirtyRect = new Rect();
@@ -165,9 +172,12 @@ public class PreviewPlacerView extends RelativeLayout {
        setLayerType(LAYER_TYPE_HARDWARE, layerPaint);
    }

    public void setOrigin(final int x, final int y) {
        mXOrigin = x;
        mYOrigin = y;
    public void setKeyboardViewGeometry(final int x, final int y, final int w, final int h) {
        mKeyboardViewOriginX = x;
        mKeyboardViewOriginY = y;
        mOffscreenOffsetY = (int)(h * EXTRA_GESTURE_TRAIL_AREA_ABOVE_KEYBOARD_RATIO);
        mOffscreenWidth = w;
        mOffscreenHeight = mOffscreenOffsetY + h;
    }

    public void setGesturePreviewMode(final boolean drawsGesturePreviewTrail,
@@ -204,29 +214,68 @@ public class PreviewPlacerView extends RelativeLayout {

    @Override
    protected void onDetachedFromWindow() {
        freeOffscreenBuffer();
    }

    private void freeOffscreenBuffer() {
        if (mOffscreenBuffer != null) {
            mOffscreenBuffer.recycle();
            mOffscreenBuffer = null;
        }
    }

    private void mayAllocateOffscreenBuffer() {
        if (mOffscreenBuffer != null && mOffscreenBuffer.getWidth() == mOffscreenWidth
                && mOffscreenBuffer.getHeight() == mOffscreenHeight) {
            return;
        }
        freeOffscreenBuffer();
        mOffscreenBuffer = Bitmap.createBitmap(
                mOffscreenWidth, mOffscreenHeight, Bitmap.Config.ARGB_8888);
        mOffscreenCanvas.setBitmap(mOffscreenBuffer);
    }

    @Override
    public void onDraw(final Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(mXOrigin, mYOrigin);
        if (mDrawsGesturePreviewTrail) {
            if (mOffscreenBuffer == null) {
                mOffscreenBuffer = Bitmap.createBitmap(
                        getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
                mOffscreenCanvas.setBitmap(mOffscreenBuffer);
            }
            mayAllocateOffscreenBuffer();
            // Draw gesture trails to offscreen buffer.
            final boolean needsUpdatingGesturePreviewTrail = drawGestureTrails(
                    mOffscreenCanvas, mGesturePaint, mOffscreenDirtyRect);
            // Transfer offscreen buffer to screen.
            if (!mOffscreenDirtyRect.isEmpty()) {
                final int offsetY = mKeyboardViewOriginY - mOffscreenOffsetY;
                canvas.translate(mKeyboardViewOriginX, offsetY);
                canvas.drawBitmap(mOffscreenBuffer, mOffscreenDirtyRect, mOffscreenDirtyRect,
                        mGesturePaint);
                canvas.translate(-mKeyboardViewOriginX, -offsetY);
                // Note: Defer clearing the dirty rectangle here because we will get cleared
                // rectangle on the canvas.
            }
            if (needsUpdatingGesturePreviewTrail) {
                mDrawingHandler.postUpdateGestureTrailPreview();
            }
        }
        if (mDrawsGestureFloatingPreviewText) {
            canvas.translate(mKeyboardViewOriginX, mKeyboardViewOriginY);
            drawGestureFloatingPreviewText(canvas, mGestureFloatingPreviewText);
            canvas.translate(-mKeyboardViewOriginX, -mKeyboardViewOriginY);
        }
    }

    private boolean drawGestureTrails(final Canvas offscreenCanvas, final Paint paint,
            final Rect dirtyRect) {
        // Clear previous dirty rectangle.
                mGesturePaint.setColor(Color.TRANSPARENT);
                mGesturePaint.setStyle(Paint.Style.FILL);
                mOffscreenCanvas.drawRect(mOffscreenDirtyRect, mGesturePaint);
                mOffscreenDirtyRect.setEmpty();
        if (!dirtyRect.isEmpty()) {
            paint.setColor(Color.TRANSPARENT);
            paint.setStyle(Paint.Style.FILL);
            offscreenCanvas.drawRect(dirtyRect, paint);
        }
        dirtyRect.setEmpty();

        // Draw gesture trails to offscreen buffer.
        offscreenCanvas.translate(0, mOffscreenOffsetY);
        boolean needsUpdatingGesturePreviewTrail = false;
        synchronized (mGesturePreviewTrails) {
            // Trails count == fingers count that have ever been active.
@@ -234,26 +283,24 @@ public class PreviewPlacerView extends RelativeLayout {
            for (int index = 0; index < trailsCount; index++) {
                final GesturePreviewTrail trail = mGesturePreviewTrails.valueAt(index);
                needsUpdatingGesturePreviewTrail |=
                            trail.drawGestureTrail(mOffscreenCanvas, mGesturePaint,
                        trail.drawGestureTrail(offscreenCanvas, paint,
                                mGesturePreviewTrailBoundsRect, mGesturePreviewTrailParams);
                // {@link #mGesturePreviewTrailBoundsRect} has bounding box of the trail.
                    mOffscreenDirtyRect.union(mGesturePreviewTrailBoundsRect);
                }
            }
            if (!mOffscreenDirtyRect.isEmpty()) {
                canvas.drawBitmap(mOffscreenBuffer, mOffscreenDirtyRect, mOffscreenDirtyRect,
                        mGesturePaint);
                // Note: Defer clearing the dirty rectangle here because we will get cleared
                // rectangle on the canvas.
            }
            if (needsUpdatingGesturePreviewTrail) {
                mDrawingHandler.postUpdateGestureTrailPreview();
                dirtyRect.union(mGesturePreviewTrailBoundsRect);
            }
        }
        if (mDrawsGestureFloatingPreviewText) {
            drawGestureFloatingPreviewText(canvas, mGestureFloatingPreviewText);
        offscreenCanvas.translate(0, -mOffscreenOffsetY);

        // Clip dirty rectangle with offscreen buffer width/height.
        dirtyRect.offset(0, mOffscreenOffsetY);
        clipRect(dirtyRect, 0, 0, mOffscreenWidth, mOffscreenHeight);
        return needsUpdatingGesturePreviewTrail;
    }
        canvas.translate(-mXOrigin, -mYOrigin);

    private static void clipRect(final Rect out, final int left, final int top, final int right,
            final int bottom) {
        out.set(Math.max(out.left, left), Math.max(out.top, top), Math.min(out.right, right),
                Math.min(out.bottom, bottom));
    }

    public void setGestureFloatingPreviewText(final String gestureFloatingPreviewText) {