Big refactor of joypad input.

This commit is contained in:
Themaister 2012-09-28 22:38:42 +02:00
parent ee8a93973f
commit c655c1d4e5
20 changed files with 574 additions and 612 deletions

View File

@ -12,6 +12,7 @@ OBJ = retroarch.o \
message.o \
rewind.o \
gfx/gfx_common.o \
input/input_common.o \
patch.o \
compat/compat.o \
screenshot.o \
@ -138,7 +139,7 @@ ifeq ($(SCALER_PERF), 1)
endif
ifeq ($(HAVE_SDL), 1)
OBJ += gfx/sdl_gfx.o input/sdl_input.o audio/sdl_audio.o fifo_buffer.o
OBJ += gfx/sdl_gfx.o input/sdl_input.o input/sdl_joypad.o audio/sdl_audio.o fifo_buffer.o
OBJ += gfx/scaler/scaler.o gfx/scaler/pixconv.o gfx/scaler/scaler_int.o gfx/scaler/filter.o
DEFINES += $(SDL_CFLAGS) $(BSD_LOCAL_INC)
LIBS += $(SDL_LIBS)

View File

@ -13,6 +13,7 @@ OBJ = retroarch.o \
rewind.o \
movie.o \
gfx/gfx_common.o \
input/input_common.o \
patch.o \
compat/compat.o \
screenshot.o \
@ -61,7 +62,7 @@ ifeq ($(TDM_GCC),)
endif
ifeq ($(HAVE_SDL), 1)
OBJ += gfx/sdl_gfx.o gfx/gl.o gfx/math/matrix.o gfx/fonts/freetype.o gfx/context/sdl_ctx.o gfx/gfx_context.o input/sdl_input.o audio/sdl_audio.o fifo_buffer.o
OBJ += gfx/sdl_gfx.o gfx/gl.o gfx/math/matrix.o gfx/fonts/freetype.o gfx/context/sdl_ctx.o gfx/gfx_context.o input/sdl_input.o input/sdl_joypad.o audio/sdl_audio.o fifo_buffer.o
OBJ += gfx/scaler/scaler.o gfx/scaler/pixconv.o gfx/scaler/scaler_int.o gfx/scaler/filter.o
LIBS += -lSDL
DEFINES += -ISDL -DHAVE_SDL

View File

@ -22,6 +22,10 @@
#include <math.h>
#include "compat/posix_string.h"
#ifdef HAVE_X11
#include "gfx/context/x11_common.h"
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@ -594,6 +598,10 @@ void init_video_input(void)
RARCH_LOG("Video @ %ux%u\n", width, height);
driver.display_type = RARCH_DISPLAY_NONE;
driver.video_display = 0;
driver.video_window = 0;
video_info_t video = {0};
video.width = width;
video.height = height;
@ -616,6 +624,14 @@ void init_video_input(void)
if (driver.video->set_rotation && g_extern.system.rotation)
video_set_rotation_func(g_extern.system.rotation);
#ifdef HAVE_X11
if (driver.display_type == RARCH_DISPLAY_X11)
{
RARCH_LOG("Suspending screensaver (X11).\n");
x11_suspend_screensaver(driver.video_window);
}
#endif
// Video driver didn't provide an input driver so we use configured one.
if (driver.input == NULL)
{

View File

@ -204,6 +204,14 @@ typedef struct video_driver
bool (*read_viewport)(void *data, uint8_t *buffer);
} video_driver_t;
enum rarch_display_type
{
RARCH_DISPLAY_NONE = 0, // Non-bindable types like consoles, KMS, VideoCore, etc.
RARCH_DISPLAY_X11, // video_display => Display*, video_window => Window
RARCH_DISPLAY_WIN32, // video_display => N/A, video_window => HWND
RARCH_DISPLAY_OSX // ?!
};
typedef struct driver
{
const audio_driver_t *audio;
@ -217,6 +225,14 @@ typedef struct driver
rarch_cmd_t *command;
#endif
bool stdin_claimed;
// Opaque handles to currently running window.
// Used by e.g. input drivers which bind to a window.
// Drivers are responsible for setting these if an input driver
// could potentially make use of this.
uintptr_t video_display;
uintptr_t video_window;
enum rarch_display_type display_type;
} driver_t;
void init_drivers(void);

View File

@ -121,6 +121,31 @@ static void gfx_ctx_destroy(void)
g_inited = false;
}
static void sdl_set_handles(void)
{
#if defined(_WIN32)
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWMInfo(&info) == 1)
{
driver.display_type = RARCH_DISPLAY_WIN32;
driver.video_display = 0;
driver.video_window = (uintptr_t)info.window;
}
#elif defined(HAVE_X11)
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWMInfo(&info) == 1)
{
driver.display_type = RARCH_DISPLAY_X11;
driver.video_display = (uintptr_t)info.info.x11.display;
driver.video_window = (uintptr_t)info.info.x11.window;
}
#endif
}
static bool gfx_ctx_set_video_mode(
unsigned width, unsigned height,
unsigned bits, bool fullscreen)
@ -161,17 +186,7 @@ static bool gfx_ctx_set_video_mode(
// Remove that ugly mouse :D
SDL_ShowCursor(SDL_DISABLE);
// Suspend screensaver on X11.
#if defined(HAVE_X11)
RARCH_LOG("Suspending screensaver (X11).\n");
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWMInfo(&info) == 1)
x11_suspend_screensaver(info.info.x11.window);
else
RARCH_ERR("Failed to get SDL WM info, cannot suspend screensaver.\n");
#endif
sdl_set_handles();
return true;
}

View File

