2010-05-02 23:27:30 +00:00
|
|
|
#define WIN32_LEAN_AND_MEAN
|
2010-05-03 01:03:06 +00:00
|
|
|
#define _WIN32_WINNT 0x0501
|
2010-05-02 23:27:30 +00:00
|
|
|
#include <windows.h>
|
|
|
|
#include "rawinput.h"
|
|
|
|
#include "winlayer.h"
|
|
|
|
#include "scancodes.h"
|
|
|
|
#include "build.h"
|
|
|
|
|
2010-05-07 20:45:40 +00:00
|
|
|
static BOOL rawinput_started = 0;
|
2010-05-05 07:31:38 +00:00
|
|
|
static uint8_t KeyboardState[256] = {0}; // VKeys
|
2010-05-02 23:27:30 +00:00
|
|
|
static int8_t MWheel = 0;
|
|
|
|
|
|
|
|
extern volatile uint8_t moustat, mousegrab;
|
|
|
|
extern uint32_t mousewheel[2];
|
2010-05-03 08:30:25 +00:00
|
|
|
extern void SetKey(int32_t key, int32_t state);
|
2010-05-02 23:27:30 +00:00
|
|
|
|
|
|
|
#define MASK_DOWN (1<<(i<<1))
|
|
|
|
#define MASK_UP (MASK_DOWN<<1)
|
|
|
|
#define MouseWheelFakePressTime 50
|
2010-05-03 08:30:25 +00:00
|
|
|
#ifndef GET_RAWINPUT_CODE_WPARAM
|
2010-05-05 07:31:38 +00:00
|
|
|
#define GET_RAWINPUT_CODE_WPARAM(wParam) ((wParam) & 0xff)
|
2010-05-03 08:30:25 +00:00
|
|
|
#endif
|
|
|
|
|
2010-05-05 07:31:38 +00:00
|
|
|
static inline void RI_ProcessMouse(const RAWMOUSE* rmouse)
|
2010-05-02 23:27:30 +00:00
|
|
|
{
|
|
|
|
int32_t i, mask;
|
|
|
|
|
2010-05-08 20:15:24 +00:00
|
|
|
if (!mousegrab || !appactive)
|
2010-05-02 23:27:30 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
mousex += rmouse->lLastX;
|
|
|
|
mousey += 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);
|
|
|
|
|
|
|
|
mousex -= pos.x;
|
|
|
|
mousey -= pos.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0, mask = 1; i < 4; i++)
|
|
|
|
{
|
|
|
|
if (rmouse->usButtonFlags & mask) // button down
|
|
|
|
{
|
|
|
|
if (mousepresscallback)
|
2010-05-05 07:31:38 +00:00
|
|
|
mousepresscallback(i, 1);
|
2010-05-02 23:27:30 +00:00
|
|
|
mouseb |= 1<<i;
|
|
|
|
}
|
|
|
|
else if (rmouse->usButtonFlags & (mask<<1)) // button up
|
|
|
|
{
|
|
|
|
if (mousepresscallback)
|
2010-05-05 07:31:38 +00:00
|
|
|
mousepresscallback(i, 0);
|
2010-05-02 23:27:30 +00:00
|
|
|
mouseb &= ~(1<<i);
|
|
|
|
}
|
|
|
|
mask <<= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
MWheel = (rmouse->usButtonFlags & RI_MOUSE_WHEEL) ? rmouse->usButtonData : 0;
|
|
|
|
|
|
|
|
if (MWheel > 0) // wheel up
|
|
|
|
{
|
|
|
|
if (mousewheel[0] > 0 && mousepresscallback) mousepresscallback(5,0);
|
|
|
|
mousewheel[0] = getticks();
|
|
|
|
mouseb |= 16;
|
|
|
|
if (mousepresscallback) mousepresscallback(5, 1);
|
|
|
|
}
|
|
|
|
else if (MWheel < 0) // wheel down
|
|
|
|
{
|
|
|
|
if (mousewheel[1] > 0 && mousepresscallback) mousepresscallback(6,0);
|
|
|
|
mousewheel[1] = getticks();
|
|
|
|
mouseb |= 32;
|
|
|
|
if (mousepresscallback) mousepresscallback(6, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-05 07:31:38 +00:00
|
|
|
static inline void RI_ProcessKeyboard(const RAWKEYBOARD* rkbd)
|
2010-05-02 23:27:30 +00:00
|
|
|
{
|
2010-05-05 07:31:38 +00:00
|
|
|
uint8_t key = rkbd->MakeCode, VKey = rkbd->VKey;
|
2010-05-02 23:27:30 +00:00
|
|
|
|
|
|
|
// 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:
|
2010-05-03 10:32:38 +00:00
|
|
|
case VK_NUMPAD8:
|
|
|
|
if (rkbd->Flags & RI_KEY_E0) VKey = VK_UP, key = sc_UpArrow;
|
2010-05-05 07:31:38 +00:00
|
|
|
else VKey = VK_NUMPAD8, key = sc_kpad_8; break;
|
2010-05-02 23:27:30 +00:00
|
|
|
case VK_DOWN:
|
2010-05-03 10:32:38 +00:00
|
|
|
case VK_NUMPAD2:
|
|
|
|
if (rkbd->Flags & RI_KEY_E0) VKey = VK_DOWN, key = sc_DownArrow;
|
2010-05-05 07:31:38 +00:00
|
|
|
else VKey = VK_NUMPAD2, key = sc_kpad_2; break;
|
2010-05-02 23:27:30 +00:00
|
|
|
case VK_LEFT:
|
2010-05-03 10:32:38 +00:00
|
|
|
case VK_NUMPAD4:
|
|
|
|
if (rkbd->Flags & RI_KEY_E0) VKey = VK_LEFT, key = sc_LeftArrow;
|
2010-05-05 07:31:38 +00:00
|
|
|
else VKey = VK_NUMPAD4, key = sc_kpad_4; break;
|
2010-05-02 23:27:30 +00:00
|
|
|
case VK_RIGHT:
|
2010-05-03 10:32:38 +00:00
|
|
|
case VK_NUMPAD6:
|
|
|
|
if (rkbd->Flags & RI_KEY_E0) VKey = VK_RIGHT, key = sc_RightArrow;
|
2010-05-05 07:31:38 +00:00
|
|
|
else VKey = VK_NUMPAD6, key = sc_kpad_6; break;
|
2010-05-25 10:56:00 +00:00
|
|
|
case VK_DIVIDE:
|
|
|
|
// if (rkbd->Flags & RI_KEY_E0) key = sc_Slash;
|
|
|
|
// else
|
|
|
|
key = sc_kpad_Slash;
|
|
|
|
break;
|
2010-05-02 23:27:30 +00:00
|
|
|
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;
|
2010-05-03 10:32:38 +00:00
|
|
|
case VK_RETURN:
|
|
|
|
if (rkbd->Flags & RI_KEY_E0) key = sc_kpad_Enter; break;
|
2010-05-07 20:45:40 +00:00
|
|
|
case VK_PAUSE:
|
|
|
|
KeyboardState[VKey] = 1 - (rkbd->Flags & RI_KEY_BREAK);
|
|
|
|
if (rkbd->Flags & RI_KEY_BREAK) return;
|
|
|
|
|
|
|
|
SetKey(sc_Pause, 1);
|
|
|
|
|
|
|
|
if (keypresscallback)
|
|
|
|
keypresscallback(sc_Pause, 1);
|
|
|
|
return;
|
2010-05-02 23:27:30 +00:00
|
|
|
}
|
|
|
|
|
2010-05-07 20:45:40 +00:00
|
|
|
KeyboardState[VKey] = 1 - (rkbd->Flags & RI_KEY_BREAK);
|
2010-05-02 23:27:30 +00:00
|
|
|
|
2010-05-07 20:45:40 +00:00
|
|
|
if (OSD_HandleScanCode(key, KeyboardState[VKey] != 0))
|
2010-05-02 23:27:30 +00:00
|
|
|
{
|
2010-05-07 20:45:40 +00:00
|
|
|
SetKey(key, KeyboardState[VKey] != 0);
|
2010-05-02 23:27:30 +00:00
|
|
|
|
|
|
|
if (keypresscallback)
|
2010-05-07 20:45:40 +00:00
|
|
|
keypresscallback(key, KeyboardState[VKey] != 0);
|
2010-05-02 23:27:30 +00:00
|
|
|
}
|
2010-05-07 20:45:40 +00:00
|
|
|
|
|
|
|
if (rkbd->Flags & RI_KEY_BREAK) return;
|
|
|
|
if (((keyasciififoend+1)&(KEYFIFOSIZ-1)) == keyasciififoplc) return;
|
|
|
|
if ((keyasciififoend - keyasciififoplc) > 0) return;
|
|
|
|
|
2010-05-16 22:53:08 +00:00
|
|
|
{
|
|
|
|
uint8_t buf[2];
|
|
|
|
|
|
|
|
if (ToAscii(VKey, key, &KeyboardState[0], (LPWORD)&buf[0], 0) != 1) return;
|
|
|
|
if ((OSD_OSDKey() < 128) && (Btolower(scantoasc[OSD_OSDKey()]) == Btolower(buf[0]))) return;
|
|
|
|
if (OSD_HandleChar(buf[0]) == 0) return;
|
|
|
|
|
|
|
|
keyasciififo[keyasciififoend] = buf[0];
|
|
|
|
keyasciififoend = ((keyasciififoend+1)&(KEYFIFOSIZ-1));
|
|
|
|
}
|
2010-05-02 23:27:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// keyboard is always captured regardless of what we tell this function
|
2010-05-16 22:53:08 +00:00
|
|
|
BOOL RI_CaptureInput(BOOL grab, HWND target)
|
2010-05-02 23:27:30 +00:00
|
|
|
{
|
|
|
|
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;
|
2010-06-07 09:03:16 +00:00
|
|
|
raw[1].dwFlags = 0;
|
2010-05-07 20:45:40 +00:00
|
|
|
raw[1].hwndTarget = target;
|
2010-05-02 23:27:30 +00:00
|
|
|
|
|
|
|
mousegrab = grab;
|
|
|
|
|
|
|
|
return (RegisterRawInputDevices(raw, 2, sizeof(raw[0])) == FALSE);
|
|
|
|
}
|
|
|
|
|
2010-05-16 22:53:08 +00:00
|
|
|
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)
|
2010-05-02 23:27:30 +00:00
|
|
|
{
|
|
|
|
int32_t i;
|
|
|
|
MSG msg;
|
|
|
|
|
2010-05-07 20:45:40 +00:00
|
|
|
if (!rawinput_started)
|
2010-05-02 23:27:30 +00:00
|
|
|
{
|
|
|
|
if (RI_CaptureInput(1, (HWND)win_gethwnd()))
|
|
|
|
return;
|
2010-05-07 20:45:40 +00:00
|
|
|
rawinput_started = 1;
|
2010-05-02 23:27:30 +00:00
|
|
|
}
|
|
|
|
|
2010-05-07 20:45:40 +00:00
|
|
|
// snapshot the whole keyboard state so we can translate key presses into ascii later
|
2010-05-02 23:27:30 +00:00
|
|
|
for (i = 0; i < 256; i++)
|
2010-05-07 20:45:40 +00:00
|
|
|
KeyboardState[i] = GetAsyncKeyState(i) >> 8;
|
2010-05-02 23:27:30 +00:00
|
|
|
|
|
|
|
MWheel = 0;
|
|
|
|
|
2010-05-16 22:53:08 +00:00
|
|
|
while (loop && PeekMessage(&msg, 0, WM_INPUT, WM_INPUT, PM_REMOVE | PM_QS_INPUT))
|
|
|
|
RI_ProcessMessage(&msg);
|
2010-05-02 23:27:30 +00:00
|
|
|
|
2010-05-08 20:15:24 +00:00
|
|
|
if (mousegrab && appactive)
|
2010-05-02 23:27:30 +00:00
|
|
|
{
|
|
|
|
// center the cursor in the window
|
|
|
|
POINT pt = { xdim>>1, ydim>>1 };
|
|
|
|
|
|
|
|
ClientToScreen((HWND)win_gethwnd(), &pt);
|
|
|
|
SetCursorPos(pt.x, pt.y);
|
|
|
|
|
|
|
|
// do this here because we only want the wheel to signal once, but hold the state for a moment
|
|
|
|
if (mousewheel[0] > 0 && getticks() - mousewheel[0] > MouseWheelFakePressTime)
|
|
|
|
{
|
|
|
|
if (mousepresscallback) mousepresscallback(5,0);
|
|
|
|
mousewheel[0] = 0; mouseb &= ~16;
|
|
|
|
}
|
|
|
|
if (mousewheel[1] > 0 && getticks() - mousewheel[1] > MouseWheelFakePressTime)
|
|
|
|
{
|
|
|
|
if (mousepresscallback) mousepresscallback(6,0);
|
|
|
|
mousewheel[1] = 0; mouseb &= ~32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t initmouse(void)
|
|
|
|
{
|
|
|
|
if (moustat) return 0;
|
|
|
|
grabmouse(moustat = 1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void uninitmouse(void)
|
|
|
|
{
|
|
|
|
if (!moustat) return;
|
|
|
|
grabmouse(moustat = 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void grabmouse(char a)
|
|
|
|
{
|
|
|
|
static POINT pos;
|
|
|
|
static int32_t d = 0;
|
|
|
|
|
|
|
|
if (!moustat) return;
|
|
|
|
|
|
|
|
if (!mousegrab || !d)
|
|
|
|
{
|
|
|
|
GetCursorPos(&pos);
|
2010-05-05 07:31:38 +00:00
|
|
|
d++;
|
2010-05-02 23:27:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ShowCursor(a == 0);
|
|
|
|
RI_CaptureInput(a, (HWND)win_gethwnd());
|
|
|
|
SetCursorPos(pos.x, pos.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
void readmousexy(int32_t *x, int32_t *y)
|
|
|
|
{
|
|
|
|
if (!moustat || !mousegrab) { *x = *y = 0; return; }
|
|
|
|
*x = mousex;
|
|
|
|
mousex = 0;
|
|
|
|
*y = mousey;
|
|
|
|
mousey = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void readmousebstatus(int32_t *b)
|
|
|
|
{
|
|
|
|
if (!moustat || !mousegrab) { *b = 0; return; }
|
|
|
|
*b = mouseb;
|
|
|
|
}
|
|
|
|
|