RetroArch/input/drivers/winraw_input.c

836 lines
23 KiB
C
Raw Normal View History

/* RetroArch - A frontend for libretro.
* Copyright (C) 2011-2017 - Daniel De Matteis
*
* 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 <windows.h>
#include "../input_keymaps.h"
#include "../../configuration.h"
#include "../../retroarch.h"
#include "../../verbosity.h"
typedef struct
{
uint8_t keys[256];
} winraw_keyboard_t;
typedef struct
{
HANDLE hnd;
LONG x, y, dlt_x, dlt_y;
LONG whl_u, whl_d;
bool btn_l, btn_m, btn_r, btn_b4, btn_b5;
} winraw_mouse_t;
typedef struct
{
double view_abs_ratio_x;
double view_abs_ratio_y;
winraw_keyboard_t keyboard;
HWND window;
winraw_mouse_t *mice;
unsigned mouse_cnt;
bool mouse_xy_mapping_ready;
2020-08-14 23:12:49 +02:00
bool mouse_grab;
} winraw_input_t;
2020-07-19 05:17:11 +02:00
/* TODO/FIXME - static globals */
static winraw_mouse_t *g_mice = NULL;
2020-09-02 01:22:34 +02:00
#define WINRAW_KEYBOARD_PRESSED(wr, key) (wr->keyboard.keys[rarch_keysym_lut[(enum retro_key)(key)]])
static HWND winraw_create_window(WNDPROC wnd_proc)
{
HWND wnd;
WNDCLASSA wc = {0};
wc.hInstance = GetModuleHandleA(NULL);
if (!wc.hInstance)
return NULL;
wc.lpfnWndProc = wnd_proc;
wc.lpszClassName = "winraw-input";
if (!RegisterClassA(&wc) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
return NULL;
wnd = CreateWindowExA(0, wc.lpszClassName, NULL, 0, 0, 0, 0, 0,
HWND_MESSAGE, NULL, NULL, NULL);
if (!wnd)
goto error;
return wnd;
error:
UnregisterClassA(wc.lpszClassName, NULL);
return NULL;
}
static void winraw_destroy_window(HWND wnd)
{
if (!wnd)
return;
2020-08-31 02:07:43 +02:00
if (!DestroyWindow(wnd))
{
2020-09-02 01:22:34 +02:00
RARCH_WARN("[WINRAW]: DestroyWindow failed with error %lu.\n",
GetLastError());
}
2020-08-31 02:07:43 +02:00
if (!UnregisterClassA("winraw-input", NULL))
{
2020-09-02 01:22:34 +02:00
RARCH_WARN("[WINRAW]: UnregisterClassA failed with error %lu.\n",
GetLastError());
}
}
2020-06-11 05:15:36 +02:00
static BOOL winraw_set_keyboard_input(HWND window)
{
RAWINPUTDEVICE rid;
rid.dwFlags = window ? 0 : RIDEV_REMOVE;
rid.hwndTarget = window;
rid.usUsagePage = 0x01; /* generic desktop */
rid.usUsage = 0x06; /* keyboard */
2020-06-11 05:15:36 +02:00
return RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE));
}
static void winraw_log_mice_info(winraw_mouse_t *mice, unsigned mouse_cnt)
{
unsigned i;
char name[256];
UINT name_size = sizeof(name);
2020-08-31 02:07:43 +02:00
name[0] = '\0';
for (i = 0; i < mouse_cnt; ++i)
{
UINT r = GetRawInputDeviceInfoA(mice[i].hnd, RIDI_DEVICENAME,
name, &name_size);
if (r == (UINT)-1 || r == 0)
name[0] = '\0';
}
}
static bool winraw_init_devices(winraw_mouse_t **mice, unsigned *mouse_cnt)
{
UINT i;
POINT crs_pos;
winraw_mouse_t *mice_r = NULL;
unsigned mouse_cnt_r = 0;
RAWINPUTDEVICELIST *devs = NULL;
UINT dev_cnt = 0;
UINT r = GetRawInputDeviceList(
NULL, &dev_cnt, sizeof(RAWINPUTDEVICELIST));
if (r == (UINT)-1)
goto error;
devs = (RAWINPUTDEVICELIST*)malloc(dev_cnt * sizeof(RAWINPUTDEVICELIST));
if (!devs)
goto error;
dev_cnt = GetRawInputDeviceList(devs, &dev_cnt, sizeof(RAWINPUTDEVICELIST));
if (dev_cnt == (UINT)-1)
goto error;
for (i = 0; i < dev_cnt; ++i)
mouse_cnt_r += devs[i].dwType == RIM_TYPEMOUSE ? 1 : 0;
if (mouse_cnt_r)
{
mice_r = (winraw_mouse_t*)calloc(1, mouse_cnt_r * sizeof(winraw_mouse_t));
if (!mice_r)
goto error;
if (!GetCursorPos(&crs_pos))
goto error;
for (i = 0; i < mouse_cnt_r; ++i)
{
mice_r[i].x = crs_pos.x;
mice_r[i].y = crs_pos.y;
}
}
/* count is already checked, so this is safe */
for (i = mouse_cnt_r = 0; i < dev_cnt; ++i)
{
if (devs[i].dwType == RIM_TYPEMOUSE)
mice_r[mouse_cnt_r++].hnd = devs[i].hDevice;
}
winraw_log_mice_info(mice_r, mouse_cnt_r);
2019-07-04 21:54:51 +02:00
free(devs);
*mice = mice_r;
*mouse_cnt = mouse_cnt_r;
return true;
error:
free(devs);
free(mice_r);
2020-09-02 01:22:34 +02:00
*mice = NULL;
*mouse_cnt = 0;
return false;
}
2020-06-11 05:15:36 +02:00
static BOOL winraw_set_mouse_input(HWND window, bool grab)
{
RAWINPUTDEVICE rid;
if (window)
rid.dwFlags = grab ? RIDEV_CAPTUREMOUSE : 0;
else
rid.dwFlags = RIDEV_REMOVE;
rid.hwndTarget = window;
rid.usUsagePage = 0x01; /* generic desktop */
rid.usUsage = 0x02; /* mouse */
2020-06-11 05:15:36 +02:00
return RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE));
}
static int16_t winraw_lightgun_aiming_state(winraw_input_t *wr,
winraw_mouse_t *mouse,
unsigned port, unsigned id)
{
2020-06-11 05:15:36 +02:00
struct video_viewport vp;
const int edge_detect = 32700;
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->y,
&res_x, &res_y, &res_screen_x, &res_screen_y)))
2019-06-23 02:34:35 +02:00
return 0;
inside = (res_x >= -edge_detect)
&& (res_y >= -edge_detect)
&& (res_x <= edge_detect)
&& (res_y <= edge_detect);
2020-08-31 02:07:43 +02:00
switch (id)
2019-06-23 02:34:35 +02:00
{
case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X:
if (inside)
return res_x;
break;
2019-06-23 02:34:35 +02:00
case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y:
if (inside)
return res_y;
break;
2019-06-23 02:34:35 +02:00
case RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN:
return !inside;
default:
break;
}
2019-06-23 02:34:35 +02:00
return 0;
}
2020-08-31 02:07:43 +02:00
static int16_t winraw_mouse_state(
winraw_mouse_t *mouse,
unsigned port, bool abs, unsigned id)
{
switch (id)
{
case RETRO_DEVICE_ID_MOUSE_X:
return abs ? mouse->x : mouse->dlt_x;
case RETRO_DEVICE_ID_MOUSE_Y:
return abs ? mouse->y : mouse->dlt_y;
case RETRO_DEVICE_ID_MOUSE_LEFT:
2020-09-02 01:22:34 +02:00
if (mouse->btn_l)
return 1;
break;
case RETRO_DEVICE_ID_MOUSE_RIGHT:
2020-09-02 01:22:34 +02:00
if (mouse->btn_r)
return 1;
break;
case RETRO_DEVICE_ID_MOUSE_WHEELUP:
2020-09-02 01:22:34 +02:00
if (mouse->whl_u)
return 1;
break;
case RETRO_DEVICE_ID_MOUSE_WHEELDOWN:
2020-09-02 01:22:34 +02:00
if (mouse->whl_d)
return 1;
break;
case RETRO_DEVICE_ID_MOUSE_MIDDLE:
2020-09-02 01:22:34 +02:00
if (mouse->btn_m)
return 1;
break;
case RETRO_DEVICE_ID_MOUSE_BUTTON_4:
2020-09-02 01:22:34 +02:00
if (mouse->btn_b4)
return 1;
break;
case RETRO_DEVICE_ID_MOUSE_BUTTON_5:
2020-09-02 01:22:34 +02:00
if (mouse->btn_b5)
return 1;
break;
}
return 0;
}
2019-06-23 02:34:35 +02:00
static bool winraw_mouse_button_pressed(
winraw_input_t *wr,
winraw_mouse_t *mouse,
unsigned port, unsigned key)
{
switch (key)
{
case RETRO_DEVICE_ID_MOUSE_LEFT:
return mouse->btn_l;
case RETRO_DEVICE_ID_MOUSE_RIGHT:
return mouse->btn_r;
case RETRO_DEVICE_ID_MOUSE_MIDDLE:
return mouse->btn_m;
case RETRO_DEVICE_ID_MOUSE_BUTTON_4:
return mouse->btn_b4;
case RETRO_DEVICE_ID_MOUSE_BUTTON_5:
return mouse->btn_b5;
case RETRO_DEVICE_ID_MOUSE_WHEELUP:
return mouse->whl_u;
case RETRO_DEVICE_ID_MOUSE_WHEELDOWN:
return mouse->whl_d;
}
return false;
}
static void winraw_init_mouse_xy_mapping(winraw_input_t *wr)
{
struct video_viewport viewport;
if (video_driver_get_viewport_info(&viewport))
{
2020-09-02 01:22:34 +02:00
unsigned i;
int center_x = viewport.x + viewport.width / 2;
int center_y = viewport.y + viewport.height / 2;
for (i = 0; i < wr->mouse_cnt; ++i)
{
g_mice[i].x = center_x;
g_mice[i].y = center_y;
}
wr->view_abs_ratio_x = (double)viewport.full_width / 65535.0;
wr->view_abs_ratio_y = (double)viewport.full_height / 65535.0;
wr->mouse_xy_mapping_ready = true;
}
}
static void winraw_update_mouse_state(winraw_input_t *wr,
winraw_mouse_t *mouse, RAWMOUSE *state)
{
POINT crs_pos;
if (state->usFlags & MOUSE_MOVE_ABSOLUTE)
{
if (wr->mouse_xy_mapping_ready)
{
state->lLastX = (LONG)(wr->view_abs_ratio_x * state->lLastX);
state->lLastY = (LONG)(wr->view_abs_ratio_y * state->lLastY);
InterlockedExchangeAdd(&mouse->dlt_x, state->lLastX - mouse->x);
InterlockedExchangeAdd(&mouse->dlt_y, state->lLastY - mouse->y);
mouse->x = state->lLastX;
mouse->y = state->lLastY;
}
else
winraw_init_mouse_xy_mapping(wr);
}
else if (state->lLastX || state->lLastY)
{
InterlockedExchangeAdd(&mouse->dlt_x, state->lLastX);
InterlockedExchangeAdd(&mouse->dlt_y, state->lLastY);
2020-06-11 05:15:36 +02:00
#ifdef DEBUG
if (!GetCursorPos(&crs_pos))
{
RARCH_WARN("[WINRAW]: GetCursorPos failed with error %lu.\n", GetLastError());
}
else if (!ScreenToClient((HWND)video_driver_window_get(), &crs_pos))
{
RARCH_WARN("[WINRAW]: ScreenToClient failed with error %lu.\n", GetLastError());
}
2020-06-11 05:15:36 +02:00
#else
if (!GetCursorPos(&crs_pos)) { }
else if (!ScreenToClient((HWND)video_driver_window_get(), &crs_pos)) { }
#endif
else
{
mouse->x = crs_pos.x;
mouse->y = crs_pos.y;
}
}
if (state->usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN)
mouse->btn_l = true;
else if (state->usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP)
mouse->btn_l = false;
if (state->usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN)
mouse->btn_m = true;
else if (state->usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP)
mouse->btn_m = false;
if (state->usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN)
mouse->btn_r = true;
else if (state->usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP)
mouse->btn_r = false;
if (state->usButtonFlags & RI_MOUSE_BUTTON_4_DOWN)
mouse->btn_b4 = true;
else if (state->usButtonFlags & RI_MOUSE_BUTTON_4_UP)
mouse->btn_b4 = false;
if (state->usButtonFlags & RI_MOUSE_BUTTON_5_DOWN)
mouse->btn_b5 = true;
else if (state->usButtonFlags & RI_MOUSE_BUTTON_5_UP)
mouse->btn_b5 = false;
if (state->usButtonFlags & RI_MOUSE_WHEEL)
{
if ((SHORT)state->usButtonData > 0)
InterlockedExchange(&mouse->whl_u, 1);
else if ((SHORT)state->usButtonData < 0)
InterlockedExchange(&mouse->whl_d, 1);
}
}
2020-08-31 02:07:43 +02:00
static LRESULT CALLBACK winraw_callback(
HWND wnd, UINT msg, WPARAM wpar, LPARAM lpar)
{
unsigned i;
2020-06-11 05:15:36 +02:00
static uint8_t data[1024];
RAWINPUT *ri = (RAWINPUT*)data;
UINT size = sizeof(data);
winraw_input_t *wr = (winraw_input_t*)(LONG_PTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
if (msg != WM_INPUT)
return DefWindowProcA(wnd, msg, wpar, lpar);
2020-08-29 19:43:53 +02:00
if (
GET_RAWINPUT_CODE_WPARAM(wpar) != RIM_INPUT /* app is in the background */
|| GetRawInputData((HRAWINPUT)lpar, RID_INPUT,
data, &size, sizeof(RAWINPUTHEADER)) == (UINT)-1)
{
2020-08-29 19:43:53 +02:00
DefWindowProcA(wnd, msg, wpar, lpar);
return 0;
}
2020-08-29 19:43:53 +02:00
switch (ri->header.dwType)
{
2020-08-29 19:43:53 +02:00
case RIM_TYPEKEYBOARD:
if (ri->data.keyboard.Message == WM_KEYDOWN)
wr->keyboard.keys[ri->data.keyboard.VKey] = 1;
2020-08-29 19:43:53 +02:00
else if (ri->data.keyboard.Message == WM_KEYUP)
wr->keyboard.keys[ri->data.keyboard.VKey] = 0;
2020-08-29 19:43:53 +02:00
break;
case RIM_TYPEMOUSE:
for (i = 0; i < wr->mouse_cnt; ++i)
{
2020-08-29 19:43:53 +02:00
if (g_mice[i].hnd == ri->header.hDevice)
{
winraw_update_mouse_state(wr, &g_mice[i], &ri->data.mouse);
2020-08-29 19:43:53 +02:00
break;
}
}
2020-08-29 19:43:53 +02:00
break;
}
DefWindowProcA(wnd, msg, wpar, lpar);
return 0;
}
static void *winraw_init(const char *joypad_driver)
{
winraw_input_t *wr = (winraw_input_t *)
calloc(1, sizeof(winraw_input_t));
if (!wr)
return NULL;
input_keymaps_init_keyboard_lut(rarch_key_map_winraw);
wr->window = winraw_create_window(winraw_callback);
if (!wr->window)
goto error;
if (!winraw_init_devices(&g_mice, &wr->mouse_cnt))
goto error;
if (wr->mouse_cnt)
{
wr->mice = (winraw_mouse_t*)
malloc(wr->mouse_cnt * sizeof(winraw_mouse_t));
if (!wr->mice)
goto error;
memcpy(wr->mice, g_mice, wr->mouse_cnt * sizeof(winraw_mouse_t));
}
2020-06-11 05:15:36 +02:00
if (!winraw_set_keyboard_input(wr->window))
goto error;
2020-06-11 05:15:36 +02:00
if (!winraw_set_mouse_input(wr->window, false))
goto error;
SetWindowLongPtr(wr->window, GWLP_USERDATA, (LONG_PTR)wr);
return wr;
error:
if (wr && wr->window)
{
winraw_set_mouse_input(NULL, false);
winraw_set_keyboard_input(NULL);
winraw_destroy_window(wr->window);
}
free(g_mice);
if (wr)
free(wr->mice);
free(wr);
return NULL;
}
static void winraw_poll(void *data)
{
unsigned i;
2020-09-01 17:41:05 +02:00
winraw_input_t *wr = (winraw_input_t*)data;
/* following keys are not handled by windows raw input api */
wr->keyboard.keys[VK_LCONTROL] = GetAsyncKeyState(VK_LCONTROL) >> 1 ? 1 : 0;
wr->keyboard.keys[VK_RCONTROL] = GetAsyncKeyState(VK_RCONTROL) >> 1 ? 1 : 0;
wr->keyboard.keys[VK_LMENU] = GetAsyncKeyState(VK_LMENU) >> 1 ? 1 : 0;
wr->keyboard.keys[VK_RMENU] = GetAsyncKeyState(VK_RMENU) >> 1 ? 1 : 0;
wr->keyboard.keys[VK_LSHIFT] = GetAsyncKeyState(VK_LSHIFT) >> 1 ? 1 : 0;
wr->keyboard.keys[VK_RSHIFT] = GetAsyncKeyState(VK_RSHIFT) >> 1 ? 1 : 0;
for (i = 0; i < wr->mouse_cnt; ++i)
{
2020-06-11 05:15:36 +02:00
wr->mice[i].x = g_mice[i].x;
wr->mice[i].y = g_mice[i].y;
wr->mice[i].dlt_x = InterlockedExchange(&g_mice[i].dlt_x, 0);
wr->mice[i].dlt_y = InterlockedExchange(&g_mice[i].dlt_y, 0);
wr->mice[i].whl_u = InterlockedExchange(&g_mice[i].whl_u, 0);
wr->mice[i].whl_d = InterlockedExchange(&g_mice[i].whl_d, 0);
wr->mice[i].btn_l = g_mice[i].btn_l;
wr->mice[i].btn_m = g_mice[i].btn_m;
wr->mice[i].btn_r = g_mice[i].btn_r;
wr->mice[i].btn_b4 = g_mice[i].btn_b4;
wr->mice[i].btn_b5 = g_mice[i].btn_b5;
}
}
2020-07-19 05:17:11 +02:00
static int16_t winraw_input_lightgun_state(
winraw_input_t *wr,
winraw_mouse_t *mouse,
2020-08-30 05:29:32 +02:00
const input_device_driver_t *joypad,
2020-07-19 05:17:11 +02:00
rarch_joypad_info_t *joypad_info,
const struct retro_keybind **binds,
bool keyboard_mapping_blocked,
unsigned port,
unsigned device,
unsigned idx,
unsigned id)
2020-07-19 05:17:11 +02:00
{
if (!keyboard_mapping_blocked)
2020-07-19 05:17:11 +02:00
if ((binds[port][id].key < RETROK_LAST)
2020-09-02 01:22:34 +02:00
&& WINRAW_KEYBOARD_PRESSED(wr, binds[port]
2020-07-19 05:17:11 +02:00
[id].key))
return 1;
if (binds[port][id].valid)
{
if (mouse && winraw_mouse_button_pressed(wr,
mouse, port, binds[port]
[id].mbutton))
return 1;
return button_is_pressed(
2020-08-30 05:29:32 +02:00
joypad, joypad_info, binds[port],
2020-07-19 05:17:11 +02:00
port, id);
}
return 0;
}
2020-08-30 05:29:32 +02:00
static int16_t winraw_input_state(
void *data,
const input_device_driver_t *joypad,
const input_device_driver_t *sec_joypad,
2020-02-27 07:33:14 +01:00
rarch_joypad_info_t *joypad_info,
const struct retro_keybind **binds,
bool keyboard_mapping_blocked,
unsigned port,
unsigned device,
unsigned idx,
unsigned id)
{
settings_t *settings = NULL;
winraw_mouse_t *mouse = NULL;
2020-08-30 05:29:32 +02:00
winraw_input_t *wr = (winraw_input_t*)data;
bool process_mouse =
(device == RETRO_DEVICE_JOYPAD)
|| (device == RETRO_DEVICE_MOUSE)
|| (device == RARCH_DEVICE_MOUSE_SCREEN)
|| (device == RETRO_DEVICE_LIGHTGUN);
if (port >= MAX_USERS)
return 0;
if (process_mouse)
{
2020-06-11 06:34:59 +02:00
unsigned i;
settings = config_get_ptr();
for (i = 0; i < wr->mouse_cnt; ++i)
{
if (i == settings->uints.input_mouse_index[port])
{
mouse = &wr->mice[i];
break;
}
}
}
switch (device)
{
case RETRO_DEVICE_JOYPAD:
if (id == RETRO_DEVICE_ID_JOYPAD_MASK)
{
unsigned i;
int16_t ret = 0;
2020-06-11 08:34:30 +02:00
if (mouse)
{
for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++)
2019-07-22 01:20:00 +02:00
{
if (binds[port][i].valid)
{
if (winraw_mouse_button_pressed(wr,
mouse, port, binds[port][i].mbutton))
ret |= (1 << i);
}
2020-06-11 08:34:30 +02:00
}
}
if (!keyboard_mapping_blocked)
2020-06-11 08:34:30 +02:00
{
for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++)
{
2020-06-12 18:28:07 +02:00
if (binds[port][i].valid)
{
if ((binds[port][i].key < RETROK_LAST) &&
2020-09-02 01:22:34 +02:00
WINRAW_KEYBOARD_PRESSED(wr, binds[port][i].key))
2020-06-12 18:28:07 +02:00
ret |= (1 << i);
}
2019-07-22 01:20:00 +02:00
}
}
2019-07-22 01:20:00 +02:00
return ret;
}
if (id < RARCH_BIND_LIST_END)
{
if (binds[port][id].valid)
2020-06-11 08:34:30 +02:00
{
if (
(binds[port][id].key < RETROK_LAST)
&& WINRAW_KEYBOARD_PRESSED(wr, binds[port][id].key)
&& (( id == RARCH_GAME_FOCUS_TOGGLE)
|| !keyboard_mapping_blocked)
)
return 1;
else if (mouse && winraw_mouse_button_pressed(wr,
mouse, port, binds[port][id].mbutton))
return 1;
2020-06-11 08:34:30 +02:00
}
}
2019-07-22 01:20:00 +02:00
break;
case RETRO_DEVICE_ANALOG:
break;
case RETRO_DEVICE_KEYBOARD:
2020-09-02 01:22:34 +02:00
return (id < RETROK_LAST) && WINRAW_KEYBOARD_PRESSED(wr, id);
case RETRO_DEVICE_MOUSE:
case RARCH_DEVICE_MOUSE_SCREEN:
if (mouse)
2020-08-31 02:07:43 +02:00
return winraw_mouse_state(mouse, port,
(device == RARCH_DEVICE_MOUSE_SCREEN),
id);
break;
case RETRO_DEVICE_LIGHTGUN:
switch ( id )
{
/*aiming*/
case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X:
case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y:
case RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN:
if (mouse)
return winraw_lightgun_aiming_state(wr, mouse, port, id);
break;
/*buttons*/
case RETRO_DEVICE_ID_LIGHTGUN_TRIGGER:
2020-08-30 05:29:32 +02:00
return winraw_input_lightgun_state(wr, mouse, joypad,
joypad_info,
binds,
keyboard_mapping_blocked,
port, device, idx, RARCH_LIGHTGUN_TRIGGER);
case RETRO_DEVICE_ID_LIGHTGUN_RELOAD:
2020-08-30 05:29:32 +02:00
return winraw_input_lightgun_state(wr, mouse, joypad,
joypad_info,
binds,
keyboard_mapping_blocked,
port, device, idx, RARCH_LIGHTGUN_RELOAD);
case RETRO_DEVICE_ID_LIGHTGUN_AUX_A:
2020-08-30 05:29:32 +02:00
return winraw_input_lightgun_state(wr, mouse, joypad,
joypad_info,
binds,
keyboard_mapping_blocked,
port, device, idx, RARCH_LIGHTGUN_AUX_A);
case RETRO_DEVICE_ID_LIGHTGUN_AUX_B:
2020-08-30 05:29:32 +02:00
return winraw_input_lightgun_state(wr, mouse, joypad,
joypad_info,
binds,
keyboard_mapping_blocked,
port, device, idx, RARCH_LIGHTGUN_AUX_B);
case RETRO_DEVICE_ID_LIGHTGUN_AUX_C:
2020-08-30 05:29:32 +02:00
return winraw_input_lightgun_state(wr, mouse, joypad,
joypad_info,
binds,
keyboard_mapping_blocked,
port, device, idx, RARCH_LIGHTGUN_AUX_C);
case RETRO_DEVICE_ID_LIGHTGUN_START:
2020-08-30 05:29:32 +02:00
return winraw_input_lightgun_state(wr, mouse, joypad,
joypad_info,
binds,
keyboard_mapping_blocked,
port, device, idx, RARCH_LIGHTGUN_START);
case RETRO_DEVICE_ID_LIGHTGUN_SELECT:
2020-08-30 05:29:32 +02:00
return winraw_input_lightgun_state(wr, mouse, joypad,
joypad_info,
binds,
keyboard_mapping_blocked,
port, device, idx, RARCH_LIGHTGUN_SELECT);
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP:
2020-08-30 05:29:32 +02:00
return winraw_input_lightgun_state(wr, mouse, joypad,
joypad_info,
binds,
keyboard_mapping_blocked,
port, device, idx, RARCH_LIGHTGUN_DPAD_UP);
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN:
2020-08-30 05:29:32 +02:00
return winraw_input_lightgun_state(wr, mouse, joypad,
joypad_info,
binds,
keyboard_mapping_blocked,
port, device, idx, RARCH_LIGHTGUN_DPAD_DOWN);
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT:
2020-08-30 05:29:32 +02:00
return winraw_input_lightgun_state(wr, mouse, joypad,
joypad_info,
binds,
keyboard_mapping_blocked,
port, device, idx, RARCH_LIGHTGUN_DPAD_LEFT);
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT:
2020-08-30 05:29:32 +02:00
return winraw_input_lightgun_state(wr, mouse, joypad,
joypad_info,
binds,
keyboard_mapping_blocked,
port, device, idx, RARCH_LIGHTGUN_DPAD_RIGHT);
/*deprecated*/
case RETRO_DEVICE_ID_LIGHTGUN_X:
case RETRO_DEVICE_ID_LIGHTGUN_Y:
if (mouse)
2020-08-31 02:07:43 +02:00
{
switch (id)
{
case RETRO_DEVICE_ID_LIGHTGUN_X:
return mouse->dlt_x;
case RETRO_DEVICE_ID_LIGHTGUN_Y:
return mouse->dlt_y;
}
}
break;
case RETRO_DEVICE_ID_LIGHTGUN_PAUSE:
2020-08-30 05:29:32 +02:00
return winraw_input_lightgun_state(wr, mouse, joypad,
joypad_info,
binds,
keyboard_mapping_blocked,
port, device, idx, RARCH_LIGHTGUN_START);
}
break;
}
return 0;
}
2020-09-02 01:22:34 +02:00
static void winraw_free(void *data)
{
2020-09-02 01:22:34 +02:00
winraw_input_t *wr = (winraw_input_t*)data;
winraw_set_mouse_input(NULL, false);
winraw_set_keyboard_input(NULL);
SetWindowLongPtr(wr->window, GWLP_USERDATA, 0);
winraw_destroy_window(wr->window);
free(g_mice);
free(wr->mice);
2020-09-02 01:22:34 +02:00
free(data);
}
static uint64_t winraw_get_capabilities(void *u)
{
return (1 << RETRO_DEVICE_KEYBOARD) |
2020-09-02 01:22:34 +02:00
(1 << RETRO_DEVICE_MOUSE) |
(1 << RETRO_DEVICE_JOYPAD) |
(1 << RETRO_DEVICE_ANALOG) |
(1 << RETRO_DEVICE_LIGHTGUN);
}
static void winraw_grab_mouse(void *d, bool grab)
{
winraw_input_t *wr = (winraw_input_t*)d;
if (grab == wr->mouse_grab)
return;
2020-09-05 07:28:52 +02:00
if (!winraw_set_mouse_input(wr->window, grab))
return;
wr->mouse_grab = grab;
}
input_driver_t input_winraw = {
winraw_init,
winraw_poll,
winraw_input_state,
winraw_free,
NULL,
NULL,
winraw_get_capabilities,
"raw",
winraw_grab_mouse,
NULL
};