From 00c8bb8ce6adf638b17eaa1bfefe5d4996c838b8 Mon Sep 17 00:00:00 2001 From: bicarus <202771338+bicarus-dev@users.noreply.github.com> Date: Wed, 22 Jul 2026 01:36:06 -0700 Subject: [PATCH] gitadora: use native touch for single-window mode (#828) ## Link to GitHub Issue or related Pull Request, if one exists #814 ## Description of change Make gitadora arena model use native touch instead of wintouchemu. Only single window mode with overlay is affected. This removes the last consumer of `INJECT_MOUSE_AS_WM_TOUCH` so all of that code can be deleted. ## Testing Tested touch screen and mouse interaction with single window mode. --- src/spice2x/games/gitadora/gitadora.cpp | 6 +- src/spice2x/hooks/graphics/graphics.cpp | 17 --- src/spice2x/misc/wintouchemu.cpp | 150 +----------------------- src/spice2x/misc/wintouchemu.h | 2 - 4 files changed, 5 insertions(+), 170 deletions(-) diff --git a/src/spice2x/games/gitadora/gitadora.cpp b/src/spice2x/games/gitadora/gitadora.cpp index b7490a2..2f131d8 100644 --- a/src/spice2x/games/gitadora/gitadora.cpp +++ b/src/spice2x/games/gitadora/gitadora.cpp @@ -11,8 +11,8 @@ #include "hooks/audio/audio.h" #include "hooks/audio/mme.h" #include "hooks/graphics/graphics.h" -#include "misc/wintouchemu.h" #include "overlay/overlay.h" +#include "touch/native/nativetouchhook.h" #include "util/cpuutils.h" #include "util/deferlog.h" #include "util/detour.h" @@ -653,9 +653,7 @@ namespace games::gitadora { // monitor/touch hooks (windowed or full screen) if (GRAPHICS_PREVENT_SECONDARY_WINDOWS) { // enable touch hook for subscreen overlay - wintouchemu::FORCE = true; - wintouchemu::INJECT_MOUSE_AS_WM_TOUCH = true; - wintouchemu::hook("GITADORA", avs::game::DLL_INSTANCE); + nativetouch::hook(avs::game::DLL_INSTANCE); #if !SPICE_XP diff --git a/src/spice2x/hooks/graphics/graphics.cpp b/src/spice2x/hooks/graphics/graphics.cpp index e5bb677..9e96831 100644 --- a/src/spice2x/hooks/graphics/graphics.cpp +++ b/src/spice2x/hooks/graphics/graphics.cpp @@ -28,7 +28,6 @@ #include "util/logging.h" #include "util/fileutils.h" #include "util/utils.h" -#include "misc/wintouchemu.h" #include "touch/native/inject.h" #include "util/time.h" #include "rawinput/rawinput.h" @@ -308,22 +307,6 @@ static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l } } - if (wintouchemu::INJECT_MOUSE_AS_WM_TOUCH) { - // drop mouse inputs since only wintouches should be used - switch (uMsg) { - case WM_MOUSEMOVE: - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - case WM_XBUTTONDOWN: - case WM_XBUTTONUP: - return true; - } - } - // window resize graphics_windowed_wndproc(hWnd, uMsg, wParam, lParam); diff --git a/src/spice2x/misc/wintouchemu.cpp b/src/spice2x/misc/wintouchemu.cpp index 8d419b3..bdb5d13 100644 --- a/src/spice2x/misc/wintouchemu.cpp +++ b/src/spice2x/misc/wintouchemu.cpp @@ -4,31 +4,18 @@ #include "wintouchemu.h" -#include "games/gitadora/gitadora.h" #include "hooks/graphics/graphics.h" #include "overlay/overlay.h" #include "touch/touch.h" #include "util/detour.h" #include "util/logging.h" -#include "util/time.h" #include "util/utils.h" namespace wintouchemu { - typedef struct { - POINT pos; - bool last_button_pressed; - DWORD touch_event; - } mouse_state_t; - // settings bool FORCE = false; - bool INJECT_MOUSE_AS_WM_TOUCH = false; - bool LOG_FPS = false; bool ADD_TOUCH_FLAG_PRIMARY = false; - - // state - double last_touch_event = 0.0; static inline bool is_emu_enabled() { return FORCE || !is_touch_available("wintouchemu::is_emu_enabled") || GRAPHICS_SHOW_CURSOR; @@ -69,13 +56,11 @@ namespace wintouchemu { // state BOOL (WINAPI *GetTouchInputInfo_orig)(HANDLE, UINT, PTOUCHINPUT, int); - bool USE_MOUSE = false; std::vector TOUCH_EVENTS; std::vector TOUCH_POINTS; HMODULE HOOKED_MODULE = nullptr; std::string WINDOW_TITLE_START = ""; bool INITIALIZED = false; - mouse_state_t mouse_state; void hook(const char *window_title, HMODULE module) { @@ -109,7 +94,6 @@ namespace wintouchemu { // set touch inputs bool result = false; - bool mouse_used = false; for (UINT input = 0; input < cInputs; input++) { auto *touch_input = &pInputs[input]; @@ -188,75 +172,6 @@ namespace wintouchemu { touch_input->cxContact = 0; touch_input->cyContact = 0; - } else if (USE_MOUSE && !mouse_used) { - - // disable further mouse inputs this call - mouse_used = true; - - if (mouse_state.touch_event) { - result = true; - touch_input->x = mouse_state.pos.x; - touch_input->y = mouse_state.pos.y; - - if (GRAPHICS_WINDOWED) { - touch_input->x -= SPICETOUCH_TOUCH_X; - touch_input->y -= SPICETOUCH_TOUCH_Y; - } - - // log_misc( - // "wintouchemu", - // "mouse state ({}, {}) event={}", - // to_string(touch_input->x), to_string(touch_input->y), mouse_state.touch_event); - - auto valid = true; - if (overlay::OVERLAY) { - valid = overlay::OVERLAY->transform_touch_point( - &touch_input->x, &touch_input->y); - } - - // touch inputs require 100x precision per pixel - touch_input->x *= 100; - touch_input->y *= 100; - touch_input->hSource = hTouchInput; - touch_input->dwID = 0; - touch_input->dwFlags = 0; - switch (mouse_state.touch_event) { - case TOUCHEVENTF_DOWN: - if (valid) { - if (ADD_TOUCH_FLAG_PRIMARY) { - touch_input->dwFlags |= TOUCHEVENTF_PRIMARY; - } - - touch_input->dwFlags |= TOUCHEVENTF_DOWN; - } - break; - case TOUCHEVENTF_MOVE: - if (valid) { - if (ADD_TOUCH_FLAG_PRIMARY) { - touch_input->dwFlags |= TOUCHEVENTF_PRIMARY; - } - - touch_input->dwFlags |= TOUCHEVENTF_MOVE; - } - break; - case TOUCHEVENTF_UP: - // don't check valid so that this touch ID can be released - if (ADD_TOUCH_FLAG_PRIMARY) { - touch_input->dwFlags |= TOUCHEVENTF_PRIMARY; - } - - touch_input->dwFlags |= TOUCHEVENTF_UP; - break; - } - touch_input->dwMask = 0; - touch_input->dwTime = 0; - touch_input->dwExtraInfo = 0; - touch_input->cxContact = 0; - touch_input->cyContact = 0; - - // reset it since the event was consumed & propagated as touch - mouse_state.touch_event = 0; - } } else { // beatstream requires a MOVE for active points in each update @@ -335,25 +250,13 @@ namespace wintouchemu { // check if windowed if (GRAPHICS_WINDOWED) { - if (games::gitadora::is_arena_model() && GRAPHICS_PREVENT_SECONDARY_WINDOWS) { - log_info("wintouchemu", "use mouse cursor API for gitadora overlay subscreen"); - USE_MOUSE = true; - } else { - // create touch window - create overlay if not yet existing at this point - log_info("wintouchemu", "create touch window relative to main game window"); - touch_create_wnd(hWnd, overlay::ENABLED && !overlay::OVERLAY); - USE_MOUSE = false; - } - } else if (INJECT_MOUSE_AS_WM_TOUCH) { - log_info( - "wintouchemu", - "using raw mouse cursor API in full screen and injecting them as WM_TOUCH events"); - USE_MOUSE = true; + // create touch window - create overlay if not yet existing at this point + log_info("wintouchemu", "create touch window relative to main game window"); + touch_create_wnd(hWnd, overlay::ENABLED && !overlay::OVERLAY); } else { log_info("wintouchemu", "activating DirectX hooks"); // mouse position based input only touch_attach_dx_hook(); - USE_MOUSE = false; } // hooks @@ -364,8 +267,6 @@ namespace wintouchemu { } } - const auto now = get_performance_milliseconds(); - // update touch events if (hWnd != nullptr) { @@ -385,56 +286,11 @@ namespace wintouchemu { // check if new events are available if (event_count > 0) { - last_touch_event = now; - // send fake event to make the game update it's touch inputs auto wndProc = (WNDPROC) GetWindowLongPtr(hWnd, GWLP_WNDPROC); wndProc(hWnd, WM_TOUCH, MAKEWORD(event_count, 0), (LPARAM) GetTouchInputInfoHook); } - // update frame logging - if (LOG_FPS) { - static int log_frames = 0; - static uint64_t log_time = 0; - log_frames++; - if (log_time < get_system_seconds()) { - if (log_time > 0) { - log_info("wintouchemu", "polling at {} touch frames per second", log_frames); - } - log_frames = 0; - log_time = get_system_seconds(); - } - } - } - - // send separate WM_TOUCH event for mouse - // this must be separate from actual touch events because some games will ignore the return - // value from GetTouchInputInfo or fail to read dwFlags for valid events, so it's not OK to - // send empty events when the mouse button is not clicked/released - if (hWnd != nullptr && USE_MOUSE) { - bool button_pressed = get_async_primary_mouse(); - - // if there was a touch event in the last 500 ms, don't insert new button presses - if (button_pressed && (now - last_touch_event) < 500) { - button_pressed = false; - } - - // figure out what kind of touch event to simulate - if (button_pressed && !mouse_state.last_button_pressed) { - mouse_state.touch_event = TOUCHEVENTF_DOWN; - } else if (button_pressed && mouse_state.last_button_pressed) { - mouse_state.touch_event = TOUCHEVENTF_MOVE; - } else if (!button_pressed && mouse_state.last_button_pressed) { - mouse_state.touch_event = TOUCHEVENTF_UP; - } - - mouse_state.last_button_pressed = button_pressed; - if (mouse_state.touch_event) { - GetCursorPos(&mouse_state.pos); - // send fake event to make the game update it's touch inputs - auto wndProc = (WNDPROC) GetWindowLongPtr(hWnd, GWLP_WNDPROC); - wndProc(hWnd, WM_TOUCH, MAKEWORD(1, 0), (LPARAM) GetTouchInputInfoHook); - } } } } diff --git a/src/spice2x/misc/wintouchemu.h b/src/spice2x/misc/wintouchemu.h index 6592913..ef57f38 100644 --- a/src/spice2x/misc/wintouchemu.h +++ b/src/spice2x/misc/wintouchemu.h @@ -6,8 +6,6 @@ namespace wintouchemu { // settings extern bool FORCE; - extern bool INJECT_MOUSE_AS_WM_TOUCH; - extern bool LOG_FPS; extern bool ADD_TOUCH_FLAG_PRIMARY; void hook(const char *window_title, HMODULE module = nullptr);