浏览代码

Improve/fix multitouch on Windows

- Fix logic error.
- Track touches to enable defensive handling and releasing on focus out.
- Change comment-out by preprocessor `#if`.
Pedro J. Estébanez 7 年之前
父节点
当前提交
cb23cc1ca4
共有 2 个文件被更改,包括 45 次插入2 次删除
  1. 42 2
      platform/windows/os_windows.cpp
  2. 3 0
      platform/windows/os_windows.h

+ 42 - 2
platform/windows/os_windows.cpp

@@ -231,6 +231,18 @@ bool OS_Windows::can_draw() const {
 
 
 void OS_Windows::_touch_event(bool p_pressed, int p_x, int p_y, int idx) {
 void OS_Windows::_touch_event(bool p_pressed, int p_x, int p_y, int idx) {
 
 
+#if WINVER >= 0x0601 // for windows 7
+	// Defensive
+	if (touch_state.has(idx) == p_pressed)
+		return;
+
+	if (p_pressed) {
+		touch_state.insert(idx, Point2i(p_x, p_y));
+	} else {
+		touch_state.erase(idx);
+	}
+#endif
+
 	InputEvent event;
 	InputEvent event;
 	event.type = InputEvent::SCREEN_TOUCH;
 	event.type = InputEvent::SCREEN_TOUCH;
 	event.ID = ++last_id;
 	event.ID = ++last_id;
@@ -248,6 +260,18 @@ void OS_Windows::_touch_event(bool p_pressed, int p_x, int p_y, int idx) {
 
 
 void OS_Windows::_drag_event(int p_x, int p_y, int idx) {
 void OS_Windows::_drag_event(int p_x, int p_y, int idx) {
 
 
+#if WINVER >= 0x0601 // for windows 7
+	Map<int, Point2i>::Element *curr = touch_state.find(idx);
+	// Defensive
+	if (!curr)
+		return;
+
+	if (curr->get() == Point2i(p_x, p_y))
+		return;
+
+	curr->get() = Point2i(p_x, p_y);
+#endif
+
 	InputEvent event;
 	InputEvent event;
 	event.type = InputEvent::SCREEN_DRAG;
 	event.type = InputEvent::SCREEN_DRAG;
 	event.ID = ++last_id;
 	event.ID = ++last_id;
@@ -292,6 +316,17 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 			return 0; // Return To The Message Loop
 			return 0; // Return To The Message Loop
 		}
 		}
 
 
+		case WM_KILLFOCUS: {
+
+#if WINVER >= 0x0601 // for windows 7
+			// Release every touch to avoid sticky points
+			for (Map<int, Point2i>::Element *E = touch_state.front(); E; E = E->next()) {
+				_touch_event(false, E->get().x, E->get().y, E->key());
+			}
+			touch_state.clear();
+#endif
+		} break;
+
 		case WM_PAINT:
 		case WM_PAINT:
 
 
 			Main::force_redraw();
 			Main::force_redraw();
@@ -682,7 +717,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 							_drag_event(ti.x / 100, ti.y / 100, ti.dwID);
 							_drag_event(ti.x / 100, ti.y / 100, ti.dwID);
 						} else if (ti.dwFlags & (TOUCHEVENTF_UP | TOUCHEVENTF_DOWN)) {
 						} else if (ti.dwFlags & (TOUCHEVENTF_UP | TOUCHEVENTF_DOWN)) {
 
 
-							_touch_event(ti.dwFlags & TOUCHEVENTF_DOWN != 0, ti.x / 100, ti.y / 100, ti.dwID);
+							_touch_event(ti.dwFlags & TOUCHEVENTF_DOWN, ti.x / 100, ti.y / 100, ti.dwID);
 						};
 						};
 					}
 					}
 					bHandled = TRUE;
 					bHandled = TRUE;
@@ -1080,7 +1115,9 @@ void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
 	tme.dwHoverTime = HOVER_DEFAULT;
 	tme.dwHoverTime = HOVER_DEFAULT;
 	TrackMouseEvent(&tme);
 	TrackMouseEvent(&tme);
 
 
-	//RegisterTouchWindow(hWnd, 0); // Windows 7
+#if WINVER >= 0x0601 // for windows 7
+	RegisterTouchWindow(hWnd, 0); // Windows 7
+#endif
 
 
 	_ensure_data_dir();
 	_ensure_data_dir();
 
 
@@ -1188,6 +1225,9 @@ void OS_Windows::finalize() {
 
 
 	memdelete(joystick);
 	memdelete(joystick);
 	memdelete(input);
 	memdelete(input);
+#if WINVER >= 0x0601 // for windows 7
+	touch_state.clear();
+#endif
 
 
 	visual_server->finish();
 	visual_server->finish();
 	memdelete(visual_server);
 	memdelete(visual_server);

+ 3 - 0
platform/windows/os_windows.h

@@ -130,6 +130,9 @@ class OS_Windows : public OS {
 
 
 	InputDefault *input;
 	InputDefault *input;
 	joystick_windows *joystick;
 	joystick_windows *joystick;
+#if WINVER >= 0x0601 // for windows 7
+	Map<int, Point2i> touch_state;
+#endif
 
 
 #ifdef WASAPI_ENABLED
 #ifdef WASAPI_ENABLED
 	AudioDriverWASAPI driver_wasapi;
 	AudioDriverWASAPI driver_wasapi;