ANDROID: Basic support for some TV remotes

And some fixes for DPAD handling

More fixes for DPAD will be coming. We currently don't handle DPAD Center, and also do not handle the case where DPAD is HATs (motion events)
This commit is contained in:
antoniou79 2023-03-25 00:01:37 +02:00
parent bea5300cf9
commit 057709fffb
3 changed files with 117 additions and 6 deletions

View file

@ -623,6 +623,28 @@ Common::KeymapperDefaultBindings *OSystem_Android::getKeymapperDefaultBindings()
// See: backends/keymapper/remap-widget.cpp: kCloseCmd = 'CLOS' // See: backends/keymapper/remap-widget.cpp: kCloseCmd = 'CLOS'
keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, "CLOS", "AC_BACK"); keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, "CLOS", "AC_BACK");
// By default DPAD directions will be used for virtual mouse in GUI context
// If the user wants to remap them, they will be able to navigate to Global Options -> Keymaps and do so.
// In some devices (eg. Android TV) with only the remote control as input, it is impossible to navigate the launcher GUI,
// if the DPAD actions are mapped to "up", "down", "left", "right" directions.
// TODO If/when full key-based (ie. non-mouse) navigation of the ScummVM GUI is implemented,
// we can revert back to the core behavior of DPAD being mapped to "up", "down", "left", "right" directions.
keymapperDefaultBindings->addDefaultBinding(Common::kGlobalKeymapName, "VMOUSEUP", "JOY_LEFT_STICK_Y-");
keymapperDefaultBindings->addDefaultBinding(Common::kGlobalKeymapName, "VMOUSEUP", "JOY_UP");
keymapperDefaultBindings->addDefaultBinding(Common::kGlobalKeymapName, "VMOUSEDOWN", "JOY_LEFT_STICK_Y+");
keymapperDefaultBindings->addDefaultBinding(Common::kGlobalKeymapName, "VMOUSEDOWN", "JOY_DOWN");
keymapperDefaultBindings->addDefaultBinding(Common::kGlobalKeymapName, "VMOUSELEFT", "JOY_LEFT_STICK_X-");
keymapperDefaultBindings->addDefaultBinding(Common::kGlobalKeymapName, "VMOUSELEFT", "JOY_LEFT");
keymapperDefaultBindings->addDefaultBinding(Common::kGlobalKeymapName, "VMOUSERIGHT", "JOY_LEFT_STICK_X+");
keymapperDefaultBindings->addDefaultBinding(Common::kGlobalKeymapName, "VMOUSERIGHT", "JOY_RIGHT");
keymapperDefaultBindings->addDefaultBinding(Common::kGuiKeymapName, Common::kStandardActionInteract, "JOY_A");
// TODO Needs JOY_CENTER to be defined
//keymapperDefaultBindings->addDefaultBinding(Common::kGuiKeymapName, Common::kStandardActionInteract, "JOY_CENTER");
keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, Common::kStandardActionMoveUp, nullptr);
keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, Common::kStandardActionMoveDown, nullptr);
keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, Common::kStandardActionMoveLeft, nullptr);
keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, Common::kStandardActionMoveRight, nullptr);
return keymapperDefaultBindings; return keymapperDefaultBindings;
} }

View file

