Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
Dual hand typing
Browse files Browse the repository at this point in the history
  • Loading branch information
keianhzo committed Mar 12, 2020
1 parent dbb8ed3 commit 0d06f72
Show file tree
Hide file tree
Showing 10 changed files with 225 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,7 @@ void dispatchCreateWidgetLayer(final int aHandle, final Surface aSurface, final

@Keep
@SuppressWarnings("unused")
void handleMotionEvent(final int aHandle, final int aDevice, final boolean aPressed, final float aX, final float aY) {
void handleMotionEvent(final int aHandle, final int aDevice, final boolean aFocused, final boolean aPressed, final float aX, final float aY) {
runOnUiThread(() -> {
Widget widget = mWidgets.get(aHandle);
if (!isWidgetInputEnabled(widget)) {
Expand All @@ -819,12 +819,14 @@ void handleMotionEvent(final int aHandle, final int aDevice, final boolean aPres
final float y = aY / scale;

if (widget == null) {
MotionEventGenerator.dispatch(mRootWidget, aDevice, aPressed, x, y);
MotionEventGenerator.dispatch(mRootWidget, aDevice, aFocused, aPressed, x, y);

} else if (widget.getBorderWidth() > 0) {
final int border = widget.getBorderWidth();
MotionEventGenerator.dispatch(widget, aDevice, aPressed, x - border, y - border);
MotionEventGenerator.dispatch(widget, aDevice, aFocused, aPressed, x - border, y - border);

} else {
MotionEventGenerator.dispatch(widget, aDevice, aPressed, x, y);
MotionEventGenerator.dispatch(widget, aDevice, aFocused, aPressed, x, y);
}
});
}
Expand All @@ -839,7 +841,7 @@ void handleScrollEvent(final int aHandle, final int aDevice, final float aX, fin
}
if (widget != null) {
float scrollDirection = mSettings.getScrollDirection() == 0 ? 1.0f : -1.0f;
MotionEventGenerator.dispatchScroll(widget, aDevice, aX * scrollDirection, aY * scrollDirection);
MotionEventGenerator.dispatchScroll(widget, aDevice, true,aX * scrollDirection, aY * scrollDirection);
} else {
Log.e(LOGTAG, "Failed to find widget for scroll event: " + aHandle);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@

import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;
import android.view.InputDevice;
import android.util.SparseArray;
import android.view.InputDevice;
import android.view.MotionEvent;

import org.mozilla.vrbrowser.ui.widgets.KeyboardWidget;
import org.mozilla.vrbrowser.ui.widgets.Widget;
import org.mozilla.vrbrowser.utils.SystemUtils;

import java.util.Arrays;
import java.util.List;

public class MotionEventGenerator {
static final String LOGTAG = SystemUtils.createLogtag(MotionEventGenerator.class);
Expand Down Expand Up @@ -53,11 +53,11 @@ static class Device {
private static SparseArray<Device> devices = new SparseArray<>();


private static void generateEvent(Widget aWidget, Device aDevice, int aAction, boolean aGeneric) {
generateEvent(aWidget, aDevice, aAction, aGeneric, aDevice.mCoords);
private static void generateEvent(Widget aWidget, Device aDevice, boolean aFocused, int aAction, boolean aGeneric) {
generateEvent(aWidget, aDevice, aFocused, aAction, aGeneric, aDevice.mCoords);
}

private static void generateEvent(Widget aWidget, Device aDevice, int aAction, boolean aGeneric, MotionEvent.PointerCoords[] aCoords) {
private static void generateEvent(Widget aWidget, Device aDevice, boolean aFocused, int aAction, boolean aGeneric, MotionEvent.PointerCoords[] aCoords) {
MotionEvent event = MotionEvent.obtain(
/*mDownTime*/ aDevice.mDownTime,
/*eventTime*/ SystemClock.uptimeMillis(),
Expand All @@ -69,19 +69,24 @@ private static void generateEvent(Widget aWidget, Device aDevice, int aAction, b
/*buttonState*/ 0,
/*xPrecision*/ 0,
/*yPrecision*/ 0,
/*deviceId*/ 0, // aDevice.mDevice,
/*deviceId*/ aDevice.mDevice,
/*edgeFlags*/ 0,
/*source*/ InputDevice.SOURCE_TOUCHSCREEN,
/*flags*/ 0);
if (aGeneric) {
aWidget.handleHoverEvent(event);
if (aWidget instanceof KeyboardWidget) {
aWidget.handleHoverEvent(event);

} else if (aFocused) {
aWidget.handleHoverEvent(event);
}
} else {
aWidget.handleTouchEvent(event);
}
event.recycle();
}

public static void dispatch(Widget aWidget, int aDevice, boolean aPressed, float aX, float aY) {
public static void dispatch(Widget aWidget, int aDevice, boolean aFocused, boolean aPressed, float aX, float aY) {
Device device = devices.get(aDevice);
if (device == null) {
device = new Device(aDevice);
Expand All @@ -99,41 +104,41 @@ public static void dispatch(Widget aWidget, int aDevice, boolean aPressed, float
}
if (!aPressed && (device.mPreviousWidget != null) && (device.mPreviousWidget != aWidget)) {
if (device.mWasPressed) {
generateEvent(device.mPreviousWidget, device, MotionEvent.ACTION_CANCEL, false);
generateEvent(device.mPreviousWidget, device, aFocused, MotionEvent.ACTION_CANCEL, false);
device.mWasPressed = false;
}
generateEvent(device.mPreviousWidget, device, MotionEvent.ACTION_HOVER_EXIT, true, device.mMouseOutCoords);
generateEvent(device.mPreviousWidget, device, aFocused, MotionEvent.ACTION_HOVER_EXIT, true, device.mMouseOutCoords);
device.mPreviousWidget = null;
}
if (aWidget == null) {
device.mPreviousWidget = null;
return;
}
if (aWidget != device.mPreviousWidget && !aPressed) {
generateEvent(aWidget, device, MotionEvent.ACTION_HOVER_ENTER, true);
generateEvent(aWidget, device, aFocused, MotionEvent.ACTION_HOVER_ENTER, true);
}
if (aPressed && !device.mWasPressed) {
device.mDownTime = SystemClock.uptimeMillis();
device.mWasPressed = true;
generateEvent(aWidget, device, MotionEvent.ACTION_HOVER_EXIT, true);
generateEvent(aWidget, device, MotionEvent.ACTION_DOWN, false);
generateEvent(aWidget, device, aFocused, MotionEvent.ACTION_HOVER_EXIT, true);
generateEvent(aWidget, device, aFocused, MotionEvent.ACTION_DOWN, false);
device.mTouchStartWidget = aWidget;
} else if (!aPressed && device.mWasPressed) {
device.mWasPressed = false;
generateEvent(device.mTouchStartWidget, device, MotionEvent.ACTION_UP, false);
generateEvent(aWidget, device, MotionEvent.ACTION_HOVER_ENTER, true);
generateEvent(device.mTouchStartWidget, device, aFocused, MotionEvent.ACTION_UP, false);
generateEvent(aWidget, device, aFocused, MotionEvent.ACTION_HOVER_ENTER, true);
} else if (moving && aPressed) {
generateEvent(aWidget, device, MotionEvent.ACTION_MOVE, false);
generateEvent(aWidget, device, aFocused, MotionEvent.ACTION_MOVE, false);
} else if (moving) {
generateEvent(aWidget, device, MotionEvent.ACTION_HOVER_MOVE, true);
generateEvent(aWidget, device, aFocused, MotionEvent.ACTION_HOVER_MOVE, true);
} else {
Log.e("VRB", "Unknown touch event action");
return;
}
device.mPreviousWidget = aWidget;
}

public static void dispatchScroll(Widget aWidget, int aDevice, float aX, float aY) {
public static void dispatchScroll(Widget aWidget, int aDevice, boolean aFocused, float aX, float aY) {
Device device = devices.get(aDevice);
if (device == null) {
device = new Device(aDevice);
Expand All @@ -142,7 +147,7 @@ public static void dispatchScroll(Widget aWidget, int aDevice, float aX, float a
device.mPreviousWidget = aWidget;
device.mCoords[0].setAxisValue(MotionEvent.AXIS_VSCROLL, aY);
device.mCoords[0].setAxisValue(MotionEvent.AXIS_HSCROLL, aX);
generateEvent(aWidget, device, MotionEvent.ACTION_SCROLL, true);
generateEvent(aWidget, device, aFocused, MotionEvent.ACTION_SCROLL, true);
device.mCoords[0].setAxisValue(MotionEvent.AXIS_VSCROLL, 0.0f);
device.mCoords[0].setAxisValue(MotionEvent.AXIS_HSCROLL, 0.0f);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ public interface OnKeyboardActionListener {
private int mLastCodeY;
private int mCurrentKey = NOT_A_KEY;
// Fork
private int mHoveredKey = NOT_A_KEY;
private int[] mHoveredKey = new int[2];
private int mDownKey = NOT_A_KEY;
private long mLastKeyTime;
private long mCurrentKeyTime;
Expand Down Expand Up @@ -344,6 +344,8 @@ public CustomKeyboardView(Context context, AttributeSet attrs, int defStyleAttr,
mShadowColor = 0;
mShadowRadius = 0;
mBackgroundDimAmount = 0.5f;
mHoveredKey[0] = NOT_A_KEY;
mHoveredKey[1] = NOT_A_KEY;

mPreviewPopup = new PopupWindow(context);
if (previewLayout != 0) {
Expand Down Expand Up @@ -757,7 +759,7 @@ private void onBufferDraw() {
int[] drawableState = key.getCurrentDrawableState();

if (((CustomKeyboard)mKeyboard).isKeyEnabled(i)) {
if (mHoveredKey == i && !key.pressed) {
if ((mHoveredKey[0] == i || mHoveredKey[1] == i) && !key.pressed) {
// Fork: implement hovered key
drawableState = KEY_STATE_HOVERED;
}
Expand Down Expand Up @@ -1144,6 +1146,8 @@ private void sendAccessibilityEventForUnicodeCharacter(int eventType, int code)
* @see #invalidateKey(int)
*/
public void invalidateAllKeys() {
mHoveredKey[0] = NOT_A_KEY;
mHoveredKey[1] = NOT_A_KEY;
mDirtyRect.union(0, 0, getWidth(), getHeight());
mDrawPending = true;
invalidate();
Expand Down Expand Up @@ -1259,17 +1263,32 @@ public boolean onHoverEvent(MotionEvent event) {
keyIndex = getKeyIndices(touchX, touchY, null);
}

int prevHovered = mHoveredKey;
mHoveredKey = keyIndex;
if (mHoveredKey != NOT_A_KEY && prevHovered != mHoveredKey) {
invalidateKey(mHoveredKey);
int prevHovered = mHoveredKey[event.getDeviceId()];
mHoveredKey[event.getDeviceId()] = keyIndex;
if (mHoveredKey[event.getDeviceId()] != NOT_A_KEY && prevHovered != mHoveredKey[event.getDeviceId()]) {
invalidateKey(mHoveredKey[event.getDeviceId()]);
}
if (prevHovered != NOT_A_KEY && prevHovered != mHoveredKey) {
if (prevHovered != NOT_A_KEY && prevHovered != mHoveredKey[event.getDeviceId()]) {
invalidateKey(prevHovered);
}
return result;
}

@Override
public void setHovered(boolean hovered) {
if (!hovered) {
mHoveredKey[0] = NOT_A_KEY;
mHoveredKey[1] = NOT_A_KEY;
invalidateAllKeys();
}
super.setHovered(hovered);
}

@Override
public boolean isHovered() {
return mHoveredKey[0] != NOT_A_KEY || mHoveredKey[1] != NOT_A_KEY;
}

public void setFeaturedKeyBackground(int resId, int[] keyCodes) {
mFeaturedKeyBackground = getResources().getDrawable(resId, getContext().getTheme());
mFeaturedKeyCodes.clear();
Expand Down
Loading

0 comments on commit 0d06f72

Please sign in to comment.