mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-23 16:19:44 +00:00
Add KeyMap key translation layer
This commit is contained in:
parent
45b2c62ddf
commit
8ea13cd3ed
@ -244,6 +244,8 @@ add_library(Common STATIC
|
||||
Common/FileUtil.h
|
||||
Common/Hash.cpp
|
||||
Common/Hash.h
|
||||
Common/KeyMap.cpp
|
||||
Common/KeyMap.h
|
||||
Common/LogManager.cpp
|
||||
Common/LogManager.h
|
||||
Common/MathUtil.cpp
|
||||
|
285
Common/KeyMap.cpp
Normal file
285
Common/KeyMap.cpp
Normal file
@ -0,0 +1,285 @@
|
||||
// Copyright (c) 2013- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "input/input_state.h"
|
||||
#include "Core/Config.h"
|
||||
#include "KeyMap.h"
|
||||
|
||||
using namespace KeyMap;
|
||||
|
||||
/* Platform specific
|
||||
* default */
|
||||
std::map<int,int> *platform_keymap = NULL;
|
||||
|
||||
/* Default key mapping */
|
||||
/* Ugly, yet the cleanest way
|
||||
* I could find to create a
|
||||
* static map.
|
||||
* Still nicer than what
|
||||
* I once did in C. */
|
||||
struct DefaultKeyMap {
|
||||
static std::map<int,int> init()
|
||||
// TODO: Fix this indentation, spaces to tabs
|
||||
{
|
||||
std::map<int,int> m;
|
||||
m[KEY_x] = PAD_BUTTON_A;
|
||||
m[KEY_z] = PAD_BUTTON_B;
|
||||
m[KEY_s] = PAD_BUTTON_X;
|
||||
m[KEY_a] = PAD_BUTTON_Y;
|
||||
m[KEY_q] = PAD_BUTTON_LBUMPER;
|
||||
m[KEY_w] = PAD_BUTTON_RBUMPER;
|
||||
m[KEY_SPACE] = PAD_BUTTON_START;
|
||||
m[KEY_ENTER] = PAD_BUTTON_SELECT;
|
||||
m[KEY_ARROW_UP] = PAD_BUTTON_UP;
|
||||
m[KEY_ARROW_DOWN] = PAD_BUTTON_DOWN;
|
||||
m[KEY_ARROW_LEFT] = PAD_BUTTON_LEFT;
|
||||
m[KEY_ARROW_RIGHT] = PAD_BUTTON_RIGHT;
|
||||
m[KEY_TAB] = PAD_BUTTON_MENU;
|
||||
m[KEY_BACKSPACE] = PAD_BUTTON_BACK;
|
||||
m[KEY_ANALOG_FAKE_UP] = PAD_BUTTON_JOY_UP;
|
||||
m[KEY_ANALOG_FAKE_DOWN] = PAD_BUTTON_JOY_DOWN;
|
||||
m[KEY_ANALOG_FAKE_LEFT] = PAD_BUTTON_JOY_LEFT;
|
||||
m[KEY_ANALOG_FAKE_RIGHT] = PAD_BUTTON_JOY_RIGHT;
|
||||
m[KEY_CTRL_LEFT] = PAD_BUTTON_LEFT_THUMB;
|
||||
m[KEY_ALT_LEFT] = PAD_BUTTON_RIGHT_THUMB;
|
||||
return m;
|
||||
}
|
||||
static std::map<int,int> KeyMap;
|
||||
|
||||
};
|
||||
|
||||
std::map<int,int> DefaultKeyMap::KeyMap = DefaultKeyMap::init();
|
||||
|
||||
/* Key & Button names */
|
||||
struct KeyMap_IntStrPair {
|
||||
int key;
|
||||
std::string name;
|
||||
};
|
||||
const KeyMap_IntStrPair key_names[] = {
|
||||
{KEY_a, "a"},
|
||||
{KEY_b, "B"},
|
||||
{KEY_c, "c"},
|
||||
{KEY_d, "d"},
|
||||
{KEY_e, "e"},
|
||||
{KEY_f, "f"},
|
||||
{KEY_g, "g"},
|
||||
{KEY_h, "h"},
|
||||
{KEY_i, "i"},
|
||||
{KEY_j, "j"},
|
||||
{KEY_k, "k"},
|
||||
{KEY_l, "l"},
|
||||
{KEY_m, "m"},
|
||||
{KEY_n, "n"},
|
||||
{KEY_o, "o"},
|
||||
{KEY_p, "p"},
|
||||
{KEY_q, "q"},
|
||||
{KEY_r, "r"},
|
||||
{KEY_s, "s"},
|
||||
{KEY_t, "t"},
|
||||
{KEY_u, "u"},
|
||||
{KEY_v, "v"},
|
||||
{KEY_w, "w"},
|
||||
{KEY_x, "x"},
|
||||
{KEY_y, "y"},
|
||||
{KEY_z, "z"},
|
||||
{KEY_1, "1"},
|
||||
{KEY_2, "2"},
|
||||
{KEY_3, "3"},
|
||||
{KEY_4, "4"},
|
||||
{KEY_5, "5"},
|
||||
{KEY_6, "6"},
|
||||
{KEY_7, "7"},
|
||||
{KEY_8, "8"},
|
||||
{KEY_9, "9"},
|
||||
{KEY_0, "0"},
|
||||
|
||||
{KEY_BACKSPACE, "Backspace"},
|
||||
{KEY_TAB, "Tab"},
|
||||
{KEY_ENTER, "Enter"},
|
||||
{KEY_SHIFT_LEFT, "Shift"},
|
||||
{KEY_SHIFT_RIGHT, "Shift"},
|
||||
{KEY_CTRL_LEFT, "Ctrl"},
|
||||
{KEY_CTRL_RIGHT, "Ctrl"},
|
||||
{KEY_ALT_LEFT, "Alt"},
|
||||
{KEY_ALT_RIGHT, "Alt"},
|
||||
{KEY_SPACE, "Space"},
|
||||
{KEY_SUPER, "Super"},
|
||||
{KEY_SPACE, "Space"},
|
||||
|
||||
{KEY_VOLUME_UP, "Vol Up"},
|
||||
{KEY_VOLUME_DOWN, "Vol Down"},
|
||||
{KEY_HOME, "Home"},
|
||||
{KEY_CALL_START, "Start Call"},
|
||||
{KEY_CALL_END, "End Call"},
|
||||
|
||||
{KEY_ARROW_LEFT, "Left"},
|
||||
{KEY_ARROW_UP, "Up"},
|
||||
{KEY_ARROW_RIGHT, "Right"},
|
||||
{KEY_ARROW_DOWN, "Down"},
|
||||
|
||||
{KEY_EXTRA1, "Extra1"},
|
||||
{KEY_EXTRA2, "Extra2"},
|
||||
{KEY_EXTRA3, "Extra3"},
|
||||
{KEY_EXTRA4, "Extra4"},
|
||||
{KEY_EXTRA5, "Extra5"},
|
||||
{KEY_EXTRA6, "Extra6"},
|
||||
{KEY_EXTRA7, "Extra7"},
|
||||
{KEY_EXTRA8, "Extra8"},
|
||||
{KEY_EXTRA9, "Extra9"},
|
||||
{KEY_EXTRA0, "Extra0"},
|
||||
};
|
||||
static int key_names_count = sizeof(key_names) / sizeof(key_names[0]);
|
||||
static std::string unknown_key_name = "Unknown";
|
||||
const KeyMap_IntStrPair psp_button_names[] = {
|
||||
{PAD_BUTTON_A, "O"},
|
||||
{PAD_BUTTON_B, "X"},
|
||||
{PAD_BUTTON_X, "[]"}, // TODO: use proper unicode symbol
|
||||
{PAD_BUTTON_Y, "^"},
|
||||
{PAD_BUTTON_LBUMPER, "L"},
|
||||
{PAD_BUTTON_RBUMPER, "R"},
|
||||
{PAD_BUTTON_START, "Start"},
|
||||
{PAD_BUTTON_SELECT, "Select"},
|
||||
{PAD_BUTTON_UP, "Up"},
|
||||
{PAD_BUTTON_DOWN, "Down"},
|
||||
{PAD_BUTTON_LEFT, "Left"},
|
||||
{PAD_BUTTON_RIGHT, "Right"},
|
||||
|
||||
{PAD_BUTTON_MENU, "Menu"},
|
||||
{PAD_BUTTON_BACK, "Back"},
|
||||
|
||||
{PAD_BUTTON_JOY_UP, "Analog Up"},
|
||||
{PAD_BUTTON_JOY_DOWN, "Analog Down"},
|
||||
{PAD_BUTTON_JOY_LEFT, "Analog Left"},
|
||||
{PAD_BUTTON_JOY_RIGHT, "Analog Right"},
|
||||
|
||||
{PAD_BUTTON_LEFT_THUMB, "Left analog click"},
|
||||
{PAD_BUTTON_RIGHT_THUMB, "Right analog click"},
|
||||
};
|
||||
static int psp_button_names_count = sizeof(psp_button_names) / sizeof(psp_button_names[0]);
|
||||
|
||||
|
||||
static std::string FindName(int key, const KeyMap_IntStrPair list[], int size)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
if (list[i].key == key)
|
||||
return list[i].name;
|
||||
|
||||
return unknown_key_name;
|
||||
}
|
||||
|
||||
static std::string KeyMap::GetKeyName(KeyMap::Key key)
|
||||
{
|
||||
return FindName((int)key, key_names, key_names_count);
|
||||
}
|
||||
|
||||
static std::string KeyMap::GetPspButtonName(int btn)
|
||||
{
|
||||
return FindName(btn, key_names, key_names_count);
|
||||
}
|
||||
|
||||
static bool FindKeyMapping(int key, int *map_id, int *psp_button)
|
||||
{
|
||||
std::map<int,int>::iterator it;
|
||||
if (*map_id >= 0) {
|
||||
// check user configuration
|
||||
std::map<int,int> user_map = g_Config.iMappingMap;
|
||||
it = user_map.find(key);
|
||||
if (it != user_map.end()) {
|
||||
*map_id = 0;
|
||||
*psp_button = it->second;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (*map_id >= 1 && platform_keymap != NULL) {
|
||||
// check optional platform specific keymap
|
||||
std::map<int,int> port_map = *platform_keymap;
|
||||
it = port_map.find(key);
|
||||
if (it != port_map.end()) {
|
||||
*map_id = 1;
|
||||
*psp_button = it->second;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (*map_id >= 2) {
|
||||
// check default keymap
|
||||
const std::map<int,int> default_map = DefaultKeyMap::KeyMap;
|
||||
const std::map<int,int>::const_iterator it = default_map.find(key);
|
||||
if (it != default_map.end()) {
|
||||
*map_id = 2;
|
||||
*psp_button = it->second;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
*map_id = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int KeyMap::KeyToPspButton(const KeyMap::Key key)
|
||||
{
|
||||
int search_start_layer = 0;
|
||||
int psp_button;
|
||||
|
||||
if (FindKeyMapping((int)key, &search_start_layer, &psp_button))
|
||||
return psp_button;
|
||||
|
||||
return KEYMAP_ERROR_UNKNOWN_KEY;
|
||||
}
|
||||
|
||||
static bool KeyMap::IsMappedKey(Key key)
|
||||
{
|
||||
return KeyMap::KeyToPspButton(key) != KEYMAP_ERROR_UNKNOWN_KEY;
|
||||
}
|
||||
|
||||
|
||||
static std::string KeyMap::NamePspButtonFromKey(KeyMap::Key key)
|
||||
{
|
||||
return KeyMap::GetPspButtonName(KeyMap::KeyToPspButton(key));
|
||||
}
|
||||
|
||||
static std::string KeyMap::NameKeyFromPspButton(int btn)
|
||||
{
|
||||
// We drive our iteration
|
||||
// with the list of key names.
|
||||
for (int i = 0; i < key_names_count; i++) {
|
||||
const struct KeyMap_IntStrPair *key_name = key_names + i;
|
||||
if (btn == KeyMap::KeyToPspButton((KeyMap::Key)key_name->key))
|
||||
return key_name->name;
|
||||
}
|
||||
|
||||
// all psp buttons are mapped from some key
|
||||
// but it appears we do not have a name
|
||||
// for this key.
|
||||
return unknown_key_name;
|
||||
}
|
||||
|
||||
static int KeyMap::SetKeyMapping(KeyMap::Key key, int btn)
|
||||
{
|
||||
if (KeyMap::IsMappedKey(key))
|
||||
return KEYMAP_ERROR_KEY_ALREADY_USED;
|
||||
|
||||
g_Config.iMappingMap[key] = btn;
|
||||
}
|
||||
|
||||
// TODO: implement RegisterPlatformDefaultKeyMap()
|
188
Common/KeyMap.h
Normal file
188
Common/KeyMap.h
Normal file
@ -0,0 +1,188 @@
|
||||
// Copyright (c) 2013- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#define KEYMAP_ERROR_KEY_ALREADY_USED -1
|
||||
#define KEYMAP_ERROR_UNKNOWN_KEY 0
|
||||
|
||||
/* KeyMap
|
||||
* A translation layer for
|
||||
* key assignment. Provides
|
||||
* integration with Core's
|
||||
* config state.
|
||||
*
|
||||
* Does not handle input
|
||||
* state managment.
|
||||
*
|
||||
* Platform ports should
|
||||
* map their platform's
|
||||
* keys to KeyMap's keys.
|
||||
* Then have KeyMap transform
|
||||
* those into psp buttons.
|
||||
*/
|
||||
namespace KeyMap {
|
||||
enum Key {
|
||||
/* Lower class latin */
|
||||
KEY_q = 1, // top row
|
||||
KEY_w,
|
||||
KEY_e,
|
||||
KEY_r,
|
||||
KEY_t,
|
||||
KEY_y,
|
||||
KEY_u,
|
||||
KEY_i,
|
||||
KEY_o,
|
||||
KEY_p,
|
||||
|
||||
KEY_a, // mid row
|
||||
KEY_s,
|
||||
KEY_d,
|
||||
KEY_f,
|
||||
KEY_g,
|
||||
KEY_h,
|
||||
KEY_j,
|
||||
KEY_k,
|
||||
KEY_l,
|
||||
|
||||
KEY_z, // low row
|
||||
KEY_x,
|
||||
KEY_c,
|
||||
KEY_v,
|
||||
KEY_b,
|
||||
KEY_n,
|
||||
KEY_m,
|
||||
|
||||
/* Numeric */
|
||||
KEY_1,
|
||||
KEY_2,
|
||||
KEY_3,
|
||||
KEY_4,
|
||||
KEY_5,
|
||||
KEY_6,
|
||||
KEY_7,
|
||||
KEY_8,
|
||||
KEY_9,
|
||||
KEY_0,
|
||||
|
||||
/* Special keys */
|
||||
KEY_ARROW_LEFT,
|
||||
KEY_ARROW_RIGHT,
|
||||
KEY_ARROW_UP,
|
||||
KEY_ARROW_DOWN,
|
||||
|
||||
KEY_ANALOG_FAKE_LEFT,
|
||||
KEY_ANALOG_FAKE_RIGHT,
|
||||
KEY_ANALOG_FAKE_UP,
|
||||
KEY_ANALOG_FAKE_DOWN,
|
||||
|
||||
KEY_SPACE,
|
||||
KEY_ENTER,
|
||||
KEY_CTRL_LEFT,
|
||||
KEY_CTRL_RIGHT,
|
||||
KEY_SHIFT_LEFT,
|
||||
KEY_SHIFT_RIGHT,
|
||||
KEY_ALT_LEFT,
|
||||
KEY_ALT_RIGHT,
|
||||
KEY_BACKSPACE,
|
||||
KEY_SUPER,
|
||||
KEY_TAB,
|
||||
|
||||
/* Mobile Keys */
|
||||
KEY_VOLUME_UP,
|
||||
KEY_VOLUME_DOWN,
|
||||
KEY_HOME,
|
||||
KEY_CALL_START,
|
||||
KEY_CALL_END,
|
||||
|
||||
/* Extra keys
|
||||
* Use for platform specific keys.
|
||||
* Example: android's back btn */
|
||||
KEY_EXTRA1,
|
||||
KEY_EXTRA2,
|
||||
KEY_EXTRA3,
|
||||
KEY_EXTRA4,
|
||||
KEY_EXTRA5,
|
||||
KEY_EXTRA6,
|
||||
KEY_EXTRA7,
|
||||
KEY_EXTRA8,
|
||||
KEY_EXTRA9,
|
||||
KEY_EXTRA0,
|
||||
|
||||
// TODO: Add fastforward key
|
||||
// TODO: Add any missing keys.
|
||||
// Many can be found in the
|
||||
// window's port's keyboard
|
||||
// files.
|
||||
};
|
||||
|
||||
/* Use if you need to
|
||||
* display the textual
|
||||
* name
|
||||
* These functions are not
|
||||
* fast, do not call them
|
||||
* a million times. */
|
||||
static std::string GetKeyName(Key);
|
||||
static std::string GetPspButtonName(int);
|
||||
|
||||
/* Use if to translate
|
||||
* KeyMap Keys to PSP
|
||||
* buttons.
|
||||
* You should have
|
||||
* already translated
|
||||
* your platform's keys
|
||||
* to KeyMap keys.
|
||||
*
|
||||
* Returns KEYMAP_ERROR_UNKNOWN_KEY
|
||||
* for any unmapped key */
|
||||
static int KeyToPspButton(Key);
|
||||
|
||||
static bool IsMappedKey(Key);
|
||||
|
||||
/* Might be usful if you want
|
||||
* to provide hints to users
|
||||
* upon mapping conflicts */
|
||||
static std::string NamePspButtonFromKey(Key);
|
||||
|
||||
/* Use for showing the existing
|
||||
* key mapping. */
|
||||
static std::string NameKeyFromPspButton(int);
|
||||
|
||||
/* Configure the key mapping.
|
||||
* Any configuration will
|
||||
* be saved to the Core
|
||||
* config.
|
||||
*
|
||||
* Returns KEYMAP_ERROR_KEY_ALREADY_USED
|
||||
* for mapping conflicts. 0 otherwise. */
|
||||
static int SetKeyMapping(Key, int);
|
||||
|
||||
/* Platform specific keymaps
|
||||
* override KeyMap's defaults.
|
||||
* They do not override user's
|
||||
* configuration.
|
||||
* A platform default keymap
|
||||
* does not need to cover
|
||||
* all psp buttons.
|
||||
* Any buttons missing will
|
||||
* fallback to KeyMap's keymap. */
|
||||
static int RegisterPlatformDefaultKeyMap(std::map<int,int> *);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user