@ -76,6 +76,7 @@ enum {
JE_BMB_UP = 19, JE_BMB_UP = 19,
JE_FMB_DOWN = 20, JE_FMB_DOWN = 20,
JE_FMB_UP = 21, JE_FMB_UP = 21,
JE_TV_REMOTE = 22,
JE_QUIT = 0x1000, JE_QUIT = 0x1000,
JE_MENU = 0x1001 JE_MENU = 0x1001
}; };
@ -551,6 +552,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
case AKEYCODE_DPAD_LEFT: case AKEYCODE_DPAD_LEFT:
// fall through // fall through
case AKEYCODE_DPAD_RIGHT: case AKEYCODE_DPAD_RIGHT:
// Treat as mouse movement
if (arg1 != AKEY_EVENT_ACTION_DOWN) if (arg1 != AKEY_EVENT_ACTION_DOWN)
return; return;
@ -586,6 +588,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
return; return;
case AKEYCODE_DPAD_CENTER: case AKEYCODE_DPAD_CENTER:
// Treat as mouse click (left click)
switch (arg1) { switch (arg1) {
case AKEY_EVENT_ACTION_DOWN: case AKEY_EVENT_ACTION_DOWN:
e.type = Common::EVENT_LBUTTONDOWN; e.type = Common::EVENT_LBUTTONDOWN;
@ -607,6 +610,49 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
return; return;
} }
case JE_TV_REMOTE:
switch (arg1) {
case AKEY_EVENT_ACTION_DOWN:
e.type = Common::EVENT_KEYDOWN;
break;
case AKEY_EVENT_ACTION_UP:
e.type = Common::EVENT_KEYUP;
break;
default:
LOGE("unhandled jaction on key: %d", arg1);
return;
}
switch (arg2) {
case AKEYCODE_MEDIA_FAST_FORWARD:
// fall through
case AKEYCODE_MEDIA_REWIND:
// fall through
case AKEYCODE_MEDIA_PLAY_PAUSE:
// Treat as keyboard presses, since they have equivalent hardware keyboard keys
e.kbd.keycode = jkeymap[arg2];
if (arg5 > 0) {
e.kbdRepeat = true;
}
break;
// Unfortunately CHANNEL_UP or CHANNEL_DOWN do not trigger for the Fire TV Stick remote (3rd gen)
// despite the documentation (https://developer.amazon.com/docs/fire-tv/remote-input.html)
// so there's no way as of yet to test for them.
// TODO Maybe enable them anyway? Should we create hardware input keys for them in the main code?
// case AKEYCODE_CHANNEL_UP:
// // fall through
// case AKEYCODE_CHANNEL_DOWN:
// break;
}
pushEvent(e);
return;
case JE_DOWN: case JE_DOWN:
// LOGD("JE_DOWN"); // LOGD("JE_DOWN");
_touch_pt_down = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->getMousePosition(); _touch_pt_down = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->getMousePosition();
@ -1161,6 +1207,27 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
e.joystick.button = Common::JOYSTICK_BUTTON_RIGHT_STICK; e.joystick.button = Common::JOYSTICK_BUTTON_RIGHT_STICK;
break; break;
case AKEYCODE_DPAD_UP:
e.joystick.button = Common::JOYSTICK_BUTTON_DPAD_UP;
break;
case AKEYCODE_DPAD_DOWN:
e.joystick.button = Common::JOYSTICK_BUTTON_DPAD_DOWN;
break;
case AKEYCODE_DPAD_LEFT:
e.joystick.button = Common::JOYSTICK_BUTTON_DPAD_LEFT;
break;
case AKEYCODE_DPAD_RIGHT:
e.joystick.button = Common::JOYSTICK_BUTTON_DPAD_RIGHT;
break;
// case AKEYCODE_DPAD_CENTER:
// // TODO This needs to be defined (backends/keymapper/hardware-input.cpp and common/events.h)
// e.joystick.button = Common::JOYSTICK_BUTTON_DPAD_CENTER;
// break;
default: default:
LOGW("unmapped gamepad key: %d", arg2); LOGW("unmapped gamepad key: %d", arg2);
return; return;

View file

