2017-12-11 23:55:31 -08:00
|
|
|
/* 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>
|
|
|
|
|
2020-09-09 23:36:21 +03:00
|
|
|
#ifdef CXX_BUILD
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <hidsdi.h>
|
|
|
|
|
2021-08-01 22:26:19 +03:00
|
|
|
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500 /* 2K */
|
|
|
|
#include <dbt.h>
|
|
|
|
#endif
|
|
|
|
|
2020-09-09 23:36:21 +03:00
|
|
|
#ifdef CXX_BUILD
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-11-06 15:07:35 +01:00
|
|
|
#include <compat/strl.h>
|
|
|
|
|
2021-02-02 00:52:03 +02:00
|
|
|
#ifndef _XBOX
|
|
|
|
#include "../../gfx/common/win32_common.h"
|
|
|
|
#endif
|
|
|
|
|
2017-12-11 23:55:31 -08:00
|
|
|
#include "../input_keymaps.h"
|
|
|
|
|
|
|
|
#include "../../configuration.h"
|
2019-06-17 15:10:22 +02:00
|
|
|
#include "../../retroarch.h"
|
2017-12-11 23:55:31 -08:00
|
|
|
#include "../../verbosity.h"
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
2021-08-04 01:56:33 +03:00
|
|
|
uint8_t keys[SC_LAST];
|
|
|
|
bool pause;
|
2017-12-11 23:55:31 -08:00
|
|
|
} 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;
|
|
|
|
|
2021-08-11 03:44:02 +02:00
|
|
|
struct winraw_pointer_status
|
2021-08-06 23:12:38 +03:00
|
|
|
{
|
2021-08-11 03:44:02 +02:00
|
|
|
struct winraw_pointer_status *next;
|
2021-08-06 23:12:38 +03:00
|
|
|
int pointer_id;
|
|
|
|
int pointer_x;
|
|
|
|
int pointer_y;
|
|
|
|
};
|
|
|
|
|
2017-12-11 23:55:31 -08:00
|
|
|
typedef struct
|
|
|
|
{
|
2020-09-05 07:14:42 +02:00
|
|
|
double view_abs_ratio_x;
|
|
|
|
double view_abs_ratio_y;
|
2017-12-11 23:55:31 -08:00
|
|
|
HWND window;
|
2021-11-06 15:07:35 +01:00
|
|
|
/* Dummy head for easier iteration */
|
|
|
|
struct winraw_pointer_status pointer_head;
|
2021-07-23 13:00:39 +01:00
|
|
|
RECT active_rect; /* Needed for checking for a windows size change */
|
2021-11-06 15:07:35 +01:00
|
|
|
RECT prev_rect; /* Needed for checking for a windows size change */
|
|
|
|
int rect_delay; /* Needed to delay resize of window */
|
2017-12-11 23:55:31 -08:00
|
|
|
winraw_mouse_t *mice;
|
2020-09-05 07:14:42 +02:00
|
|
|
unsigned mouse_cnt;
|
2020-09-05 07:29:37 +02:00
|
|
|
winraw_keyboard_t keyboard;
|
2020-09-05 07:14:42 +02:00
|
|
|
bool mouse_xy_mapping_ready;
|
2020-08-14 23:12:49 +02:00
|
|
|
bool mouse_grab;
|
2017-12-11 23:55:31 -08:00
|
|
|
} winraw_input_t;
|
|
|
|
|
2020-07-19 05:17:11 +02:00
|
|
|
/* TODO/FIXME - static globals */
|
2017-12-11 23:55:31 -08:00
|
|
|
static winraw_mouse_t *g_mice = NULL;
|
2021-08-07 04:24:20 +03:00
|
|
|
static bool winraw_focus = false;
|
2017-12-11 23:55:31 -08:00
|
|
|
|
2020-09-02 01:22:34 +02:00
|
|
|
#define WINRAW_KEYBOARD_PRESSED(wr, key) (wr->keyboard.keys[rarch_keysym_lut[(enum retro_key)(key)]])
|
|
|
|
|
2017-12-11 23:55:31 -08:00
|
|
|
static HWND winraw_create_window(WNDPROC wnd_proc)
|
|
|
|
{
|
|
|
|
HWND wnd;
|
2020-09-05 08:35:33 +02:00
|
|
|
WNDCLASSA wc = {0};
|
2017-12-11 23:55:31 -08:00
|
|
|
|
2020-09-05 08:35:33 +02:00
|
|
|
wc.hInstance = GetModuleHandleA(NULL);
|
2017-12-11 23:55:31 -08:00
|
|
|
|
|
|
|
if (!wc.hInstance)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
wc.lpfnWndProc = wnd_proc;
|
|
|
|
wc.lpszClassName = "winraw-input";
|
2020-09-05 08:35:33 +02:00
|
|
|
if ( !RegisterClassA(&wc)
|
|
|
|
&& GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
|
2017-12-11 23:55:31 -08:00
|
|
|
return NULL;
|
|
|
|
|
2020-09-05 08:35:33 +02:00
|
|
|
if (!(wnd = CreateWindowExA(0, wc.lpszClassName,
|
|
|
|
NULL, 0, 0, 0, 0, 0,
|
|
|
|
HWND_MESSAGE, NULL, NULL, NULL)))
|
|
|
|
{
|
|
|
|
UnregisterClassA(wc.lpszClassName, NULL);
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-12-11 23:55:31 -08:00
|
|
|
|
|
|
|
return wnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void winraw_destroy_window(HWND wnd)
|
|
|
|
{
|
|
|
|
if (!wnd)
|
|
|
|
return;
|
|
|
|
|
2020-09-05 08:35:33 +02:00
|
|
|
DestroyWindow(wnd);
|
|
|
|
UnregisterClassA("winraw-input", NULL);
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
|
|
|
|
2020-06-11 05:15:36 +02:00
|
|
|
static BOOL winraw_set_keyboard_input(HWND window)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
|
|
|
RAWINPUTDEVICE rid;
|
2020-12-09 00:03:40 +02:00
|
|
|
settings_t *settings;
|
|
|
|
|
|
|
|
settings = config_get_ptr();
|
2017-12-11 23:55:31 -08:00
|
|
|
|
|
|
|
rid.dwFlags = window ? 0 : RIDEV_REMOVE;
|
|
|
|
rid.hwndTarget = window;
|
2021-11-06 15:07:35 +01:00
|
|
|
rid.usUsagePage = 0x01; /* Generic desktop */
|
|
|
|
rid.usUsage = 0x06; /* Keyboard */
|
2020-12-09 00:03:40 +02:00
|
|
|
if (settings->bools.input_nowinkey_enable)
|
2021-11-06 15:07:35 +01:00
|
|
|
rid.dwFlags |= RIDEV_NOHOTKEYS; /* Disable win keys while focused */
|
2017-12-11 23:55:31 -08:00
|
|
|
|
2020-06-11 05:15:36 +02:00
|
|
|
return RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE));
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void winraw_log_mice_info(winraw_mouse_t *mice, unsigned mouse_cnt)
|
|
|
|
{
|
|
|
|
unsigned i;
|
|
|
|
char name[256];
|
|
|
|
UINT name_size = sizeof(name);
|
2020-09-09 23:36:21 +03:00
|
|
|
char prod_name[128];
|
|
|
|
wchar_t prod_buf[128];
|
2017-12-11 23:55:31 -08:00
|
|
|
|
2020-09-09 23:36:21 +03:00
|
|
|
name[0] = '\0';
|
2019-01-10 21:47:15 +01:00
|
|
|
|
2017-12-11 23:55:31 -08:00
|
|
|
for (i = 0; i < mouse_cnt; ++i)
|
|
|
|
{
|
2019-01-10 21:47:15 +01:00
|
|
|
UINT r = GetRawInputDeviceInfoA(mice[i].hnd, RIDI_DEVICENAME,
|
|
|
|
name, &name_size);
|
2017-12-11 23:55:31 -08:00
|
|
|
if (r == (UINT)-1 || r == 0)
|
|
|
|
name[0] = '\0';
|
2020-09-09 23:36:21 +03:00
|
|
|
|
|
|
|
prod_name[0] = '\0';
|
|
|
|
prod_buf[0] = '\0';
|
|
|
|
if (name[0])
|
|
|
|
{
|
2021-11-06 15:07:35 +01:00
|
|
|
HANDLE hhid = CreateFile(name,
|
|
|
|
0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
|
|
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
|
2020-09-09 23:36:21 +03:00
|
|
|
if (hhid != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
if (HidD_GetProductString (hhid, prod_buf, sizeof(prod_buf)))
|
|
|
|
wcstombs(prod_name, prod_buf, sizeof(prod_name));
|
|
|
|
}
|
|
|
|
CloseHandle(hhid);
|
|
|
|
}
|
|
|
|
if (prod_name[0])
|
2021-11-06 15:07:35 +01:00
|
|
|
strlcpy(name, prod_name, sizeof(name));
|
2020-09-09 23:36:21 +03:00
|
|
|
|
|
|
|
if (!name[0])
|
2021-11-06 15:07:35 +01:00
|
|
|
strlcpy(name, "<name not found>", sizeof(name));
|
2020-09-09 23:36:21 +03:00
|
|
|
|
2021-08-06 00:21:17 +03:00
|
|
|
input_config_set_mouse_display_name(i, name);
|
|
|
|
|
2021-12-17 19:04:24 +02:00
|
|
|
RARCH_LOG("[WinRaw]: Mouse #%u: \"%s\".\n", i, name);
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2021-11-06 15:07:35 +01:00
|
|
|
devs = (RAWINPUTDEVICELIST*)malloc(
|
|
|
|
dev_cnt * sizeof(RAWINPUTDEVICELIST));
|
2017-12-11 23:55:31 -08:00
|
|
|
if (!devs)
|
|
|
|
goto error;
|
|
|
|
|
2021-11-06 15:07:35 +01:00
|
|
|
dev_cnt = GetRawInputDeviceList(devs,
|
|
|
|
&dev_cnt, sizeof(RAWINPUTDEVICELIST));
|
2017-12-11 23:55:31 -08:00
|
|
|
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)
|
|
|
|
{
|
2021-11-06 15:07:35 +01:00
|
|
|
mice_r = (winraw_mouse_t*)calloc(
|
|
|
|
1, mouse_cnt_r * sizeof(winraw_mouse_t));
|
2017-12-11 23:55:31 -08:00
|
|
|
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);
|
2017-12-11 23:55:31 -08:00
|
|
|
|
|
|
|
*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;
|
2017-12-11 23:55:31 -08:00
|
|
|
*mouse_cnt = 0;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-02-09 18:34:01 +02:00
|
|
|
static BOOL winraw_set_mouse_input(HWND window)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
|
|
|
RAWINPUTDEVICE rid;
|
|
|
|
|
2021-02-09 18:34:01 +02:00
|
|
|
rid.dwFlags = (window) ? 0 : RIDEV_REMOVE;
|
2017-12-11 23:55:31 -08:00
|
|
|
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));
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int16_t winraw_lightgun_aiming_state(winraw_input_t *wr,
|
2020-06-11 06:29:36 +02:00
|
|
|
winraw_mouse_t *mouse,
|
2017-12-11 23:55:31 -08:00
|
|
|
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;
|
2017-12-11 23:55:31 -08:00
|
|
|
|
2020-06-11 06:29:36 +02:00
|
|
|
vp.x = 0;
|
|
|
|
vp.y = 0;
|
|
|
|
vp.width = 0;
|
|
|
|
vp.height = 0;
|
|
|
|
vp.full_width = 0;
|
|
|
|
vp.full_height = 0;
|
2017-12-11 23:55:31 -08:00
|
|
|
|
2020-06-11 16:50:36 +02:00
|
|
|
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;
|
2017-12-11 23:55:31 -08:00
|
|
|
|
2020-06-11 16:50:36 +02:00
|
|
|
inside = (res_x >= -edge_detect)
|
|
|
|
&& (res_y >= -edge_detect)
|
|
|
|
&& (res_x <= edge_detect)
|
|
|
|
&& (res_y <= edge_detect);
|
2017-12-11 23:55:31 -08:00
|
|
|
|
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:
|
2020-06-11 16:50:36 +02:00
|
|
|
if (inside)
|
|
|
|
return res_x;
|
|
|
|
break;
|
2019-06-23 02:34:35 +02:00
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y:
|
2020-06-11 16:50:36 +02:00
|
|
|
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;
|
|
|
|
}
|
2017-12-11 23:55:31 -08:00
|
|
|
|
2019-06-23 02:34:35 +02:00
|
|
|
return 0;
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
|
|
|
|
2019-06-23 02:34:35 +02:00
|
|
|
static bool winraw_mouse_button_pressed(
|
2020-06-11 06:29:36 +02:00
|
|
|
winraw_input_t *wr,
|
|
|
|
winraw_mouse_t *mouse,
|
|
|
|
unsigned port, unsigned key)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
2020-06-11 06:29:36 +02:00
|
|
|
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;
|
|
|
|
}
|
2017-12-11 23:55:31 -08:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-09-05 07:14:42 +02:00
|
|
|
static void winraw_init_mouse_xy_mapping(winraw_input_t *wr)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
|
|
|
struct video_viewport viewport;
|
|
|
|
|
|
|
|
if (video_driver_get_viewport_info(&viewport))
|
|
|
|
{
|
2020-09-02 01:22:34 +02:00
|
|
|
unsigned i;
|
2020-09-05 08:35:33 +02:00
|
|
|
int center_x = viewport.x + viewport.width / 2;
|
|
|
|
int center_y = viewport.y + viewport.height / 2;
|
2017-12-11 23:55:31 -08:00
|
|
|
|
2020-09-05 07:14:42 +02:00
|
|
|
for (i = 0; i < wr->mouse_cnt; ++i)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
2020-09-05 08:35:33 +02:00
|
|
|
g_mice[i].x = center_x;
|
|
|
|
g_mice[i].y = center_y;
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
|
|
|
|
2020-09-05 07:14:42 +02:00
|
|
|
wr->view_abs_ratio_x = (double)viewport.full_width / 65535.0;
|
|
|
|
wr->view_abs_ratio_y = (double)viewport.full_height / 65535.0;
|
2017-12-11 23:55:31 -08:00
|
|
|
|
2020-09-05 07:14:42 +02:00
|
|
|
wr->mouse_xy_mapping_ready = true;
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-05 07:14:42 +02:00
|
|
|
static void winraw_update_mouse_state(winraw_input_t *wr,
|
|
|
|
winraw_mouse_t *mouse, RAWMOUSE *state)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
|
|
|
POINT crs_pos;
|
2021-06-22 19:47:56 +03:00
|
|
|
|
2021-07-25 16:36:48 +02:00
|
|
|
/* Used for fixing coordinates after switching resolutions */
|
2021-07-23 13:00:39 +01:00
|
|
|
GetClientRect((HWND)video_driver_window_get(), &wr->prev_rect);
|
|
|
|
|
|
|
|
if (!EqualRect(&wr->active_rect, &wr->prev_rect))
|
2021-05-11 02:08:15 -07:00
|
|
|
{
|
2021-08-07 04:31:32 +03:00
|
|
|
if (wr->rect_delay < 10)
|
2021-07-23 13:00:39 +01:00
|
|
|
{
|
2021-12-17 19:04:24 +02:00
|
|
|
RARCH_DBG("[CRT][WinRaw]: Resize RECT delay for absolute co-ords - %d \n", wr->rect_delay);
|
2021-07-25 16:36:48 +02:00
|
|
|
winraw_init_mouse_xy_mapping(wr); /* Triggering fewer times seems to fix the issue. Forcing resize while resolution is changing */
|
2021-07-23 13:00:39 +01:00
|
|
|
wr->rect_delay ++;
|
2021-07-25 16:36:48 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int bottom = wr->prev_rect.bottom;
|
|
|
|
int right = wr->prev_rect.right;
|
2021-12-17 19:04:24 +02:00
|
|
|
RARCH_DBG("[CRT][WinRaw]: Resizing RECT for absolute coordinates to match new resolution - %dx%d\n", right ,bottom);
|
2021-07-25 16:36:48 +02:00
|
|
|
wr->active_rect = wr->prev_rect;
|
|
|
|
winraw_init_mouse_xy_mapping(wr);
|
|
|
|
wr->rect_delay = 0;
|
2021-07-23 13:00:39 +01:00
|
|
|
}
|
2021-05-11 02:08:15 -07:00
|
|
|
}
|
2017-12-11 23:55:31 -08:00
|
|
|
|
|
|
|
if (state->usFlags & MOUSE_MOVE_ABSOLUTE)
|
|
|
|
{
|
2020-09-05 07:14:42 +02:00
|
|
|
if (wr->mouse_xy_mapping_ready)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
2020-09-05 07:14:42 +02:00
|
|
|
state->lLastX = (LONG)(wr->view_abs_ratio_x * state->lLastX);
|
|
|
|
state->lLastY = (LONG)(wr->view_abs_ratio_y * state->lLastY);
|
2017-12-11 23:55:31 -08:00
|
|
|
InterlockedExchangeAdd(&mouse->dlt_x, state->lLastX - mouse->x);
|
|
|
|
InterlockedExchangeAdd(&mouse->dlt_y, state->lLastY - mouse->y);
|
2020-09-05 08:35:33 +02:00
|
|
|
mouse->x = state->lLastX;
|
|
|
|
mouse->y = state->lLastY;
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
|
|
|
else
|
2020-09-05 07:14:42 +02:00
|
|
|
winraw_init_mouse_xy_mapping(wr);
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
|
|
|
else if (state->lLastX || state->lLastY)
|
|
|
|
{
|
|
|
|
InterlockedExchangeAdd(&mouse->dlt_x, state->lLastX);
|
|
|
|
InterlockedExchangeAdd(&mouse->dlt_y, state->lLastY);
|
|
|
|
|
|
|
|
if (!GetCursorPos(&crs_pos))
|
2021-12-17 19:04:24 +02:00
|
|
|
RARCH_DBG("[WinRaw]: GetCursorPos failed with error %lu.\n", GetLastError());
|
2017-12-11 23:55:31 -08:00
|
|
|
else if (!ScreenToClient((HWND)video_driver_window_get(), &crs_pos))
|
2021-12-17 19:04:24 +02:00
|
|
|
RARCH_DBG("[WinRaw]: ScreenToClient failed with error %lu.\n", GetLastError());
|
2017-12-11 23:55:31 -08:00
|
|
|
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)
|
2021-11-06 15:07:35 +01:00
|
|
|
mouse->btn_m = true;
|
2017-12-11 23:55:31 -08:00
|
|
|
else if (state->usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP)
|
2021-11-06 15:07:35 +01:00
|
|
|
mouse->btn_m = false;
|
2017-12-11 23:55:31 -08:00
|
|
|
|
|
|
|
if (state->usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN)
|
2021-11-06 15:07:35 +01:00
|
|
|
mouse->btn_r = true;
|
2017-12-11 23:55:31 -08:00
|
|
|
else if (state->usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP)
|
2021-11-06 15:07:35 +01:00
|
|
|
mouse->btn_r = false;
|
2017-12-11 23:55:31 -08:00
|
|
|
|
|
|
|
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)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
|
|
|
unsigned i;
|
2021-08-04 01:56:33 +03:00
|
|
|
unsigned mcode, flags, kdown;
|
2020-06-11 05:15:36 +02:00
|
|
|
static uint8_t data[1024];
|
2020-09-05 07:11:04 +02:00
|
|
|
RAWINPUT *ri = (RAWINPUT*)data;
|
|
|
|
UINT size = sizeof(data);
|
2020-09-05 08:35:33 +02:00
|
|
|
winraw_input_t *wr = (winraw_input_t*)(LONG_PTR)
|
|
|
|
GetWindowLongPtr(wnd, GWLP_USERDATA);
|
2017-12-11 23:55:31 -08:00
|
|
|
|
|
|
|
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)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
2020-08-29 19:43:53 +02:00
|
|
|
DefWindowProcA(wnd, msg, wpar, lpar);
|
|
|
|
return 0;
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
2020-08-29 19:43:53 +02:00
|
|
|
|
|
|
|
switch (ri->header.dwType)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
2020-08-29 19:43:53 +02:00
|
|
|
case RIM_TYPEKEYBOARD:
|
2021-08-04 01:56:33 +03:00
|
|
|
mcode = ri->data.keyboard.MakeCode;
|
2021-03-20 00:58:11 +02:00
|
|
|
flags = ri->data.keyboard.Flags;
|
2021-08-04 01:56:33 +03:00
|
|
|
kdown = (flags & RI_KEY_BREAK) ? 0 : 1;
|
2021-03-20 00:58:11 +02:00
|
|
|
|
2021-08-04 01:56:33 +03:00
|
|
|
/* Extended scancodes */
|
|
|
|
if (flags & RI_KEY_E0)
|
|
|
|
mcode |= 0xE000;
|
|
|
|
else if (flags & RI_KEY_E1)
|
|
|
|
mcode |= 0xE100;
|
2021-03-20 00:58:11 +02:00
|
|
|
|
2021-08-04 01:56:33 +03:00
|
|
|
/* Special pause-key handling due to
|
|
|
|
* scancode 0xE11D45 incoming separately */
|
|
|
|
if (wr->keyboard.pause)
|
|
|
|
{
|
|
|
|
wr->keyboard.pause = false;
|
|
|
|
if (mcode == SC_NUMLOCK)
|
|
|
|
mcode = SC_PAUSE;
|
|
|
|
}
|
|
|
|
else if (mcode == 0xE11D)
|
|
|
|
wr->keyboard.pause = true;
|
2020-11-08 12:08:17 +02:00
|
|
|
|
2021-08-04 01:56:33 +03:00
|
|
|
/* Ignored scancodes */
|
|
|
|
switch (mcode)
|
2021-03-20 00:58:11 +02:00
|
|
|
{
|
2021-08-04 01:56:33 +03:00
|
|
|
case 0xE11D:
|
|
|
|
case 0xE02A:
|
|
|
|
case 0xE036:
|
|
|
|
case 0xE0AA:
|
|
|
|
case 0xE0B6:
|
|
|
|
return 0;
|
2021-03-20 00:58:11 +02:00
|
|
|
}
|
2021-08-04 01:56:33 +03:00
|
|
|
|
|
|
|
wr->keyboard.keys[mcode] = kdown;
|
|
|
|
input_keyboard_event(kdown,
|
|
|
|
input_keymaps_translate_keysym_to_rk(mcode),
|
|
|
|
0, 0, RETRO_DEVICE_KEYBOARD);
|
2020-08-29 19:43:53 +02:00
|
|
|
break;
|
|
|
|
case RIM_TYPEMOUSE:
|
2020-09-05 07:14:42 +02:00
|
|
|
for (i = 0; i < wr->mouse_cnt; ++i)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
2020-08-29 19:43:53 +02:00
|
|
|
if (g_mice[i].hnd == ri->header.hDevice)
|
|
|
|
{
|
2020-09-05 08:35:33 +02:00
|
|
|
winraw_update_mouse_state(wr,
|
|
|
|
&g_mice[i], &ri->data.mouse);
|
2020-08-29 19:43:53 +02:00
|
|
|
break;
|
|
|
|
}
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
2020-08-29 19:43:53 +02:00
|
|
|
break;
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
2020-09-05 07:11:04 +02:00
|
|
|
if (!wr)
|
|
|
|
return NULL;
|
2017-12-11 23:55:31 -08:00
|
|
|
|
|
|
|
input_keymaps_init_keyboard_lut(rarch_key_map_winraw);
|
|
|
|
|
|
|
|
wr->window = winraw_create_window(winraw_callback);
|
|
|
|
if (!wr->window)
|
|
|
|
goto error;
|
|
|
|
|
2020-09-05 07:14:42 +02:00
|
|
|
if (!winraw_init_devices(&g_mice, &wr->mouse_cnt))
|
2017-12-11 23:55:31 -08:00
|
|
|
goto error;
|
|
|
|
|
2020-09-05 07:14:42 +02:00
|
|
|
if (wr->mouse_cnt)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
|
|
|
wr->mice = (winraw_mouse_t*)
|
2020-09-05 07:14:42 +02:00
|
|
|
malloc(wr->mouse_cnt * sizeof(winraw_mouse_t));
|
2017-12-11 23:55:31 -08:00
|
|
|
if (!wr->mice)
|
|
|
|
goto error;
|
|
|
|
|
2020-09-05 07:14:42 +02:00
|
|
|
memcpy(wr->mice, g_mice, wr->mouse_cnt * sizeof(winraw_mouse_t));
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
|
|
|
|
2020-06-11 05:15:36 +02:00
|
|
|
if (!winraw_set_keyboard_input(wr->window))
|
2017-12-11 23:55:31 -08:00
|
|
|
goto error;
|
|
|
|
|
2021-02-09 18:34:01 +02:00
|
|
|
if (!winraw_set_mouse_input(wr->window))
|
2017-12-11 23:55:31 -08:00
|
|
|
goto error;
|
|
|
|
|
2020-09-05 07:11:04 +02:00
|
|
|
SetWindowLongPtr(wr->window, GWLP_USERDATA, (LONG_PTR)wr);
|
|
|
|
|
2017-12-11 23:55:31 -08:00
|
|
|
return wr;
|
|
|
|
|
|
|
|
error:
|
|
|
|
if (wr && wr->window)
|
|
|
|
{
|
2021-02-09 18:34:01 +02:00
|
|
|
winraw_set_mouse_input(NULL);
|
2017-12-11 23:55:31 -08:00
|
|
|
winraw_set_keyboard_input(NULL);
|
|
|
|
winraw_destroy_window(wr->window);
|
|
|
|
}
|
|
|
|
free(g_mice);
|
|
|
|
if (wr)
|
|
|
|
free(wr->mice);
|
|
|
|
free(wr);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-09-01 21:43:19 +02:00
|
|
|
static void winraw_poll(void *data)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
|
|
|
unsigned i;
|
2021-11-06 15:07:35 +01:00
|
|
|
winraw_input_t *wr = (winraw_input_t*)data;
|
2017-12-11 23:55:31 -08:00
|
|
|
|
2020-09-05 07:14:42 +02:00
|
|
|
for (i = 0; i < wr->mouse_cnt; ++i)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
2021-11-06 15:07:35 +01: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;
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
2021-08-07 04:24:20 +03:00
|
|
|
|
|
|
|
/* Prevent LAlt sticky after unfocusing with Alt-Tab */
|
2021-11-06 15:07:35 +01:00
|
|
|
if ( !winraw_focus
|
|
|
|
&& wr->keyboard.keys[SC_LALT]
|
|
|
|
&& !(GetKeyState(VK_MENU) & 0x8000))
|
2021-08-07 04:24:20 +03:00
|
|
|
{
|
|
|
|
wr->keyboard.keys[SC_LALT] = 0;
|
|
|
|
input_keyboard_event(0,
|
|
|
|
input_keymaps_translate_keysym_to_rk(SC_LALT),
|
|
|
|
0, 0, RETRO_DEVICE_KEYBOARD);
|
|
|
|
}
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
|
|
|
|
2021-04-11 16:31:46 +02:00
|
|
|
static unsigned winraw_retro_id_to_rarch(unsigned id)
|
|
|
|
{
|
|
|
|
switch (id)
|
|
|
|
{
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT:
|
|
|
|
return RARCH_LIGHTGUN_DPAD_RIGHT;
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT:
|
|
|
|
return RARCH_LIGHTGUN_DPAD_LEFT;
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP:
|
|
|
|
return RARCH_LIGHTGUN_DPAD_UP;
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN:
|
|
|
|
return RARCH_LIGHTGUN_DPAD_DOWN;
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_SELECT:
|
|
|
|
return RARCH_LIGHTGUN_SELECT;
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_PAUSE:
|
|
|
|
return RARCH_LIGHTGUN_START;
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_RELOAD:
|
|
|
|
return RARCH_LIGHTGUN_RELOAD;
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_TRIGGER:
|
|
|
|
return RARCH_LIGHTGUN_TRIGGER;
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_AUX_A:
|
|
|
|
return RARCH_LIGHTGUN_AUX_A;
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_AUX_B:
|
|
|
|
return RARCH_LIGHTGUN_AUX_B;
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_AUX_C:
|
|
|
|
return RARCH_LIGHTGUN_AUX_C;
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_START:
|
|
|
|
return RARCH_LIGHTGUN_START;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
2021-11-03 08:32:15 -07:00
|
|
|
const retro_keybind_set *binds,
|
2020-08-30 18:47:29 +02:00
|
|
|
bool keyboard_mapping_blocked,
|
|
|
|
unsigned port,
|
|
|
|
unsigned device,
|
|
|
|
unsigned idx,
|
|
|
|
unsigned id)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
2020-06-11 06:29:36 +02:00
|
|
|
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;
|
2020-06-13 17:27:12 +02:00
|
|
|
bool process_mouse =
|
|
|
|
(device == RETRO_DEVICE_JOYPAD)
|
|
|
|
|| (device == RETRO_DEVICE_MOUSE)
|
|
|
|
|| (device == RARCH_DEVICE_MOUSE_SCREEN)
|
2021-08-06 23:12:38 +03:00
|
|
|
|| (device == RETRO_DEVICE_LIGHTGUN)
|
|
|
|
|| (device == RETRO_DEVICE_POINTER);
|
2020-06-11 06:29:36 +02:00
|
|
|
|
|
|
|
if (port >= MAX_USERS)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (process_mouse)
|
|
|
|
{
|
2020-06-11 06:34:59 +02:00
|
|
|
unsigned i;
|
2020-06-11 06:29:36 +02:00
|
|
|
settings = config_get_ptr();
|
2020-09-05 07:14:42 +02:00
|
|
|
for (i = 0; i < wr->mouse_cnt; ++i)
|
2020-06-11 06:29:36 +02:00
|
|
|
{
|
|
|
|
if (i == settings->uints.input_mouse_index[port])
|
|
|
|
{
|
|
|
|
mouse = &wr->mice[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-12-11 23:55:31 -08:00
|
|
|
|
|
|
|
switch (device)
|
|
|
|
{
|
|
|
|
case RETRO_DEVICE_JOYPAD:
|
2019-06-23 06:09:45 +02:00
|
|
|
if (id == RETRO_DEVICE_ID_JOYPAD_MASK)
|
|
|
|
{
|
|
|
|
unsigned i;
|
2020-09-02 15:26:03 +02:00
|
|
|
int16_t ret = 0;
|
2020-06-11 08:34:30 +02:00
|
|
|
|
2020-07-19 03:18:12 +02:00
|
|
|
if (mouse)
|
2019-06-23 06:09:45 +02:00
|
|
|
{
|
2020-07-19 03:18:12 +02:00
|
|
|
for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++)
|
2019-07-22 01:20:00 +02:00
|
|
|
{
|
2020-07-19 03:18:12 +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
|
|
|
}
|
|
|
|
}
|
2020-07-19 03:18:12 +02:00
|
|
|
|
2020-08-30 18:47:29 +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)
|
2020-06-12 06:37:36 +02:00
|
|
|
{
|
2020-07-14 01:39:07 +02:00
|
|
|
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);
|
2020-06-12 06:37:36 +02:00
|
|
|
}
|
2019-07-22 01:20:00 +02:00
|
|
|
}
|
2019-06-23 06:09:45 +02:00
|
|
|
}
|
2019-07-22 01:20:00 +02:00
|
|
|
|
|
|
|
return ret;
|
2019-06-23 06:09:45 +02:00
|
|
|
}
|
2020-09-02 15:26:03 +02:00
|
|
|
|
|
|
|
if (id < RARCH_BIND_LIST_END)
|
2019-06-23 06:09:45 +02:00
|
|
|
{
|
2020-09-02 15:26:03 +02:00
|
|
|
if (binds[port][id].valid)
|
2020-06-11 08:34:30 +02:00
|
|
|
{
|
2020-09-02 15:26:03 +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-06-23 06:09:45 +02:00
|
|
|
}
|
2019-07-22 01:20:00 +02:00
|
|
|
break;
|
2019-06-23 06:09:45 +02:00
|
|
|
case RETRO_DEVICE_ANALOG:
|
2021-08-21 22:01:12 +03:00
|
|
|
if (binds[port])
|
|
|
|
{
|
|
|
|
int id_minus_key = 0;
|
|
|
|
int id_plus_key = 0;
|
|
|
|
unsigned id_minus = 0;
|
|
|
|
unsigned id_plus = 0;
|
|
|
|
int16_t ret = 0;
|
|
|
|
bool id_plus_valid = false;
|
|
|
|
bool id_minus_valid = false;
|
|
|
|
|
|
|
|
input_conv_analog_id_to_bind_id(idx, id, id_minus, id_plus);
|
|
|
|
|
|
|
|
id_minus_valid = binds[port][id_minus].valid;
|
|
|
|
id_plus_valid = binds[port][id_plus].valid;
|
|
|
|
id_minus_key = binds[port][id_minus].key;
|
|
|
|
id_plus_key = binds[port][id_plus].key;
|
|
|
|
|
|
|
|
if (id_plus_valid && id_plus_key < RETROK_LAST)
|
|
|
|
{
|
|
|
|
if (WINRAW_KEYBOARD_PRESSED(wr, id_plus_key))
|
|
|
|
ret = 0x7fff;
|
|
|
|
}
|
|
|
|
if (id_minus_valid && id_minus_key < RETROK_LAST)
|
|
|
|
{
|
|
|
|
if (WINRAW_KEYBOARD_PRESSED(wr, id_minus_key))
|
|
|
|
ret += -0x7fff;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2017-12-11 23:55:31 -08:00
|
|
|
break;
|
|
|
|
case RETRO_DEVICE_KEYBOARD:
|
2020-09-02 01:22:34 +02:00
|
|
|
return (id < RETROK_LAST) && WINRAW_KEYBOARD_PRESSED(wr, id);
|
2017-12-11 23:55:31 -08:00
|
|
|
case RETRO_DEVICE_MOUSE:
|
|
|
|
case RARCH_DEVICE_MOUSE_SCREEN:
|
2020-06-11 06:29:36 +02:00
|
|
|
if (mouse)
|
2020-09-05 08:35:33 +02:00
|
|
|
{
|
|
|
|
bool abs = (device == RARCH_DEVICE_MOUSE_SCREEN);
|
|
|
|
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:
|
|
|
|
if (mouse->btn_l)
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
case RETRO_DEVICE_ID_MOUSE_RIGHT:
|
|
|
|
if (mouse->btn_r)
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
case RETRO_DEVICE_ID_MOUSE_WHEELUP:
|
|
|
|
if (mouse->whl_u)
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
case RETRO_DEVICE_ID_MOUSE_WHEELDOWN:
|
|
|
|
if (mouse->whl_d)
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
case RETRO_DEVICE_ID_MOUSE_MIDDLE:
|
|
|
|
if (mouse->btn_m)
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
case RETRO_DEVICE_ID_MOUSE_BUTTON_4:
|
|
|
|
if (mouse->btn_b4)
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
case RETRO_DEVICE_ID_MOUSE_BUTTON_5:
|
|
|
|
if (mouse->btn_b5)
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-06-11 06:29:36 +02:00
|
|
|
break;
|
2021-08-06 23:12:38 +03:00
|
|
|
case RETRO_DEVICE_POINTER:
|
|
|
|
case RARCH_DEVICE_POINTER_SCREEN:
|
|
|
|
{
|
|
|
|
struct video_viewport vp;
|
|
|
|
bool pointer_down = false;
|
|
|
|
bool inside = false;
|
|
|
|
int x = 0;
|
|
|
|
int y = 0;
|
|
|
|
int16_t res_x = 0;
|
|
|
|
int16_t res_y = 0;
|
|
|
|
int16_t res_screen_x = 0;
|
|
|
|
int16_t res_screen_y = 0;
|
|
|
|
unsigned num = 0;
|
2021-08-11 03:44:02 +02:00
|
|
|
struct winraw_pointer_status *
|
2021-08-06 23:12:38 +03:00
|
|
|
check_pos = wr->pointer_head.next;
|
|
|
|
|
|
|
|
vp.x = 0;
|
|
|
|
vp.y = 0;
|
|
|
|
vp.width = 0;
|
|
|
|
vp.height = 0;
|
|
|
|
vp.full_width = 0;
|
|
|
|
vp.full_height = 0;
|
|
|
|
|
|
|
|
while (check_pos && num < idx)
|
|
|
|
{
|
|
|
|
num++;
|
|
|
|
check_pos = check_pos->next;
|
|
|
|
}
|
|
|
|
if (!check_pos && idx > 0) /* idx = 0 has mouse fallback. */
|
|
|
|
return 0;
|
|
|
|
|
2021-08-24 17:03:28 +03:00
|
|
|
if (mouse)
|
|
|
|
{
|
|
|
|
x = mouse->x;
|
|
|
|
y = mouse->y;
|
|
|
|
pointer_down = mouse->btn_l;
|
|
|
|
}
|
2021-08-06 23:12:38 +03:00
|
|
|
|
|
|
|
if (check_pos)
|
|
|
|
{
|
|
|
|
x = check_pos->pointer_x;
|
|
|
|
y = check_pos->pointer_y;
|
|
|
|
pointer_down = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(video_driver_translate_coord_viewport_wrap(&vp, x, y,
|
|
|
|
&res_x, &res_y, &res_screen_x, &res_screen_y)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (device == RARCH_DEVICE_POINTER_SCREEN)
|
|
|
|
{
|
|
|
|
res_x = res_screen_x;
|
|
|
|
res_y = res_screen_y;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(inside = (res_x >= -0x7fff) && (res_y >= -0x7fff)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (id)
|
|
|
|
{
|
|
|
|
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 pointer_down;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2017-12-11 23:55:31 -08:00
|
|
|
case RETRO_DEVICE_LIGHTGUN:
|
2021-08-07 04:31:32 +03:00
|
|
|
switch (id)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
|
|
|
/*aiming*/
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X:
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y:
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN:
|
2021-07-25 16:36:48 +02:00
|
|
|
if (mouse)
|
|
|
|
return winraw_lightgun_aiming_state(wr, mouse, port, id);
|
|
|
|
break;
|
2021-08-07 04:31:32 +03:00
|
|
|
/*buttons*/
|
2017-12-11 23:55:31 -08:00
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_TRIGGER:
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_RELOAD:
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_AUX_A:
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_AUX_B:
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_AUX_C:
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_START:
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_SELECT:
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP:
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN:
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT:
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT:
|
2021-04-11 16:31:46 +02:00
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_PAUSE: /* deprecated */
|
2021-11-06 15:07:35 +01:00
|
|
|
{
|
|
|
|
unsigned new_id = winraw_retro_id_to_rarch(id);
|
|
|
|
const uint64_t bind_joykey = input_config_binds[port][new_id].joykey;
|
|
|
|
const uint64_t bind_joyaxis = input_config_binds[port][new_id].joyaxis;
|
|
|
|
const uint64_t autobind_joykey = input_autoconf_binds[port][new_id].joykey;
|
|
|
|
const uint64_t autobind_joyaxis= input_autoconf_binds[port][new_id].joyaxis;
|
|
|
|
uint16_t port = joypad_info->joy_idx;
|
|
|
|
float axis_threshold = joypad_info->axis_threshold;
|
|
|
|
const uint64_t joykey = (bind_joykey != NO_BTN)
|
|
|
|
? bind_joykey : autobind_joykey;
|
|
|
|
const uint32_t joyaxis = (bind_joyaxis != AXIS_NONE)
|
|
|
|
? bind_joyaxis : autobind_joyaxis;
|
|
|
|
if (binds[port][new_id].valid)
|
|
|
|
{
|
|
|
|
if ((uint16_t)joykey != NO_BTN && joypad->button(
|
|
|
|
port, (uint16_t)joykey))
|
|
|
|
return 1;
|
|
|
|
if (joyaxis != AXIS_NONE &&
|
|
|
|
((float)abs(joypad->axis(port, joyaxis))
|
|
|
|
/ 0x8000) > axis_threshold)
|
|
|
|
return 1;
|
|
|
|
else if (
|
|
|
|
binds[port][new_id].key < RETROK_LAST
|
|
|
|
&& !keyboard_mapping_blocked
|
|
|
|
&& WINRAW_KEYBOARD_PRESSED(wr, binds[port]
|
|
|
|
[new_id].key)
|
|
|
|
)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (
|
|
|
|
mouse && winraw_mouse_button_pressed(wr,
|
|
|
|
mouse, port, binds[port][new_id].mbutton)
|
|
|
|
)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
/*deprecated*/
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_X:
|
|
|
|
if (mouse)
|
|
|
|
return mouse->dlt_x;
|
|
|
|
break;
|
|
|
|
case RETRO_DEVICE_ID_LIGHTGUN_Y:
|
|
|
|
if (mouse)
|
|
|
|
return mouse->dlt_y;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-08-01 22:26:19 +03:00
|
|
|
#if !defined(_XBOX)
|
2021-08-07 04:31:32 +03:00
|
|
|
bool winraw_handle_message(UINT msg,
|
|
|
|
WPARAM wpar, LPARAM lpar)
|
2021-08-01 22:26:19 +03:00
|
|
|
{
|
2021-08-07 04:31:32 +03:00
|
|
|
switch (msg)
|
2021-08-01 22:26:19 +03:00
|
|
|
{
|
2021-08-07 04:24:20 +03:00
|
|
|
case WM_SETFOCUS:
|
|
|
|
winraw_focus = true;
|
|
|
|
break;
|
|
|
|
case WM_KILLFOCUS:
|
|
|
|
winraw_focus = false;
|
|
|
|
break;
|
|
|
|
|
2021-08-01 22:26:19 +03:00
|
|
|
case WM_DEVICECHANGE:
|
|
|
|
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500 /* 2K */
|
2021-08-07 04:31:32 +03:00
|
|
|
if (wpar == DBT_DEVICEARRIVAL ||
|
|
|
|
wpar == DBT_DEVICEREMOVECOMPLETE)
|
2021-08-01 22:26:19 +03:00
|
|
|
{
|
2021-08-07 04:31:32 +03:00
|
|
|
PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lpar;
|
2021-08-01 22:26:19 +03:00
|
|
|
if (pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
|
2021-08-07 04:31:32 +03:00
|
|
|
joypad_driver_reinit(NULL, NULL);
|
2021-08-01 22:26:19 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-09-02 01:22:34 +02:00
|
|
|
static void winraw_free(void *data)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
2020-09-02 01:22:34 +02:00
|
|
|
winraw_input_t *wr = (winraw_input_t*)data;
|
2017-12-11 23:55:31 -08:00
|
|
|
|
2021-02-09 18:34:01 +02:00
|
|
|
winraw_set_mouse_input(NULL);
|
2017-12-11 23:55:31 -08:00
|
|
|
winraw_set_keyboard_input(NULL);
|
2020-09-05 07:11:04 +02:00
|
|
|
SetWindowLongPtr(wr->window, GWLP_USERDATA, 0);
|
2017-12-11 23:55:31 -08:00
|
|
|
winraw_destroy_window(wr->window);
|
|
|
|
free(g_mice);
|
|
|
|
free(wr->mice);
|
|
|
|
|
2020-09-02 01:22:34 +02:00
|
|
|
free(data);
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
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) |
|
2021-08-06 23:12:38 +03:00
|
|
|
(1 << RETRO_DEVICE_POINTER) |
|
2017-12-11 23:55:31 -08:00
|
|
|
(1 << RETRO_DEVICE_LIGHTGUN);
|
|
|
|
}
|
|
|
|
|
2021-02-02 00:52:03 +02:00
|
|
|
static void winraw_grab_mouse(void *d, bool state)
|
2017-12-11 23:55:31 -08:00
|
|
|
{
|
|
|
|
winraw_input_t *wr = (winraw_input_t*)d;
|
|
|
|
|
2021-02-02 00:52:03 +02:00
|
|
|
if (state == wr->mouse_grab)
|
2017-12-11 23:55:31 -08:00
|
|
|
return;
|
|
|
|
|
2021-02-09 18:34:01 +02:00
|
|
|
if (!winraw_set_mouse_input(wr->window))
|
2017-12-11 23:55:31 -08:00
|
|
|
return;
|
|
|
|
|
2021-02-02 00:52:03 +02:00
|
|
|
wr->mouse_grab = state;
|
|
|
|
|
|
|
|
#ifndef _XBOX
|
|
|
|
win32_clip_window(state);
|
|
|
|
#endif
|
2017-12-11 23:55:31 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
input_driver_t input_winraw = {
|
|
|
|
winraw_init,
|
|
|
|
winraw_poll,
|
|
|
|
winraw_input_state,
|
|
|
|
winraw_free,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
winraw_get_capabilities,
|
|
|
|
"raw",
|
|
|
|
winraw_grab_mouse,
|
2020-09-02 00:38:11 +02:00
|
|
|
NULL
|
2017-12-11 23:55:31 -08:00
|
|
|
};
|