RetroArch/input/drivers/winraw_input.c

1050 lines
30 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>
#ifdef CXX_BUILD
extern "C" {
#endif
#include <hidsdi.h>
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500 /* 2K */
#include <dbt.h>
#endif
#ifdef CXX_BUILD
}
#endif
2021-11-06 15:07:35 +01:00
#include <compat/strl.h>
#ifndef _XBOX
#include "../../gfx/common/win32_common.h"
#endif
#include "../input_keymaps.h"
#include "../../configuration.h"
#include "../../retroarch.h"
#include "../../verbosity.h"
typedef struct
{
uint8_t keys[SC_LAST];
bool pause;
} 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;
struct winraw_pointer_status
2021-08-06 23:12:38 +03:00
{
struct winraw_pointer_status *next;
2021-08-06 23:12:38 +03:00
int pointer_id;
int pointer_x;
int pointer_y;
};
typedef struct
{
double view_abs_ratio_x;
double view_abs_ratio_y;
HWND window;
2021-11-06 15:07:35 +01:00
/* Dummy head for easier iteration */
struct winraw_pointer_status pointer_head;
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 */
winraw_mouse_t *mice;
unsigned mouse_cnt;
2020-09-05 07:29:37 +02:00
winraw_keyboard_t keyboard;
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;
static bool winraw_focus = false;
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;
2020-09-05 08:35:33 +02:00
WNDCLASSA wc = {0};
2020-09-05 08:35:33 +02:00
wc.hInstance = GetModuleHandleA(NULL);
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)
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;
}
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);
}
2020-06-11 05:15:36 +02:00
static BOOL winraw_set_keyboard_input(HWND window)
{
RAWINPUTDEVICE rid;
settings_t *settings;
settings = config_get_ptr();
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 */
if (settings->bools.input_nowinkey_enable)
2021-11-06 15:07:35 +01:00
rid.dwFlags |= RIDEV_NOHOTKEYS; /* Disable win keys while focused */
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);
char prod_name[128];
wchar_t prod_buf[128];
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';
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);
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));
if (!name[0])
2021-11-06 15:07:35 +01:00
strlcpy(name, "<name not found>", sizeof(name));
input_config_set_mouse_display_name(i, name);
RARCH_LOG("[WINRAW]: Mouse #%u: \"%s\".\n", i, name);
}
}
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));
if (!devs)
goto error;
2021-11-06 15:07:35 +01:00
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)
{
2021-11-06 15:07:35 +01:00
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;
}
2021-02-09 18:34:01 +02:00
static BOOL winraw_set_mouse_input(HWND window)
{
RAWINPUTDEVICE rid;
2021-02-09 18:34:01 +02:00
rid.dwFlags = (window) ? 0 : 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;
}
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;
2020-09-05 08:35:33 +02:00
int center_x = viewport.x + viewport.width / 2;
int center_y = viewport.y + viewport.height / 2;
for (i = 0; i < wr->mouse_cnt; ++i)
{
2020-09-05 08:35:33 +02:00
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;
2021-06-22 19:47:56 +03:00
/* Used for fixing coordinates after switching resolutions */
GetClientRect((HWND)video_driver_window_get(), &wr->prev_rect);
if (!EqualRect(&wr->active_rect, &wr->prev_rect))
Ver 0.9.2 SR2 (Switchres API) Implimantation Fixed SR close match refresh bug. Added menu high resolution option. Fixed desktop restore bug cuusing endless resolution change requests. Fixed file conflicts Added destop restore resolution back in for manu only. Pulled Switchres fixes. Added better PI rsolution support. Ver 0.7 SR2 (Switchres API) Implimantation Removed HH experimetal check. This is better done via teh switchres.ini at present. Fixed refresh rate bug. Now new resolution and refesh is added correctly. Removed SR deinit from menu restore. Meanu now stays at last content resolution. Ver 0.6.2 SR2 (Switchres API) Implimantation Fixed super resolution bug casuing abnormal video size and aspect ratio Fixed logging issue casuing seg falts on RA exit Ver 0.6 SR2 (Switchres API) Implimantation Ver 0.2 SR2 (Switchres API) Implimantation Added forced super resolutions. Added Multi-monitor/monitor selection support. Added desktop resolution restore when switching back to menu only. Added new menu items for 31KHz standard and 120hz monitor profiles. Added new menu item INI. load monitor profile from switchrss.ini. Fixed winraw driver. Coordinates new refreshed after a resolution change. Fixed Menu aspect ratio in super resolutions. Removed static glabals. These have been added to videocrt_switch struct. Ver 0.1 SR2 (Switchres API) Implimantation Removed old CRTSwitchRes method. Added new SR2 API implimantaion. Resolution swithcing is now done by switchres libs. Both Linux and Windows working with native and super resolutions. Working multi-monitor support with monitor index selection. Working 31KHz support with standard and 120Hxz modes. The monitor index selection is still done via the RA UI. Only choose native and 15KHz form the CRT options in the RA UI as all options are now set in the switchres.ini. All other CRT optoins in the RA UI currently do nothing. Added SR wrapper to fix compile issues. Added back RPi functionality Fixed windows resize/scaling issues on resolution change Thanks @Calamity no more need for crt_switch_driver_refresh() Fix broken case after prevous commit Monitor preset options 15/31KHz now active. Added new meu option. Moitor persets can now be choosen fom the RA UI. 15KHz and 31KHz will set arcade_15 and aracde_31 respectivly. New option INI, if this is chosen your monitor preset will be selected from your switchres.ini file. Added 3KHhz, 120Hz. for old RA users. Renamed 31KHz to 31 KHz, Standard Fixed winraw input coordinates after switching resolution. Code cleanup Fixed menu aspect ratio issue Added menu resolution restore after closing content Fixed aspect ratio after menu resolution restore. code clean up Fxed menu Resulition Restore Aspect Ratio. When SR uses non integer scalled resolution. super width bug with restoring menu resolution fix added super resolution check after setting desktop resolutoion variables when menu active only sr_deinit() used to restore desktop mode. Fixed menu sr_deinit bug. now setting sr_active false Removed static globals, added them to video_switch struct Fixex compile bug due to comment // Fixed compile issues doe to c++ comments in teh switchres_wrapper.h Temporarily removed SR2 logging to fix compile isses for c90 added logging back in. Removed support for winnt and osx Added define for C89. Disabled SR if defined C89 Removed all RA compile fixes fro C89 C90 etc. Swithing now working again. Put Switchres behind HAVE_SR2. HAVE_SR2=no by default. --enable-sr2 Ver 0.5 SR2 Implimentation. Ver 0.4 SR2 Implimantation. Bake SR inside RA Removed temporary log files Disable switchres when C89/C99 builds. Removed C89 and C90 checks for SR Fixed switchres_wrapper.h location Ver 0.3 SR2 Implimenation Dissable logging for C89 __STDC__ Fix For RPi fixed missing EOL fixed RPi function definition added vidrocrt_switch stuct to RPI funcion fixed xoffset for RPi Removed old RPi function call SR disabled for videocore until VC4 switching ported Reverted back to state 5c8a56c Bake SR inside RA Use native win32 api for threads. Fix static lib linking LIBERROR would be defined twice otherwise + improper function names prefixed by __imp_ Added lidstc++ to makefile.common for switchres Fixed RPi switching. Disabled Switchres for videocore unill it is ported. removed RAA.log. Should not exist Added check for when SR fails to set mode with an aspect ratio fix. added video driver re init for RPi GB, GBA and GBC core check, adjusted reseolutions and scale. Please turn on integer scalling in the RA UI Added logas back in. Checking STDC verstion >= C11 Fixed c89 for loop declaration. Code clean up. Added new functions Fix resolution switching bug introduces with HH code clean up. Fixed menu restore bug on closw content after code clean up Moved SR logging to relevant RA logs Update makefile. Checks for X11 and xrandr fixed makefile Use native win32 api for threads. Fix static lib linking LIBERROR would be defined twice otherwise + improper function names prefixed by __imp_ Update switchres_wrapper.* header comments Update year copyright DRMKMS: build only if libdrm has the required version XRANDR: build only if xrandr is available Simplified maklefile Fixed RPI compile error with unsued functions. As before Disable Griffin. No switching support available. Never has been Removed log file 1 Added Win32 static define Added SR source Removed Videocore check on destroy SR Moved SR deinit to trigger earlier on RA exit. Fixed compile error after upstream rebase Fixed aspect ration bug cused by super resolutions. Temporarily disbabled SR logging Re inabled runtim eSR loggind. Disableed all RARCH logging on retro_deinit_drivers Removed srdeinit from menu restore. Menu stays in current reolution until a fix can be found Fixed refresh rate changes when no reolution change is detected. Forgot to add teh resolution cahge in with the refresh change oops Fixed endless no detection log. Removed HH check. This can been better adjusted using the switchres.ini fixed compile issue Added better PI crt switching and fixed typo Pulled Swicthres fixes. Updated desktop restore resolution. removed unused makefile Lockec menu refresh to 60hz fixed missing new line Fixed file conflicts Forced 640x480@60 for menu Added high resolution menu option Removed item logg checker Fixed typos Removed unused functions Fixed SR close match refesh bug. Fixed typo
2021-05-11 02:08:15 -07:00
{
2021-08-07 04:31:32 +03:00
if (wr->rect_delay < 10)
{
2021-08-07 04:31:32 +03:00
RARCH_DBG("[CRT][WINRAW]: Resize RECT delay for absolute co-ords - %d \n", wr->rect_delay);
winraw_init_mouse_xy_mapping(wr); /* Triggering fewer times seems to fix the issue. Forcing resize while resolution is changing */
wr->rect_delay ++;
}
else
{
int bottom = wr->prev_rect.bottom;
int right = wr->prev_rect.right;
2021-08-07 04:31:32 +03:00
RARCH_DBG("[CRT][WINRAW]: Resizing RECT for absolute coordinates to match new resolution - %dx%d\n", right ,bottom);
wr->active_rect = wr->prev_rect;
winraw_init_mouse_xy_mapping(wr);
wr->rect_delay = 0;
}
Ver 0.9.2 SR2 (Switchres API) Implimantation Fixed SR close match refresh bug. Added menu high resolution option. Fixed desktop restore bug cuusing endless resolution change requests. Fixed file conflicts Added destop restore resolution back in for manu only. Pulled Switchres fixes. Added better PI rsolution support. Ver 0.7 SR2 (Switchres API) Implimantation Removed HH experimetal check. This is better done via teh switchres.ini at present. Fixed refresh rate bug. Now new resolution and refesh is added correctly. Removed SR deinit from menu restore. Meanu now stays at last content resolution. Ver 0.6.2 SR2 (Switchres API) Implimantation Fixed super resolution bug casuing abnormal video size and aspect ratio Fixed logging issue casuing seg falts on RA exit Ver 0.6 SR2 (Switchres API) Implimantation Ver 0.2 SR2 (Switchres API) Implimantation Added forced super resolutions. Added Multi-monitor/monitor selection support. Added desktop resolution restore when switching back to menu only. Added new menu items for 31KHz standard and 120hz monitor profiles. Added new menu item INI. load monitor profile from switchrss.ini. Fixed winraw driver. Coordinates new refreshed after a resolution change. Fixed Menu aspect ratio in super resolutions. Removed static glabals. These have been added to videocrt_switch struct. Ver 0.1 SR2 (Switchres API) Implimantation Removed old CRTSwitchRes method. Added new SR2 API implimantaion. Resolution swithcing is now done by switchres libs. Both Linux and Windows working with native and super resolutions. Working multi-monitor support with monitor index selection. Working 31KHz support with standard and 120Hxz modes. The monitor index selection is still done via the RA UI. Only choose native and 15KHz form the CRT options in the RA UI as all options are now set in the switchres.ini. All other CRT optoins in the RA UI currently do nothing. Added SR wrapper to fix compile issues. Added back RPi functionality Fixed windows resize/scaling issues on resolution change Thanks @Calamity no more need for crt_switch_driver_refresh() Fix broken case after prevous commit Monitor preset options 15/31KHz now active. Added new meu option. Moitor persets can now be choosen fom the RA UI. 15KHz and 31KHz will set arcade_15 and aracde_31 respectivly. New option INI, if this is chosen your monitor preset will be selected from your switchres.ini file. Added 3KHhz, 120Hz. for old RA users. Renamed 31KHz to 31 KHz, Standard Fixed winraw input coordinates after switching resolution. Code cleanup Fixed menu aspect ratio issue Added menu resolution restore after closing content Fixed aspect ratio after menu resolution restore. code clean up Fxed menu Resulition Restore Aspect Ratio. When SR uses non integer scalled resolution. super width bug with restoring menu resolution fix added super resolution check after setting desktop resolutoion variables when menu active only sr_deinit() used to restore desktop mode. Fixed menu sr_deinit bug. now setting sr_active false Removed static globals, added them to video_switch struct Fixex compile bug due to comment // Fixed compile issues doe to c++ comments in teh switchres_wrapper.h Temporarily removed SR2 logging to fix compile isses for c90 added logging back in. Removed support for winnt and osx Added define for C89. Disabled SR if defined C89 Removed all RA compile fixes fro C89 C90 etc. Swithing now working again. Put Switchres behind HAVE_SR2. HAVE_SR2=no by default. --enable-sr2 Ver 0.5 SR2 Implimentation. Ver 0.4 SR2 Implimantation. Bake SR inside RA Removed temporary log files Disable switchres when C89/C99 builds. Removed C89 and C90 checks for SR Fixed switchres_wrapper.h location Ver 0.3 SR2 Implimenation Dissable logging for C89 __STDC__ Fix For RPi fixed missing EOL fixed RPi function definition added vidrocrt_switch stuct to RPI funcion fixed xoffset for RPi Removed old RPi function call SR disabled for videocore until VC4 switching ported Reverted back to state 5c8a56c Bake SR inside RA Use native win32 api for threads. Fix static lib linking LIBERROR would be defined twice otherwise + improper function names prefixed by __imp_ Added lidstc++ to makefile.common for switchres Fixed RPi switching. Disabled Switchres for videocore unill it is ported. removed RAA.log. Should not exist Added check for when SR fails to set mode with an aspect ratio fix. added video driver re init for RPi GB, GBA and GBC core check, adjusted reseolutions and scale. Please turn on integer scalling in the RA UI Added logas back in. Checking STDC verstion >= C11 Fixed c89 for loop declaration. Code clean up. Added new functions Fix resolution switching bug introduces with HH code clean up. Fixed menu restore bug on closw content after code clean up Moved SR logging to relevant RA logs Update makefile. Checks for X11 and xrandr fixed makefile Use native win32 api for threads. Fix static lib linking LIBERROR would be defined twice otherwise + improper function names prefixed by __imp_ Update switchres_wrapper.* header comments Update year copyright DRMKMS: build only if libdrm has the required version XRANDR: build only if xrandr is available Simplified maklefile Fixed RPI compile error with unsued functions. As before Disable Griffin. No switching support available. Never has been Removed log file 1 Added Win32 static define Added SR source Removed Videocore check on destroy SR Moved SR deinit to trigger earlier on RA exit. Fixed compile error after upstream rebase Fixed aspect ration bug cused by super resolutions. Temporarily disbabled SR logging Re inabled runtim eSR loggind. Disableed all RARCH logging on retro_deinit_drivers Removed srdeinit from menu restore. Menu stays in current reolution until a fix can be found Fixed refresh rate changes when no reolution change is detected. Forgot to add teh resolution cahge in with the refresh change oops Fixed endless no detection log. Removed HH check. This can been better adjusted using the switchres.ini fixed compile issue Added better PI crt switching and fixed typo Pulled Swicthres fixes. Updated desktop restore resolution. removed unused makefile Lockec menu refresh to 60hz fixed missing new line Fixed file conflicts Forced 640x480@60 for menu Added high resolution menu option Removed item logg checker Fixed typos Removed unused functions Fixed SR close match refesh bug. Fixed typo
2021-05-11 02:08:15 -07:00
}
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);
2020-09-05 08:35:33 +02:00
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);
if (!GetCursorPos(&crs_pos))
2021-08-07 04:31:32 +03:00
RARCH_DBG("[WINRAW]: GetCursorPos failed with error %lu.\n", GetLastError());
else if (!ScreenToClient((HWND)video_driver_window_get(), &crs_pos))
2021-08-07 04:31:32 +03:00
RARCH_DBG("[WINRAW]: ScreenToClient failed with error %lu.\n", GetLastError());
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;
else if (state->usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP)
2021-11-06 15:07:35 +01:00
mouse->btn_m = false;
if (state->usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN)
2021-11-06 15:07:35 +01:00
mouse->btn_r = true;
else if (state->usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP)
2021-11-06 15:07:35 +01:00
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;
unsigned mcode, flags, kdown;
2020-06-11 05:15:36 +02:00
static uint8_t data[1024];
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);
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:
mcode = ri->data.keyboard.MakeCode;
2021-03-20 00:58:11 +02:00
flags = ri->data.keyboard.Flags;
kdown = (flags & RI_KEY_BREAK) ? 0 : 1;
2021-03-20 00:58:11 +02: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
/* 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
/* Ignored scancodes */
switch (mcode)
2021-03-20 00:58:11 +02:00
{
case 0xE11D:
case 0xE02A:
case 0xE036:
case 0xE0AA:
case 0xE0B6:
return 0;
2021-03-20 00:58:11 +02: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:
for (i = 0; i < wr->mouse_cnt; ++i)
{
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;
}
}
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;
2021-02-09 18:34:01 +02:00
if (!winraw_set_mouse_input(wr->window))
goto error;
SetWindowLongPtr(wr->window, GWLP_USERDATA, (LONG_PTR)wr);
return wr;
error:
if (wr && wr->window)
{
2021-02-09 18:34:01 +02:00
winraw_set_mouse_input(NULL);
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;
2021-11-06 15:07:35 +01:00
winraw_input_t *wr = (winraw_input_t*)data;
for (i = 0; i < wr->mouse_cnt; ++i)
{
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;
}
/* 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))
{
wr->keyboard.keys[SC_LALT] = 0;
input_keyboard_event(0,
input_keymaps_translate_keysym_to_rk(SC_LALT),
0, 0, RETRO_DEVICE_KEYBOARD);
}
}
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,
const retro_keybind_set *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)
2021-08-06 23:12:38 +03:00
|| (device == RETRO_DEVICE_LIGHTGUN)
|| (device == RETRO_DEVICE_POINTER);
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:
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;
}
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-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;
}
}
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;
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;
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;
case RETRO_DEVICE_LIGHTGUN:
2021-08-07 04:31:32 +03:00
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;
2021-08-07 04:31:32 +03:00
/*buttons*/
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:
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;
}
return 0;
}
#if !defined(_XBOX)
2021-08-07 04:31:32 +03:00
bool winraw_handle_message(UINT msg,
WPARAM wpar, LPARAM lpar)
{
2021-08-07 04:31:32 +03:00
switch (msg)
{
case WM_SETFOCUS:
winraw_focus = true;
break;
case WM_KILLFOCUS:
winraw_focus = false;
break;
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-07 04:31:32 +03:00
PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lpar;
if (pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
2021-08-07 04:31:32 +03:00
joypad_driver_reinit(NULL, NULL);
}
#endif
break;
}
return false;
}
#endif
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;
2021-02-09 18:34:01 +02:00
winraw_set_mouse_input(NULL);
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) |
2021-08-06 23:12:38 +03:00
(1 << RETRO_DEVICE_POINTER) |
(1 << RETRO_DEVICE_LIGHTGUN);
}
static void winraw_grab_mouse(void *d, bool state)
{
winraw_input_t *wr = (winraw_input_t*)d;
if (state == wr->mouse_grab)
return;
2021-02-09 18:34:01 +02:00
if (!winraw_set_mouse_input(wr->window))
return;
wr->mouse_grab = state;
#ifndef _XBOX
win32_clip_window(state);
#endif
}
input_driver_t input_winraw = {
winraw_init,
winraw_poll,
winraw_input_state,
winraw_free,
NULL,
NULL,
winraw_get_capabilities,
"raw",
winraw_grab_mouse,
NULL
};