@ -48,6 +48,7 @@ public class ScummVMEventsBase implements
public static final int JE_BMB_UP = 19; public static final int JE_BMB_UP = 19;
public static final int JE_FMB_DOWN = 20; public static final int JE_FMB_DOWN = 20;
public static final int JE_FMB_UP = 21; public static final int JE_FMB_UP = 21;
public static final int JE_TV_REMOTE = 22;
public static final int JE_QUIT = 0x1000; public static final int JE_QUIT = 0x1000;
public static final int JE_MENU = 0x1001; public static final int JE_MENU = 0x1001;
@ -222,11 +223,12 @@ public class ScummVMEventsBase implements
// case KeyEvent.ACTION_DOWN: // case KeyEvent.ACTION_DOWN:
// actionStr = "KeyEvent.ACTION_DOWN"; // actionStr = "KeyEvent.ACTION_DOWN";
// break; // break;
// case KeyEvent.ACTION_MULTIPLE:
// actionStr = "KeyEvent.ACTION_MULTIPLE";
// break;
// default: // default:
// actionStr = e.toString(); // if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && e.getAction() == KeyEvent.ACTION_MULTIPLE) {
// actionStr = "KeyEvent.ACTION_MULTIPLE";
// } else {
// actionStr = e.toString();
// }
// } // }
// Log.d(ScummVM.LOG_TAG, "SCUMMV-EVENTS-BASE - onKEY:::" + keyCode + " Action::" + actionStr); // Called // Log.d(ScummVM.LOG_TAG, "SCUMMV-EVENTS-BASE - onKEY:::" + keyCode + " Action::" + actionStr); // Called
@ -369,17 +371,34 @@ public class ScummVMEventsBase implements
case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_VOLUME_UP:
// We ignore these so that they can be handled by Android. // We ignore these so that they can be handled by Android.
return false; return false;
// case KeyEvent.KEYCODE_CHANNEL_UP:
// case KeyEvent.KEYCODE_CHANNEL_DOWN:
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
case KeyEvent.KEYCODE_MEDIA_REWIND:
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
type = JE_TV_REMOTE;
break;
case KeyEvent.KEYCODE_DPAD_UP: case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN: case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_DPAD_LEFT: case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT: case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_CENTER: case KeyEvent.KEYCODE_DPAD_CENTER:
if (e.getSource() == InputDevice.SOURCE_DPAD) { if ((e.getSource() & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) {
// When interpreted as JE_DPAD it will work as a mouse (translated in Android backend, events.cpp)
// This is a case for FireTV Stick remote control's DPAD
// The remote control itself is: InputDevice.SOURCE_DPAD | InputDevice.SOURCE_KEYBOARD
// since it also has "buttons" for fast-forward, play/pause toggle, and rewind.
// TODO Evaluate merging this case with setting the type as "JE_GAMEPAD"
// and delegating the key mapping to ScummVM's keymapper
type = JE_DPAD; type = JE_DPAD;
} else { } else {
type = JE_KEY; // When interpreted as JE_GAMEPAD it will be forwarded to ScummVM's keymapper
type = JE_GAMEPAD;
} }
break; break;
case KeyEvent.KEYCODE_BUTTON_A: case KeyEvent.KEYCODE_BUTTON_A:
case KeyEvent.KEYCODE_BUTTON_B: case KeyEvent.KEYCODE_BUTTON_B:
case KeyEvent.KEYCODE_BUTTON_C: case KeyEvent.KEYCODE_BUTTON_C:
@ -397,6 +416,7 @@ public class ScummVMEventsBase implements
case KeyEvent.KEYCODE_BUTTON_MODE: case KeyEvent.KEYCODE_BUTTON_MODE:
type = JE_GAMEPAD; type = JE_GAMEPAD;
break; break;
case KeyEvent.KEYCODE_BUTTON_1: case KeyEvent.KEYCODE_BUTTON_1:
case KeyEvent.KEYCODE_BUTTON_2: case KeyEvent.KEYCODE_BUTTON_2:
case KeyEvent.KEYCODE_BUTTON_3: case KeyEvent.KEYCODE_BUTTON_3:
@ -404,6 +424,7 @@ public class ScummVMEventsBase implements
// These are oddly detected with SOURCE_KEYBOARD for joystick so don't bother checking the e.getSource() // These are oddly detected with SOURCE_KEYBOARD for joystick so don't bother checking the e.getSource()
type = JE_JOYSTICK; type = JE_JOYSTICK;
break; break;
default: default:
if (e.isSystem()) { if (e.isSystem()) {
type = JE_SYS_KEY; type = JE_SYS_KEY;
@ -414,6 +435,7 @@ public class ScummVMEventsBase implements
} }
//_scummvm.displayMessageOnOSD("GetKey: " + keyCode + " unic=" + eventUnicodeChar+ " arg3= " + (eventUnicodeChar& KeyCharacterMap.COMBINING_ACCENT_MASK) + " meta: " + e.getMetaState()); //_scummvm.displayMessageOnOSD("GetKey: " + keyCode + " unic=" + eventUnicodeChar+ " arg3= " + (eventUnicodeChar& KeyCharacterMap.COMBINING_ACCENT_MASK) + " meta: " + e.getMetaState());
//_scummvm.displayMessageOnOSD("GetKey: " + keyCode + " type=" + type + " source=" + e.getSource() + " action= " + action + " arg5= " + e.getRepeatCount());
//Log.d(ScummVM.LOG_TAG,"GetKey: " + keyCode + " unic=" + eventUnicodeChar+ " arg3= " + (eventUnicodeChar& KeyCharacterMap.COMBINING_ACCENT_MASK) + " meta: " + e.getMetaState()); //Log.d(ScummVM.LOG_TAG,"GetKey: " + keyCode + " unic=" + eventUnicodeChar+ " arg3= " + (eventUnicodeChar& KeyCharacterMap.COMBINING_ACCENT_MASK) + " meta: " + e.getMetaState());
// look in events.cpp for how this is handled // look in events.cpp for how this is handled