ANDROID: Handle repeating keys for virtual keyboard

This commit is contained in:
antoniou 2020-10-24 16:03:45 +03:00
parent 3eb363ed7f
commit ddc0e26fbf
3 changed files with 144 additions and 44 deletions

View file

@ -467,6 +467,7 @@ public class CustomKeyboardView extends View implements View.OnClickListener {
float deltaY = me2.getY() - me1.getY();
int travelX = getWidth() / 2; // Half the keyboard width
int travelY = getHeight() / 2; // Half the keyboard height
//Log.d(ScummVM.LOG_TAG, "mSwipeTracker.computeCurrentVelocity()");
mSwipeTracker.computeCurrentVelocity(1000);
final float endingVelocityX = mSwipeTracker.getXVelocity();
final float endingVelocityY = mSwipeTracker.getYVelocity();
@ -502,7 +503,8 @@ public class CustomKeyboardView extends View implements View.OnClickListener {
}
if (sendDownKey) {
detectAndSendKey(mDownKey, mStartX, mStartY, me1.getEventTime());
//Log.d(ScummVM.LOG_TAG, "CustomKeyboardView:: initGestureDetector() - sendDownKey");
detectAndSendKey(mDownKey, mStartX, mStartY, me1.getEventTime(), false, false);
}
return false;
}
@ -889,11 +891,12 @@ public class CustomKeyboardView extends View implements View.OnClickListener {
return primaryIndex;
}
private void detectAndSendKey(int index, int x, int y, long eventTime) {
private void detectAndSendKey(int index, int x, int y, long eventTime, boolean isRepeated, boolean isReleaseKey) {
if (index != NOT_A_KEY && index < mKeys.length) {
final CustomKeyboard.CustomKey key = mKeys[index];
if (key.text != null) {
mKeyboardActionListener.onText(key.text);
//Log.d(ScummVM.LOG_TAG, "CustomKeyboardView:: detectAndSendKey - (key.text != null)");
mKeyboardActionListener.onRelease(NOT_A_KEY);
} else {
int code = key.codes[0];
@ -910,8 +913,13 @@ public class CustomKeyboardView extends View implements View.OnClickListener {
}
code = key.codes[mTapCount];
}
mKeyboardActionListener.onKey(code, codes);
mKeyboardActionListener.onRelease(code);
//Log.d(ScummVM.LOG_TAG, "CustomKeyboardView:: detectAndSendKey - (key.text is null) code = " + code + " x: " + x + " y: " + y);
if (!isReleaseKey) {
mKeyboardActionListener.onKey(code, codes);
}
if (!isRepeated || isReleaseKey) {
mKeyboardActionListener.onRelease(code);
}
}
mLastSentIndex = index;
mLastTapTime = eventTime;
@ -1394,6 +1402,19 @@ public class CustomKeyboardView extends View implements View.OnClickListener {
mCurrentKeyTime + eventTime - mLastMoveTime;
mCurrentKey = keyIndex;
mCurrentKeyTime = 0;
} else {
// if (mRepeatKeyIndex != NOT_A_KEY)
// New - handle the case where the user holds their finger and moves out of the key button
// Unfortunately, we will also get a "release" event on MotionEvent.ACTION_UP but that is safe since it is ignored
removeMessages();
if (mRepeatKeyIndex >= 0 && !mMiniKeyboardOnScreen && !mAbortKey) {
//Log.d(ScummVM.LOG_TAG, "CustomKeyboardView:: onModifiedTouchEvent - MotionEvent.ACTION_MOVE Final Rep");
detectAndSendKey(mCurrentKey, touchX, touchY, eventTime, true, true);
}
showPreview(NOT_A_KEY);
Arrays.fill(mKeyIndices, NOT_A_KEY);
invalidateKey(keyIndex);
mRepeatKeyIndex = NOT_A_KEY;
}
}
}
@ -1431,7 +1452,11 @@ public class CustomKeyboardView extends View implements View.OnClickListener {
Arrays.fill(mKeyIndices, NOT_A_KEY);
// If we're not on a repeating key (which sends on a DOWN event)
if (mRepeatKeyIndex == NOT_A_KEY && !mMiniKeyboardOnScreen && !mAbortKey) {
detectAndSendKey(mCurrentKey, touchX, touchY, eventTime);
//Log.d(ScummVM.LOG_TAG, "CustomKeyboardView:: onModifiedTouchEvent - MotionEvent.ACTION_UP No Rep");
detectAndSendKey(mCurrentKey, touchX, touchY, eventTime, false, true);
} else if (mRepeatKeyIndex >= 0 && mRepeatKeyIndex != NOT_A_KEY && !mMiniKeyboardOnScreen && !mAbortKey) {
//Log.d(ScummVM.LOG_TAG, "CustomKeyboardView:: onModifiedTouchEvent - MotionEvent.ACTION_UP Final Rep");
detectAndSendKey(mCurrentKey, touchX, touchY, eventTime, true, true);
}
invalidateKey(keyIndex);
mRepeatKeyIndex = NOT_A_KEY;
@ -1452,7 +1477,8 @@ public class CustomKeyboardView extends View implements View.OnClickListener {
// @UnsupportedAppUsage
private boolean repeatKey() {
CustomKeyboard.CustomKey key = mKeys[mRepeatKeyIndex];
detectAndSendKey(mCurrentKey, key.x, key.y, mLastTapTime);
//Log.d(ScummVM.LOG_TAG, "CustomKeyboardView:: repeatKey");
detectAndSendKey(mCurrentKey, key.x, key.y, mLastTapTime, true, false);
return true;
}
@ -1557,6 +1583,7 @@ public class CustomKeyboardView extends View implements View.OnClickListener {
}
public void addMovement(MotionEvent ev) {
//Log.d(ScummVM.LOG_TAG, "SwipeTracker - Add Movement");
long time = ev.getEventTime();
final int N = ev.getHistorySize();
for (int i=0; i<N; i++) {

View file

@ -164,19 +164,20 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
public boolean shift = false;
public boolean alt = false;
public final TreeSet<Integer> stickyKeys = new TreeSet<>();
public long mEventTime = -1;
public long mEventPressTime = -1;
public int mKeyRepeatedCount = 0;
public BuiltInKeyboardView(Context context, android.util.AttributeSet attrs) {
super(context, attrs);
}
public boolean onKeyDown(int key, final KeyEvent event) {
Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - onKeyDown()" );
//Log.d(ScummVM.LOG_TAG, "BuiltInKeyboardView- 001 - onKeyDown()" );
return false;
}
public boolean onKeyUp(int key, final KeyEvent event) {
Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - onKeyUp()" );
//Log.d(ScummVM.LOG_TAG, "BuiltInKeyboardView - 001 - onKeyUp()" );
return false;
}
@ -265,6 +266,12 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
//ScummVMActivity.this._scummvm.displayMessageOnOSD ("NEW KEYBOARD LAYOUT: QWERTY"
// + (alt ? " ALT " : "") + (shift? " SHIFT" : ""));
}
public void resetEventAndTimestamps() {
// clear event timestamps and repetition counts
mEventPressTime = -1;
mKeyRepeatedCount = -1;
}
}
final BuiltInKeyboardView builtinKeyboard = new BuiltInKeyboardView(ScummVMActivity.this, null);
@ -273,7 +280,9 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
builtinKeyboard.setOnKeyboardActionListener(new CustomKeyboardView.OnKeyboardActionListener() {
public void onPress(int key) {
//Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - onPress key: " + key ); // CALLED
builtinKeyboard.resetEventAndTimestamps();
// Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - onPress key: " + key );
if (key == KeyEvent.KEYCODE_BACK) {
return;
}
@ -288,35 +297,21 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
}
}
int compiledMetaState = builtinKeyboard.getCompiledMetaState();
// keys with keyCode greater than 100000, should be submitted with a LEFT_SHIFT_ modifier (and decreased by 100000 to get their proper code)
if (key > 100000) {
key -= 100000;
compiledMetaState |= KeyEvent.META_SHIFT_LEFT_ON;
}
//
// downTime (long) - The time (in SystemClock.uptimeMillis()) at which this key code originally went down.
// ** Since this is a down event, this will be the same as getEventTime(). **
// Note that when chording keys, this value is the down time of the most recently pressed key, which may not be the same physical key of this event.
// eventTime (long) - The time (in SystemClock.uptimeMillis()) at which this event happened.
// TODO update repeat and event time? with
builtinKeyboard.mEventTime = SystemClock.uptimeMillis();
KeyEvent compiledKeyEvent = new KeyEvent(builtinKeyboard.mEventTime,
builtinKeyboard.mEventTime,
KeyEvent.ACTION_DOWN,
key,
0,
compiledMetaState);
builtinKeyboard.mEventPressTime = SystemClock.uptimeMillis();
_main_surface.dispatchKeyEvent(compiledKeyEvent);
}
public void onRelease(int key) {
//Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - onRelease key: " + key );
// Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - onRelease key: " + key );
if (key == KeyEvent.KEYCODE_BACK) {
builtinKeyboard.setOnKeyboardActionListener(null);
builtinKeyboard.resetEventAndTimestamps();
showScreenKeyboardWithoutTextInputField(0); // Hide keyboard
return;
}
@ -327,6 +322,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
if (key == CustomKeyboard.KEYCODE_SHIFT) {
builtinKeyboard.shift = !builtinKeyboard.shift;
builtinKeyboard.ChangeKeyboard();
builtinKeyboard.resetEventAndTimestamps();
return;
}
@ -336,10 +332,12 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
builtinKeyboard.shift = false;
}
builtinKeyboard.ChangeKeyboard();
builtinKeyboard.resetEventAndTimestamps();
return;
}
if (key <= 0) {
builtinKeyboard.resetEventAndTimestamps();
return;
}
@ -358,6 +356,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
builtinKeyboard.stickyKeys.add(key);
}
builtinKeyboard.recheckStickyKeys();
builtinKeyboard.resetEventAndTimestamps();
return;
}
}
@ -371,16 +370,18 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
compiledMetaState |= KeyEvent.META_SHIFT_LEFT_ON;
}
// TODO properly set repeat value?
KeyEvent compiledKeyEvent = new KeyEvent(builtinKeyboard.mEventTime,
// The repeat argument (int) is:
// A repeat count for down events (> 0 if this is after the initial down)
// or event count for multiple events.
KeyEvent compiledKeyEvent = new KeyEvent(builtinKeyboard.mEventPressTime,
SystemClock.uptimeMillis(),
KeyEvent.ACTION_UP,
key,
0,
builtinKeyboard.mKeyRepeatedCount,
compiledMetaState);
_main_surface.dispatchKeyEvent(compiledKeyEvent);
builtinKeyboard.mEventTime = -1; // reset event time
builtinKeyboard.resetEventAndTimestamps();
// Excluding the CAPS LOCK NUM LOCK AND SCROLL LOCK keys,
// clear the state of all other sticky keys that are used in a key combo
@ -402,17 +403,55 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
}
public void onText(CharSequence p1) {}
public void swipeLeft() {}
public void swipeRight() {}
public void swipeDown() {}
public void swipeUp() {}
public void onKey(int p1, int[] p2) {}
public void swipeLeft() {
//Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeLeft");
}
public void swipeRight() {
//Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeRight" );
}
public void swipeDown() {
//Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeDown" );
}
public void swipeUp() {
//Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeUp ");
}
public void onKey(int key, int[] keysAround) {
// Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - onKey key: " + key );
if (builtinKeyboard.mEventPressTime == -1) {
return;
}
if (builtinKeyboard.mKeyRepeatedCount < Integer.MAX_VALUE) {
++builtinKeyboard.mKeyRepeatedCount;
}
int compiledMetaState = builtinKeyboard.getCompiledMetaState();
// keys with keyCode greater than 100000, should be submitted with a LEFT_SHIFT_ modifier (and decreased by 100000 to get their proper code)
if (key > 100000) {
key -= 100000;
compiledMetaState |= KeyEvent.META_SHIFT_LEFT_ON;
}
// update the eventTime after the above check for first time "hit"
KeyEvent compiledKeyEvent = new KeyEvent(builtinKeyboard.mEventPressTime,
SystemClock.uptimeMillis(),
KeyEvent.ACTION_DOWN,
key,
builtinKeyboard.mKeyRepeatedCount,
compiledMetaState);
_main_surface.dispatchKeyEvent(compiledKeyEvent);
}
});
_screenKeyboard = builtinKeyboard;
// TODO better to have specific dimensions in dp and not adjusted to parent
// it may resolve the issue of resizing the keyboard wrongly (smaller) when returning to the suspended Activity in low resolution
FrameLayout.LayoutParams sKeyboardLayout = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
FrameLayout.LayoutParams sKeyboardLayout = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL | Gravity.FILL_HORIZONTAL);
_videoLayout.addView(_screenKeyboard, sKeyboardLayout);
_videoLayout.bringChildToFront(_screenKeyboard);
@ -492,10 +531,14 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
return _screenKeyboard != null;
}
public View getScreenKeyboard () {
public View getScreenKeyboard() {
return _screenKeyboard;
}
// public View getMainSurfaceView() {
// return _main_surface;
// }
//
// END OF new screenKeyboardCode
// ---------------------------------------------------------------------------------------------------------------------------

View file

@ -156,7 +156,23 @@ public class ScummVMEventsBase implements
// OnKeyListener
@Override
final public boolean onKey(View v, int keyCode, KeyEvent e) {
// Log.d(ScummVM.LOG_TAG, "SCUMMV-EVENTS-BASE - onKEY:::" + keyCode); // Called
// String actionStr = "";
// switch (e.getAction()) {
// case KeyEvent.ACTION_UP:
// actionStr = "KeyEvent.ACTION_UP";
// break;
// case KeyEvent.ACTION_DOWN:
// actionStr = "KeyEvent.ACTION_DOWN";
// break;
// case KeyEvent.ACTION_MULTIPLE:
// actionStr = "KeyEvent.ACTION_MULTIPLE";
// break;
// default:
// actionStr = e.toString();
// }
// Log.d(ScummVM.LOG_TAG, "SCUMMV-EVENTS-BASE - onKEY:::" + keyCode + " Action::" + actionStr + " View:: " + actionView); // Called
final int action = e.getAction();
int eventUnicodeChar = e.getUnicodeChar();
@ -191,8 +207,10 @@ public class ScummVMEventsBase implements
if (action == KeyEvent.ACTION_DOWN) {
return true;
} else if (action == KeyEvent.ACTION_UP) {
// Hide keyboard (the argument here (0) does not matter)
((ScummVMActivity) _context).showScreenKeyboardWithoutTextInputField(0);
// Hide keyboard
if (((ScummVMActivity) _context).isScreenKeyboardShown()) {
((ScummVMActivity) _context).hideScreenKeyboard();
}
return true;
}
}
@ -200,8 +218,9 @@ public class ScummVMEventsBase implements
if (e.isSystem()) {
// no repeats for system keys
if (e.getRepeatCount() > 0)
if (e.getRepeatCount() > 0) {
return false;
}
// Have to reimplement hold-down-menu-brings-up-softkeybd
// ourselves, since we are otherwise hijacking the menu key :(
@ -335,7 +354,18 @@ public class ScummVMEventsBase implements
// OnTouchListener
@Override
final public boolean onTouch(View v, final MotionEvent event) {
//Log.d(ScummVM.LOG_TAG, "SCUMMV-EVENTS-BASE - onTOUCH");
// String actionStr = "";
// switch (event.getAction()) {
// case MotionEvent.ACTION_UP:
// actionStr = "MotionEvent.ACTION_UP";
// break;
// case MotionEvent.ACTION_DOWN:
// actionStr = "MotionEvent.ACTION_DOWN";
// break;
// default:
// actionStr = event.toString();
// }
// Log.d(ScummVM.LOG_TAG, "SCUMMV-EVENTS-BASE - onTOUCH event" + actionStr);
if (ScummVMActivity.keyboardWithoutTextInputShown
&& ((ScummVMActivity) _context).isScreenKeyboardShown()
@ -383,7 +413,7 @@ public class ScummVMEventsBase implements
// OnGestureListener
@Override
final public boolean onDown(MotionEvent e) {
//Log.d(ScummVM.LOG_TAG, "SCUMMV-EVENTS-BASE - onDONW");
//Log.d(ScummVM.LOG_TAG, "SCUMMV-EVENTS-BASE - onDOWN MotionEvent");
_scummvm.pushEvent(JE_DOWN, (int)e.getX(), (int)e.getY(), 0, 0, 0, 0);
return true;
}