mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
rawinput, touch: attempt to remove touchscreens injecting mouse events (#687)
## Link to GitHub Issue or related Pull Request, if one exists Fixes #562 ## Description of change ### rawinput touch fixes In rawinput touch handler, if the mouse events (`WM_LBUTTONDOWN`, `WM_MOUSEMOVE`, `WM_LBUTTONUP`) originated from a touch screen, drop them on the floor instead of treating them as touch events. This is an attempt to fix phantom touch issues we see with some screens. Fix another issue where, if mouse is clicked inside the window, and then dragged outside the window and button is released, touch point (id 0) continues to be held. ### wintouchemu fixes If we detected a touch input recently (500ms), ignore new mouse clicks. This isn't perfect, but hopefully it helps with filtering out mouse clicks originating from touch screens. Also, switch over to detecting the primary mouse button correctly, not just the left mouse button. ### notes Future investigation: are there really touchscreens that report a mouse HID capability & insert mouse events? We could have a way to filter them at rawinput level but it'll be ugly. ## Testing Tried jubeat, beatstream..
This commit is contained in:
+66
-49
@@ -67,6 +67,8 @@ static const char *LOG_MODULE_NAME = "touch";
|
||||
|
||||
static TouchHandler *TOUCH_HANDLER = nullptr;
|
||||
|
||||
static bool is_mouse_message_from_touchscreen();
|
||||
|
||||
TouchHandler::TouchHandler(std::string name) {
|
||||
log_info("touch", "Using touch handler: {}", name);
|
||||
}
|
||||
@@ -215,6 +217,30 @@ void update_card_button() {
|
||||
}
|
||||
}
|
||||
|
||||
static void release_all_mouse_touch_points() {
|
||||
std::lock_guard<std::mutex> lock_points(TOUCH_POINTS_M);
|
||||
std::lock_guard<std::mutex> lock_events(TOUCH_EVENTS_M);
|
||||
|
||||
for (size_t x = 0; x < TOUCH_POINTS.size();) {
|
||||
TouchPoint *tp = &TOUCH_POINTS[x];
|
||||
|
||||
if (tp->id == 0u) {
|
||||
TouchEvent te {
|
||||
.id = tp->id,
|
||||
.x = tp->x,
|
||||
.y = tp->y,
|
||||
.type = TOUCH_UP,
|
||||
.mouse = tp->mouse,
|
||||
};
|
||||
add_touch_event(&te);
|
||||
|
||||
TOUCH_POINTS.erase(TOUCH_POINTS.begin() + x);
|
||||
} else {
|
||||
x++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK SpiceTouchWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||
|
||||
// check if touch was registered
|
||||
@@ -490,35 +516,22 @@ static LRESULT CALLBACK SpiceTouchWndProc(HWND hWnd, UINT msg, WPARAM wParam, LP
|
||||
// parse mouse messages
|
||||
switch (msg) {
|
||||
case WM_LBUTTONDOWN: {
|
||||
|
||||
// check if mouse is enabled
|
||||
if (SPICETOUCH_ENABLE_MOUSE) {
|
||||
if (is_mouse_message_from_touchscreen()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// subscribe to mouse messages even when the cursor leaves the window
|
||||
SetCapture(hWnd);
|
||||
|
||||
// release all old events before inserting a new one
|
||||
release_all_mouse_touch_points();
|
||||
|
||||
// lock touch points
|
||||
std::lock_guard<std::mutex> lock_points(TOUCH_POINTS_M);
|
||||
std::lock_guard<std::mutex> lock_events(TOUCH_EVENTS_M);
|
||||
|
||||
// remove all points with ID 0
|
||||
for (size_t x = 0; x < TOUCH_POINTS.size(); x++) {
|
||||
TouchPoint *tp = &TOUCH_POINTS[x];
|
||||
|
||||
if (tp->id == 0u) {
|
||||
|
||||
// generate touch up event
|
||||
TouchEvent te {
|
||||
.id = tp->id,
|
||||
.x = tp->x,
|
||||
.y = tp->y,
|
||||
.type = TOUCH_UP,
|
||||
.mouse = tp->mouse,
|
||||
};
|
||||
add_touch_event(&te);
|
||||
|
||||
// erase touch point
|
||||
TOUCH_POINTS.erase(TOUCH_POINTS.begin() + x);
|
||||
}
|
||||
}
|
||||
|
||||
// create touch point
|
||||
TouchPoint tp {
|
||||
.id = 0,
|
||||
@@ -545,9 +558,11 @@ static LRESULT CALLBACK SpiceTouchWndProc(HWND hWnd, UINT msg, WPARAM wParam, LP
|
||||
break;
|
||||
}
|
||||
case WM_MOUSEMOVE: {
|
||||
|
||||
// check if mouse is enabled
|
||||
if (SPICETOUCH_ENABLE_MOUSE) {
|
||||
if (is_mouse_message_from_touchscreen()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// lock touch points
|
||||
std::lock_guard<std::mutex> lock_points(TOUCH_POINTS_M);
|
||||
@@ -582,40 +597,31 @@ static LRESULT CALLBACK SpiceTouchWndProc(HWND hWnd, UINT msg, WPARAM wParam, LP
|
||||
break;
|
||||
}
|
||||
case WM_LBUTTONUP: {
|
||||
|
||||
// check if mouse is enabled
|
||||
if (SPICETOUCH_ENABLE_MOUSE) {
|
||||
if (is_mouse_message_from_touchscreen()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// lock touch points
|
||||
std::lock_guard<std::mutex> lock_points(TOUCH_POINTS_M);
|
||||
std::lock_guard<std::mutex> lock_events(TOUCH_EVENTS_M);
|
||||
|
||||
// remove all points with ID 0
|
||||
for (size_t x = 0; x < TOUCH_POINTS.size(); x++) {
|
||||
TouchPoint *tp = &TOUCH_POINTS[x];
|
||||
|
||||
if (tp->id == 0u) {
|
||||
|
||||
// generate touch up event
|
||||
TouchEvent te {
|
||||
.id = tp->id,
|
||||
.x = tp->x,
|
||||
.y = tp->y,
|
||||
.type = TOUCH_UP,
|
||||
.mouse = tp->mouse,
|
||||
};
|
||||
add_touch_event(&te);
|
||||
|
||||
// remove touch point
|
||||
TOUCH_POINTS.erase(TOUCH_POINTS.begin() + x);
|
||||
}
|
||||
release_all_mouse_touch_points();
|
||||
if (GetCapture() == hWnd) {
|
||||
ReleaseCapture();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
case WM_CAPTURECHANGED:
|
||||
case WM_CANCELMODE: {
|
||||
// to deal with window losing the capture after SetCapture
|
||||
release_all_mouse_touch_points();
|
||||
if (msg == WM_CANCELMODE && GetCapture() == hWnd) {
|
||||
ReleaseCapture();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// call original function
|
||||
if (SPICETOUCH_CALL_OLD_PROC && SPICETOUCH_OLD_PROC != nullptr) {
|
||||
return SPICETOUCH_OLD_PROC(hWnd, msg, wParam, lParam);
|
||||
@@ -663,6 +669,8 @@ void touch_attach_dx_hook() {
|
||||
// initialize touch handler
|
||||
touch_initialize();
|
||||
|
||||
log_info("touch", "touch_attach_dx_hook: attaching SpiceTouchWndProc...");
|
||||
|
||||
// add dx hook
|
||||
graphics_add_wnd_proc(SpiceTouchWndProc);
|
||||
|
||||
@@ -681,6 +689,8 @@ void touch_create_wnd(HWND hWnd, bool overlay) {
|
||||
// initialize touch handler
|
||||
touch_initialize();
|
||||
|
||||
log_info("touch", "touch_create_wnd: creating SPICETOUCH_TOUCH_THREAD...");
|
||||
|
||||
// create thread
|
||||
SPICETOUCH_TOUCH_THREAD = new std::thread([hWnd, overlay]() {
|
||||
|
||||
@@ -956,4 +966,11 @@ void update_spicetouch_window_dimensions(HWND hWnd) {
|
||||
SPICETOUCH_TOUCH_Y = topleft.y;
|
||||
SPICETOUCH_TOUCH_WIDTH = bottomright.x - topleft.x;
|
||||
SPICETOUCH_TOUCH_HEIGHT = bottomright.y - topleft.y;
|
||||
}
|
||||
}
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/tablet/system-events-and-mouse-messages
|
||||
static bool is_mouse_message_from_touchscreen() {
|
||||
constexpr ULONG_PTR MI_WP_SIGNATURE = 0xFF515700;
|
||||
constexpr ULONG_PTR SIGNATURE_MASK = 0xFFFFFF00;
|
||||
return (GetMessageExtraInfo() & SIGNATURE_MASK) == MI_WP_SIGNATURE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user