Loading java/src/com/android/inputmethod/keyboard/KeyboardView.java +2 −1 Original line number Diff line number Diff line Loading @@ -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"); Loading java/src/com/android/inputmethod/keyboard/PointerTracker.java +15 −13 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -590,6 +591,7 @@ public class PointerTracker implements PointerTrackerQueue.Element { mListener.onUpdateBatchInput(sAggregratedPointers); } } } final boolean isOldestTracker = sPointerTrackerQueue.getOldestElement() == this; mDrawingProxy.showGesturePreviewTrail(this, isOldestTracker); } Loading Loading @@ -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); } } } Loading java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java +79 −32 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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(); Loading Loading @@ -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, Loading Loading @@ -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. Loading @@ -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) { Loading Loading
java/src/com/android/inputmethod/keyboard/KeyboardView.java +2 −1 Original line number Diff line number Diff line Loading @@ -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"); Loading
java/src/com/android/inputmethod/keyboard/PointerTracker.java +15 −13 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -590,6 +591,7 @@ public class PointerTracker implements PointerTrackerQueue.Element { mListener.onUpdateBatchInput(sAggregratedPointers); } } } final boolean isOldestTracker = sPointerTrackerQueue.getOldestElement() == this; mDrawingProxy.showGesturePreviewTrail(this, isOldestTracker); } Loading Loading @@ -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); } } } Loading
java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java +79 −32 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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(); Loading Loading @@ -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, Loading Loading @@ -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. Loading @@ -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) { Loading