Relative motion based on raw input for Windows

This commit is contained in:
Mikko Mustonen 2018-07-27 19:32:27 +03:00
parent 3f01f40e91
commit dcbbc445db
2 changed files with 72 additions and 0 deletions

View file

@ -387,7 +387,63 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
input->set_mouse_in_window(false); input->set_mouse_in_window(false);
} break; } break;
case WM_INPUT: {
if (mouse_mode != MOUSE_MODE_CAPTURED || !use_raw_input) {
break;
}
UINT dwSize;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
LPBYTE lpb = new BYTE[dwSize];
if (lpb == NULL) {
return 0;
}
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize)
OutputDebugString(TEXT("GetRawInputData does not return correct size !\n"));
RAWINPUT *raw = (RAWINPUT *)lpb;
if (raw->header.dwType == RIM_TYPEMOUSE) {
Ref<InputEventMouseMotion> mm;
mm.instance();
mm->set_control(control_mem);
mm->set_shift(shift_mem);
mm->set_alt(alt_mem);
mm->set_button_mask(last_button_state);
Point2i c(video_mode.width / 2, video_mode.height / 2);
// centering just so it works as before
POINT pos = { (int)c.x, (int)c.y };
ClientToScreen(hWnd, &pos);
SetCursorPos(pos.x, pos.y);
mm->set_position(c);
mm->set_global_position(c);
input->set_mouse_position(c);
mm->set_speed(Vector2(0, 0));
if (raw->data.mouse.usFlags == 0) {
mm->set_relative(Vector2(raw->data.mouse.lLastX, raw->data.mouse.lLastY));
} else if (raw->data.mouse.usFlags == 1) {
mm->set_relative(Vector2(raw->data.mouse.lLastX, raw->data.mouse.lLastY) - last_absolute_position);
last_absolute_position = Vector2(raw->data.mouse.lLastX, raw->data.mouse.lLastY);
}
if (window_has_focus && main_loop)
input->parse_input_event(mm);
}
delete[] lpb;
} break;
case WM_MOUSEMOVE: { case WM_MOUSEMOVE: {
if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) {
break;
}
if (input->is_emulating_mouse_from_touch()) { if (input->is_emulating_mouse_from_touch()) {
// Universal translation enabled; ignore OS translation // Universal translation enabled; ignore OS translation
@ -1066,6 +1122,20 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
return ERR_UNAVAILABLE; return ERR_UNAVAILABLE;
} }
use_raw_input = true;
RAWINPUTDEVICE Rid[1];
Rid[0].usUsagePage = 0x01;
Rid[0].usUsage = 0x02;
Rid[0].dwFlags = 0;
Rid[0].hwndTarget = 0;
if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE) {
//registration failed.
use_raw_input = false;
}
pre_fs_valid = true; pre_fs_valid = true;
if (video_mode.fullscreen) { if (video_mode.fullscreen) {

View file

@ -125,6 +125,8 @@ class OS_Windows : public OS {
bool force_quit; bool force_quit;
bool window_has_focus; bool window_has_focus;
uint32_t last_button_state; uint32_t last_button_state;
Vector2 last_absolute_position;
bool use_raw_input;
HCURSOR cursors[CURSOR_MAX] = { NULL }; HCURSOR cursors[CURSOR_MAX] = { NULL };
CursorShape cursor_shape; CursorShape cursor_shape;