@ -22,7 +22,6 @@
#include "../gl_common.h"
#include "../gfx_common.h"
#include "x11_common.h"
#include "../../input/x11_input.h"
#include <signal.h>
#include <stdint.h>
@ -302,13 +301,16 @@ static bool gfx_ctx_set_video_mode(
if (g_quit_atom)
XSetWMProtocols(g_dpy, g_win, &g_quit_atom, 1);
x11_suspend_screensaver(g_win);
gfx_ctx_swap_interval(g_interval);
XFree(vi);
g_has_focus = true;
g_inited = true;
driver.display_type = RARCH_DISPLAY_X11;
driver.video_display = (uintptr_t)g_dpy;
driver.video_window = (Window)g_win;
return true;
error:
@ -366,9 +368,6 @@ static void gfx_ctx_input_driver(const input_driver_t **input, void **input_data
void *xinput = input_x.init();
*input = xinput ? &input_x : NULL;
*input_data = xinput;
if (xinput)
x_input_set_disp_win((x11_input_t*)xinput, g_dpy, g_win);
}
static bool gfx_ctx_has_focus(void)

View File

@ -32,10 +32,6 @@
#include "gfx_context.h"
#include "../compat/strl.h"
#ifdef HAVE_SDL
#include "../input/rarch_sdl_input.h"
#endif
#ifdef HAVE_CG
#include "shader_cg.h"
#endif

View File

@ -18,7 +18,6 @@
#include <stdlib.h>
#include <string.h>
#include "../general.h"
#include "../input/rarch_sdl_input.h"
#include "scaler/scaler.h"
#include "gfx_common.h"
#include "gfx_context.h"
@ -299,6 +298,32 @@ static void sdl_render_msg_32(sdl_video_t *vid, SDL_Surface *buffer, const char
#endif
}
static void sdl_gfx_set_handles(void)
{
// SysWMinfo headers are broken on OSX. :(
#if defined(_WIN32)
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWMInfo(&info) == 1)
{
driver.display_type = RARCH_DISPLAY_WIN32;
driver.video_display = 0;
driver.video_window = (uintptr_t)info.window;
}
#elif defined(HAVE_X11)
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWMInfo(&info) == 1)
{
driver.display_type = RARCH_DISPLAY_X11;
driver.video_display = (uintptr_t)info.info.x11.display;
driver.video_window = (uintptr_t)info.info.x11.window;
}
#endif
}
static void *sdl_gfx_init(const video_info_t *video, const input_driver_t **input, void **input_data)
{
#ifdef _WIN32
@ -317,7 +342,7 @@ static void *sdl_gfx_init(const video_info_t *video, const input_driver_t **inpu
unsigned full_y = video_info->current_h;
RARCH_LOG("Detecting desktop resolution %ux%u.\n", full_x, full_y);
sdl_input_t *sdl_input = NULL;
void *sdl_input = NULL;
const SDL_PixelFormat *fmt = NULL;
if (!video->fullscreen)
@ -337,16 +362,6 @@ static void *sdl_gfx_init(const video_info_t *video, const input_driver_t **inpu
SDL_ShowCursor(SDL_DISABLE);
#if defined(HAVE_X11)
RARCH_LOG("Suspending screensaver (X11).\n");
SDL_SysWMinfo wm_info;
SDL_VERSION(&wm_info.version);
if (SDL_GetWMInfo(&wm_info) == 1)
x11_suspend_screensaver(wm_info.info.x11.window);
else
RARCH_ERR("Failed to suspend screensaver.\n");
#endif
fmt = vid->screen->format;
if (vid->render32)
{
@ -371,7 +386,9 @@ static void *sdl_gfx_init(const video_info_t *video, const input_driver_t **inpu
goto error;
}
sdl_input = (sdl_input_t*)input_sdl.init();
sdl_gfx_set_handles();
sdl_input = input_sdl.init();
if (sdl_input)
{
*input = &input_sdl;

View File

@ -20,7 +20,6 @@
#include <signal.h>
#include <math.h>
#include "gfx_common.h"
#include "../input/x11_input.h"
#ifdef HAVE_FREETYPE
#include "fonts/fonts.h"
@ -531,8 +530,9 @@ static void *xv_init(const video_info_t *video, const input_driver_t **input, vo
xv_set_nonblock_state(xv, !video->vsync);
xv->focus = true;
RARCH_LOG("Suspending screensaver (X11).\n");
x11_suspend_screensaver(xv->window);
driver.display_type = RARCH_DISPLAY_X11;
driver.video_display = (uintptr_t)xv->display;
driver.video_window = (Window)xv->window;
xinput = input_x.init();
if (xinput)
@ -543,9 +543,6 @@ static void *xv_init(const video_info_t *video, const input_driver_t **input, vo
else
*input = NULL;
if (xinput)
x_input_set_disp_win((x11_input_t*)xinput, xv->display, xv->window);
init_yuv_tables(xv);
xv_init_font(xv, g_settings.video.font_path, g_settings.video.font_size);

View File

@ -13,33 +13,45 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "rarch_dinput.h"
#include "SDL.h"
#include "SDL_syswm.h"
#undef DIRECTINPUT_VERSION
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
#include "../general.h"
#include "../boolean.h"
#include "input_common.h"
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include "../gfx/gfx_context.h"
void sdl_dinput_free(sdl_dinput_t *di)
static LPDIRECTINPUT8 g_ctx;
struct dinput_joypad
{
if (di)
LPDIRECTINPUTDEVICE8 joypad;
DIJOYSTATE2 joy_state;
};
static unsigned g_joypad_cnt;
static struct dinput_joypad g_pads[MAX_PLAYERS];
static void dinput_destroy(void)
{
for (unsigned i = 0; i < MAX_PLAYERS; i++)
{
for (unsigned i = 0; i < MAX_PLAYERS; i++)
if (g_pads[i].joypad)
{
if (di->joypad[i])
{
IDirectInputDevice8_Unacquire(di->joypad[i]);
IDirectInputDevice8_Release(di->joypad[i]);
}
IDirectInputDevice8_Unacquire(g_pads[i].joypad);
IDirectInputDevice8_Release(g_pads[i].joypad);
}
if (di->ctx)
IDirectInput8_Release(di->ctx);
free(di);
}
if (g_ctx)
IDirectInput8_Release(g_ctx);
g_ctx = NULL;
g_joypad_cnt = 0;
memset(g_pads, 0, sizeof(g_pads));
}
static BOOL CALLBACK enum_axes_cb(const DIDEVICEOBJECTINSTANCE *inst, void *p)
@ -61,68 +73,49 @@ static BOOL CALLBACK enum_axes_cb(const DIDEVICEOBJECTINSTANCE *inst, void *p)
static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p)
{
sdl_dinput_t *di = (sdl_dinput_t*)p;
(void)p;
if (g_joypad_cnt == MAX_PLAYERS)
return DIENUM_STOP;
unsigned active = 0;
unsigned n;
for (n = 0; n < MAX_PLAYERS; n++)
{
if (!di->joypad[n] && g_settings.input.joypad_map[n] == (int)di->joypad_cnt)
break;
if (di->joypad[n])
active++;
}
if (active == MAX_PLAYERS) return DIENUM_STOP;
di->joypad_cnt++;
if (n == MAX_PLAYERS)
return DIENUM_CONTINUE;
LPDIRECTINPUTDEVICE8 *pad = &g_pads[g_joypad_cnt].joypad;
#ifdef __cplusplus
if (FAILED(IDirectInput8_CreateDevice(di->ctx, inst->guidInstance, &di->joypad[n], NULL)))
if (FAILED(IDirectInput8_CreateDevice(g_ctx, inst->guidInstance, pad, NULL)))
#else
if (FAILED(IDirectInput8_CreateDevice(di->ctx, &inst->guidInstance, &di->joypad[n], NULL)))
if (FAILED(IDirectInput8_CreateDevice(g_ctx, &inst->guidInstance, pad, NULL)))
#endif
return DIENUM_CONTINUE;
IDirectInputDevice8_SetDataFormat(di->joypad[n], &c_dfDIJoystick2);
IDirectInputDevice8_SetCooperativeLevel(di->joypad[n], di->hWnd,
IDirectInputDevice8_SetDataFormat(*pad, &c_dfDIJoystick2);
IDirectInputDevice8_SetCooperativeLevel(*pad, (HWND)driver.video_window,
DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
IDirectInputDevice8_EnumObjects(di->joypad[n], enum_axes_cb,
di->joypad[n], DIDFT_ABSAXIS);
IDirectInputDevice8_EnumObjects(*pad, enum_axes_cb,
*pad, DIDFT_ABSAXIS);
g_joypad_cnt++;
return DIENUM_CONTINUE;
}
sdl_dinput_t* sdl_dinput_init(void)
static bool dinput_init(void)
{
sdl_dinput_t *di = (sdl_dinput_t*)calloc(1, sizeof(*di));
if (!di)
return NULL;
CoInitialize(NULL);
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWMInfo(&info) != 1)
if (driver.display_type != RARCH_DISPLAY_WIN32)
{
RARCH_ERR("Failed to get SysWM info.\n");
goto error;
RARCH_ERR("Cannot open DInput as no Win32 window is present.\n");
return false;
}
di->hWnd = info.window;
CoInitialize(NULL);
#ifdef __cplusplus
if (FAILED(DirectInput8Create(
GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8,
(void**)&di->ctx, NULL)))
(void**)&g_ctx, NULL)))
#else
if (FAILED(DirectInput8Create(
GetModuleHandle(NULL), DIRECTINPUT_VERSION, &IID_IDirectInput8,
(void**)&di->ctx, NULL)))
(void**)&g_ctx, NULL)))
#endif
{
RARCH_ERR("Failed to init DirectInput.\n");
@ -130,31 +123,33 @@ sdl_dinput_t* sdl_dinput_init(void)
}
RARCH_LOG("Enumerating DInput devices ...\n");
IDirectInput8_EnumDevices(di->ctx, DI8DEVCLASS_GAMECTRL, enum_joypad_cb, di, DIEDFL_ATTACHEDONLY);
IDirectInput8_EnumDevices(g_ctx, DI8DEVCLASS_GAMECTRL, enum_joypad_cb, NULL, DIEDFL_ATTACHEDONLY);
RARCH_LOG("Done enumerating DInput devices ...\n");
return di;
return true;
error:
sdl_dinput_free(di);
dinput_destroy();
return NULL;
}
static bool dinput_joykey_pressed(sdl_dinput_t *di, unsigned port_num, uint16_t joykey)
static bool dinput_button(unsigned port_num, uint16_t joykey)
{
if (joykey == NO_BTN)
return false;
const struct dinput_joypad *pad = &g_pads[port_num];
// Check hat.
if (GET_HAT_DIR(joykey))
{
unsigned hat = GET_HAT(joykey);
unsigned elems = sizeof(di->joy_state[0].rgdwPOV) / sizeof(di->joy_state[0].rgdwPOV[0]);
unsigned elems = sizeof(pad->joy_state.rgdwPOV) / sizeof(pad->joy_state.rgdwPOV[0]);
if (hat >= elems)
return false;
unsigned pov = di->joy_state[port_num].rgdwPOV[hat];
unsigned pov = pad->joy_state.rgdwPOV[hat];
// Magic numbers I'm not sure where originate from.
if (pov < 36000)
@ -176,22 +171,22 @@ static bool dinput_joykey_pressed(sdl_dinput_t *di, unsigned port_num, uint16_t
}
else
{
unsigned elems = sizeof(di->joy_state[0].rgbButtons) / sizeof(di->joy_state[0].rgbButtons[0]);
unsigned elems = sizeof(pad->joy_state.rgbButtons) / sizeof(pad->joy_state.rgbButtons[0]);
if (joykey < elems)
return di->joy_state[port_num].rgbButtons[joykey];
return pad->joy_state.rgbButtons[joykey];
}
return false;
}
int16_t sdl_dinput_axis(sdl_dinput_t *di, unsigned port_num, const struct retro_keybind *key)
static int16_t dinput_axis(unsigned port_num, uint32_t joyaxis)
{
uint32_t joyaxis = key->joyaxis;
if (joyaxis == AXIS_NONE)
return 0;
const struct dinput_joypad *pad = &g_pads[port_num];
int val = 0;
int axis = -1;
@ -211,12 +206,12 @@ int16_t sdl_dinput_axis(sdl_dinput_t *di, unsigned port_num, const struct retro_
switch (axis)
{
case 0: val = di->joy_state[port_num].lX; break;
case 1: val = di->joy_state[port_num].lY; break;
case 2: val = di->joy_state[port_num].lZ; break;
case 3: val = di->joy_state[port_num].lRx; break;
case 4: val = di->joy_state[port_num].lRy; break;
case 5: val = di->joy_state[port_num].lRz; break;
case 0: val = pad->joy_state.lX; break;
case 1: val = pad->joy_state.lY; break;
case 2: val = pad->joy_state.lZ; break;
case 3: val = pad->joy_state.lRx; break;
case 4: val = pad->joy_state.lRy; break;
case 5: val = pad->joy_state.lRz; break;
}
if (val < -0x7fff) // So abs() of -0x8000 can't mess us up.
@ -230,44 +225,33 @@ int16_t sdl_dinput_axis(sdl_dinput_t *di, unsigned port_num, const struct retro_
return val;
}
static bool dinput_joyaxis_pressed(sdl_dinput_t *di, unsigned port_num, const struct retro_keybind *key)
static void dinput_poll(void)
{
if (key->joyaxis == AXIS_NONE)
return false;
int min = 0x7fff * g_settings.input.axis_threshold;
int16_t val = sdl_dinput_axis(di, port_num, key);
return abs(val) > min;
}
bool sdl_dinput_pressed(sdl_dinput_t *di, unsigned port_num, const struct retro_keybind *key)
{
if (di->joypad[port_num] == NULL)
return false;
if (dinput_joykey_pressed(di, port_num, key->joykey))
return true;
if (dinput_joyaxis_pressed(di, port_num, key))
return true;
return false;
}
void sdl_dinput_poll(sdl_dinput_t *di)
{
memset(di->joy_state, 0, sizeof(di->joy_state));
for (unsigned i = 0; i < MAX_PLAYERS; i++)
{
if (di->joypad[i])
struct dinput_joypad *pad = &g_pads[i];
if (pad->joypad)
{
if (FAILED(IDirectInputDevice8_Poll(di->joypad[i])))
memset(&pad->joy_state, 0, sizeof(pad->joy_state));
if (FAILED(IDirectInputDevice8_Poll(pad->joypad)))
{
IDirectInputDevice8_Acquire(di->joypad[i]);
IDirectInputDevice8_Acquire(pad->joypad);
continue;
}
IDirectInputDevice8_GetDeviceState(di->joypad[i], sizeof(DIJOYSTATE2), &di->joy_state[i]);
IDirectInputDevice8_GetDeviceState(pad->joypad, sizeof(DIJOYSTATE2), &pad->joy_state);
}
}
}
const rarch_joypad_driver_t dinput_joypad = {
dinput_init,
dinput_destroy,
dinput_button,
dinput_axis,
dinput_poll,
"DInput",
};

113
input/input_common.c Normal file
View File

@ -0,0 +1,113 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* 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 "input_common.h"
#include <string.h>
#include <stdlib.h>
#include "../general.h"
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
static const rarch_joypad_driver_t *joypad_drivers[] = {
#ifdef HAVE_DINPUT
&dinput_joypad,
#endif
#if defined(__linux) && 0
&linuxraw_joypad,
#endif
#ifdef HAVE_SDL
&sdl_joypad,
#endif
};
const rarch_joypad_driver_t *input_joypad_find_driver(const char *ident)
{
for (unsigned i = 0; i < sizeof(joypad_drivers) / sizeof(joypad_drivers[0]); i++)
if (strcmp(ident, joypad_drivers[i]->ident) == 0)
return joypad_drivers[i];
return NULL;
}
const rarch_joypad_driver_t *input_joypad_init_first(void)
{
for (unsigned i = 0; i < sizeof(joypad_drivers) / sizeof(joypad_drivers[0]); i++)
if (joypad_drivers[i]->init())
return joypad_drivers[i];
return NULL;
}
void input_joypad_poll(const rarch_joypad_driver_t *driver)
{
if (driver)
driver->poll();
}
bool input_joypad_pressed(const rarch_joypad_driver_t *driver,
unsigned port, const struct retro_keybind *key)
{
if (!driver)
return false;
int joy_index = g_settings.input.joypad_map[port];
if (joy_index < 0 || joy_index >= MAX_PLAYERS)
return false;
if (!key->valid)
return false;
if (driver->button(joy_index, key->joykey))
return true;
int16_t axis = driver->axis(joy_index, key->joyaxis);
float scaled_axis = (float)abs(axis) / 0x8000;
return scaled_axis > g_settings.input.axis_threshold;
}
int16_t input_joypad_analog(const rarch_joypad_driver_t *driver,
unsigned port, unsigned index, unsigned id, const struct retro_keybind *binds)
{
if (!driver)
return 0;
int joy_index = g_settings.input.joypad_map[port];
if (joy_index < 0)
return 0;
unsigned id_minus = 0;
unsigned id_plus = 0;
input_conv_analog_id_to_bind_id(index, id, &id_minus, &id_plus);
const struct retro_keybind *bind_minus = &binds[id_minus];
const struct retro_keybind *bind_plus = &binds[id_plus];
if (!bind_minus->valid || !bind_plus->valid)
return 0;
int16_t pressed_minus = abs(driver->axis(joy_index, bind_minus->joyaxis));
int16_t pressed_plus = abs(driver->axis(joy_index, bind_plus->joyaxis));
int16_t res = pressed_plus - pressed_minus;
if (res != 0)
return res;
int16_t digital_left = driver->button(joy_index, bind_minus->joykey) ? -0x7fff : 0;
int16_t digital_right = driver->button(joy_index, bind_plus->joykey) ? 0x7fff : 0;
return digital_right + digital_left;
}

View File

@ -17,6 +17,7 @@
#define INPUT_COMMON_H__
#include "../driver.h"
#include <stdint.h>
static inline void input_conv_analog_id_to_bind_id(unsigned index, unsigned id,
unsigned *id_minus, unsigned *id_plus)
@ -45,5 +46,31 @@ static inline void input_conv_analog_id_to_bind_id(unsigned index, unsigned id,
}
}
typedef struct rarch_joypad_driver
{
bool (*init)(void);
void (*destroy)(void);
bool (*button)(unsigned, uint16_t);
int16_t (*axis)(unsigned, uint32_t);
void (*poll)(void);
const char *ident;
} rarch_joypad_driver_t;
const rarch_joypad_driver_t *input_joypad_find_driver(const char *ident);
const rarch_joypad_driver_t *input_joypad_init_first(void);
bool input_joypad_pressed(const rarch_joypad_driver_t *driver,
unsigned port, const struct retro_keybind *key);
int16_t input_joypad_analog(const rarch_joypad_driver_t *driver,
unsigned port, unsigned index, unsigned id, const struct retro_keybind *binds);
void input_joypad_poll(const rarch_joypad_driver_t *driver);
extern const rarch_joypad_driver_t dinput_joypad;
extern const rarch_joypad_driver_t linuxraw_joypad;
extern const rarch_joypad_driver_t sdl_joypad;
#endif

View File

@ -23,13 +23,18 @@
#include <unistd.h>
#include <signal.h>
#include "../general.h"
#include "linuxraw_input.h"
#include "rarch_sdl_input.h"
#include "input_common.h"
static long oldKbmd = 0xffff;
static struct termios oldTerm, newTerm;
typedef struct linuxraw_input
{
const rarch_joypad_driver_t *joypad;
bool state[0x80];
} linuxraw_input_t;
struct key_bind
{
uint8_t x;
@ -152,7 +157,7 @@ static void init_lut(void)
keysym_lut[lut_binds[i].sk] = lut_binds[i].x;
}
static void linuxraw_resetKbmd()
static void linuxraw_resetKbmd(void)
{
if (oldKbmd != 0xffff)
{
@ -221,17 +226,9 @@ static void *linuxraw_input_init(void)
atexit(linuxraw_resetKbmd);
linuxraw->sdl = (sdl_input_t*)input_sdl.init();
if (!linuxraw->sdl)
{
linuxraw_resetKbmd();
free(linuxraw);
return NULL;
}
linuxraw->joypad = input_joypad_init_first();
init_lut();
linuxraw->sdl->use_keyboard = false;
driver.stdin_claimed = true; // We need to disable use of stdin command interface if stdin is supposed to be used for input.
return linuxraw;
}
@ -256,30 +253,7 @@ static bool linuxraw_bind_button_pressed(void *data, int key)
{
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
return linuxraw_is_pressed(linuxraw, g_settings.input.binds[0], key) ||
input_sdl.key_pressed(linuxraw->sdl, key);
}
static int16_t raw_analog_state(linuxraw_input_t *linuxraw, const struct retro_keybind **binds_,
unsigned port, unsigned index, unsigned id)
{
const struct retro_keybind *binds = binds_[port];
if (id >= RARCH_BIND_LIST_END)
return 0;
unsigned id_minus = 0;
unsigned id_plus = 0;
input_conv_analog_id_to_bind_id(index, id, &id_minus, &id_plus);
const struct retro_keybind *bind_minus = &binds[id_minus];
const struct retro_keybind *bind_plus = &binds[id_plus];
if (!bind_minus->valid || !bind_plus->valid)
return 0;
int16_t res_minus = linuxraw_is_pressed(linuxraw, binds, id_minus) ? -0x7fff : 0;
int16_t res_plus = linuxraw_is_pressed(linuxraw, binds, id_plus) ? 0x7fff : 0;
return res_plus + res_minus;
input_joypad_pressed(linuxraw->joypad, 0, &g_settings.input.binds[0][key]);
}
static int16_t linuxraw_input_state(void *data, const struct retro_keybind **binds, unsigned port, unsigned device, unsigned index, unsigned id)
@ -290,15 +264,10 @@ static int16_t linuxraw_input_state(void *data, const struct retro_keybind **bin
{
case RETRO_DEVICE_JOYPAD:
return linuxraw_is_pressed(linuxraw, binds[port], id) ||
input_sdl.input_state(linuxraw->sdl, binds, port, device, index, id);
input_joypad_pressed(linuxraw->joypad, port, &binds[port][id]);
case RETRO_DEVICE_ANALOG:
{
int16_t ret = input_sdl.input_state(linuxraw->sdl, binds, port, device, index, id);
if (!ret)
ret = raw_analog_state(linuxraw, binds, port, index, id);
return ret;
}
return input_joypad_analog(linuxraw->joypad, port, index, id, binds[port]);
default:
return 0;
@ -308,7 +277,10 @@ static int16_t linuxraw_input_state(void *data, const struct retro_keybind **bin
static void linuxraw_input_free(void *data)
{
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
input_sdl.free(linuxraw->sdl);
if (linuxraw->joypad)
linuxraw->joypad->destroy();
linuxraw_resetKbmd();
free(data);
}
@ -334,7 +306,7 @@ static void linuxraw_input_poll(void *data)
linuxraw->state[c] = pressed;
}
input_sdl.poll(linuxraw->sdl);
input_joypad_poll(linuxraw->joypad);
}
const input_driver_t input_linuxraw = {

View File

@ -1,29 +0,0 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2012 - 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/>.
*/
#ifndef LINUXRAW_INPUT_H__
#define LINUXRAW_INPUT_H__
#include "../general.h"
#include "rarch_sdl_input.h"
typedef struct linuxraw_input
{
sdl_input_t *sdl;
bool state[0x80];
} linuxraw_input_t;
#endif

View File

@ -1,49 +0,0 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* 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/>.
*/
#ifndef __RARCH_DINPUT_H
#define __RARCH_DINPUT_H
#undef DIRECTINPUT_VERSION
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
#include "../boolean.h"
#include "../general.h"
// Piggyback joypad driver for SDL.
typedef struct sdl_dinput
{
HWND hWnd;
LPDIRECTINPUT8 ctx;
LPDIRECTINPUTDEVICE8 joypad[MAX_PLAYERS];
unsigned joypad_cnt;
DIJOYSTATE2 joy_state[MAX_PLAYERS];
} sdl_dinput_t;
sdl_dinput_t *sdl_dinput_init(void);
void sdl_dinput_free(sdl_dinput_t *di);
bool sdl_dinput_pressed(sdl_dinput_t *di, unsigned port_num,
const struct retro_keybind *key);
int16_t sdl_dinput_axis(sdl_dinput_t *di, unsigned port_num,
const struct retro_keybind *key);
void sdl_dinput_poll(sdl_dinput_t *di);
#endif

View File

@ -1,44 +0,0 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* 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/>.
*/
#ifndef __RARCH_SDL_INPUT_H
#define __RARCH_SDL_INPUT_H
#include "SDL.h"
#include "../general.h"
#ifdef HAVE_DINPUT
#include "rarch_dinput.h"
#endif
typedef struct sdl_input
{
#ifdef HAVE_DINPUT
sdl_dinput_t *di;
#else
SDL_Joystick *joysticks[MAX_PLAYERS];
unsigned num_axes[MAX_PLAYERS];
unsigned num_buttons[MAX_PLAYERS];
unsigned num_hats[MAX_PLAYERS];
unsigned num_joysticks;
#endif
bool use_keyboard;
int16_t mouse_x, mouse_y;
int16_t mouse_l, mouse_r, mouse_m;
} sdl_input_t;
#endif

View File

@ -15,15 +15,23 @@
#include "../driver.h"
#include "SDL.h"
#include "../gfx/gfx_context.h"
#include "../boolean.h"
#include "../general.h"
#include <stdint.h>
#include <stdlib.h>
#include "../libretro.h"
#include "rarch_sdl_input.h"
#include "input_common.h"
typedef struct sdl_input
{
const rarch_joypad_driver_t *joypad;
int16_t mouse_x, mouse_y;
int16_t mouse_l, mouse_r, mouse_m;
} sdl_input_t;
struct key_bind
{
unsigned sdl;
@ -132,52 +140,12 @@ static void *sdl_input_init(void)
if (!sdl)
return NULL;
#ifdef HAVE_DINPUT
sdl->di = sdl_dinput_init();
if (!sdl->di)
{
free(sdl);
RARCH_ERR("Failed to init SDL/DInput.\n");
return NULL;
}
#else
if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
return NULL;
sdl->joypad = input_joypad_init_first();
if (sdl->joypad)
RARCH_LOG("SDL: Found joypad driver: %s\n", sdl->joypad->ident);
else
RARCH_WARN("SDL: Didn't find suitable input driver.\n");
SDL_JoystickEventState(SDL_IGNORE);
sdl->num_joysticks = SDL_NumJoysticks();
for (unsigned i = 0; i < MAX_PLAYERS; i++)
{
if (g_settings.input.joypad_map[i] < 0)
continue;
unsigned port = g_settings.input.joypad_map[i];
if (sdl->num_joysticks <= port)
continue;
sdl->joysticks[i] = SDL_JoystickOpen(port);
if (!sdl->joysticks[i])
{
RARCH_ERR("Couldn't open SDL joystick #%u on SNES port %u\n", port, i + 1);
free(sdl);
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
return NULL;
}
RARCH_LOG("Opened Joystick: %s (#%u) on port %u\n",
SDL_JoystickName(port), port, i + 1);
sdl->num_axes[i] = SDL_JoystickNumAxes(sdl->joysticks[i]);
sdl->num_buttons[i] = SDL_JoystickNumButtons(sdl->joysticks[i]);
sdl->num_hats[i] = SDL_JoystickNumHats(sdl->joysticks[i]);
RARCH_LOG("Joypad has: %u axes, %u buttons, %u hats.\n",
sdl->num_axes[i], sdl->num_buttons[i], sdl->num_hats[i]);
}
#endif
sdl->use_keyboard = true;
return sdl;
}
@ -194,95 +162,12 @@ static bool sdl_key_pressed(int key)
return keymap[key];
}
#ifndef HAVE_DINPUT
static bool sdl_joykey_pressed(sdl_input_t *sdl, int port_num, uint16_t joykey)
{
if (joykey == NO_BTN)
return false;
// Check hat.
if (GET_HAT_DIR(joykey))
{
uint16_t hat = GET_HAT(joykey);
if (hat >= sdl->num_hats[port_num])
return false;
Uint8 dir = SDL_JoystickGetHat(sdl->joysticks[port_num], hat);
switch (GET_HAT_DIR(joykey))
{
case HAT_UP_MASK:
return dir & SDL_HAT_UP;
case HAT_DOWN_MASK:
return dir & SDL_HAT_DOWN;
case HAT_LEFT_MASK:
return dir & SDL_HAT_LEFT;
case HAT_RIGHT_MASK:
return dir & SDL_HAT_RIGHT;
default:
return false;
}
}
else // Check the button
{
if (joykey < sdl->num_buttons[port_num] && SDL_JoystickGetButton(sdl->joysticks[port_num], joykey))
return true;
return false;
}
}
static int16_t sdl_axis_analog(sdl_input_t *sdl, unsigned port_num, uint32_t joyaxis)
{
if (joyaxis == AXIS_NONE)
return 0;
Sint16 val = 0;
if (AXIS_NEG_GET(joyaxis) < sdl->num_axes[port_num])
{
val = SDL_JoystickGetAxis(sdl->joysticks[port_num], AXIS_NEG_GET(joyaxis));
if (val > 0)
val = 0;
else if (val < -0x8000) // -0x8000 can cause trouble if we later abs() it.
val = -0x7fff;
}
else if (AXIS_POS_GET(joyaxis) < sdl->num_axes[port_num])
{
val = SDL_JoystickGetAxis(sdl->joysticks[port_num], AXIS_POS_GET(joyaxis));
if (val < 0)
val = 0;
}
return val;
}
static bool sdl_axis_pressed(sdl_input_t *sdl, unsigned port_num, uint32_t joyaxis)
{
int16_t val = sdl_axis_analog(sdl, port_num, joyaxis);
float scaled = (float)abs(val) / 0x8000;
return scaled > g_settings.input.axis_threshold;
}
#endif
static bool sdl_is_pressed(sdl_input_t *sdl, unsigned port_num, const struct retro_keybind *key)
{
if (sdl->use_keyboard && sdl_key_pressed(key->key))
if (sdl_key_pressed(key->key))
return true;
#ifdef HAVE_DINPUT
return sdl_dinput_pressed(sdl->di, port_num, key);
#else
if (sdl->joysticks[port_num] == NULL)
return false;
if (sdl_joykey_pressed(sdl, port_num, key->joykey))
return true;
if (sdl_axis_pressed(sdl, port_num, key->joyaxis))
return true;
#endif
return false;
return input_joypad_pressed(sdl->joypad, port_num, key);
}
static bool sdl_bind_button_pressed(void *data, int key)
@ -304,51 +189,21 @@ static int16_t sdl_joypad_device_state(sdl_input_t *sdl, const struct retro_keyb
if (id < RARCH_BIND_LIST_END)
{
const struct retro_keybind *bind = &binds[id];
return bind->valid ? (sdl_is_pressed(sdl, port_num, bind) ? 1 : 0) : 0;
return bind->valid && sdl_is_pressed(sdl, port_num, bind);
}
else
return 0;
}
static int16_t sdl_analog_device_state(sdl_input_t *sdl, const struct retro_keybind **binds_,
static int16_t sdl_analog_device_state(sdl_input_t *sdl, const struct retro_keybind **binds,
unsigned port_num, unsigned index, unsigned id)
{
const struct retro_keybind *binds = binds_[port_num];
if (id >= RARCH_BIND_LIST_END)
return 0;
unsigned id_minus = 0;
unsigned id_plus = 0;
input_conv_analog_id_to_bind_id(index, id, &id_minus, &id_plus);
const struct retro_keybind *bind_minus = &binds[id_minus];
const struct retro_keybind *bind_plus = &binds[id_plus];
if (!bind_minus->valid || !bind_plus->valid)
return 0;
// A user might have bound minus axis to positive axis in SDL.
#ifdef HAVE_DINPUT
int16_t pressed_minus = abs(sdl_dinput_axis(sdl->di, port_num, bind_minus));
int16_t pressed_plus = abs(sdl_dinput_axis(sdl->di, port_num, bind_plus));
#else
int16_t pressed_minus = abs(sdl_axis_analog(sdl, port_num, bind_minus->joyaxis));
int16_t pressed_plus = abs(sdl_axis_analog(sdl, port_num, bind_plus->joyaxis));
#endif
int16_t res = pressed_plus - pressed_minus;
// TODO: Does it make sense to use axis thresholding here?
if (res != 0)
return res;
int16_t digital_left = sdl_is_pressed(sdl, port_num, bind_minus) ? -0x7fff : 0;
int16_t digital_right = sdl_is_pressed(sdl, port_num, bind_plus) ? 0x7fff : 0;
return digital_right + digital_left;
return input_joypad_analog(sdl->joypad, port_num, index, id, binds[port_num]);
}
static int16_t sdl_keyboard_device_state(sdl_input_t *sdl, unsigned id)
{
return sdl->use_keyboard && sdl_key_pressed(id);
return sdl_key_pressed(id);
}
static int16_t sdl_mouse_device_state(sdl_input_t *sdl, unsigned id)
@ -414,27 +269,19 @@ static int16_t sdl_input_state(void *data_, const struct retro_keybind **binds,
static void sdl_input_free(void *data)
{
if (data)
{
// Flush out all pending events.
SDL_Event event;
while (SDL_PollEvent(&event));
if (!data)
return;
sdl_input_t *sdl = (sdl_input_t*)data;
// Flush out all pending events.
SDL_Event event;
while (SDL_PollEvent(&event));
#ifdef HAVE_DINPUT
sdl_dinput_free(sdl->di);
#else
for (int i = 0; i < MAX_PLAYERS; i++)
{
if (sdl->joysticks[i])
SDL_JoystickClose(sdl->joysticks[i]);
}
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
#endif
sdl_input_t *sdl = (sdl_input_t*)data;
free(data);
}
if (sdl->joypad)
sdl->joypad->destroy();
free(data);
}
static void sdl_poll_mouse(sdl_input_t *sdl)
@ -453,12 +300,6 @@ static void sdl_input_poll(void *data)
SDL_PumpEvents();
sdl_input_t *sdl = (sdl_input_t*)data;
#ifdef HAVE_DINPUT
sdl_dinput_poll(sdl->di);
#else
SDL_JoystickUpdate();
#endif
sdl_poll_mouse(sdl);
}
@ -468,6 +309,6 @@ const input_driver_t input_sdl = {
sdl_input_state,
sdl_bind_button_pressed,
sdl_input_free,
"sdl"
"sdl",
};

161
input/sdl_joypad.c Normal file
View File

@ -0,0 +1,161 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* 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 "input_common.h"
#include "SDL.h"
#include "../general.h"
struct sdl_joypad
{
SDL_Joystick *joypad;
unsigned num_axes;
unsigned num_buttons;
unsigned num_hats;
};
static struct sdl_joypad g_pads[MAX_PLAYERS];
static void sdl_joypad_destroy(void)
{
for (unsigned i = 0; i < MAX_PLAYERS; i++)
{
if (g_pads[i].joypad)
SDL_JoystickClose(g_pads[i].joypad);
}
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
memset(g_pads, 0, sizeof(g_pads));
}
static bool sdl_joypad_init(void)
{
if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
return false;
unsigned num_sticks = SDL_NumJoysticks();
if (num_sticks > MAX_PLAYERS)
num_sticks = MAX_PLAYERS;
for (unsigned i = 0; i < num_sticks; i++)
{
struct sdl_joypad *pad = &g_pads[i];
pad->joypad = SDL_JoystickOpen(i);
if (!pad->joypad)
{
RARCH_ERR("Couldn't open SDL joystick #%u.\n", i);
goto error;
}
RARCH_LOG("Opened Joystick: %s (#%u).\n",
SDL_JoystickName(i), i);
pad->num_axes = SDL_JoystickNumAxes(pad->joypad);
pad->num_buttons = SDL_JoystickNumButtons(pad->joypad);
pad->num_hats = SDL_JoystickNumHats(pad->joypad);
RARCH_LOG("Joypad has: %u axes, %u buttons, %u hats.\n",
pad->num_axes, pad->num_buttons, pad->num_hats);
}
return true;
error:
sdl_joypad_destroy();
return false;
}
static bool sdl_joypad_button(unsigned port, uint16_t joykey)
{
if (joykey == NO_BTN)
return false;
const struct sdl_joypad *pad = &g_pads[port];
if (!pad->joypad)
return false;
// Check hat.
if (GET_HAT_DIR(joykey))
{
uint16_t hat = GET_HAT(joykey);
if (hat >= pad->num_hats)
return false;
Uint8 dir = SDL_JoystickGetHat(pad->joypad, hat);
switch (GET_HAT_DIR(joykey))
{
case HAT_UP_MASK:
return dir & SDL_HAT_UP;
case HAT_DOWN_MASK:
return dir & SDL_HAT_DOWN;
case HAT_LEFT_MASK:
return dir & SDL_HAT_LEFT;
case HAT_RIGHT_MASK:
return dir & SDL_HAT_RIGHT;
default:
return false;
}
}
else // Check the button
{
if (joykey < pad->num_buttons && SDL_JoystickGetButton(pad->joypad, joykey))
return true;
return false;
}
}
static int16_t sdl_joypad_axis(unsigned port, uint32_t joyaxis)
{
if (joyaxis == AXIS_NONE)
return 0;
const struct sdl_joypad *pad = &g_pads[port];
if (!pad->joypad)
return false;
Sint16 val = 0;
if (AXIS_NEG_GET(joyaxis) < pad->num_axes)
{
val = SDL_JoystickGetAxis(pad->joypad, AXIS_NEG_GET(joyaxis));
if (val > 0)
val = 0;
else if (val < -0x7fff) // -0x8000 can cause trouble if we later abs() it.
val = -0x7fff;
}
else if (AXIS_POS_GET(joyaxis) < pad->num_axes)
{
val = SDL_JoystickGetAxis(pad->joypad, AXIS_POS_GET(joyaxis));
if (val < 0)
val = 0;
}
return val;
}
static void sdl_joypad_poll(void)
{
SDL_JoystickUpdate();
}
const rarch_joypad_driver_t sdl_joypad = {
sdl_joypad_init,
sdl_joypad_destroy,
sdl_joypad_button,
sdl_joypad_axis,
sdl_joypad_poll,
"sdl",
};

View File

@ -13,26 +13,39 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "x11_input.h"
#include "input_common.h"
#include "../driver.h"
#include "SDL.h"
#include "../boolean.h"
#include "../general.h"
#include <stdint.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
typedef struct x11_input
{
const rarch_joypad_driver_t *joypad;
Display *display;
Window win;
char state[32];
bool mouse_l, mouse_r, mouse_m;
int mouse_x, mouse_y;
int mouse_last_x, mouse_last_y;
} x11_input_t;
struct key_bind
{
unsigned x;
enum retro_key sk;
};
void x_input_set_disp_win(x11_input_t *x11, Display *dpy, Window win)
{
if (x11->display && !x11->inherit_disp)
{
x11->inherit_disp = true;
XCloseDisplay(x11->display);
x11->display = dpy;
x11->win = win;
}
}
static unsigned keysym_lut[RETROK_LAST];
static const struct key_bind lut_binds[] = {
{ XK_Left, RETROK_LEFT },
@ -130,27 +143,23 @@ static void init_lut(void)
static void *x_input_init(void)
{
if (driver.display_type != RARCH_DISPLAY_X11)
{
RARCH_ERR("Currently active window is not an X11 window. Cannot use this driver.\n");
return NULL;
}
x11_input_t *x11 = (x11_input_t*)calloc(1, sizeof(*x11));
if (!x11)
return NULL;
x11->display = XOpenDisplay(NULL);
if (!x11->display)
{
free(x11);
return NULL;
}
x11->sdl = (sdl_input_t*)input_sdl.init();
if (!x11->sdl)
{
free(x11);
return NULL;
}
// Borrow the active X window ...
x11->display = (Display*)driver.video_display;
x11->win = (Window)driver.video_window;
x11->joypad = input_joypad_init_first();
init_lut();
x11->sdl->use_keyboard = false;
return x11;
}
@ -180,30 +189,7 @@ static bool x_bind_button_pressed(void *data, int key)
{
x11_input_t *x11 = (x11_input_t*)data;
return x_is_pressed(x11, g_settings.input.binds[0], key) ||
input_sdl.key_pressed(x11->sdl, key);
}
static int16_t x_analog_state(x11_input_t *x11, const struct retro_keybind **binds_,
unsigned port, unsigned index, unsigned id)
{
const struct retro_keybind *binds = binds_[port];
if (id >= RARCH_BIND_LIST_END)
return 0;
unsigned id_minus = 0;
unsigned id_plus = 0;
input_conv_analog_id_to_bind_id(index, id, &id_minus, &id_plus);
const struct retro_keybind *bind_minus = &binds[id_minus];
const struct retro_keybind *bind_plus = &binds[id_plus];
if (!bind_minus->valid || !bind_plus->valid)
return 0;
int16_t res_minus = x_is_pressed(x11, binds, id_minus) ? -0x7fff : 0;
int16_t res_plus = x_is_pressed(x11, binds, id_plus) ? 0x7fff : 0;
return res_plus + res_minus;
input_joypad_pressed(x11->joypad, 0, g_settings.input.binds[0]);
}
static int16_t x_mouse_state(x11_input_t *x11, unsigned id)
@ -254,18 +240,13 @@ static int16_t x_input_state(void *data, const struct retro_keybind **binds, uns
{
case RETRO_DEVICE_JOYPAD:
return x_is_pressed(x11, binds[port], id) ||
input_sdl.input_state(x11->sdl, binds, port, device, index, id);
input_joypad_pressed(x11->joypad, port, &binds[port][id]);
case RETRO_DEVICE_KEYBOARD:
return x_key_pressed(x11, id);
case RETRO_DEVICE_ANALOG:
{
int16_t ret = input_sdl.input_state(x11->sdl, binds, port, device, index, id);
if (!ret)
ret = x_analog_state(x11, binds, port, index, id);
return ret;
}
return input_joypad_analog(x11->joypad, port, index, id, binds[port]);
case RETRO_DEVICE_MOUSE:
return x_mouse_state(x11, id);
@ -281,19 +262,15 @@ static int16_t x_input_state(void *data, const struct retro_keybind **binds, uns
static void x_input_free(void *data)
{
x11_input_t *x11 = (x11_input_t*)data;
input_sdl.free(x11->sdl);
if (!x11->inherit_disp)
XCloseDisplay(x11->display);
if (x11->joypad)
x11->joypad->destroy();
free(data);
}
static void x_input_poll_mouse(x11_input_t *x11)
{
if (!x11->inherit_disp)
return;
Window root_win, child_win;
int root_x, root_y, win_x, win_y;
unsigned mask;
@ -329,7 +306,7 @@ static void x_input_poll(void *data)
memset(x11->state, 0, sizeof(x11->state));
x_input_poll_mouse(x11);
input_sdl.poll(x11->sdl);
input_joypad_poll(x11->joypad);
}
const input_driver_t input_x = {

View File

@ -1,49 +0,0 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* 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/>.
*/
#ifndef X11_INPUT_H__
#define X11_INPUT_H__
#include "../driver.h"
#include "SDL.h"
#include "../boolean.h"
#include "../general.h"
#include <stdint.h>
#include <stdlib.h>
#include "rarch_sdl_input.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
typedef struct x11_input
{
sdl_input_t *sdl;
bool inherit_disp;
Display *display;
Window win;
char state[32];
bool mouse_l, mouse_r, mouse_m;
int mouse_x, mouse_y;
int mouse_last_x, mouse_last_y;
} x11_input_t;
void x_input_set_disp_win(x11_input_t *x11, Display *dpy, Window win);
#endif