mirror of
https://github.com/libretro/RetroArch
synced 2025-02-06 18:40:49 +00:00
Merge pull request #6106 from ToadKing/emscripten-fixes
Emscripten rewrites
This commit is contained in:
commit
9b0b16e2c0
@ -554,6 +554,7 @@ endif
|
||||
ifeq ($(HAVE_EMSCRIPTEN), 1)
|
||||
OBJ += frontend/drivers/platform_emscripten.o \
|
||||
input/drivers/rwebinput_input.o \
|
||||
input/drivers_joypad/rwebpad_joypad.o \
|
||||
audio/drivers/rwebaudio.o \
|
||||
camera/drivers/rwebcam.o
|
||||
endif
|
||||
|
@ -18,7 +18,7 @@ HAVE_RPNG = 1
|
||||
HAVE_EMSCRIPTEN = 1
|
||||
HAVE_RGUI = 1
|
||||
HAVE_SDL = 0
|
||||
HAVE_SDL2 = 1
|
||||
HAVE_SDL2 = 0
|
||||
HAVE_ZLIB = 1
|
||||
WANT_ZLIB = 1
|
||||
HAVE_STATIC_VIDEO_FILTERS = 1
|
||||
@ -32,17 +32,12 @@ ifneq ($(NATIVE_ZLIB),)
|
||||
WANT_ZLIB = 0
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SDL2), 1)
|
||||
DEFINES += -DHAVE_SDL2
|
||||
endif
|
||||
|
||||
#if you compile with SDL2 flag add this Emscripten flag "-s USE_SDL=2" to LDFLAGS:
|
||||
|
||||
LIBS := -s USE_SDL=2 -s USE_ZLIB=1
|
||||
LDFLAGS := -L. --no-heap-copy -s USE_ZLIB=1 -s TOTAL_MEMORY=$(MEMORY) \
|
||||
LIBS := -s USE_ZLIB=1
|
||||
LDFLAGS := -L. --no-heap-copy -s USE_ZLIB=1 -s TOTAL_MEMORY=$(MEMORY) -s NO_EXIT_RUNTIME=0 \
|
||||
-s EXPORTED_FUNCTIONS="['_main', '_malloc', '_cmd_savefiles', '_cmd_save_state', '_cmd_load_state', '_cmd_take_screenshot']" \
|
||||
--js-library emscripten/library_rwebaudio.js \
|
||||
--js-library emscripten/library_rwebinput.js \
|
||||
--js-library emscripten/library_rwebcam.js
|
||||
ifneq ($(PTHREAD), 0)
|
||||
LDFLAGS += -s USE_PTHREADS=$(PTHREAD) -s PTHREAD_POOL_SIZE=2
|
||||
@ -50,7 +45,12 @@ endif
|
||||
|
||||
ifeq ($(ASYNC), 1)
|
||||
LDFLAGS += -s ASYNCIFY=$(ASYNC)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SDL2), 1)
|
||||
LIBS += -s USE_SDL=2
|
||||
DEFINES += -DHAVE_SDL2
|
||||
endif
|
||||
|
||||
include Makefile.common
|
||||
|
||||
|
@ -69,7 +69,7 @@ static const bool def_playlist_entry_rename = true;
|
||||
|
||||
static const unsigned int def_user_language = 0;
|
||||
|
||||
#if (defined(_WIN32) && !defined(_XBOX)) || (defined(__linux) && !defined(ANDROID) && !defined(HAVE_LAKKA)) || (defined(__MACH__) && !defined(IOS))
|
||||
#if (defined(_WIN32) && !defined(_XBOX)) || (defined(__linux) && !defined(ANDROID) && !defined(HAVE_LAKKA)) || (defined(__MACH__) && !defined(IOS)) || defined(EMSCRIPTEN)
|
||||
static const bool def_mouse_enable = true;
|
||||
#else
|
||||
static const bool def_mouse_enable = false;
|
||||
|
@ -1,143 +0,0 @@
|
||||
//"use strict";
|
||||
|
||||
var LibraryRWebInput = {
|
||||
$RI__deps: ['$Browser'],
|
||||
$RI: {
|
||||
temp: null,
|
||||
contexts: [],
|
||||
stateX: 0,
|
||||
stateY: 0,
|
||||
currentX: 0,
|
||||
currentY: 0,
|
||||
|
||||
canvasEventHandler: function(event) {
|
||||
switch (event.type) {
|
||||
case 'mouseup':
|
||||
case 'mousedown':
|
||||
var value;
|
||||
var offset;
|
||||
if (event.button === 0) offset = 40;
|
||||
else if (event.button === 2) offset = 41;
|
||||
else break;
|
||||
if (event.type === 'mouseup') value = 0;
|
||||
else value = 1;
|
||||
for (var i = 0; i < RI.contexts.length; i++) {
|
||||
{{{ makeSetValue('RI.contexts[i].state', 'offset', 'value', 'i8') }}};
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
eventHandler: function(event) {
|
||||
var i;
|
||||
switch (event.type) {
|
||||
case 'mousemove':
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
|
||||
var newX = event['clientX'] - Module.canvas.offsetLeft;
|
||||
var newY = event['clientY'] - Module.canvas.offsetTop;
|
||||
|
||||
if (newX < 0) {
|
||||
newX = 0;
|
||||
x = -Module.canvas.offsetWidth;
|
||||
} else if (newX > Module.canvas.offsetWidth) {
|
||||
newX = Module.canvas.offsetWidth;
|
||||
x = Module.canvas.offsetWidth;
|
||||
} else {
|
||||
x = newX - RI.currentX;
|
||||
}
|
||||
|
||||
if (newY < 0) {
|
||||
newY = 0;
|
||||
y = -Module.canvas.offsetHeight;
|
||||
} else if (newY > Module.canvas.offsetHeight) {
|
||||
newY = Module.canvas.offsetHeight;
|
||||
y = Module.canvas.offsetHeight;
|
||||
} else {
|
||||
y = newY - RI.currentY;
|
||||
}
|
||||
|
||||
RI.currentX = newX;
|
||||
RI.currentY = newY;
|
||||
|
||||
for (i = 0; i < RI.contexts.length; i++) {
|
||||
{{{ makeSetValue('RI.contexts[i].state', '32', 'x', 'i32') }}};
|
||||
{{{ makeSetValue('RI.contexts[i].state', '36', 'y', 'i32') }}};
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'keyup':
|
||||
case 'keydown':
|
||||
var key = event.keyCode;
|
||||
var offset = key >> 3;
|
||||
var bit = 1 << (key & 7);
|
||||
if (offset >= 32) throw 'key code error! bad code: ' + key;
|
||||
for (i = 0; i < RI.contexts.length; i++) {
|
||||
var value = {{{ makeGetValue('RI.contexts[i].state', 'offset', 'i8') }}};
|
||||
if (event.type === 'keyup') value &= ~bit;
|
||||
else value |= bit;
|
||||
{{{ makeSetValue('RI.contexts[i].state', 'offset', 'value', 'i8') }}};
|
||||
}
|
||||
event.preventDefault();
|
||||
break;
|
||||
|
||||
case 'blur':
|
||||
case 'visibilitychange':
|
||||
for (i = 0; i < RI.contexts.length; i++) {
|
||||
_memset(RI.contexts[i].state, 0, 42);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
RWebInputInit: function() {
|
||||
if (RI.contexts.length === 0) {
|
||||
document.addEventListener('keyup', RI.eventHandler, false);
|
||||
document.addEventListener('keydown', RI.eventHandler, false);
|
||||
document.addEventListener('mousemove', RI.eventHandler, false);
|
||||
Module.canvas.addEventListener('mouseup', RI.canvasEventHandler, false);
|
||||
Module.canvas.addEventListener('mousedown', RI.canvasEventHandler, false);
|
||||
document.addEventListener('blur', RI.eventHandler, false);
|
||||
document.addEventListener('onvisbilitychange', RI.eventHandler, false);
|
||||
}
|
||||
if (RI.temp === null) RI.temp = _malloc(42);
|
||||
|
||||
var s = _malloc(42);
|
||||
_memset(s, 0, 42);
|
||||
RI.contexts.push({
|
||||
state: s
|
||||
});
|
||||
return RI.contexts.length;
|
||||
},
|
||||
|
||||
RWebInputPoll: function(context) {
|
||||
context -= 1;
|
||||
var state = RI.contexts[context].state;
|
||||
_memcpy(RI.temp, state, 42);
|
||||
// reset mouse movements
|
||||
{{{ makeSetValue('RI.contexts[context].state', '32', '0', 'i32') }}};
|
||||
{{{ makeSetValue('RI.contexts[context].state', '36', '0', 'i32') }}};
|
||||
return RI.temp;
|
||||
},
|
||||
|
||||
RWebInputDestroy: function (context) {
|
||||
if (context === RI.contexts.length) {
|
||||
RI.contexts.pop();
|
||||
if (RI.contexts.length === 0) {
|
||||
document.removeEventListener('keyup', RI.eventHandler, false);
|
||||
document.removeEventListener('keydown', RI.eventHandler, false);
|
||||
document.removeEventListener('mousemove', RI.eventHandler, false);
|
||||
Module.canvas.removeEventListener('mouseup', RI.canvasEventHandler, false);
|
||||
Module.canvas.removeEventListener('mousedown', RI.canvasEventHandler, false);
|
||||
document.removeEventListener('blur', RI.eventHandler, false);
|
||||
document.removeEventListener('onvisbilitychange', RI.eventHandler, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
autoAddDeps(LibraryRWebInput, '$RI');
|
||||
mergeInto(LibraryManager.library, LibraryRWebInput);
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include <emscripten/emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <file/config_file.h>
|
||||
@ -56,7 +57,7 @@ static void emscripten_mainloop(void)
|
||||
return;
|
||||
|
||||
main_exit(NULL);
|
||||
exit(0);
|
||||
emscripten_force_exit(0);
|
||||
}
|
||||
|
||||
void cmd_savefiles(void)
|
||||
@ -169,7 +170,8 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
emscripten_set_canvas_size(800, 600);
|
||||
emscripten_set_canvas_element_size("#canvas", 800, 600);
|
||||
emscripten_set_element_css_size("#canvas", 800.0, 600.0);
|
||||
rarch_main(argc, argv, NULL);
|
||||
emscripten_set_main_loop(emscripten_mainloop,
|
||||
settings->bools.video_vsync ? 0 : INT_MAX, 1);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <emscripten/emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../../config.h"
|
||||
@ -44,6 +45,9 @@ typedef struct
|
||||
unsigned fb_height;
|
||||
} emscripten_ctx_data_t;
|
||||
|
||||
static int emscripten_initial_width;
|
||||
static int emscripten_initial_height;
|
||||
|
||||
static void gfx_ctx_emscripten_swap_interval(void *data, unsigned interval)
|
||||
{
|
||||
(void)data;
|
||||
@ -51,23 +55,82 @@ static void gfx_ctx_emscripten_swap_interval(void *data, unsigned interval)
|
||||
(void)interval;
|
||||
}
|
||||
|
||||
static void gfx_ctx_emscripten_get_canvas_size(int *width, int *height)
|
||||
{
|
||||
EMSCRIPTEN_RESULT r;
|
||||
EmscriptenFullscreenChangeEvent fullscreen_status;
|
||||
bool is_fullscreen = false;
|
||||
|
||||
r = emscripten_get_fullscreen_status(&fullscreen_status);
|
||||
|
||||
if (r == EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
if (fullscreen_status.isFullscreen)
|
||||
{
|
||||
is_fullscreen = true;
|
||||
*width = fullscreen_status.screenWidth;
|
||||
*height = fullscreen_status.screenHeight;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_fullscreen)
|
||||
{
|
||||
r = emscripten_get_canvas_element_size("#canvas", width, height);
|
||||
|
||||
if (r != EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
RARCH_ERR("[EMSCRIPTEN/EGL]: Could not get screen dimensions: %d\n",
|
||||
r);
|
||||
*width = 800;
|
||||
*height = 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_ctx_emscripten_check_window(void *data, bool *quit,
|
||||
bool *resize, unsigned *width, unsigned *height, bool is_shutdown)
|
||||
{
|
||||
EMSCRIPTEN_RESULT r;
|
||||
int input_width;
|
||||
int input_height;
|
||||
int is_fullscreen;
|
||||
emscripten_ctx_data_t *emscripten = (emscripten_ctx_data_t*)data;
|
||||
|
||||
(void)data;
|
||||
gfx_ctx_emscripten_get_canvas_size(&input_width, &input_height);
|
||||
|
||||
if (input_width == 0 || input_height == 0)
|
||||
{
|
||||
input_width = emscripten_initial_width;
|
||||
input_height = emscripten_initial_height;
|
||||
emscripten->fb_width = emscripten->fb_height = 0;
|
||||
}
|
||||
|
||||
emscripten_get_canvas_size(&input_width, &input_height, &is_fullscreen);
|
||||
*width = (unsigned)input_width;
|
||||
*height = (unsigned)input_height;
|
||||
*resize = false;
|
||||
|
||||
if (*width != emscripten->fb_width || *height != emscripten->fb_height)
|
||||
if (input_width != emscripten->fb_width ||
|
||||
input_height != emscripten->fb_height)
|
||||
{
|
||||
r = emscripten_set_canvas_element_size("#canvas",
|
||||
input_width, input_height);
|
||||
|
||||
if (r != EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
RARCH_ERR("[EMSCRIPTEN/EGL]: error resizing canvas: %d\n", r);
|
||||
}
|
||||
|
||||
/* fix Module.requestFullscreen messing with the canvas size */
|
||||
r = emscripten_set_element_css_size("#canvas",
|
||||
(double)input_width, (double)input_height);
|
||||
|
||||
if (r != EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
RARCH_ERR("[EMSCRIPTEN/EGL]: error resizing canvas css: %d\n", r);
|
||||
}
|
||||
|
||||
*resize = true;
|
||||
emscripten_reinit_video = true;
|
||||
}
|
||||
|
||||
emscripten->fb_width = (unsigned)input_width;
|
||||
emscripten->fb_height = (unsigned)input_height;
|
||||
@ -98,7 +161,8 @@ static void gfx_ctx_emscripten_destroy(void *data)
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void *gfx_ctx_emscripten_init(video_frame_info_t *video_info, void *video_driver)
|
||||
static void *gfx_ctx_emscripten_init(video_frame_info_t *video_info,
|
||||
void *video_driver)
|
||||
{
|
||||
#ifdef HAVE_EGL
|
||||
unsigned width, height;
|
||||
@ -128,6 +192,10 @@ static void *gfx_ctx_emscripten_init(video_frame_info_t *video_info, void *video
|
||||
|
||||
(void)video_driver;
|
||||
|
||||
if (emscripten_initial_width == 0 || emscripten_initial_height == 0)
|
||||
emscripten_get_canvas_element_size("#canvas",
|
||||
&emscripten_initial_width, &emscripten_initial_height);
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
if (g_egl_inited)
|
||||
{
|
||||
@ -135,8 +203,8 @@ static void *gfx_ctx_emscripten_init(video_frame_info_t *video_info, void *video
|
||||
return (void*)"emscripten";
|
||||
}
|
||||
|
||||
if (!egl_init_context(&emscripten->egl, EGL_NONE, EGL_DEFAULT_DISPLAY,
|
||||
&major, &minor, &n, attribute_list))
|
||||
if (!egl_init_context(&emscripten->egl, EGL_NONE,
|
||||
(void *)EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribute_list))
|
||||
{
|
||||
egl_report_error();
|
||||
goto error;
|
||||
@ -202,20 +270,10 @@ static void gfx_ctx_emscripten_input_driver(void *data,
|
||||
const char *name,
|
||||
const input_driver_t **input, void **input_data)
|
||||
{
|
||||
void *rwebinput = NULL;
|
||||
void *rwebinput = input_rwebinput.init(name);
|
||||
|
||||
*input = NULL;
|
||||
*input_data = NULL;
|
||||
|
||||
#ifndef HAVE_SDL2
|
||||
rwebinput = input_rwebinput.init();
|
||||
|
||||
if (!rwebinput)
|
||||
return;
|
||||
|
||||
*input = &input_rwebinput;
|
||||
*input = rwebinput ? &input_rwebinput : NULL;
|
||||
*input_data = rwebinput;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool gfx_ctx_emscripten_has_focus(void *data)
|
||||
|
@ -548,6 +548,7 @@ INPUT
|
||||
#include "../input/drivers_joypad/qnx_joypad.c"
|
||||
#elif defined(EMSCRIPTEN)
|
||||
#include "../input/drivers/rwebinput_input.c"
|
||||
#include "../input/drivers_joypad/rwebpad_joypad.c"
|
||||
#elif defined(DJGPP)
|
||||
#include "../input/drivers/dos_input.c"
|
||||
#include "../input/drivers_joypad/dos_joypad.c"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2015 - Michael Lelli
|
||||
* Copyright (C) 2010-2018 - Michael Lelli
|
||||
* Copyright (C) 2011-2017 - Daniel De Matteis
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
@ -19,107 +19,487 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <boolean.h>
|
||||
#include <retro_assert.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <encodings/crc32.h>
|
||||
#include <encodings/utf.h>
|
||||
|
||||
#include <emscripten/html5.h>
|
||||
|
||||
#include "../input_driver.h"
|
||||
#include "../input_keymaps.h"
|
||||
|
||||
#include "../../tasks/tasks_internal.h"
|
||||
#include "../../configuration.h"
|
||||
#include "../../verbosity.h"
|
||||
|
||||
typedef struct rwebinput_state
|
||||
/* https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button */
|
||||
#define RWEBINPUT_MOUSE_BTNL 0
|
||||
#define RWEBINPUT_MOUSE_BTNM 1
|
||||
#define RWEBINPUT_MOUSE_BTNR 2
|
||||
#define RWEBINPUT_MOUSE_BTN4 3
|
||||
#define RWEBINPUT_MOUSE_BTN5 4
|
||||
|
||||
typedef struct rwebinput_key_to_code_map_entry
|
||||
{
|
||||
uint8_t keys[32];
|
||||
int mouse_x;
|
||||
int mouse_y;
|
||||
char mouse_l;
|
||||
char mouse_r;
|
||||
bool blocked;
|
||||
} rwebinput_state_t;
|
||||
const char *key;
|
||||
enum retro_key rk;
|
||||
} rwebinput_key_to_code_map_entry_t;
|
||||
|
||||
int RWebInputInit(void);
|
||||
rwebinput_state_t *RWebInputPoll(int context);
|
||||
void RWebInputDestroy(int context);
|
||||
typedef struct rwebinput_keyboard_event
|
||||
{
|
||||
int type;
|
||||
EmscriptenKeyboardEvent event;
|
||||
} rwebinput_keyboard_event_t;
|
||||
|
||||
typedef struct rwebinput_keyboard_event_queue
|
||||
{
|
||||
size_t count;
|
||||
size_t max_size;
|
||||
rwebinput_keyboard_event_t *events;
|
||||
} rwebinput_keyboard_event_queue_t;
|
||||
|
||||
typedef struct rwebinput_mouse_states
|
||||
{
|
||||
signed x;
|
||||
signed y;
|
||||
signed delta_x;
|
||||
signed delta_y;
|
||||
uint8_t buttons;
|
||||
double scroll_x;
|
||||
double scroll_y;
|
||||
} rwebinput_mouse_state_t;
|
||||
|
||||
typedef struct rwebinput_input
|
||||
{
|
||||
rwebinput_state_t state;
|
||||
int context;
|
||||
bool keys[RETROK_LAST];
|
||||
rwebinput_mouse_state_t mouse;
|
||||
const input_device_driver_t *joypad;
|
||||
bool blocked;
|
||||
} rwebinput_input_t;
|
||||
|
||||
/* KeyboardEvent.keyCode has been deprecated for a while and doesn't have
|
||||
* separate left/right modifer codes, so we have to map string labels from
|
||||
* KeyboardEvent.code to retro keys */
|
||||
static const rwebinput_key_to_code_map_entry_t rwebinput_key_to_code_map[] =
|
||||
{
|
||||
{ "KeyA", RETROK_a },
|
||||
{ "KeyB", RETROK_b },
|
||||
{ "KeyC", RETROK_c },
|
||||
{ "KeyD", RETROK_d },
|
||||
{ "KeyE", RETROK_e },
|
||||
{ "KeyF", RETROK_f },
|
||||
{ "KeyG", RETROK_g },
|
||||
{ "KeyH", RETROK_h },
|
||||
{ "KeyI", RETROK_i },
|
||||
{ "KeyJ", RETROK_j },
|
||||
{ "KeyK", RETROK_k },
|
||||
{ "KeyL", RETROK_l },
|
||||
{ "KeyM", RETROK_m },
|
||||
{ "KeyN", RETROK_n },
|
||||
{ "KeyO", RETROK_o },
|
||||
{ "KeyP", RETROK_p },
|
||||
{ "KeyQ", RETROK_q },
|
||||
{ "KeyR", RETROK_r },
|
||||
{ "KeyS", RETROK_s },
|
||||
{ "KeyT", RETROK_t },
|
||||
{ "KeyU", RETROK_u },
|
||||
{ "KeyV", RETROK_v },
|
||||
{ "KeyW", RETROK_w },
|
||||
{ "KeyX", RETROK_x },
|
||||
{ "KeyY", RETROK_y },
|
||||
{ "KeyZ", RETROK_z },
|
||||
{ "ArrowLeft", RETROK_LEFT },
|
||||
{ "ArrowRight", RETROK_RIGHT },
|
||||
{ "ArrowUp", RETROK_UP },
|
||||
{ "ArrowDown", RETROK_DOWN },
|
||||
{ "Enter", RETROK_RETURN },
|
||||
{ "NumpadEnter", RETROK_KP_ENTER },
|
||||
{ "Tab", RETROK_TAB },
|
||||
{ "Insert", RETROK_INSERT },
|
||||
{ "Delete", RETROK_DELETE },
|
||||
{ "End", RETROK_END },
|
||||
{ "Home", RETROK_HOME },
|
||||
{ "ShiftRight", RETROK_RSHIFT },
|
||||
{ "ShiftLeft", RETROK_LSHIFT },
|
||||
{ "ControlLeft", RETROK_LCTRL },
|
||||
{ "AltLeft", RETROK_LALT },
|
||||
{ "Space", RETROK_SPACE },
|
||||
{ "Escape", RETROK_ESCAPE },
|
||||
{ "NumpadAdd", RETROK_KP_PLUS },
|
||||
{ "NumpadSubtract", RETROK_KP_MINUS },
|
||||
{ "F1", RETROK_F1 },
|
||||
{ "F2", RETROK_F2 },
|
||||
{ "F3", RETROK_F3 },
|
||||
{ "F4", RETROK_F4 },
|
||||
{ "F5", RETROK_F5 },
|
||||
{ "F6", RETROK_F6 },
|
||||
{ "F7", RETROK_F7 },
|
||||
{ "F8", RETROK_F8 },
|
||||
{ "F9", RETROK_F9 },
|
||||
{ "F10", RETROK_F10 },
|
||||
{ "F11", RETROK_F11 },
|
||||
{ "F12", RETROK_F12 },
|
||||
{ "Digit0", RETROK_0 },
|
||||
{ "Digit1", RETROK_1 },
|
||||
{ "Digit2", RETROK_2 },
|
||||
{ "Digit3", RETROK_3 },
|
||||
{ "Digit4", RETROK_4 },
|
||||
{ "Digit5", RETROK_5 },
|
||||
{ "Digit6", RETROK_6 },
|
||||
{ "Digit7", RETROK_7 },
|
||||
{ "Digit8", RETROK_8 },
|
||||
{ "Digit9", RETROK_9 },
|
||||
{ "PageUp", RETROK_PAGEUP },
|
||||
{ "PageDown", RETROK_PAGEDOWN },
|
||||
{ "Numpad0", RETROK_KP0 },
|
||||
{ "Numpad1", RETROK_KP1 },
|
||||
{ "Numpad2", RETROK_KP2 },
|
||||
{ "Numpad3", RETROK_KP3 },
|
||||
{ "Numpad4", RETROK_KP4 },
|
||||
{ "Numpad5", RETROK_KP5 },
|
||||
{ "Numpad6", RETROK_KP6 },
|
||||
{ "Numpad7", RETROK_KP7 },
|
||||
{ "Numpad8", RETROK_KP8 },
|
||||
{ "Numpad9", RETROK_KP9 },
|
||||
{ "Period", RETROK_PERIOD },
|
||||
{ "CapsLock", RETROK_CAPSLOCK },
|
||||
{ "NumLock", RETROK_NUMLOCK },
|
||||
{ "Backspace", RETROK_BACKSPACE },
|
||||
{ "NumpadMultiply", RETROK_KP_MULTIPLY },
|
||||
{ "NumpadDivide", RETROK_KP_DIVIDE },
|
||||
{ "PrintScreen", RETROK_PRINT },
|
||||
{ "ScrollLock", RETROK_SCROLLOCK },
|
||||
{ "Backquote", RETROK_BACKQUOTE },
|
||||
{ "Pause", RETROK_PAUSE },
|
||||
{ "Quote", RETROK_QUOTE },
|
||||
{ "Comma", RETROK_COMMA },
|
||||
{ "Minus", RETROK_MINUS },
|
||||
{ "Slash", RETROK_SLASH },
|
||||
{ "Semicolon", RETROK_SEMICOLON },
|
||||
{ "Equal", RETROK_EQUALS },
|
||||
{ "BracketLeft", RETROK_LEFTBRACKET },
|
||||
{ "Backslash", RETROK_BACKSLASH },
|
||||
{ "BracketRight", RETROK_RIGHTBRACKET },
|
||||
{ "NumpadDecimal", RETROK_KP_PERIOD },
|
||||
{ "NumpadEqual", RETROK_KP_EQUALS },
|
||||
{ "ControlRight", RETROK_RCTRL },
|
||||
{ "AltRight", RETROK_RALT },
|
||||
{ "F13", RETROK_F13 },
|
||||
{ "F14", RETROK_F14 },
|
||||
{ "F15", RETROK_F15 },
|
||||
{ "MetaRight", RETROK_RMETA },
|
||||
{ "MetaLeft", RETROK_LMETA },
|
||||
{ "Help", RETROK_HELP },
|
||||
{ "ContextMenu", RETROK_MENU },
|
||||
{ "Power", RETROK_POWER },
|
||||
};
|
||||
|
||||
static bool g_rwebinput_initialized;
|
||||
static rwebinput_keyboard_event_queue_t *g_rwebinput_keyboard;
|
||||
static rwebinput_mouse_state_t *g_rwebinput_mouse;
|
||||
|
||||
/* to make the string labels for codes from JavaScript work, we convert them
|
||||
* to CRC32 hashes for the LUT */
|
||||
static void rwebinput_generate_lut(void)
|
||||
{
|
||||
int i;
|
||||
struct rarch_key_map *key_map;
|
||||
|
||||
retro_assert(ARRAY_SIZE(rarch_key_map_rwebinput) ==
|
||||
ARRAY_SIZE(rwebinput_key_to_code_map) + 1);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rwebinput_key_to_code_map); i++)
|
||||
{
|
||||
int j;
|
||||
uint32_t crc;
|
||||
const rwebinput_key_to_code_map_entry_t *key_to_code =
|
||||
&rwebinput_key_to_code_map[i];
|
||||
key_map = &rarch_key_map_rwebinput[i];
|
||||
crc = encoding_crc32(0, (const uint8_t *)key_to_code->key,
|
||||
strlen(key_to_code->key));
|
||||
|
||||
/* sanity check: make sure there's no collisions */
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
retro_assert(rarch_key_map_rwebinput[j].sym != crc);
|
||||
}
|
||||
|
||||
key_map->rk = key_to_code->rk;
|
||||
key_map->sym = crc;
|
||||
}
|
||||
|
||||
/* set terminating entry */
|
||||
key_map = &rarch_key_map_rwebinput[ARRAY_SIZE(rarch_key_map_rwebinput) - 1];
|
||||
key_map->rk = RETROK_UNKNOWN;
|
||||
key_map->sym = 0;
|
||||
}
|
||||
|
||||
static EM_BOOL rwebinput_keyboard_cb(int event_type,
|
||||
const EmscriptenKeyboardEvent *key_event, void *user_data)
|
||||
{
|
||||
if (event_type == EMSCRIPTEN_EVENT_KEYPRESS)
|
||||
return EM_TRUE;
|
||||
|
||||
if (g_rwebinput_keyboard->count >= g_rwebinput_keyboard->max_size)
|
||||
{
|
||||
size_t new_max = MAX(1, g_rwebinput_keyboard->max_size << 1);
|
||||
g_rwebinput_keyboard->events = realloc(g_rwebinput_keyboard->events,
|
||||
new_max * sizeof(g_rwebinput_keyboard->events[0]));
|
||||
retro_assert(g_rwebinput_keyboard->events != NULL);
|
||||
g_rwebinput_keyboard->max_size = new_max;
|
||||
}
|
||||
|
||||
g_rwebinput_keyboard->events[g_rwebinput_keyboard->count].type = event_type;
|
||||
memcpy(&g_rwebinput_keyboard->events[g_rwebinput_keyboard->count].event,
|
||||
key_event, sizeof(*key_event));
|
||||
g_rwebinput_keyboard->count++;
|
||||
|
||||
return EM_TRUE;
|
||||
}
|
||||
|
||||
static EM_BOOL rwebinput_mouse_cb(int event_type,
|
||||
const EmscriptenMouseEvent *mouse_event, void *user_data)
|
||||
{
|
||||
(void)user_data;
|
||||
|
||||
uint8_t mask = 1 << mouse_event->button;
|
||||
|
||||
g_rwebinput_mouse->x = mouse_event->canvasX;
|
||||
g_rwebinput_mouse->y = mouse_event->canvasY;
|
||||
g_rwebinput_mouse->delta_x += mouse_event->movementX;
|
||||
g_rwebinput_mouse->delta_y += mouse_event->movementY;
|
||||
|
||||
if (event_type == EMSCRIPTEN_EVENT_MOUSEDOWN)
|
||||
{
|
||||
g_rwebinput_mouse->buttons |= mask;
|
||||
}
|
||||
else if (event_type == EMSCRIPTEN_EVENT_MOUSEUP)
|
||||
{
|
||||
g_rwebinput_mouse->buttons &= ~mask;
|
||||
}
|
||||
|
||||
return EM_TRUE;
|
||||
}
|
||||
|
||||
static EM_BOOL rwebinput_wheel_cb(int event_type,
|
||||
const EmscriptenWheelEvent *wheel_event, void *user_data)
|
||||
{
|
||||
(void)event_type;
|
||||
(void)user_data;
|
||||
|
||||
g_rwebinput_mouse->scroll_x += wheel_event->deltaX;
|
||||
g_rwebinput_mouse->scroll_y += wheel_event->deltaY;
|
||||
|
||||
return EM_TRUE;
|
||||
}
|
||||
|
||||
static void *rwebinput_input_init(const char *joypad_driver)
|
||||
{
|
||||
rwebinput_input_t *rwebinput = (rwebinput_input_t*)calloc(1, sizeof(*rwebinput));
|
||||
if (!rwebinput)
|
||||
rwebinput_input_t *rwebinput =
|
||||
(rwebinput_input_t*)calloc(1, sizeof(*rwebinput));
|
||||
g_rwebinput_keyboard = (rwebinput_keyboard_event_queue_t*)
|
||||
calloc(1, sizeof(rwebinput_keyboard_event_queue_t));
|
||||
g_rwebinput_mouse = (rwebinput_mouse_state_t*)
|
||||
calloc(1, sizeof(rwebinput_mouse_state_t));
|
||||
|
||||
if (!rwebinput || !g_rwebinput_keyboard || !g_rwebinput_mouse)
|
||||
goto error;
|
||||
|
||||
rwebinput->context = RWebInputInit();
|
||||
if (!rwebinput->context)
|
||||
goto error;
|
||||
if (!g_rwebinput_initialized)
|
||||
{
|
||||
EMSCRIPTEN_RESULT r;
|
||||
|
||||
g_rwebinput_initialized = true;
|
||||
rwebinput_generate_lut();
|
||||
|
||||
/* emscripten currently doesn't have an API to remove handlers, so make
|
||||
* once and reuse it */
|
||||
r = emscripten_set_keydown_callback("#document", NULL, false,
|
||||
rwebinput_keyboard_cb);
|
||||
if (r != EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
RARCH_ERR(
|
||||
"[EMSCRIPTEN/INPUT] failed to create keydown callback: %d\n", r);
|
||||
}
|
||||
|
||||
r = emscripten_set_keyup_callback("#document", NULL, false,
|
||||
rwebinput_keyboard_cb);
|
||||
if (r != EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
RARCH_ERR(
|
||||
"[EMSCRIPTEN/INPUT] failed to create keydown callback: %d\n", r);
|
||||
}
|
||||
|
||||
r = emscripten_set_keypress_callback("#document", NULL, false,
|
||||
rwebinput_keyboard_cb);
|
||||
if (r != EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
RARCH_ERR(
|
||||
"[EMSCRIPTEN/INPUT] failed to create keypress callback: %d\n", r);
|
||||
}
|
||||
|
||||
r = emscripten_set_mousedown_callback("#canvas", NULL, false,
|
||||
rwebinput_mouse_cb);
|
||||
if (r != EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
RARCH_ERR(
|
||||
"[EMSCRIPTEN/INPUT] failed to create mousedown callback: %d\n", r);
|
||||
}
|
||||
|
||||
r = emscripten_set_mouseup_callback("#canvas", NULL, false,
|
||||
rwebinput_mouse_cb);
|
||||
if (r != EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
RARCH_ERR(
|
||||
"[EMSCRIPTEN/INPUT] failed to create mouseup callback: %d\n", r);
|
||||
}
|
||||
|
||||
r = emscripten_set_mousemove_callback("#canvas", NULL, false,
|
||||
rwebinput_mouse_cb);
|
||||
if (r != EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
RARCH_ERR(
|
||||
"[EMSCRIPTEN/INPUT] failed to create mousemove callback: %d\n", r);
|
||||
}
|
||||
|
||||
r = emscripten_set_wheel_callback("#document", NULL, false,
|
||||
rwebinput_wheel_cb);
|
||||
if (r != EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
RARCH_ERR(
|
||||
"[EMSCRIPTEN/INPUT] failed to create wheel callback: %d\n", r);
|
||||
}
|
||||
}
|
||||
|
||||
input_keymaps_init_keyboard_lut(rarch_key_map_rwebinput);
|
||||
|
||||
rwebinput->joypad = input_joypad_init_driver(joypad_driver, rwebinput);
|
||||
|
||||
return rwebinput;
|
||||
|
||||
error:
|
||||
if (rwebinput)
|
||||
free(rwebinput);
|
||||
free(g_rwebinput_keyboard);
|
||||
free(g_rwebinput_mouse);
|
||||
free(rwebinput);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool rwebinput_key_pressed_internal(void *data, int key)
|
||||
static bool rwebinput_key_pressed(rwebinput_input_t *rwebinput, int key)
|
||||
{
|
||||
unsigned sym;
|
||||
bool ret;
|
||||
rwebinput_input_t *rwebinput = (rwebinput_input_t*)data;
|
||||
|
||||
if (key >= RETROK_LAST)
|
||||
return false;
|
||||
|
||||
sym = rarch_keysym_lut[(enum retro_key)key];
|
||||
ret = rwebinput->state.keys[sym >> 3] & (1 << (sym & 7));
|
||||
|
||||
return ret;
|
||||
return rwebinput->keys[key];
|
||||
}
|
||||
|
||||
static bool rwebinput_is_pressed(rwebinput_input_t *rwebinput,
|
||||
const struct retro_keybind *binds, unsigned id)
|
||||
static int16_t rwebinput_pointer_device_state(rwebinput_mouse_state_t *mouse,
|
||||
unsigned id, bool screen)
|
||||
{
|
||||
if (id < RARCH_BIND_LIST_END)
|
||||
struct video_viewport vp;
|
||||
bool inside = false;
|
||||
int16_t res_x = 0;
|
||||
int16_t res_y = 0;
|
||||
int16_t res_screen_x = 0;
|
||||
int16_t res_screen_y = 0;
|
||||
|
||||
vp.x = 0;
|
||||
vp.y = 0;
|
||||
vp.width = 0;
|
||||
vp.height = 0;
|
||||
vp.full_width = 0;
|
||||
vp.full_height = 0;
|
||||
|
||||
if (!(video_driver_translate_coord_viewport_wrap(&vp, mouse->x, mouse->x,
|
||||
&res_x, &res_y, &res_screen_x, &res_screen_y)))
|
||||
return 0;
|
||||
|
||||
if (screen)
|
||||
{
|
||||
const struct retro_keybind *bind = &binds[id];
|
||||
int key = binds[id].key;
|
||||
return bind->valid && (key < RETROK_LAST)
|
||||
&& rwebinput_key_pressed_internal(rwebinput, key);
|
||||
res_x = res_screen_x;
|
||||
res_y = res_screen_y;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
inside = (res_x >= -0x7fff) && (res_y >= -0x7fff);
|
||||
|
||||
static bool rwebinput_key_pressed(void *data, int key)
|
||||
{
|
||||
rwebinput_input_t *rwebinput = (rwebinput_input_t*)data;
|
||||
return rwebinput_is_pressed(rwebinput, input_config_binds[0], key);
|
||||
}
|
||||
if (!inside)
|
||||
return 0;
|
||||
|
||||
static int16_t rwebinput_mouse_state(rwebinput_input_t *rwebinput, unsigned id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case RETRO_DEVICE_ID_MOUSE_X:
|
||||
return (int16_t) rwebinput->state.mouse_x;
|
||||
case RETRO_DEVICE_ID_MOUSE_Y:
|
||||
return (int16_t) rwebinput->state.mouse_y;
|
||||
case RETRO_DEVICE_ID_MOUSE_LEFT:
|
||||
return rwebinput->state.mouse_l;
|
||||
case RETRO_DEVICE_ID_MOUSE_RIGHT:
|
||||
return rwebinput->state.mouse_r;
|
||||
case RETRO_DEVICE_ID_POINTER_X:
|
||||
return res_x;
|
||||
case RETRO_DEVICE_ID_POINTER_Y:
|
||||
return res_y;
|
||||
case RETRO_DEVICE_ID_POINTER_PRESSED:
|
||||
return !!(mouse->buttons & (1 << RWEBINPUT_MOUSE_BTNL));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int16_t rwebinput_mouse_state(rwebinput_mouse_state_t *mouse,
|
||||
unsigned id, bool screen)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case RETRO_DEVICE_ID_MOUSE_X:
|
||||
return (int16_t)(screen ? mouse->x : mouse->delta_x);
|
||||
case RETRO_DEVICE_ID_MOUSE_Y:
|
||||
return (int16_t)(screen ? mouse->y : mouse->delta_y);
|
||||
case RETRO_DEVICE_ID_MOUSE_LEFT:
|
||||
return !!(mouse->buttons & (1 << RWEBINPUT_MOUSE_BTNL));
|
||||
case RETRO_DEVICE_ID_MOUSE_RIGHT:
|
||||
return !!(mouse->buttons & (1 << RWEBINPUT_MOUSE_BTNR));
|
||||
case RETRO_DEVICE_ID_MOUSE_MIDDLE:
|
||||
return !!(mouse->buttons & (1 << RWEBINPUT_MOUSE_BTNM));
|
||||
case RETRO_DEVICE_ID_MOUSE_BUTTON_4:
|
||||
return !!(mouse->buttons & (1 << RWEBINPUT_MOUSE_BTN4));
|
||||
case RETRO_DEVICE_ID_MOUSE_BUTTON_5:
|
||||
return !!(mouse->buttons & (1 << RWEBINPUT_MOUSE_BTN5));
|
||||
case RETRO_DEVICE_ID_MOUSE_WHEELUP:
|
||||
return mouse->scroll_y < 0.0;
|
||||
case RETRO_DEVICE_ID_MOUSE_WHEELDOWN:
|
||||
return mouse->scroll_y > 0.0;
|
||||
case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP:
|
||||
return mouse->scroll_x < 0.0;
|
||||
case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN:
|
||||
return mouse->scroll_x > 0.0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool rwebinput_is_pressed(rwebinput_input_t *rwebinput,
|
||||
rarch_joypad_info_t joypad_info, const struct retro_keybind *binds,
|
||||
unsigned port, unsigned id)
|
||||
{
|
||||
if (id < RARCH_BIND_LIST_END)
|
||||
{
|
||||
const struct retro_keybind *bind = &binds[id];
|
||||
int key = bind->key;
|
||||
|
||||
if (!rwebinput->blocked && (bind->key < RETROK_LAST) &&
|
||||
rwebinput_key_pressed(rwebinput, key))
|
||||
return true;
|
||||
|
||||
if (bind->valid)
|
||||
{
|
||||
if (port == 0 && !!rwebinput_mouse_state(&rwebinput->mouse,
|
||||
bind->mbutton, false))
|
||||
return true;
|
||||
if (input_joypad_pressed(rwebinput->joypad, joypad_info, port, binds,
|
||||
id))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int16_t rwebinput_analog_pressed(rwebinput_input_t *rwebinput,
|
||||
const struct retro_keybind *binds, unsigned idx, unsigned id)
|
||||
rarch_joypad_info_t joypad_info, const struct retro_keybind *binds,
|
||||
unsigned idx, unsigned id)
|
||||
{
|
||||
int16_t pressed_minus = 0, pressed_plus = 0;
|
||||
unsigned id_minus = 0;
|
||||
@ -127,9 +507,9 @@ static int16_t rwebinput_analog_pressed(rwebinput_input_t *rwebinput,
|
||||
|
||||
input_conv_analog_id_to_bind_id(idx, id, &id_minus, &id_plus);
|
||||
|
||||
if (rwebinput_is_pressed(rwebinput, binds, id_minus))
|
||||
if (rwebinput_is_pressed(rwebinput, joypad_info, binds, idx, id_minus))
|
||||
pressed_minus = -0x7fff;
|
||||
if (rwebinput_is_pressed(rwebinput, binds, id_plus))
|
||||
if (rwebinput_is_pressed(rwebinput, joypad_info, binds, idx, id_plus))
|
||||
pressed_plus = 0x7fff;
|
||||
|
||||
return pressed_plus + pressed_minus;
|
||||
@ -140,18 +520,33 @@ static int16_t rwebinput_input_state(void *data,
|
||||
const struct retro_keybind **binds,
|
||||
unsigned port, unsigned device, unsigned idx, unsigned id)
|
||||
{
|
||||
int16_t ret;
|
||||
rwebinput_input_t *rwebinput = (rwebinput_input_t*)data;
|
||||
|
||||
switch (device)
|
||||
{
|
||||
case RETRO_DEVICE_JOYPAD:
|
||||
return rwebinput_is_pressed(rwebinput, binds[port], id);
|
||||
if (id < RARCH_BIND_LIST_END)
|
||||
return rwebinput_is_pressed(rwebinput, joypad_info, binds[port],
|
||||
port, id);
|
||||
break;
|
||||
case RETRO_DEVICE_ANALOG:
|
||||
return rwebinput_analog_pressed(rwebinput, binds[port], idx, id);
|
||||
ret = rwebinput_analog_pressed(rwebinput, joypad_info, binds[port],
|
||||
idx, id);
|
||||
if (!ret && binds[port])
|
||||
ret = input_joypad_analog(rwebinput->joypad, joypad_info, port,
|
||||
idx, id, binds[port]);
|
||||
return ret;
|
||||
case RETRO_DEVICE_KEYBOARD:
|
||||
return rwebinput_key_pressed(rwebinput, id);
|
||||
case RETRO_DEVICE_MOUSE:
|
||||
return rwebinput_mouse_state(rwebinput, id);
|
||||
return rwebinput_mouse_state(&rwebinput->mouse, id, false);
|
||||
case RARCH_DEVICE_MOUSE_SCREEN:
|
||||
return rwebinput_mouse_state(&rwebinput->mouse, id, true);
|
||||
case RETRO_DEVICE_POINTER:
|
||||
return rwebinput_pointer_device_state(&rwebinput->mouse, id, false);
|
||||
case RARCH_DEVICE_POINTER_SCREEN:
|
||||
return rwebinput_pointer_device_state(&rwebinput->mouse, id, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -161,47 +556,88 @@ static void rwebinput_input_free(void *data)
|
||||
{
|
||||
rwebinput_input_t *rwebinput = (rwebinput_input_t*)data;
|
||||
|
||||
if (!rwebinput)
|
||||
return;
|
||||
|
||||
RWebInputDestroy(rwebinput->context);
|
||||
|
||||
if (g_rwebinput_keyboard)
|
||||
free(g_rwebinput_keyboard->events);
|
||||
free(g_rwebinput_keyboard);
|
||||
g_rwebinput_keyboard = NULL;
|
||||
free(g_rwebinput_mouse);
|
||||
g_rwebinput_mouse = NULL;
|
||||
free(rwebinput);
|
||||
}
|
||||
static void rwebinput_process_keyboard_events(rwebinput_input_t *rwebinput,
|
||||
rwebinput_keyboard_event_t *event)
|
||||
{
|
||||
uint32_t crc;
|
||||
uint32_t keycode;
|
||||
unsigned translated_keycode;
|
||||
uint32_t character = 0;
|
||||
uint16_t mod = 0;
|
||||
const EmscriptenKeyboardEvent *key_event = &event->event;
|
||||
bool keydown = event->type == EMSCRIPTEN_EVENT_KEYDOWN;
|
||||
|
||||
/* a printable key: populate character field */
|
||||
if (utf8len(key_event->key) == 1)
|
||||
{
|
||||
const char *key_ptr = &key_event->key[0];
|
||||
character = utf8_walk(&key_ptr);
|
||||
}
|
||||
|
||||
if (key_event->ctrlKey)
|
||||
mod |= RETROKMOD_CTRL;
|
||||
if (key_event->altKey)
|
||||
mod |= RETROKMOD_ALT;
|
||||
if (key_event->shiftKey)
|
||||
mod |= RETROKMOD_SHIFT;
|
||||
if (key_event->metaKey)
|
||||
mod |= RETROKMOD_META;
|
||||
|
||||
keycode = encoding_crc32(0, (const uint8_t *)key_event->code,
|
||||
strnlen(key_event->code, sizeof(key_event->code)));
|
||||
translated_keycode = input_keymaps_translate_keysym_to_rk(keycode);
|
||||
|
||||
if (translated_keycode == RETROK_BACKSPACE)
|
||||
character = '\b';
|
||||
else if (translated_keycode == RETROK_RETURN ||
|
||||
translated_keycode == RETROK_KP_ENTER)
|
||||
character = '\n';
|
||||
else if (translated_keycode == RETROK_TAB)
|
||||
character = '\t';
|
||||
|
||||
input_keyboard_event(keydown, translated_keycode, character, mod,
|
||||
RETRO_DEVICE_KEYBOARD);
|
||||
|
||||
if (translated_keycode < RETROK_LAST)
|
||||
{
|
||||
rwebinput->keys[translated_keycode] = keydown;
|
||||
}
|
||||
}
|
||||
|
||||
static void rwebinput_input_poll(void *data)
|
||||
{
|
||||
unsigned i;
|
||||
size_t i;
|
||||
rwebinput_input_t *rwebinput = (rwebinput_input_t*)data;
|
||||
rwebinput_state_t *state = RWebInputPoll(rwebinput->context);
|
||||
|
||||
/* Get new keys. */
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
unsigned k;
|
||||
uint8_t diff;
|
||||
for (i = 0; i < g_rwebinput_keyboard->count; i++)
|
||||
rwebinput_process_keyboard_events(rwebinput,
|
||||
&g_rwebinput_keyboard->events[i]);
|
||||
g_rwebinput_keyboard->count = 0;
|
||||
|
||||
if (state->keys[i] == rwebinput->state.keys[i])
|
||||
continue;
|
||||
memcpy(&rwebinput->mouse, g_rwebinput_mouse, sizeof(*g_rwebinput_mouse));
|
||||
g_rwebinput_mouse->delta_x = g_rwebinput_mouse->delta_y = 0;
|
||||
g_rwebinput_mouse->scroll_x = g_rwebinput_mouse->scroll_y = 0.0;
|
||||
|
||||
diff = state->keys[i] ^ rwebinput->state.keys[i];
|
||||
|
||||
for (k = 0; diff; diff >>= 1, k++)
|
||||
{
|
||||
if (diff & 1)
|
||||
input_keyboard_event((state->keys[i] & (1 << k)) != 0,
|
||||
input_keymaps_translate_keysym_to_rk(i * 8 + k), 0, 0,
|
||||
RETRO_DEVICE_KEYBOARD);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&rwebinput->state, state, sizeof(rwebinput->state));
|
||||
if (rwebinput->joypad)
|
||||
rwebinput->joypad->poll();
|
||||
}
|
||||
|
||||
static void rwebinput_grab_mouse(void *data, bool state)
|
||||
{
|
||||
(void)data;
|
||||
(void)state;
|
||||
|
||||
if (state)
|
||||
emscripten_request_pointerlock("#canvas", EM_TRUE);
|
||||
else
|
||||
emscripten_exit_pointerlock();
|
||||
}
|
||||
|
||||
static bool rwebinput_set_rumble(void *data, unsigned port,
|
||||
@ -215,6 +651,14 @@ static bool rwebinput_set_rumble(void *data, unsigned port,
|
||||
return false;
|
||||
}
|
||||
|
||||
static const input_device_driver_t *rwebinput_get_joypad_driver(void *data)
|
||||
{
|
||||
rwebinput_input_t *rwebinput = (rwebinput_input_t*)data;
|
||||
if (!rwebinput)
|
||||
return NULL;
|
||||
return rwebinput->joypad;
|
||||
}
|
||||
|
||||
static uint64_t rwebinput_get_capabilities(void *data)
|
||||
{
|
||||
uint64_t caps = 0;
|
||||
@ -223,6 +667,7 @@ static uint64_t rwebinput_get_capabilities(void *data)
|
||||
caps |= (1 << RETRO_DEVICE_ANALOG);
|
||||
caps |= (1 << RETRO_DEVICE_KEYBOARD);
|
||||
caps |= (1 << RETRO_DEVICE_MOUSE);
|
||||
caps |= (1 << RETRO_DEVICE_POINTER);
|
||||
|
||||
return caps;
|
||||
}
|
||||
@ -232,7 +677,7 @@ static bool rwebinput_keyboard_mapping_is_blocked(void *data)
|
||||
rwebinput_input_t *rwebinput = (rwebinput_input_t*)data;
|
||||
if (!rwebinput)
|
||||
return false;
|
||||
return rwebinput->state.blocked;
|
||||
return rwebinput->blocked;
|
||||
}
|
||||
|
||||
static void rwebinput_keyboard_mapping_set_block(void *data, bool value)
|
||||
@ -240,7 +685,7 @@ static void rwebinput_keyboard_mapping_set_block(void *data, bool value)
|
||||
rwebinput_input_t *rwebinput = (rwebinput_input_t*)data;
|
||||
if (!rwebinput)
|
||||
return;
|
||||
rwebinput->state.blocked = value;
|
||||
rwebinput->blocked = value;
|
||||
}
|
||||
|
||||
input_driver_t input_rwebinput = {
|
||||
@ -255,7 +700,7 @@ input_driver_t input_rwebinput = {
|
||||
rwebinput_grab_mouse,
|
||||
NULL,
|
||||
rwebinput_set_rumble,
|
||||
NULL,
|
||||
rwebinput_get_joypad_driver,
|
||||
NULL,
|
||||
rwebinput_keyboard_mapping_is_blocked,
|
||||
rwebinput_keyboard_mapping_set_block,
|
||||
|
219
input/drivers_joypad/rwebpad_joypad.c
Normal file
219
input/drivers_joypad/rwebpad_joypad.c
Normal file
@ -0,0 +1,219 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2018 - Michael Lelli
|
||||
*
|
||||
* 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-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <boolean.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <emscripten/html5.h>
|
||||
|
||||
#include "../input_driver.h"
|
||||
|
||||
#include "../../tasks/tasks_internal.h"
|
||||
#include "../../verbosity.h"
|
||||
|
||||
#define CLAMPDOUBLE(x) MIN(1.0, MAX(-1.0, (x)))
|
||||
|
||||
static bool g_rwebpad_initialized;
|
||||
|
||||
static EM_BOOL rwebpad_gamepad_cb(int event_type,
|
||||
const EmscriptenGamepadEvent *gamepad_event, void *user_data)
|
||||
{
|
||||
unsigned vid = 0;
|
||||
unsigned pid = 0;
|
||||
|
||||
(void)event_type;
|
||||
(void)gamepad_event;
|
||||
(void)user_data;
|
||||
|
||||
if (strncmp(gamepad_event->mapping, "standard",
|
||||
sizeof(gamepad_event->mapping)) == 0)
|
||||
{
|
||||
/* give a dummy vid/pid for automapping */
|
||||
vid = 1;
|
||||
pid = 1;
|
||||
}
|
||||
|
||||
|
||||
if (event_type == EMSCRIPTEN_EVENT_GAMEPADCONNECTED)
|
||||
{
|
||||
if(!input_autoconfigure_connect(
|
||||
gamepad_event->id, /* name */
|
||||
NULL, /* display name */
|
||||
rwebpad_joypad.ident, /* driver */
|
||||
gamepad_event->index, /* idx */
|
||||
vid, /* vid */
|
||||
pid)) /* pid */
|
||||
input_config_set_device_name(gamepad_event->index,
|
||||
gamepad_event->id);
|
||||
}
|
||||
else if (event_type == EMSCRIPTEN_EVENT_GAMEPADDISCONNECTED)
|
||||
{
|
||||
input_autoconfigure_disconnect(gamepad_event->index,
|
||||
rwebpad_joypad.ident);
|
||||
}
|
||||
|
||||
return EM_TRUE;
|
||||
}
|
||||
|
||||
static bool rwebpad_joypad_init(void *data)
|
||||
{
|
||||
int supported = emscripten_get_num_gamepads();
|
||||
(void)data;
|
||||
|
||||
if (supported == EMSCRIPTEN_RESULT_NOT_SUPPORTED)
|
||||
return false;
|
||||
|
||||
if (!g_rwebpad_initialized)
|
||||
{
|
||||
EMSCRIPTEN_RESULT r;
|
||||
g_rwebpad_initialized = true;
|
||||
|
||||
/* callbacks needs to be registered for gamepads to connect */
|
||||
r = emscripten_set_gamepadconnected_callback(NULL, false,
|
||||
rwebpad_gamepad_cb);
|
||||
if (r != EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
RARCH_ERR(
|
||||
"[EMSCRIPTEN/PAD] failed to create connect callback: %d\n", r);
|
||||
}
|
||||
|
||||
r = emscripten_set_gamepaddisconnected_callback(NULL, false,
|
||||
rwebpad_gamepad_cb);
|
||||
if (r != EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
RARCH_ERR(
|
||||
"[EMSCRIPTEN/PAD] failed to create disconnect callback: %d\n", r);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *rwebpad_joypad_name(unsigned pad)
|
||||
{
|
||||
static EmscriptenGamepadEvent gamepad_state;
|
||||
EMSCRIPTEN_RESULT r;
|
||||
|
||||
r = emscripten_get_gamepad_status(pad, &gamepad_state);
|
||||
|
||||
if (r == EMSCRIPTEN_RESULT_SUCCESS)
|
||||
return gamepad_state.id;
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
static bool rwebpad_joypad_button(unsigned port_num, uint16_t joykey)
|
||||
{
|
||||
EmscriptenGamepadEvent gamepad_state;
|
||||
EMSCRIPTEN_RESULT r;
|
||||
|
||||
r = emscripten_get_gamepad_status(port_num, &gamepad_state);
|
||||
|
||||
if (r == EMSCRIPTEN_RESULT_SUCCESS)
|
||||
if (joykey < gamepad_state.numButtons)
|
||||
return gamepad_state.digitalButton[joykey];
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void rwebpad_joypad_get_buttons(unsigned port_num, retro_bits_t *state)
|
||||
{
|
||||
EmscriptenGamepadEvent gamepad_state;
|
||||
EMSCRIPTEN_RESULT r;
|
||||
|
||||
r = emscripten_get_gamepad_status(port_num, &gamepad_state);
|
||||
|
||||
if (r == EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < gamepad_state.numButtons; i++)
|
||||
{
|
||||
if (gamepad_state.digitalButton[i])
|
||||
BIT256_SET_PTR(state, i);
|
||||
}
|
||||
}
|
||||
else
|
||||
BIT256_CLEAR_ALL_PTR(state);
|
||||
}
|
||||
|
||||
static int16_t rwebpad_joypad_axis(unsigned port_num, uint32_t joyaxis)
|
||||
{
|
||||
EmscriptenGamepadEvent gamepad_state;
|
||||
EMSCRIPTEN_RESULT r;
|
||||
int16_t val = 0;
|
||||
|
||||
if (joyaxis == 0xFFFFFFFF)
|
||||
return 0;
|
||||
|
||||
r = emscripten_get_gamepad_status(port_num, &gamepad_state);
|
||||
|
||||
if (r == EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
if (AXIS_NEG_GET(joyaxis) < gamepad_state.numAxes)
|
||||
{
|
||||
val = CLAMPDOUBLE(gamepad_state.axis[AXIS_NEG_GET(joyaxis)]) * 0x7FFF;
|
||||
if (val > 0)
|
||||
val = 0;
|
||||
}
|
||||
else if (AXIS_POS_GET(joyaxis) < gamepad_state.numAxes)
|
||||
{
|
||||
val = CLAMPDOUBLE(gamepad_state.axis[AXIS_POS_GET(joyaxis)]) * 0x7FFF;
|
||||
if (val < 0)
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void rwebpad_joypad_poll(void)
|
||||
{
|
||||
/* this call makes emscripten poll gamepad state */
|
||||
(void)emscripten_get_num_gamepads();
|
||||
}
|
||||
|
||||
static bool rwebpad_joypad_query_pad(unsigned pad)
|
||||
{
|
||||
EmscriptenGamepadEvent gamepad_state;
|
||||
EMSCRIPTEN_RESULT r;
|
||||
|
||||
r = emscripten_get_gamepad_status(pad, &gamepad_state);
|
||||
|
||||
if (r == EMSCRIPTEN_RESULT_SUCCESS)
|
||||
return gamepad_state.connected == EM_TRUE;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void rwebpad_joypad_destroy(void)
|
||||
{
|
||||
}
|
||||
|
||||
input_device_driver_t rwebpad_joypad = {
|
||||
rwebpad_joypad_init,
|
||||
rwebpad_joypad_query_pad,
|
||||
rwebpad_joypad_destroy,
|
||||
rwebpad_joypad_button,
|
||||
rwebpad_joypad_get_buttons,
|
||||
rwebpad_joypad_axis,
|
||||
rwebpad_joypad_poll,
|
||||
NULL,
|
||||
rwebpad_joypad_name,
|
||||
"rwebpad",
|
||||
};
|
@ -37,7 +37,8 @@
|
||||
#define DECL_AXIS(axis, bind) "input_" #axis "_axis = " #bind "\n"
|
||||
#define DECL_AXIS_EX(axis, bind, name) "input_" #axis "_axis = " #bind "\ninput_" #axis "_axis_label = \"" name "\"\n"
|
||||
#define DECL_MENU(btn) "input_menu_toggle_btn = " #btn "\n"
|
||||
#define DECL_AUTOCONF_DEVICE(device, driver, binds) "input_device = \"" device "\" \ninput_driver = \"" driver "\" \n" binds
|
||||
#define DECL_AUTOCONF_DEVICE(device, driver, binds) "input_device = \"" device "\"\ninput_driver = \"" driver "\"\n" binds
|
||||
#define DECL_AUTOCONF_PID(pid, vid, driver, binds) "input_product_id = " #pid "\ninput_vendor_id = " #vid "\ninput_driver = \"" driver "\"\n" binds
|
||||
|
||||
/* TODO/FIXME - Missing L2/R2 */
|
||||
|
||||
@ -528,6 +529,32 @@ DECL_AXIS(r_x_minus, -2) \
|
||||
DECL_AXIS(r_y_plus, +3) \
|
||||
DECL_AXIS(r_y_minus, -3)
|
||||
|
||||
#define EMSCRIPTEN_DEFAULT_BINDS \
|
||||
DECL_BTN(a, 1) \
|
||||
DECL_BTN(b, 0) \
|
||||
DECL_BTN(x, 3) \
|
||||
DECL_BTN(y, 2) \
|
||||
DECL_BTN(start, 9) \
|
||||
DECL_BTN(select, 8) \
|
||||
DECL_BTN(up, 12) \
|
||||
DECL_BTN(down, 13) \
|
||||
DECL_BTN(left, 14) \
|
||||
DECL_BTN(right, 15) \
|
||||
DECL_BTN(l, 4) \
|
||||
DECL_BTN(r, 5) \
|
||||
DECL_BTN(l2, 6) \
|
||||
DECL_BTN(r2, 7) \
|
||||
DECL_BTN(l3, 10) \
|
||||
DECL_BTN(r3, 11) \
|
||||
DECL_AXIS(l_x_plus, +0) \
|
||||
DECL_AXIS(l_x_minus, -0) \
|
||||
DECL_AXIS(l_y_plus, +1) \
|
||||
DECL_AXIS(l_y_minus, -1) \
|
||||
DECL_AXIS(r_x_plus, +2) \
|
||||
DECL_AXIS(r_x_minus, -2) \
|
||||
DECL_AXIS(r_y_plus, +3) \
|
||||
DECL_AXIS(r_y_minus, -3)
|
||||
|
||||
const char* const input_builtin_autoconfs[] =
|
||||
{
|
||||
#if defined(_WIN32) && defined(_XBOX)
|
||||
@ -588,6 +615,9 @@ const char* const input_builtin_autoconfs[] =
|
||||
#endif
|
||||
#ifdef __SWITCH__
|
||||
DECL_AUTOCONF_DEVICE("Switch Controller", "switch", SWITCH_DEFAULT_BINDS),
|
||||
#endif
|
||||
#ifdef EMSCRIPTEN
|
||||
DECL_AUTOCONF_PID(1, 1, "rwebpad", EMSCRIPTEN_DEFAULT_BINDS),
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
@ -181,6 +181,9 @@ static input_device_driver_t *joypad_drivers[] = {
|
||||
* to be selectable in the UI. */
|
||||
#if defined(HAVE_HID) && !defined(WIIU)
|
||||
&hid_joypad,
|
||||
#endif
|
||||
#ifdef EMSCRIPTEN
|
||||
&rwebpad_joypad,
|
||||
#endif
|
||||
&null_joypad,
|
||||
NULL,
|
||||
@ -804,7 +807,7 @@ void state_tracker_update_input(uint16_t *input1, uint16_t *input2)
|
||||
static INLINE bool input_keys_pressed_iterate(unsigned i,
|
||||
retro_bits_t* p_new_state)
|
||||
{
|
||||
if ((i >= RARCH_FIRST_META_KEY) &&
|
||||
if ((i >= RARCH_FIRST_META_KEY) &&
|
||||
BIT64_GET(lifecycle_state, i)
|
||||
)
|
||||
return true;
|
||||
|
@ -814,6 +814,7 @@ extern input_device_driver_t qnx_joypad;
|
||||
extern input_device_driver_t null_joypad;
|
||||
extern input_device_driver_t mfi_joypad;
|
||||
extern input_device_driver_t dos_joypad;
|
||||
extern input_device_driver_t rwebpad_joypad;
|
||||
|
||||
extern input_driver_t input_android;
|
||||
extern input_driver_t input_sdl;
|
||||
|
@ -579,109 +579,8 @@ const struct rarch_key_map rarch_key_map_dinput[] = {
|
||||
#endif
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
const struct rarch_key_map rarch_key_map_rwebinput[] = {
|
||||
{ 37, RETROK_LEFT },
|
||||
{ 39, RETROK_RIGHT },
|
||||
{ 38, RETROK_UP },
|
||||
{ 40, RETROK_DOWN },
|
||||
{ 13, RETROK_RETURN },
|
||||
{ 9, RETROK_TAB },
|
||||
{ 45, RETROK_INSERT },
|
||||
{ 46, RETROK_DELETE },
|
||||
{ 16, RETROK_RSHIFT },
|
||||
{ 16, RETROK_LSHIFT },
|
||||
{ 17, RETROK_LCTRL },
|
||||
{ 35, RETROK_END },
|
||||
{ 36, RETROK_HOME },
|
||||
{ 34, RETROK_PAGEDOWN },
|
||||
{ 33, RETROK_PAGEUP },
|
||||
{ 18, RETROK_LALT },
|
||||
{ 32, RETROK_SPACE },
|
||||
{ 27, RETROK_ESCAPE },
|
||||
{ 8, RETROK_BACKSPACE },
|
||||
{ 13, RETROK_KP_ENTER },
|
||||
{ 107, RETROK_KP_PLUS },
|
||||
{ 109, RETROK_KP_MINUS },
|
||||
{ 106, RETROK_KP_MULTIPLY },
|
||||
{ 111, RETROK_KP_DIVIDE },
|
||||
{ 192, RETROK_BACKQUOTE },
|
||||
{ 19, RETROK_PAUSE },
|
||||
{ 96, RETROK_KP0 },
|
||||
{ 97, RETROK_KP1 },
|
||||
{ 98, RETROK_KP2 },
|
||||
{ 99, RETROK_KP3 },
|
||||
{ 100, RETROK_KP4 },
|
||||
{ 101, RETROK_KP5 },
|
||||
{ 102, RETROK_KP6 },
|
||||
{ 103, RETROK_KP7 },
|
||||
{ 104, RETROK_KP8 },
|
||||
{ 105, RETROK_KP9 },
|
||||
{ 48, RETROK_0 },
|
||||
{ 49, RETROK_1 },
|
||||
{ 50, RETROK_2 },
|
||||
{ 51, RETROK_3 },
|
||||
{ 52, RETROK_4 },
|
||||
{ 53, RETROK_5 },
|
||||
{ 54, RETROK_6 },
|
||||
{ 55, RETROK_7 },
|
||||
{ 56, RETROK_8 },
|
||||
{ 57, RETROK_9 },
|
||||
{ 112, RETROK_F1 },
|
||||
{ 113, RETROK_F2 },
|
||||
{ 114, RETROK_F3 },
|
||||
{ 115, RETROK_F4 },
|
||||
{ 116, RETROK_F5 },
|
||||
{ 117, RETROK_F6 },
|
||||
{ 118, RETROK_F7 },
|
||||
{ 119, RETROK_F8 },
|
||||
{ 120, RETROK_F9 },
|
||||
{ 121, RETROK_F10 },
|
||||
{ 122, RETROK_F11 },
|
||||
{ 123, RETROK_F12 },
|
||||
{ 65, RETROK_a },
|
||||
{ 66, RETROK_b },
|
||||
{ 67, RETROK_c },
|
||||
{ 68, RETROK_d },
|
||||
{ 69, RETROK_e },
|
||||
{ 70, RETROK_f },
|
||||
{ 71, RETROK_g },
|
||||
{ 72, RETROK_h },
|
||||
{ 73, RETROK_i },
|
||||
{ 74, RETROK_j },
|
||||
{ 75, RETROK_k },
|
||||
{ 76, RETROK_l },
|
||||
{ 77, RETROK_m },
|
||||
{ 78, RETROK_n },
|
||||
{ 79, RETROK_o },
|
||||
{ 80, RETROK_p },
|
||||
{ 81, RETROK_q },
|
||||
{ 82, RETROK_r },
|
||||
{ 83, RETROK_s },
|
||||
{ 84, RETROK_t },
|
||||
{ 85, RETROK_u },
|
||||
{ 86, RETROK_v },
|
||||
{ 87, RETROK_w },
|
||||
{ 88, RETROK_x },
|
||||
{ 89, RETROK_y },
|
||||
{ 90, RETROK_z },
|
||||
{ 222, RETROK_QUOTE },
|
||||
{ 188, RETROK_COMMA },
|
||||
{ 173, RETROK_MINUS },
|
||||
{ 191, RETROK_SLASH },
|
||||
{ 59, RETROK_SEMICOLON },
|
||||
{ 61, RETROK_EQUALS },
|
||||
{ 219, RETROK_LEFTBRACKET },
|
||||
{ 220, RETROK_BACKSLASH },
|
||||
{ 221, RETROK_RIGHTBRACKET },
|
||||
{ 188, RETROK_KP_PERIOD },
|
||||
{ 17, RETROK_RCTRL },
|
||||
{ 18, RETROK_RALT },
|
||||
{ 190, RETROK_PERIOD },
|
||||
{ 145, RETROK_SCROLLOCK },
|
||||
{ 20, RETROK_CAPSLOCK },
|
||||
{ 144, RETROK_NUMLOCK },
|
||||
{ 0, RETROK_UNKNOWN },
|
||||
};
|
||||
/* this is generated at runtime, so it isn't constant */
|
||||
struct rarch_key_map rarch_key_map_rwebinput[RARCH_KEY_MAP_RWEBINPUT_SIZE];
|
||||
#endif
|
||||
|
||||
#ifdef WIIU
|
||||
|
@ -46,13 +46,18 @@ struct apple_key_name_map_entry
|
||||
extern const struct apple_key_name_map_entry apple_key_name_map[];
|
||||
#endif
|
||||
|
||||
#define RARCH_KEY_MAP_RWEBINPUT_SIZE 111
|
||||
|
||||
extern const struct input_key_map input_config_key_map[];
|
||||
|
||||
extern const struct rarch_key_map rarch_key_map_x11[];
|
||||
extern const struct rarch_key_map rarch_key_map_sdl[];
|
||||
extern const struct rarch_key_map rarch_key_map_sdl2[];
|
||||
extern const struct rarch_key_map rarch_key_map_dinput[];
|
||||
extern const struct rarch_key_map rarch_key_map_rwebinput[];
|
||||
|
||||
/* is generated at runtime so can't be const */
|
||||
extern struct rarch_key_map rarch_key_map_rwebinput[RARCH_KEY_MAP_RWEBINPUT_SIZE];
|
||||
|
||||
extern const struct rarch_key_map rarch_key_map_linux[];
|
||||
extern const struct rarch_key_map rarch_key_map_apple_hid[];
|
||||
extern const struct rarch_key_map rarch_key_map_android[];
|
||||
@ -96,4 +101,3 @@ extern enum retro_key rarch_keysym_lut[RETROK_LAST];
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -10,11 +10,11 @@
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.0/css/font-awesome.min.css">
|
||||
<!-- Material Design Bootstrap -->
|
||||
<link href="//cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.1.1/css/mdb.min.css" rel="stylesheet">
|
||||
<link href="//cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.1.1/css/mdb.min.css" rel="stylesheet">
|
||||
<link href="embed.css" rel="stylesheet" type="text/css">
|
||||
<link rel="shortcut icon" href="media/retroarch.ico" />
|
||||
</head>
|
||||
<body>
|
||||
<body>
|
||||
<!--Navbar-->
|
||||
<nav class="navbar navbar-dark bg-warning">
|
||||
<div class="container">
|
||||
@ -101,7 +101,7 @@
|
||||
<div class="bg-inverse webplayer-container">
|
||||
<div class="container">
|
||||
<div class="webplayer_border text-xs-center" id="canvas_div">
|
||||
<canvas class="webplayer col-xs-12" id="canvas" tabindex="1" oncontextmenu="event.preventDefault()" style="display: none"></canvas>
|
||||
<canvas class="webplayer" id="canvas" tabindex="1" oncontextmenu="event.preventDefault()" style="display: none"></canvas>
|
||||
<img class="webplayer-preview img-fluid" src="media/canvas.png" width="960px" height="720px" alt="RetroArch Logo">
|
||||
</div>
|
||||
</div>
|
||||
|
@ -11,11 +11,11 @@
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.0/css/font-awesome.min.css">
|
||||
<!-- Material Design Bootstrap -->
|
||||
<link href="//cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.1.1/css/mdb.min.css" rel="stylesheet">
|
||||
|
||||
|
||||
<link href="itch.css" rel="stylesheet" type="text/css">
|
||||
<link rel="shortcut icon" href="https://buildbot.libretro.com/web/media/retroarch.ico" />
|
||||
</head>
|
||||
<body>
|
||||
<body>
|
||||
<!--Navbar-->
|
||||
<nav class="navbar navbar-dark bg-danger">
|
||||
<div class="container">
|
||||
@ -105,7 +105,7 @@
|
||||
<div class="bg-inverse webplayer-container">
|
||||
<div class="container">
|
||||
<div class="webplayer_border text-xs-center" id="canvas_div">
|
||||
<canvas class="webplayer col-xs-12" id="canvas" tabindex="1" oncontextmenu="event.preventDefault()" style="display: none"></canvas>
|
||||
<canvas class="webplayer" id="canvas" tabindex="1" oncontextmenu="event.preventDefault()" style="display: none"></canvas>
|
||||
<img class="webplayer-preview img-fluid" src="https://buildbot.libretro.com/web/media/canvas.png" width="960px" height="720px" alt="RetroArch Logo">
|
||||
</div>
|
||||
</div>
|
||||
|
@ -102,7 +102,7 @@
|
||||
<div class="bg-inverse webplayer-container">
|
||||
<div class="container">
|
||||
<div class="webplayer_border text-xs-center" id="canvas_div">
|
||||
<canvas class="webplayer col-xs-12" id="canvas" tabindex="1" oncontextmenu="event.preventDefault()" style="display: none"></canvas>
|
||||
<canvas class="webplayer" id="canvas" tabindex="1" oncontextmenu="event.preventDefault()" style="display: none"></canvas>
|
||||
<img class="webplayer-preview img-fluid" src="media/canvas.png" width="960px" height="720px" alt="RetroArch Logo">
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user