2012-03-24 23:39:19 +01:00
|
|
|
#pragma once
|
|
|
|
|
|
2013-07-06 19:07:48 +02:00
|
|
|
// For more detailed and configurable input, implement NativeTouch, NativeKey and NativeAxis and do your
|
|
|
|
|
// own mapping. Might later move the mapping system from PPSSPP to native.
|
|
|
|
|
|
2021-04-04 08:39:49 -07:00
|
|
|
#include <unordered_map>
|
|
|
|
|
#include <vector>
|
2023-04-01 13:43:42 +02:00
|
|
|
#include <string>
|
2014-02-05 20:01:33 +01:00
|
|
|
|
2020-10-01 09:36:43 +02:00
|
|
|
#include "Common/Input/KeyCodes.h"
|
2023-03-29 11:59:31 +02:00
|
|
|
#include "Common/Log.h"
|
2012-03-24 23:39:19 +01:00
|
|
|
|
2013-07-06 19:07:48 +02:00
|
|
|
// Default device IDs
|
|
|
|
|
|
2023-05-26 18:40:13 +02:00
|
|
|
enum InputDeviceID {
|
2015-08-29 21:52:53 +02:00
|
|
|
DEVICE_ID_ANY = -1, // Represents any device ID
|
2013-07-06 19:07:48 +02:00
|
|
|
DEVICE_ID_DEFAULT = 0, // Old Android
|
|
|
|
|
DEVICE_ID_KEYBOARD = 1, // PC keyboard, android keyboards
|
2013-07-08 12:34:39 +02:00
|
|
|
DEVICE_ID_MOUSE = 2, // PC mouse only (not touchscreen!)
|
2013-07-06 19:07:48 +02:00
|
|
|
DEVICE_ID_PAD_0 = 10, // Generic joypads
|
2014-06-01 11:35:57 +02:00
|
|
|
DEVICE_ID_PAD_1 = 11, // these should stay as contiguous numbers
|
|
|
|
|
DEVICE_ID_PAD_2 = 12,
|
|
|
|
|
DEVICE_ID_PAD_3 = 13,
|
|
|
|
|
DEVICE_ID_PAD_4 = 14,
|
|
|
|
|
DEVICE_ID_PAD_5 = 15,
|
|
|
|
|
DEVICE_ID_PAD_6 = 16,
|
|
|
|
|
DEVICE_ID_PAD_7 = 17,
|
|
|
|
|
DEVICE_ID_PAD_8 = 18,
|
|
|
|
|
DEVICE_ID_PAD_9 = 19,
|
2021-08-28 15:38:03 +02:00
|
|
|
DEVICE_ID_XINPUT_0 = 20, // XInput joypads
|
|
|
|
|
DEVICE_ID_XINPUT_1 = 21,
|
|
|
|
|
DEVICE_ID_XINPUT_2 = 22,
|
|
|
|
|
DEVICE_ID_XINPUT_3 = 23,
|
2013-07-06 19:07:48 +02:00
|
|
|
DEVICE_ID_ACCELEROMETER = 30,
|
2023-01-28 11:50:46 +01:00
|
|
|
DEVICE_ID_XR_HMD = 39,
|
2022-07-22 18:47:37 +02:00
|
|
|
DEVICE_ID_XR_CONTROLLER_LEFT = 40,
|
|
|
|
|
DEVICE_ID_XR_CONTROLLER_RIGHT = 41,
|
2022-11-23 12:22:59 +01:00
|
|
|
DEVICE_ID_TOUCH = 42,
|
2023-08-23 18:42:20 +02:00
|
|
|
DEVICE_ID_COUNT,
|
2013-07-06 19:07:48 +02:00
|
|
|
};
|
|
|
|
|
|
2023-05-26 18:40:13 +02:00
|
|
|
inline InputDeviceID operator +(InputDeviceID deviceID, int addend) {
|
|
|
|
|
return (InputDeviceID)((int)deviceID + addend);
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-01 11:35:57 +02:00
|
|
|
//number of contiguous generic joypad IDs
|
|
|
|
|
const int MAX_NUM_PADS = 10;
|
|
|
|
|
|
2013-07-06 19:07:48 +02:00
|
|
|
const char *GetDeviceName(int deviceId);
|
|
|
|
|
|
2013-06-24 21:47:29 -07:00
|
|
|
#ifndef MAX_KEYQUEUESIZE
|
|
|
|
|
#define MAX_KEYQUEUESIZE 20
|
|
|
|
|
#endif
|
2013-07-06 19:07:48 +02:00
|
|
|
|
2015-08-28 16:51:07 +02:00
|
|
|
// Represents a single bindable key
|
2023-03-29 11:59:31 +02:00
|
|
|
static const int AXIS_BIND_NKCODE_START = 4000;
|
|
|
|
|
|
|
|
|
|
inline int TranslateKeyCodeToAxis(int keyCode, int *direction) {
|
|
|
|
|
if (keyCode < AXIS_BIND_NKCODE_START)
|
|
|
|
|
return 0;
|
|
|
|
|
int k = keyCode - AXIS_BIND_NKCODE_START;
|
|
|
|
|
// Even/odd for direction.
|
2023-05-02 21:36:17 +02:00
|
|
|
if (direction)
|
|
|
|
|
*direction = k & 1 ? -1 : 1;
|
2023-03-29 11:59:31 +02:00
|
|
|
return k / 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class InputMapping {
|
|
|
|
|
private:
|
|
|
|
|
inline int TranslateKeyCodeFromAxis(int axisId, int direction) {
|
|
|
|
|
return AXIS_BIND_NKCODE_START + axisId * 2 + (direction < 0 ? 1 : 0);
|
|
|
|
|
}
|
2015-08-28 16:51:07 +02:00
|
|
|
public:
|
2023-05-26 18:40:13 +02:00
|
|
|
InputMapping() : deviceId(DEVICE_ID_DEFAULT), keyCode(0) {}
|
2023-03-29 11:59:31 +02:00
|
|
|
// From a key mapping
|
2023-05-26 18:40:13 +02:00
|
|
|
InputMapping(InputDeviceID _deviceId, int key) : deviceId(_deviceId), keyCode(key) {}
|
2023-03-29 11:59:31 +02:00
|
|
|
// From an axis
|
2023-05-26 18:40:13 +02:00
|
|
|
InputMapping(InputDeviceID _deviceId, int axis, int direction) : deviceId(_deviceId), keyCode(TranslateKeyCodeFromAxis(axis, direction)) {
|
2023-03-29 11:59:31 +02:00
|
|
|
_dbg_assert_(direction != 0);
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-01 13:43:42 +02:00
|
|
|
static InputMapping FromConfigString(const std::string &str);
|
|
|
|
|
std::string ToConfigString() const;
|
|
|
|
|
|
2023-05-26 18:40:13 +02:00
|
|
|
InputDeviceID deviceId;
|
2023-03-29 11:59:31 +02:00
|
|
|
int keyCode; // Can also represent an axis with direction, if encoded properly.
|
|
|
|
|
|
|
|
|
|
bool IsAxis() const {
|
|
|
|
|
return keyCode >= AXIS_BIND_NKCODE_START;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Axis(int *direction) const {
|
|
|
|
|
_dbg_assert_(IsAxis());
|
|
|
|
|
return TranslateKeyCodeToAxis(keyCode, direction);
|
|
|
|
|
}
|
2015-08-28 16:51:07 +02:00
|
|
|
|
2023-03-30 21:25:49 +02:00
|
|
|
InputMapping FlipDirection() const {
|
|
|
|
|
_dbg_assert_(IsAxis());
|
|
|
|
|
InputMapping other = *this;
|
|
|
|
|
other.keyCode ^= 1;
|
|
|
|
|
return other;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-17 22:07:22 +02:00
|
|
|
// If you want to use std::find and match ANY, you need to perform an explicit search for that.
|
2023-03-29 11:59:31 +02:00
|
|
|
bool operator < (const InputMapping &other) const {
|
2015-08-28 16:51:07 +02:00
|
|
|
if (deviceId < other.deviceId) return true;
|
|
|
|
|
if (deviceId > other.deviceId) return false;
|
|
|
|
|
if (keyCode < other.keyCode) return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2023-04-01 00:12:14 +02:00
|
|
|
// Needed for composition.
|
|
|
|
|
bool operator > (const InputMapping &other) const {
|
|
|
|
|
if (deviceId > other.deviceId) return true;
|
|
|
|
|
if (deviceId < other.deviceId) return false;
|
|
|
|
|
if (keyCode > other.keyCode) return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This one is iffy with the != ANY checks. Should probably be a named method.
|
2023-03-29 11:59:31 +02:00
|
|
|
bool operator == (const InputMapping &other) const {
|
2015-08-29 21:52:53 +02:00
|
|
|
if (deviceId != other.deviceId && deviceId != DEVICE_ID_ANY && other.deviceId != DEVICE_ID_ANY) return false;
|
2015-08-28 16:51:07 +02:00
|
|
|
if (keyCode != other.keyCode) return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2023-08-23 18:42:20 +02:00
|
|
|
bool operator != (const InputMapping &other) const {
|
|
|
|
|
return !(*this == other);
|
|
|
|
|
}
|
2023-03-31 20:12:48 +02:00
|
|
|
|
|
|
|
|
void FormatDebug(char *buffer, size_t bufSize) const;
|
2015-08-28 16:51:07 +02:00
|
|
|
};
|
|
|
|
|
|
2013-05-03 00:21:39 +02:00
|
|
|
enum {
|
2014-02-05 20:01:33 +01:00
|
|
|
TOUCH_MOVE = 1 << 0,
|
|
|
|
|
TOUCH_DOWN = 1 << 1,
|
|
|
|
|
TOUCH_UP = 1 << 2,
|
|
|
|
|
TOUCH_CANCEL = 1 << 3, // Sent by scrollviews to their children when they detect a scroll
|
2014-07-20 22:20:09 +02:00
|
|
|
TOUCH_WHEEL = 1 << 4, // Scrollwheel event. Usually only affects Y but can potentially affect X.
|
|
|
|
|
TOUCH_MOUSE = 1 << 5, // Identifies that this touch event came from a mouse
|
2015-05-21 10:45:49 +02:00
|
|
|
TOUCH_RELEASE_ALL = 1 << 6, // Useful for app focus switches when events may be lost.
|
2014-02-05 20:01:33 +01:00
|
|
|
|
|
|
|
|
// These are the Android getToolType() codes, shifted by 10.
|
|
|
|
|
TOUCH_TOOL_MASK = 7 << 10,
|
|
|
|
|
TOUCH_TOOL_UNKNOWN = 0 << 10,
|
|
|
|
|
TOUCH_TOOL_FINGER = 1 << 10,
|
|
|
|
|
TOUCH_TOOL_STYLUS = 2 << 10,
|
|
|
|
|
TOUCH_TOOL_MOUSE = 3 << 10,
|
|
|
|
|
TOUCH_TOOL_ERASER = 4 << 10,
|
2013-05-03 00:21:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Used for asynchronous touch input.
|
|
|
|
|
// DOWN is always on its own.
|
|
|
|
|
// MOVE and UP can be combined.
|
|
|
|
|
struct TouchInput {
|
|
|
|
|
float x;
|
|
|
|
|
float y;
|
2017-03-14 22:16:09 -07:00
|
|
|
int id; // Needs to be <= GestureDetector::MAX_PTRS (10.)
|
2013-05-03 00:21:39 +02:00
|
|
|
int flags;
|
|
|
|
|
double timestamp;
|
|
|
|
|
};
|
|
|
|
|
|
2013-07-07 17:46:37 +10:00
|
|
|
#undef KEY_DOWN
|
2013-07-08 12:34:39 +02:00
|
|
|
#undef KEY_UP
|
2013-07-07 17:46:37 +10:00
|
|
|
|
2013-07-06 19:07:48 +02:00
|
|
|
enum {
|
2014-02-05 20:01:33 +01:00
|
|
|
KEY_DOWN = 1 << 0,
|
|
|
|
|
KEY_UP = 1 << 1,
|
|
|
|
|
KEY_HASWHEELDELTA = 1 << 2,
|
2014-06-15 13:04:10 +02:00
|
|
|
KEY_IS_REPEAT = 1 << 3,
|
2014-06-29 23:31:09 +02:00
|
|
|
KEY_CHAR = 1 << 4, // Unicode character input. Cannot detect keyups of these so KEY_DOWN and KEY_UP are zero when this is set.
|
2013-07-06 19:07:48 +02:00
|
|
|
};
|
2013-06-24 21:47:29 -07:00
|
|
|
|
2013-07-06 19:07:48 +02:00
|
|
|
struct KeyInput {
|
2013-07-09 16:33:05 +02:00
|
|
|
KeyInput() {}
|
2023-05-26 18:40:13 +02:00
|
|
|
KeyInput(InputDeviceID devId, InputKeyCode code, int fl) : deviceId(devId), keyCode(code), flags(fl) {}
|
|
|
|
|
KeyInput(InputDeviceID devId, int unicode) : deviceId(devId), unicodeChar(unicode), flags(KEY_CHAR) {}
|
|
|
|
|
InputDeviceID deviceId;
|
|
|
|
|
union {
|
|
|
|
|
InputKeyCode keyCode; // Android keycodes are the canonical keycodes, everyone else map to them.
|
|
|
|
|
int unicodeChar; // for KEY_CHAR
|
|
|
|
|
};
|
2013-07-06 19:07:48 +02:00
|
|
|
int flags;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct AxisInput {
|
2023-05-26 18:40:13 +02:00
|
|
|
InputDeviceID deviceId;
|
|
|
|
|
InputAxis axisId;
|
2013-07-06 19:07:48 +02:00
|
|
|
float value;
|
|
|
|
|
};
|
2013-07-15 17:37:16 +02:00
|
|
|
|
2013-08-22 06:45:45 -04:00
|
|
|
// Is there a nicer place for this stuff? It's here to avoid dozens of linking errors in UnitTest..
|
2023-03-29 11:59:31 +02:00
|
|
|
extern std::vector<InputMapping> dpadKeys;
|
|
|
|
|
extern std::vector<InputMapping> confirmKeys;
|
|
|
|
|
extern std::vector<InputMapping> cancelKeys;
|
|
|
|
|
extern std::vector<InputMapping> tabLeftKeys;
|
|
|
|
|
extern std::vector<InputMapping> tabRightKeys;
|
|
|
|
|
void SetDPadKeys(const std::vector<InputMapping> &leftKey, const std::vector<InputMapping> &rightKey,
|
|
|
|
|
const std::vector<InputMapping> &upKey, const std::vector<InputMapping> &downKey);
|
|
|
|
|
void SetConfirmCancelKeys(const std::vector<InputMapping> &confirm, const std::vector<InputMapping> &cancel);
|
|
|
|
|
void SetTabLeftRightKeys(const std::vector<InputMapping> &tabLeft, const std::vector<InputMapping> &tabRight);
|
2021-04-04 08:39:49 -07:00
|
|
|
|
|
|
|
|
// 0 means unknown (attempt autodetect), -1 means flip, 1 means original direction.
|
2023-05-26 18:40:13 +02:00
|
|
|
void SetAnalogFlipY(std::unordered_map<InputDeviceID, int> flipYByDeviceId);
|
|
|
|
|
int GetAnalogYDirection(InputDeviceID deviceId);
|