Improved two-thumb support for touch keyboard

This commit is contained in:
Aaron Culliney 2019-03-02 16:48:17 -08:00
parent 75be89d1ab
commit 5bd8e25739
7 changed files with 119 additions and 29 deletions

View File

@ -351,6 +351,41 @@ public class Apple2KeyboardSettingsMenu extends Apple2AbstractMenu {
return convertView;
}
},
KEYBOARD_ENABLE_DUO_TOUCH {
@Override
public final String getTitle(Apple2Activity activity) {
return activity.getResources().getString(R.string.keyboard_duotouch_enabled);
}
@Override
public final String getSummary(Apple2Activity activity) {
return activity.getResources().getString(R.string.keyboard_duotouch_enabled_summary);
}
@Override
public String getPrefKey() {
return "duoTouchEnabled";
}
@Override
public Object getPrefDefault() {
return false;
}
@Override
public View getView(final Apple2Activity activity, View convertView) {
convertView = _basicView(activity, this, convertView);
CheckBox cb = _addCheckbox(activity, this, convertView, (boolean) Apple2Preferences.getJSONPref(this));
final IMenuEnum self = this;
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Apple2Preferences.setJSONPref(self, isChecked);
}
});
return convertView;
}
},
KEYBOARD_ENABLE_LOWERCASE {
@Override
public final String getTitle(Apple2Activity activity) {

View File

@ -201,5 +201,7 @@
<string name="show_half_scanlines_summary">Renders pixel vertical divisions</string>
<string name="release_notes">Release notes</string>
<string name="release_notes_summary">View notes for this release</string>
<string name="keyboard_duotouch_enabled">Enable dual-touch</string>
<string name="keyboard_duotouch_enabled_summary">Support two-thumb input</string>
</resources>

View File

@ -201,5 +201,7 @@
<string name="show_half_scanlines_summary">Renders pixel vertical divisions</string>
<string name="release_notes">Release notes</string>
<string name="release_notes_summary">View notes for this release</string>
<string name="keyboard_duotouch_enabled">Enable dual-touch</string>
<string name="keyboard_duotouch_enabled_summary">Support two-thumb input</string>
</resources>

View File

@ -201,5 +201,7 @@
<string name="show_half_scanlines_summary">Renders pixel vertical divisions</string>
<string name="release_notes">Release notes</string>
<string name="release_notes_summary">View notes for this release</string>
<string name="keyboard_duotouch_enabled">Enable dual-touch</string>
<string name="keyboard_duotouch_enabled_summary">Support two-thumb input</string>
</resources>

View File

@ -201,5 +201,7 @@
<string name="show_half_scanlines_summary">Renders pixel vertical divisions</string>
<string name="release_notes">Release notes</string>
<string name="release_notes_summary">View notes for this release</string>
<string name="keyboard_duotouch_enabled">Enable dual-touch</string>
<string name="keyboard_duotouch_enabled_summary">Support two-thumb input</string>
</resources>

View File

@ -72,6 +72,7 @@
#define PREF_KEYBOARD_CAPS "caps"
#define PREF_KEYBOARD_ALT_PATH "altPath"
#define PREF_KEYBOARD_VARIANT "variant"
#define PREF_KEYBOARD_DUO_TOUCH "duoTouchEnabled"
#define PREF_LOWERCASE_ENABLED "lowercaseEnabled"
#define PREF_PORTRAIT_HEIGHT_SCALE "portraitHeightScale"
#define PREF_PORTRAIT_POSITION_SCALE "portraitPositionScale"

View File

@ -133,6 +133,7 @@ static struct {
int ctrlRow;
bool ctrlPressed;
bool duoTouch;
unsigned int glyphMultiplier;
float portraitHeightScale;
@ -364,7 +365,6 @@ static inline int64_t _tap_key_at_point(float x, float y) {
break;
case ICONTEXT_NONACTIONABLE:
scancode = 0;
handled = false;
break;
@ -455,15 +455,17 @@ static inline int64_t _tap_key_at_point(float x, float y) {
assert(key < 0x80);
scancode = c_keys_ascii_to_scancode(key);
if (kbd.ctrlPressed) {
c_keys_handle_input(scancode, /*pressed*/true, /*ASCII:*/false);
c_keys_handle_input(scancode, /*pressed*/true, /*ASCII:*/false);
c_keys_handle_input(scancode, /*pressed*/false, /*ASCII:*/false);
} else {
c_keys_handle_input(key, /*pressed:*/true, /*ASCII:*/true);
c_keys_handle_input(key, /*pressed:*/false, /*ASCII:*/true);
}
if (key == ' ' && isCalibrating) {
key = ICONTEXT_SPACE_VISUAL;
}
} else if (isCTRL) {
assert(scancode == SCODE_L_CTRL);
c_keys_handle_input(scancode, /*pressed:*/kbd.ctrlPressed, /*ASCII:*/false);
} else if (scancode) {
// perform a press of other keys (ESC, Arrows, etc)
@ -481,9 +483,6 @@ static inline int64_t _tap_key_at_point(float x, float y) {
flags |= TOUCH_FLAGS_HANDLED;
}
key = key & 0xff;
scancode = scancode & 0xff;
flags |= ( (int64_t)((key << 8) | scancode) << TOUCH_FLAGS_ASCII_AND_SCANCODE_SHIFT);
return flags;
}
@ -670,13 +669,27 @@ static void gltouchkbd_reshape(int w, int h, bool landscape) {
static int64_t gltouchkbd_onTouchEvent(interface_touch_event_t action, int pointer_count, int pointer_idx, float *x_coords, float *y_coords) {
if (!isAvailable) {
if (UNLIKELY(pointer_idx < 0)) {
TOUCH_KBD_LOG("!!!KBD : IGNORING TRACKING INDEX %d", pointer_idx);
return 0x0LL;
}
static int trackingIndex0 = TRACKING_NONE;
static int trackingIndex1 = TRACKING_NONE;
if (UNLIKELY(!isAvailable)) {
trackingIndex0 = TRACKING_NONE;
trackingIndex1 = TRACKING_NONE;
return 0x0LL;
}
if (UNLIKELY(kbd.prefsChanged)) {
return 0x0;
trackingIndex0 = TRACKING_NONE;
trackingIndex1 = TRACKING_NONE;
return 0x0LL;
}
if (!ownsScreen) {
trackingIndex0 = TRACKING_NONE;
trackingIndex1 = TRACKING_NONE;
return 0x0LL;
}
@ -687,41 +700,72 @@ static int64_t gltouchkbd_onTouchEvent(interface_touch_event_t action, int point
clock_gettime(CLOCK_MONOTONIC, &kbd.timingBegin);
static int trackingIndex = TRACKING_NONE;
switch (action) {
case TOUCH_DOWN:
case TOUCH_POINTER_DOWN:
if (/*isOnKeyboardModel:*/true) {// TODO FIXME : nonactionable areas could defer to joystick ...
trackingIndex = pointer_idx;
flags |= TOUCH_FLAGS_HANDLED;
}
break;
case TOUCH_MOVE:
flags |= ((pointer_idx == trackingIndex) ? TOUCH_FLAGS_HANDLED : 0);
break;
case TOUCH_UP:
case TOUCH_POINTER_UP:
{
if (trackingIndex == pointer_idx) {
int64_t handledAndData = _tap_key_at_point(x, y);
flags |= ((handledAndData & TOUCH_FLAGS_HANDLED) ? (TOUCH_FLAGS_HANDLED|TOUCH_FLAGS_KEY_TAP) : 0x0LL);
flags |= (handledAndData & TOUCH_FLAGS_REQUEST_SYSTEM_KBD);
flags |= (handledAndData & TOUCH_FLAGS_ASCII_AND_SCANCODE_MASK);
trackingIndex = TRACKING_NONE;
if (trackingIndex0 == TRACKING_NONE) {
trackingIndex0 = pointer_idx;
flags |= TOUCH_FLAGS_HANDLED;
TOUCH_KBD_LOG("---KBD TOUCH DOWN 0");
} else if (kbd.duoTouch && trackingIndex1 == TRACKING_NONE) {
trackingIndex1 = pointer_idx;
flags |= TOUCH_FLAGS_HANDLED;
TOUCH_KBD_LOG("---KBD TOUCH DOWN 1");
} else {
TOUCH_KBD_LOG("!!!KBD : IGNORING OTHER TOUCH DOWN %d", pointer_idx);
}
}
break;
case TOUCH_MOVE:
if (pointer_idx == trackingIndex0) {
flags |= TOUCH_FLAGS_HANDLED;
} else if (kbd.duoTouch && pointer_idx == trackingIndex1) {
flags |= TOUCH_FLAGS_HANDLED;
} else {
// ...
}
break;
case TOUCH_UP:
case TOUCH_POINTER_UP:
// tap is performed on touch up ...
if (trackingIndex0 == pointer_idx || (kbd.duoTouch && trackingIndex1 == pointer_idx)) {
int64_t handledAndData = _tap_key_at_point(x, y);
flags |= ((handledAndData & TOUCH_FLAGS_HANDLED) ? (TOUCH_FLAGS_HANDLED|TOUCH_FLAGS_KEY_TAP) : 0x0LL);
flags |= (handledAndData & TOUCH_FLAGS_REQUEST_SYSTEM_KBD);
flags |= (handledAndData & TOUCH_FLAGS_ASCII_AND_SCANCODE_MASK);
if (trackingIndex0 == pointer_idx) {
TOUCH_KBD_LOG("---KBD TOUCH UP 0");
if (trackingIndex1 != TRACKING_NONE) {
// TODO FIXME ... verify this is needed for iOS ... it is apparently needed for Android, ugh
TOUCH_KBD_LOG("---KBD MIGRATING TRACKING 1 -> 0");
trackingIndex1 = TRACKING_NONE;
} else {
trackingIndex0 = TRACKING_NONE;
}
} else {
TOUCH_KBD_LOG("---KBD TOUCH UP 1");
trackingIndex1 = TRACKING_NONE;
}
} else {
TOUCH_KBD_LOG("!!!KBD : IGNORING OTHER TOUCH UP %d", pointer_idx);
// ...
}
break;
case TOUCH_CANCEL:
trackingIndex = TRACKING_NONE;
trackingIndex0 = TRACKING_NONE;
trackingIndex1 = TRACKING_NONE;
LOG("---KBD TOUCH CANCEL");
return 0x0LL;
default:
trackingIndex = TRACKING_NONE;
trackingIndex0 = TRACKING_NONE;
trackingIndex1 = TRACKING_NONE;
LOG("!!!KBD UNKNOWN TOUCH EVENT : %d", action);
return 0x0LL;
}
@ -913,6 +957,8 @@ static void gltouchkbd_applyPrefs(void) {
= prefs_parseLongValue (PREF_DOMAIN_TOUCHSCREEN, PREF_SCREEN_OWNER, &lVal, /*base:*/10) ? (interface_device_t)lVal : TOUCH_DEVICE_KEYBOARD;
ownsScreen = (screenOwner == TOUCH_DEVICE_KEYBOARD || screenOwner == TOUCH_DEVICE_NONE);
kbd.duoTouch = prefs_parseBoolValue(PREF_DOMAIN_KEYBOARD, PREF_KEYBOARD_DUO_TOUCH, &bVal) ? bVal : false;
if (ownsScreen) {
minAlpha = minAlphaWhenOwnsScreen;
if (allowLowercase) {
@ -931,7 +977,7 @@ static void gltouchkbd_applyPrefs(void) {
glhud_setupDefault(kbd.model);
}
// reset CTRL state upon leaving this touch device
// reset CTRL pressed state upon leaving this touch device
kbd.ctrlPressed = false;
c_keys_handle_input(SCODE_L_CTRL, /*pressed:*/false, /*ASCII:*/false);
}