Explorar o código

Merge pull request #20523 from moiman100/windows-raw-input

Raw input relative motion for Windows
Juan Linietsky %!s(int64=7) %!d(string=hai) anos
pai
achega
106e5a8d5e
Modificáronse 2 ficheiros con 72 adicións e 0 borrados
  1. 70 0
      platform/windows/os_windows.cpp
  2. 2 0
      platform/windows/os_windows.h

+ 70 - 0
platform/windows/os_windows.cpp

@@ -409,7 +409,63 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 				input->set_mouse_in_window(false);
 
 		} 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: {
+			if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) {
+				break;
+			}
 
 			if (input->is_emulating_mouse_from_touch()) {
 				// Universal translation enabled; ignore OS translation
@@ -1088,6 +1144,20 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
 		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;
 	if (video_mode.fullscreen) {
 

+ 2 - 0
platform/windows/os_windows.h

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