Add multiple mice support

This commit is contained in:
Zoran Vuckovic 2017-05-27 20:21:39 +02:00 committed by twinaphex
parent c83d72d589
commit 451db1fac5

View File

@ -35,6 +35,7 @@ typedef struct
typedef struct
{
HANDLE hnd;
LONG x, y, dlt_x, dlt_y;
LONG whl_u, whl_d;
bool btn_l, btn_m, btn_r;
@ -43,15 +44,20 @@ typedef struct
typedef struct
{
winraw_keyboard_t keyboard;
winraw_mouse_t mouse;
winraw_mouse_t *mice;
const input_device_driver_t *joypad;
HWND window;
bool kbd_mapp_block;
bool mouse_grab;
} winraw_input_t;
/*static int g_mice_x_min, g_mice_x_max;
static int g_mice_y_min, g_mice_y_max;
static double g_mice_x_gain, g_mice_y_gain;*/
static winraw_keyboard_t *g_keyboard = NULL;
static winraw_mouse_t *g_mouse = NULL;
static winraw_mouse_t *g_mice = NULL;
static unsigned g_mouse_cnt = 0;
static HWND winraw_create_window(WNDPROC wnd_proc)
{
@ -128,6 +134,81 @@ static bool winraw_set_keyboard_input(HWND window)
return true;
}
static bool winraw_init_devices(winraw_mouse_t **mice, unsigned *mouse_cnt)
{
UINT r, i;
POINT crs_pos;
winraw_mouse_t *mice_r = NULL;
unsigned mouse_cnt_r = 0;
RAWINPUTDEVICELIST *devs = NULL;
UINT dev_cnt = 0;
r = GetRawInputDeviceList(NULL, &dev_cnt, sizeof(RAWINPUTDEVICELIST));
if (r == (UINT)-1)
{
WINRAW_SYS_ERR("GetRawInputDeviceList");
goto error;
}
devs = (RAWINPUTDEVICELIST*)malloc(dev_cnt * sizeof(RAWINPUTDEVICELIST));
if (!devs)
{
WINRAW_ERR("malloc failed");
goto error;
}
dev_cnt = GetRawInputDeviceList(devs, &dev_cnt, sizeof(RAWINPUTDEVICELIST));
if (dev_cnt == (UINT)-1)
{
WINRAW_SYS_ERR("GetRawInputDeviceList");
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)
{
WINRAW_ERR("calloc failed");
goto error;
}
if (!GetCursorPos(&crs_pos))
{
WINRAW_SYS_WRN("GetCursorPos");
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;
}
*mice = mice_r;
*mouse_cnt = mouse_cnt_r;
return true;
error:
free(devs);
free(mice_r);
*mice = NULL;
*mouse_cnt = 0;
return false;
}
static bool winraw_set_mouse_input(HWND window, bool grab)
{
RAWINPUTDEVICE rid;
@ -164,24 +245,24 @@ static int16_t winraw_keyboard_state(winraw_input_t *wr, unsigned id)
return wr->keyboard.keys[key];
}
static int16_t winraw_mouse_state(winraw_input_t *wr, bool abs, unsigned id)
static int16_t winraw_mouse_state(winraw_mouse_t *mouse, bool abs, unsigned id)
{
switch (id)
{
case RETRO_DEVICE_ID_MOUSE_X:
return abs ? wr->mouse.x : wr->mouse.dlt_x;
return abs ? mouse->x : mouse->dlt_x;
case RETRO_DEVICE_ID_MOUSE_Y:
return abs ? wr->mouse.y : wr->mouse.dlt_y;
return abs ? mouse->y : mouse->dlt_y;
case RETRO_DEVICE_ID_MOUSE_LEFT:
return wr->mouse.btn_l ? 1 : 0;
return mouse->btn_l ? 1 : 0;
case RETRO_DEVICE_ID_MOUSE_RIGHT:
return wr->mouse.btn_r ? 1 : 0;
return mouse->btn_r ? 1 : 0;
case RETRO_DEVICE_ID_MOUSE_WHEELUP:
return wr->mouse.whl_u ? 1 : 0;
return mouse->whl_u ? 1 : 0;
case RETRO_DEVICE_ID_MOUSE_WHEELDOWN:
return wr->mouse.whl_d ? 1 : 0;
return mouse->whl_d ? 1 : 0;
case RETRO_DEVICE_ID_MOUSE_MIDDLE:
return wr->mouse.btn_m ? 1 : 0;
return mouse->btn_m ? 1 : 0;
}
return 0;
@ -200,11 +281,69 @@ static int16_t winraw_joypad_state(winraw_input_t *wr,
return input_joypad_pressed(wr->joypad, joypad_info, port, binds, id);
}
static void winraw_update_mouse_state(winraw_mouse_t *mouse, RAWMOUSE *state)
{
POINT crs_pos;
if (state->usFlags & MOUSE_MOVE_ABSOLUTE)
{
mouse->x = state->lLastX;
mouse->y = state->lLastY;
}
else if (state->lLastX || state->lLastY)
{
InterlockedExchangeAdd(&mouse->dlt_x, state->lLastX);
InterlockedExchangeAdd(&mouse->dlt_y, state->lLastY);
if (!GetCursorPos(&crs_pos))
WINRAW_SYS_WRN("GetCursorPos");
else if (!ScreenToClient((HWND)video_driver_window_get(), &crs_pos))
WINRAW_SYS_WRN("ScreenToClient");
else
{
mouse->x = crs_pos.x;
mouse->y = crs_pos.y;
}
}
/*if (mouse->x < g_mice_x_min)
mouse->x = g_mice_x_min;
else if (mouse->x > g_mice_x_max)
mouse->x = g_mice_x_max;
if (mouse->y < g_mice_y_min)
mouse->y = g_mice_y_min;
else if (mouse->y > g_mice_y_max)
mouse->y = g_mice_y_max;*/
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_WHEEL)
{
if ((SHORT)state->usButtonData > 0)
InterlockedExchange(&mouse->whl_u, 1);
else if ((SHORT)state->usButtonData < 0)
InterlockedExchange(&mouse->whl_d, 1);
}
}
static LRESULT CALLBACK winraw_callback(HWND wnd, UINT msg, WPARAM wpar, LPARAM lpar)
{
static uint8_t data[1024];
UINT r;
POINT crs_pos;
unsigned i;
RAWINPUT *ri = (RAWINPUT*)data;
UINT size = sizeof(data);
@ -230,49 +369,14 @@ static LRESULT CALLBACK winraw_callback(HWND wnd, UINT msg, WPARAM wpar, LPARAM
}
else if (ri->header.dwType == RIM_TYPEMOUSE)
{
if (ri->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
for (i = 0; i < g_mouse_cnt; ++i)
{
g_mouse->x = ri->data.mouse.lLastX;
g_mouse->y = ri->data.mouse.lLastY;
}
else if (ri->data.mouse.lLastX || ri->data.mouse.lLastY)
{
InterlockedExchangeAdd(&g_mouse->dlt_x, ri->data.mouse.lLastX);
InterlockedExchangeAdd(&g_mouse->dlt_y, ri->data.mouse.lLastY);
if (!GetCursorPos(&crs_pos))
WINRAW_SYS_WRN("GetCursorPos");
else if (!ScreenToClient((HWND)video_driver_window_get(), &crs_pos))
WINRAW_SYS_WRN("ScreenToClient");
else
if (g_mice[i].hnd == ri->header.hDevice)
{
g_mouse->x = crs_pos.x;
g_mouse->y = crs_pos.y;
winraw_update_mouse_state(&g_mice[i], &ri->data.mouse);
break;
}
}
if (ri->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN)
g_mouse->btn_l = true;
else if (ri->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP)
g_mouse->btn_l = false;
if (ri->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN)
g_mouse->btn_m = true;
else if (ri->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP)
g_mouse->btn_m = false;
if (ri->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN)
g_mouse->btn_r = true;
else if (ri->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP)
g_mouse->btn_r = false;
if (ri->data.mouse.usButtonFlags & RI_MOUSE_WHEEL)
{
if ((SHORT)ri->data.mouse.usButtonData > 0)
InterlockedExchange(&g_mouse->whl_u, 1);
else if ((SHORT)ri->data.mouse.usButtonData < 0)
InterlockedExchange(&g_mouse->whl_d, 1);
}
}
end:
@ -282,12 +386,13 @@ end:
static void *winraw_init(const char *joypad_driver)
{
bool r = false;
bool r;
video_viewport_t dst_vid_info;
struct retro_system_av_info *src_vid_info;
winraw_input_t *wr = (winraw_input_t *)calloc(1, sizeof(winraw_input_t));
g_keyboard = (winraw_keyboard_t*)calloc(1, sizeof(winraw_keyboard_t));
g_mouse = (winraw_mouse_t*)calloc(1, sizeof(winraw_mouse_t));
if (!wr || !g_keyboard || !g_mouse)
if (!wr || !g_keyboard)
{
WINRAW_ERR("calloc failed.");
goto error;
@ -304,6 +409,47 @@ static void *winraw_init(const char *joypad_driver)
goto error;
}
r = winraw_init_devices(&g_mice, &g_mouse_cnt);
if (!r)
{
WINRAW_ERR("winraw_init_devices failed.");
goto error;
}
if (!g_mouse_cnt)
WINRAW_LOG("Mouse unavailable.");
else
{
/*src_vid_info = video_viewport_get_system_av_info();
r = video_driver_get_viewport_info(&dst_vid_info);
if (!r)
{
WINRAW_ERR("video_driver_get_viewport_info failed");
goto error;
}
RARCH_LOG("[WINRAW]: src vid: width=%u, height=%u",
src_vid_info->geometry.base_width,
src_vid_info->geometry.base_height);
RARCH_LOG("[WINRAW]: dst vid: x=%u, y=%u, width=%u, height=%u",
dst_vid_info.x, dst_vid_info.y,
dst_vid_info.width, dst_vid_info.height);
g_mice_x_min = dst_vid_info.x;
g_mice_x_max = dst_vid_info.x + dst_vid_info.width - 1;
g_mice_y_min = dst_vid_info.y;
g_mice_y_max = dst_vid_info.y + dst_vid_info.height - 1;*/
wr->mice = (winraw_mouse_t*)malloc(g_mouse_cnt * sizeof(winraw_mouse_t));
if (!wr->mice)
{
WINRAW_ERR("malloc failed.");
goto error;
}
memcpy(wr->mice, g_mice, g_mouse_cnt * sizeof(winraw_mouse_t));
}
r = winraw_set_keyboard_input(wr->window);
if (!r)
{
@ -330,8 +476,10 @@ error:
winraw_set_keyboard_input(NULL);
winraw_destroy_window(wr->window);
}
free(g_mouse);
free(g_keyboard);
free(g_mice);
if (wr)
free(wr->mice);
free(wr);
WINRAW_ERR("Input driver initialization failed.");
return NULL;
@ -339,19 +487,23 @@ error:
static void winraw_poll(void *d)
{
unsigned i;
winraw_input_t *wr = (winraw_input_t*)d;
memcpy(&wr->keyboard, g_keyboard, sizeof(winraw_keyboard_t));
wr->mouse.x = g_mouse->x;
wr->mouse.y = g_mouse->y;
wr->mouse.dlt_x = InterlockedExchange(&g_mouse->dlt_x, 0);
wr->mouse.dlt_y = InterlockedExchange(&g_mouse->dlt_y, 0);
wr->mouse.whl_u = InterlockedExchange(&g_mouse->whl_u, 0);
wr->mouse.whl_d = InterlockedExchange(&g_mouse->whl_d, 0);
wr->mouse.btn_l = g_mouse->btn_l;
wr->mouse.btn_m = g_mouse->btn_m;
wr->mouse.btn_r = g_mouse->btn_r;
for (i = 0; i < g_mouse_cnt; ++i)
{
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;
}
if (wr->joypad)
wr->joypad->poll();
@ -369,15 +521,22 @@ static int16_t winraw_input_state(void *d,
case RETRO_DEVICE_KEYBOARD:
return winraw_keyboard_state(wr, id);
case RETRO_DEVICE_MOUSE:
return winraw_mouse_state(wr, false, id);
if (port < g_mouse_cnt)
return winraw_mouse_state(&wr->mice[port], false, id);
return 0;
case RARCH_DEVICE_MOUSE_SCREEN:
return winraw_mouse_state(wr, true, id);
if (port < g_mouse_cnt)
return winraw_mouse_state(&wr->mice[port], true, id);
return 0;
case RETRO_DEVICE_JOYPAD:
return winraw_joypad_state(wr, joypad_info, binds[port], port, id);
case RETRO_DEVICE_ANALOG:
if (binds[port])
return input_joypad_analog(wr->joypad, joypad_info,
port, index, id, binds[port]);
case RETRO_DEVICE_POINTER:
/* TODO */
return 0;
}
return 0;
@ -399,8 +558,9 @@ static void winraw_free(void *d)
winraw_set_mouse_input(NULL, false);
winraw_set_keyboard_input(NULL);
winraw_destroy_window(wr->window);
free(g_mouse);
free(g_mice);
free(g_keyboard);
free(wr->mice);
free(wr);
WINRAW_LOG("Input driver deinitialized.");
@ -411,7 +571,8 @@ static uint64_t winraw_get_capabilities(void *u)
return RETRO_DEVICE_KEYBOARD |
RETRO_DEVICE_MOUSE |
RETRO_DEVICE_JOYPAD |
RETRO_DEVICE_ANALOG;
RETRO_DEVICE_ANALOG |
RETRO_DEVICE_POINTER;
}
static void winraw_grab_mouse(void *d, bool grab)