mirror of
https://github.com/libretro/RetroArch
synced 2025-02-21 18:40:09 +00:00
Merge pull request #72 from meancoot/master
Allow libretro core to receive keyboard input using events rather than polling.
This commit is contained in:
commit
3c5aec41a1
@ -482,6 +482,15 @@ static bool environment_cb(unsigned cmd, void *data)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK:
|
||||||
|
{
|
||||||
|
const struct retro_keyboard_callback *info = (const struct retro_keyboard_callback*)data;
|
||||||
|
|
||||||
|
g_extern.system.key_event = info->callback;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
RARCH_LOG("Environ UNSUPPORTED (#%u).\n", cmd);
|
RARCH_LOG("Environ UNSUPPORTED (#%u).\n", cmd);
|
||||||
|
@ -324,6 +324,8 @@ struct global
|
|||||||
bool force_nonblock;
|
bool force_nonblock;
|
||||||
|
|
||||||
const char *input_desc_btn[MAX_PLAYERS][RARCH_FIRST_CUSTOM_BIND];
|
const char *input_desc_btn[MAX_PLAYERS][RARCH_FIRST_CUSTOM_BIND];
|
||||||
|
|
||||||
|
retro_keyboard_event_t key_event;
|
||||||
} system;
|
} system;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
|
@ -49,6 +49,108 @@ static bool g_is_double;
|
|||||||
|
|
||||||
static int (*g_pglSwapInterval)(int);
|
static int (*g_pglSwapInterval)(int);
|
||||||
|
|
||||||
|
struct key_bind
|
||||||
|
{
|
||||||
|
unsigned x;
|
||||||
|
enum retro_key sk;
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned keysym_lut[RETROK_LAST];
|
||||||
|
|
||||||
|
static const struct key_bind lut_binds[] = {
|
||||||
|
{ XK_Left, RETROK_LEFT },
|
||||||
|
{ XK_Right, RETROK_RIGHT },
|
||||||
|
{ XK_Up, RETROK_UP },
|
||||||
|
{ XK_Down, RETROK_DOWN },
|
||||||
|
{ XK_Return, RETROK_RETURN },
|
||||||
|
{ XK_Tab, RETROK_TAB },
|
||||||
|
{ XK_Insert, RETROK_INSERT },
|
||||||
|
{ XK_Home, RETROK_HOME },
|
||||||
|
{ XK_End, RETROK_END },
|
||||||
|
{ XK_Page_Up, RETROK_PAGEUP },
|
||||||
|
{ XK_Page_Down, RETROK_PAGEDOWN },
|
||||||
|
{ XK_Delete, RETROK_DELETE },
|
||||||
|
{ XK_Shift_R, RETROK_RSHIFT },
|
||||||
|
{ XK_Shift_L, RETROK_LSHIFT },
|
||||||
|
{ XK_Control_L, RETROK_LCTRL },
|
||||||
|
{ XK_Alt_L, RETROK_LALT },
|
||||||
|
{ XK_space, RETROK_SPACE },
|
||||||
|
{ XK_Escape, RETROK_ESCAPE },
|
||||||
|
{ XK_BackSpace, RETROK_BACKSPACE },
|
||||||
|
{ XK_KP_Enter, RETROK_KP_ENTER },
|
||||||
|
{ XK_KP_Add, RETROK_KP_PLUS },
|
||||||
|
{ XK_KP_Subtract, RETROK_KP_MINUS },
|
||||||
|
{ XK_KP_Multiply, RETROK_KP_MULTIPLY },
|
||||||
|
{ XK_KP_Divide, RETROK_KP_DIVIDE },
|
||||||
|
{ XK_grave, RETROK_BACKQUOTE },
|
||||||
|
{ XK_Pause, RETROK_PAUSE },
|
||||||
|
{ XK_KP_0, RETROK_KP0 },
|
||||||
|
{ XK_KP_1, RETROK_KP1 },
|
||||||
|
{ XK_KP_2, RETROK_KP2 },
|
||||||
|
{ XK_KP_3, RETROK_KP3 },
|
||||||
|
{ XK_KP_4, RETROK_KP4 },
|
||||||
|
{ XK_KP_5, RETROK_KP5 },
|
||||||
|
{ XK_KP_6, RETROK_KP6 },
|
||||||
|
{ XK_KP_7, RETROK_KP7 },
|
||||||
|
{ XK_KP_8, RETROK_KP8 },
|
||||||
|
{ XK_KP_9, RETROK_KP9 },
|
||||||
|
{ XK_0, RETROK_0 },
|
||||||
|
{ XK_1, RETROK_1 },
|
||||||
|
{ XK_2, RETROK_2 },
|
||||||
|
{ XK_3, RETROK_3 },
|
||||||
|
{ XK_4, RETROK_4 },
|
||||||
|
{ XK_5, RETROK_5 },
|
||||||
|
{ XK_6, RETROK_6 },
|
||||||
|
{ XK_7, RETROK_7 },
|
||||||
|
{ XK_8, RETROK_8 },
|
||||||
|
{ XK_9, RETROK_9 },
|
||||||
|
{ XK_F1, RETROK_F1 },
|
||||||
|
{ XK_F2, RETROK_F2 },
|
||||||
|
{ XK_F3, RETROK_F3 },
|
||||||
|
{ XK_F4, RETROK_F4 },
|
||||||
|
{ XK_F5, RETROK_F5 },
|
||||||
|
{ XK_F6, RETROK_F6 },
|
||||||
|
{ XK_F7, RETROK_F7 },
|
||||||
|
{ XK_F8, RETROK_F8 },
|
||||||
|
{ XK_F9, RETROK_F9 },
|
||||||
|
{ XK_F10, RETROK_F10 },
|
||||||
|
{ XK_F11, RETROK_F11 },
|
||||||
|
{ XK_F12, RETROK_F12 },
|
||||||
|
{ XK_a, RETROK_a },
|
||||||
|
{ XK_b, RETROK_b },
|
||||||
|
{ XK_c, RETROK_c },
|
||||||
|
{ XK_d, RETROK_d },
|
||||||
|
{ XK_e, RETROK_e },
|
||||||
|
{ XK_f, RETROK_f },
|
||||||
|
{ XK_g, RETROK_g },
|
||||||
|
{ XK_h, RETROK_h },
|
||||||
|
{ XK_i, RETROK_i },
|
||||||
|
{ XK_j, RETROK_j },
|
||||||
|
{ XK_k, RETROK_k },
|
||||||
|
{ XK_l, RETROK_l },
|
||||||
|
{ XK_m, RETROK_m },
|
||||||
|
{ XK_n, RETROK_n },
|
||||||
|
{ XK_o, RETROK_o },
|
||||||
|
{ XK_p, RETROK_p },
|
||||||
|
{ XK_q, RETROK_q },
|
||||||
|
{ XK_r, RETROK_r },
|
||||||
|
{ XK_s, RETROK_s },
|
||||||
|
{ XK_t, RETROK_t },
|
||||||
|
{ XK_u, RETROK_u },
|
||||||
|
{ XK_v, RETROK_v },
|
||||||
|
{ XK_w, RETROK_w },
|
||||||
|
{ XK_x, RETROK_x },
|
||||||
|
{ XK_y, RETROK_y },
|
||||||
|
{ XK_z, RETROK_z },
|
||||||
|
};
|
||||||
|
|
||||||
|
static void init_lut(void)
|
||||||
|
{
|
||||||
|
memset(keysym_lut, 0, sizeof(keysym_lut));
|
||||||
|
for (unsigned i = 0; i < sizeof(lut_binds) / sizeof(lut_binds[0]); i++)
|
||||||
|
keysym_lut[lut_binds[i].sk] = lut_binds[i].x;
|
||||||
|
}
|
||||||
|
|
||||||
static void sighandler(int sig)
|
static void sighandler(int sig)
|
||||||
{
|
{
|
||||||
(void)sig;
|
(void)sig;
|
||||||
@ -113,6 +215,36 @@ static void gfx_ctx_check_window(bool *quit,
|
|||||||
case UnmapNotify:
|
case UnmapNotify:
|
||||||
g_has_focus = false;
|
g_has_focus = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case KeyPress:
|
||||||
|
case KeyRelease:
|
||||||
|
if (g_extern.system.key_event)
|
||||||
|
{
|
||||||
|
static XComposeStatus state;
|
||||||
|
char keybuf[32];
|
||||||
|
const unsigned x_keycode = XKeycodeToKeysym(g_dpy, event.xkey.keycode, 0);
|
||||||
|
|
||||||
|
bool down = event.type == KeyPress;
|
||||||
|
uint32_t character = 0;
|
||||||
|
unsigned key = RETROK_UNKNOWN;
|
||||||
|
|
||||||
|
for (int i = 0; i != RETROK_LAST; i ++)
|
||||||
|
{
|
||||||
|
if (keysym_lut[i] == x_keycode)
|
||||||
|
{
|
||||||
|
key = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (down && XLookupString(&event.xkey, keybuf, sizeof(keybuf), 0, &state))
|
||||||
|
{
|
||||||
|
character = keybuf[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
g_extern.system.key_event(down, key, character, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,6 +324,8 @@ static bool gfx_ctx_init(void)
|
|||||||
|
|
||||||
g_quit = 0;
|
g_quit = 0;
|
||||||
|
|
||||||
|
init_lut();
|
||||||
|
|
||||||
g_dpy = XOpenDisplay(NULL);
|
g_dpy = XOpenDisplay(NULL);
|
||||||
if (!g_dpy)
|
if (!g_dpy)
|
||||||
goto error;
|
goto error;
|
||||||
@ -249,7 +383,7 @@ static bool gfx_ctx_set_video_mode(
|
|||||||
|
|
||||||
swa.colormap = g_cmap = XCreateColormap(g_dpy, RootWindow(g_dpy, vi->screen),
|
swa.colormap = g_cmap = XCreateColormap(g_dpy, RootWindow(g_dpy, vi->screen),
|
||||||
vi->visual, AllocNone);
|
vi->visual, AllocNone);
|
||||||
swa.event_mask = StructureNotifyMask;
|
swa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask;
|
||||||
swa.override_redirect = fullscreen ? True : False;
|
swa.override_redirect = fullscreen ? True : False;
|
||||||
|
|
||||||
if (fullscreen && !windowed_full)
|
if (fullscreen && !windowed_full)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* RetroArch - A frontend for libretro.
|
/* RetroArch - A frontend for libretro.
|
||||||
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
|
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
|
||||||
*
|
*
|
||||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
* RetroArch 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 Found-
|
* of the GNU General Public License as published by the Free Software Found-
|
||||||
* ation, either version 3 of the License, or (at your option) any later version.
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
@ -70,11 +70,11 @@ static void gfx_ctx_swap_interval(unsigned interval)
|
|||||||
GL_SYM_WRAP(glx_swap_interval, "glXSwapInterval");
|
GL_SYM_WRAP(glx_swap_interval, "glXSwapInterval");
|
||||||
if (!glx_swap_interval)
|
if (!glx_swap_interval)
|
||||||
GL_SYM_WRAP(glx_swap_interval, "glXSwapIntervalMESA");
|
GL_SYM_WRAP(glx_swap_interval, "glXSwapIntervalMESA");
|
||||||
if (!glx_swap_interval)
|
if (!glx_swap_interval)
|
||||||
GL_SYM_WRAP(glx_swap_interval, "glXSwapIntervalSGI");
|
GL_SYM_WRAP(glx_swap_interval, "glXSwapIntervalSGI");
|
||||||
if (glx_swap_interval)
|
if (glx_swap_interval)
|
||||||
success = glx_swap_interval(g_interval) == 0;
|
success = glx_swap_interval(g_interval) == 0;
|
||||||
else
|
else
|
||||||
RARCH_WARN("Could not find GLX VSync call.\n");
|
RARCH_WARN("Could not find GLX VSync call.\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -118,7 +118,7 @@ static bool gfx_ctx_init(void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gfx_ctx_destroy(void)
|
static void gfx_ctx_destroy(void)
|
||||||
{
|
{
|
||||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||||
g_inited = false;
|
g_inited = false;
|
||||||
@ -254,6 +254,34 @@ static void gfx_ctx_check_window(bool *quit,
|
|||||||
*width = event.resize.w;
|
*width = event.resize.w;
|
||||||
*height = event.resize.h;
|
*height = event.resize.h;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
case SDL_KEYUP:
|
||||||
|
if (g_extern.system.key_event)
|
||||||
|
{
|
||||||
|
SDL_EnableUNICODE(true);
|
||||||
|
|
||||||
|
uint16_t mods = 0;
|
||||||
|
|
||||||
|
if (event.key.keysym.mod)
|
||||||
|
{
|
||||||
|
mods |= (event.key.keysym.mod & KMOD_CTRL) ? RETROKMOD_CTRL : 0;
|
||||||
|
mods |= (event.key.keysym.mod & KMOD_ALT) ? RETROKMOD_ALT : 0;
|
||||||
|
mods |= (event.key.keysym.mod & KMOD_SHIFT) ? RETROKMOD_SHIFT : 0;
|
||||||
|
mods |= (event.key.keysym.mod & KMOD_META) ? RETROKMOD_META : 0;
|
||||||
|
mods |= (event.key.keysym.mod & KMOD_NUM) ? RETROKMOD_NUMLOCK : 0;
|
||||||
|
mods |= (event.key.keysym.mod & KMOD_CAPS) ? RETROKMOD_CAPSLOCK : 0;
|
||||||
|
|
||||||
|
// TODO: What is KMOD_MODE in SDL?
|
||||||
|
mods |= (event.key.keysym.mod & KMOD_MODE) ? RETROKMOD_SCROLLOCK : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For now it seems that all RETROK_* constant values match the SDLK_* values.
|
||||||
|
// Ultimately the table in sdl_input.c should be used in case this changes.
|
||||||
|
// TODO: event.key.keysym.unicode is UTF-16
|
||||||
|
g_extern.system.key_event(event.type == SDL_KEYDOWN, event.key.keysym.sym, event.key.keysym.unicode, mods);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
libretro.h
32
libretro.h
@ -310,6 +310,21 @@ enum retro_key
|
|||||||
RETROK_LAST
|
RETROK_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum retro_mod
|
||||||
|
{
|
||||||
|
RETROKMOD_NONE = 0x0000,
|
||||||
|
|
||||||
|
RETROKMOD_SHIFT = 0x01,
|
||||||
|
RETROKMOD_CTRL = 0x02,
|
||||||
|
RETROKMOD_ALT = 0x04,
|
||||||
|
RETROKMOD_META = 0x08,
|
||||||
|
|
||||||
|
RETROKMOD_NUMLOCK = 0x10,
|
||||||
|
RETROKMOD_CAPSLOCK = 0x20,
|
||||||
|
RETROKMOD_SCROLLOCK = 0x40
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Environment commands.
|
// Environment commands.
|
||||||
#define RETRO_ENVIRONMENT_SET_ROTATION 1 // const unsigned * --
|
#define RETRO_ENVIRONMENT_SET_ROTATION 1 // const unsigned * --
|
||||||
// Sets screen rotation of graphics.
|
// Sets screen rotation of graphics.
|
||||||
@ -353,7 +368,7 @@ enum retro_key
|
|||||||
//
|
//
|
||||||
// It can be used by the frontend to potentially warn
|
// It can be used by the frontend to potentially warn
|
||||||
// about too demanding implementations.
|
// about too demanding implementations.
|
||||||
//
|
//
|
||||||
// The levels are "floating", but roughly defined as:
|
// The levels are "floating", but roughly defined as:
|
||||||
// 0: Low-powered embedded devices such as Raspberry Pi
|
// 0: Low-powered embedded devices such as Raspberry Pi
|
||||||
// 1: 6th generation consoles, such as Wii/Xbox 1, and phones, tablets, etc.
|
// 1: 6th generation consoles, such as Wii/Xbox 1, and phones, tablets, etc.
|
||||||
@ -388,8 +403,23 @@ enum retro_key
|
|||||||
// It is up to the frontend to present this in a usable way.
|
// It is up to the frontend to present this in a usable way.
|
||||||
// The array is terminated by retro_input_descriptor::description being set to NULL.
|
// The array is terminated by retro_input_descriptor::description being set to NULL.
|
||||||
// This function can be called at any time, but it is recommended to call it as early as possible.
|
// This function can be called at any time, but it is recommended to call it as early as possible.
|
||||||
|
#define RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK 12
|
||||||
|
// const struct retro_keyboard_callback * --
|
||||||
|
// Sets a callback function used to notify core about keyboard events.
|
||||||
|
|
||||||
|
|
||||||
|
// Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. Called by the frontend in response to keyboard events.
|
||||||
|
// down is set if the key is being pressed, or false if it is being released.
|
||||||
|
// keycode is the RETROK value of the char.
|
||||||
|
// character is the text character of the pressed key. (UTF-32).
|
||||||
|
// key_modifiers is a set of RETROKMOD values or'ed together.
|
||||||
|
typedef void (*retro_keyboard_event_t)(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers);
|
||||||
|
|
||||||
|
struct retro_keyboard_callback
|
||||||
|
{
|
||||||
|
retro_keyboard_event_t callback;
|
||||||
|
};
|
||||||
|
|
||||||
enum retro_pixel_format
|
enum retro_pixel_format
|
||||||
{
|
{
|
||||||
// 0RGB1555, native endian. 0 bit must be set to 0.
|
// 0RGB1555, native endian. 0 bit must be set to 0.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user