raze/source/build/src/rawinput.cpp
terminx 5164ab4a25 More control/input cleanup
git-svn-id: https://svn.eduke32.com/eduke32@7181 1a8010ca-5511-0410-912e-c29ae57300e0
2018-11-18 18:08:53 +00:00

315 lines
7.8 KiB
C++

#include "windows_inc.h"
#include "compat.h"
#include "rawinput.h"
#include "winlayer.h"
#include "scancodes.h"
#include "build.h"
static BOOL rawinput_started = 0;
static uint8_t KeyboardState[256] = {0}; // VKeys
extern bool g_mouseEnabled, g_mouseGrabbed;
extern void keySetState(int32_t key, int32_t state);
//#define MASK_DOWN (1<<(i<<1))
//#define MASK_UP (MASK_DOWN<<1)
#ifndef GET_RAWINPUT_CODE_WPARAM
#define GET_RAWINPUT_CODE_WPARAM(wParam) ((wParam) & 0xff)
#endif
static inline void RI_ProcessMouse(const RAWMOUSE *rmouse)
{
int32_t i, mask;
int8_t MWheel = 0;
if (!g_mouseGrabbed || !appactive)
return;
g_mousePos.x += rmouse->lLastX;
g_mousePos.y += rmouse->lLastY;
if (rmouse->usFlags & MOUSE_MOVE_ABSOLUTE)
{
// untested... maybe devices like wacom tablets set this flag?
POINT pos = { xdim>>1, ydim>>1 };
ClientToScreen((HWND)win_gethwnd(), &pos);
g_mousePos.x -= pos.x;
g_mousePos.y -= pos.y;
}
for (i = 0, mask = (1<<0); mask <= (1<<8); i++, mask<<=2)
{
// usButtonFlags:
// 1<<0: left down -> 1 / 1<<0
// 1<<2: middle down -> 2 / 1<<1
// 1<<4: right down -> 3 / 1<<2
// 1<<6: x1 down -> 4 / 1<<3
// ----------- mwheel here
// 1<<8: x2 down -> 7 / 1<<6
if (mask == 1<<8)
i = 6;
if (rmouse->usButtonFlags & mask) // button down
{
if (g_mouseCallback)
g_mouseCallback(i+1, 1);
g_mouseBits |= 1<<i;
}
else if (rmouse->usButtonFlags & (mask<<1)) // button up
{
if (g_mouseCallback)
g_mouseCallback(i+1, 0);
g_mouseBits &= ~(1<<i);
}
}
MWheel = (rmouse->usButtonFlags & RI_MOUSE_WHEEL) ? rmouse->usButtonData : 0;
if (MWheel > 0) // wheel up
{
g_mouseBits |= 16;
if (g_mouseCallback) g_mouseCallback(5, 1);
}
else if (MWheel < 0) // wheel down
{
g_mouseBits |= 32;
if (g_mouseCallback) g_mouseCallback(6, 1);
}
}
static inline void RI_ProcessKeyboard(const RAWKEYBOARD *rkbd)
{
uint8_t key = rkbd->MakeCode, VKey = rkbd->VKey;
// for some reason rkbd->MakeCode is wrong for these
// even though rkbd->VKey is right...
switch (VKey)
{
case VK_SHIFT:
if (rkbd->Flags & RI_KEY_E0)
VKey = VK_RSHIFT, key = sc_RightShift;
break;
case VK_CONTROL:
if (rkbd->Flags & RI_KEY_E0)
VKey = VK_RCONTROL, key = sc_RightControl;
break;
case VK_MENU:
if (rkbd->Flags & RI_KEY_E0)
VKey = VK_RMENU, key = sc_RightAlt;
break;
case VK_UP:
case VK_NUMPAD8:
if (rkbd->Flags & RI_KEY_E0)
VKey = VK_UP, key = sc_UpArrow;
else
VKey = VK_NUMPAD8, key = sc_kpad_8;
break;
case VK_DOWN:
case VK_NUMPAD2:
if (rkbd->Flags & RI_KEY_E0)
VKey = VK_DOWN, key = sc_DownArrow;
else
VKey = VK_NUMPAD2, key = sc_kpad_2;
break;
case VK_LEFT:
case VK_NUMPAD4:
if (rkbd->Flags & RI_KEY_E0)
VKey = VK_LEFT, key = sc_LeftArrow;
else
VKey = VK_NUMPAD4, key = sc_kpad_4;
break;
case VK_RIGHT:
case VK_NUMPAD6:
if (rkbd->Flags & RI_KEY_E0)
VKey = VK_RIGHT, key = sc_RightArrow;
else
VKey = VK_NUMPAD6, key = sc_kpad_6;
break;
case VK_DIVIDE:
#if 0
if (rkbd->Flags & RI_KEY_E0)
key = sc_Slash;
else
#endif
key = sc_kpad_Slash;
break;
case VK_INSERT:
key = sc_Insert;
break;
case VK_HOME:
key = sc_Home;
break;
case VK_DELETE:
key = sc_Delete;
break;
case VK_END:
key = sc_End;
break;
case VK_PRIOR:
key = sc_PgUp;
break;
case VK_NEXT:
key = sc_PgDn;
break;
case VK_RETURN:
if (rkbd->Flags & RI_KEY_E0)
key = sc_kpad_Enter;
break;
case VK_PAUSE:
KeyboardState[VKey] = 1 - (rkbd->Flags & RI_KEY_BREAK);
if (rkbd->Flags & RI_KEY_BREAK)
return;
keySetState(sc_Pause, 1);
if (keypresscallback)
keypresscallback(sc_Pause, 1);
case 0xFF:
return;
}
KeyboardState[VKey] = 1 - (rkbd->Flags & RI_KEY_BREAK);
if (OSD_HandleScanCode(key, KeyboardState[VKey] > 0))
{
keySetState(key, KeyboardState[VKey] != 0);
if (keypresscallback)
keypresscallback(key, KeyboardState[VKey] != 0);
}
if (rkbd->Flags & RI_KEY_BREAK) return;
if (((g_keyAsciiEnd+1)&(KEYFIFOSIZ-1)) == g_keyAsciiPos) return;
if ((g_keyAsciiEnd - g_keyAsciiPos) > 0) return;
{
uint8_t buf[2];
if (ToAscii(VKey, key, &KeyboardState[0], (LPWORD)&buf[0], 0) != 1) return;
if ((OSD_OSDKey() < 128) && (Btolower(g_keyAsciiTable[OSD_OSDKey()]) == Btolower(buf[0]))) return;
if (OSD_HandleChar(buf[0]) == 0) return;
g_keyAsciiFIFO[g_keyAsciiEnd] = buf[0];
g_keyAsciiEnd = ((g_keyAsciiEnd+1)&(KEYFIFOSIZ-1));
}
}
// keyboard is always captured regardless of what we tell this function
BOOL RI_CaptureInput(BOOL grab, HWND target)
{
RAWINPUTDEVICE raw[2];
raw[0].usUsagePage = 0x01;
raw[0].usUsage = 0x02;
raw[0].dwFlags = grab ? (RIDEV_NOLEGACY | RIDEV_CAPTUREMOUSE) : 0;
raw[0].hwndTarget = grab ? target : NULL;
raw[1].usUsagePage = 0x01;
raw[1].usUsage = 0x06;
raw[1].dwFlags = 0;
raw[1].hwndTarget = target;
g_mouseGrabbed = grab;
return (RegisterRawInputDevices(raw, 2, sizeof(raw[0])) == FALSE);
}
void RI_ProcessMessage(MSG *msg)
{
if (GET_RAWINPUT_CODE_WPARAM(msg->wParam) == RIM_INPUT)
{
UINT dwSize = sizeof(RAWINPUT);
RAWINPUT raw;
GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, &raw, &dwSize, sizeof(RAWINPUTHEADER));
if (raw.header.dwType == RIM_TYPEKEYBOARD)
RI_ProcessKeyboard(&raw.data.keyboard);
else if (raw.header.dwType == RIM_TYPEMOUSE)
RI_ProcessMouse(&raw.data.mouse);
}
DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
}
void RI_PollDevices(BOOL loop)
{
int32_t i;
MSG msg;
if (!rawinput_started)
{
if (RI_CaptureInput(1, (HWND)win_gethwnd()))
return;
rawinput_started = 1;
}
if (inputchecked)
{
if (g_mouseCallback)
{
if (g_mouseBits & 16)
g_mouseCallback(5, 0);
if (g_mouseBits & 32)
g_mouseCallback(6, 0);
}
g_mouseBits &= ~(16|32);
}
// snapshot the whole keyboard state so we can translate key presses into ascii later
for (i = 0; i < 256; i++)
KeyboardState[i] = GetAsyncKeyState(i) >> 8;
while (loop && PeekMessage(&msg, 0, WM_INPUT, WM_INPUT, PM_REMOVE | PM_QS_INPUT))
RI_ProcessMessage(&msg);
if (g_mouseGrabbed && appactive)
{
// center the cursor in the window
POINT pt = { xdim>>1, ydim>>1 };
ClientToScreen((HWND)win_gethwnd(), &pt);
SetCursorPos(pt.x, pt.y);
}
}
void mouseInit(void)
{
if (!g_mouseEnabled)
mouseGrabInput(g_mouseEnabled = g_mouseLockedToWindow);
}
void mouseUninit(void)
{
if (!g_mouseEnabled) return;
mouseGrabInput(g_mouseEnabled = 0);
}
void mouseGrabInput(bool grab)
{
static POINT pos;
static int32_t d = 0;
if (!g_mouseEnabled) return;
if (!g_mouseGrabbed || !d)
{
GetCursorPos(&pos);
d++;
}
ShowCursor(grab == 0);
RI_CaptureInput(grab, (HWND)win_gethwnd());
SetCursorPos(pos.x, pos.y);
}
void mouseLockToWindow(char a)
{
UNREFERENCED_PARAMETER(a);
}