mirror of
https://gitea.tendokyu.moe/TeamTofuShop/bananatools.git
synced 2026-09-22 22:37:56 +03:00
sao: improve touch hook
This commit is contained in:
@@ -14,3 +14,14 @@ void dvd_config_load(struct dvd_config *cfg, const wchar_t *filename)
|
||||
|
||||
cfg->enable = GetPrivateProfileIntW(L"dvd", L"enable", 1, filename);
|
||||
}
|
||||
|
||||
void touch_screen_config_load(struct touch_screen_config *cfg, const wchar_t *filename)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
cfg->enable = GetPrivateProfileIntW(L"touch", L"enable", 1, filename);
|
||||
cfg->remap = GetPrivateProfileIntW(L"touch", L"remap", 1, filename);
|
||||
cfg->cursor = GetPrivateProfileIntW(L"touch", L"cursor", 1, filename);
|
||||
cfg->setwndptr = GetPrivateProfileIntW(L"touch", L"setwndptr", 0, filename);
|
||||
}
|
||||
|
||||
@@ -3,5 +3,7 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#include "hooklib/dvd.h"
|
||||
#include "hooklib/touch.h"
|
||||
|
||||
void dvd_config_load(struct dvd_config *cfg, const wchar_t *filename);
|
||||
void touch_screen_config_load(struct touch_screen_config *cfg, const wchar_t *filename);
|
||||
|
||||
@@ -26,5 +26,7 @@ hooklib_lib = static_library(
|
||||
'setupapi.h',
|
||||
'spike.c',
|
||||
'spike.h',
|
||||
'touch.c',
|
||||
'touch.h',
|
||||
],
|
||||
)
|
||||
|
||||
+298
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
This part (touch screen hook) is mostly taken from spicetools, which is GPL.
|
||||
This means there can be some license issues if you do use this code in some other places without including source code.
|
||||
*/
|
||||
#include <windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "hook/com-proxy.h"
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "hooklib/config.h"
|
||||
#include "hooklib/dll.h"
|
||||
#include "hooklib/touch.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
/* API hooks */
|
||||
|
||||
static LRESULT hook_wndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
static ATOM WINAPI hook_RegisterClassExA(
|
||||
WNDCLASSEXA* wndClass
|
||||
);
|
||||
|
||||
static int WINAPI hook_GetSystemMetrics(
|
||||
int nIndex
|
||||
);
|
||||
|
||||
static BOOL WINAPI hook_RegisterTouchWindow(
|
||||
HWND hwnd,
|
||||
ULONG ulFlags
|
||||
);
|
||||
|
||||
static BOOL WINAPI hook_GetTouchInputInfo(
|
||||
HANDLE hTouchInput,
|
||||
UINT cInputs,
|
||||
PTOUCHINPUT pInputs,
|
||||
int cbSize
|
||||
);
|
||||
|
||||
static HCURSOR WINAPI hook_SetCursor(HCURSOR cursor);
|
||||
|
||||
static int WINAPI hook_ShowCursor(BOOL bShow);
|
||||
|
||||
static LONG_PTR WINAPI hook_SetWindowLongPtrA(HWND hWnd, int nIndex, LONG_PTR dwNewLong);
|
||||
|
||||
/* Link pointers */
|
||||
|
||||
static ATOM (WINAPI *next_RegisterClassExA)(
|
||||
const WNDCLASSEXA* wndClass
|
||||
);
|
||||
|
||||
static int (WINAPI *next_GetSystemMetrics)(
|
||||
int nIndex
|
||||
);
|
||||
|
||||
static BOOL (WINAPI *next_RegisterTouchWindow)(
|
||||
HWND hwnd,
|
||||
ULONG ulFlags
|
||||
);
|
||||
|
||||
static BOOL (WINAPI *next_GetTouchInputInfo)(
|
||||
HANDLE hTouchInput,
|
||||
UINT cInputs,
|
||||
PTOUCHINPUT pInputs,
|
||||
int cbSize
|
||||
);
|
||||
|
||||
static HCURSOR(WINAPI *next_SetCursor)(HCURSOR cursor);
|
||||
|
||||
static int (WINAPI *next_ShowCursor)(BOOL bShow);
|
||||
|
||||
static LONG_PTR (WINAPI *next_SetWindowLongPtrA)(HWND hWnd, int nIndex, LONG_PTR dwNewLong);
|
||||
|
||||
static bool touch_hook_initted;
|
||||
static bool touch_held;
|
||||
static HWND registered_hWnd;
|
||||
static struct touch_screen_config touch_config;
|
||||
static WNDPROC orig_wndProc;
|
||||
static HCURSOR defaultCursor;
|
||||
|
||||
static const struct hook_symbol touch_hooks[] = {
|
||||
{
|
||||
.name = "RegisterClassExA",
|
||||
.patch = hook_RegisterClassExA,
|
||||
.link = (void**)&next_RegisterClassExA
|
||||
},
|
||||
{
|
||||
.name = "GetSystemMetrics",
|
||||
.patch = hook_GetSystemMetrics,
|
||||
.link = (void **) &next_GetSystemMetrics
|
||||
},
|
||||
{
|
||||
.name = "RegisterTouchWindow",
|
||||
.patch = hook_RegisterTouchWindow,
|
||||
.link = (void **) &next_RegisterTouchWindow
|
||||
},
|
||||
{
|
||||
.name = "GetTouchInputInfo",
|
||||
.patch = hook_GetTouchInputInfo,
|
||||
.link = (void **) &next_GetTouchInputInfo
|
||||
},
|
||||
{
|
||||
.name = "ShowCursor",
|
||||
.patch = hook_ShowCursor,
|
||||
.link = (void **) &next_ShowCursor
|
||||
},
|
||||
{
|
||||
.name = "SetCursor",
|
||||
.patch = hook_SetCursor,
|
||||
.link = (void **) &next_SetCursor
|
||||
},
|
||||
{
|
||||
.name = "SetWindowLongPtrA",
|
||||
.patch = hook_SetWindowLongPtrA,
|
||||
.link = (void**) &next_SetWindowLongPtrA
|
||||
},
|
||||
};
|
||||
|
||||
void touch_screen_hook_init(const struct touch_screen_config *cfg, HINSTANCE self)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
|
||||
if (!cfg->enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (touch_hook_initted) {
|
||||
return;
|
||||
}
|
||||
|
||||
touch_hook_initted = true;
|
||||
|
||||
defaultCursor = LoadCursorA(NULL, IDC_CROSS);
|
||||
|
||||
memcpy(&touch_config, cfg, sizeof(*cfg));
|
||||
touch_hook_insert_hooks(NULL);
|
||||
dprintf("TOUCH: hook enabled.\n");
|
||||
}
|
||||
|
||||
void touch_hook_insert_hooks(HMODULE target)
|
||||
{
|
||||
hook_table_apply(
|
||||
target,
|
||||
"user32.dll",
|
||||
touch_hooks,
|
||||
_countof(touch_hooks));
|
||||
}
|
||||
|
||||
static int WINAPI hook_ShowCursor(BOOL bShow)
|
||||
{
|
||||
if (touch_config.cursor) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return next_ShowCursor(bShow);
|
||||
}
|
||||
|
||||
static HCURSOR WINAPI hook_SetCursor(HCURSOR cursor) {
|
||||
if (cursor == 0 && touch_config.cursor)
|
||||
return next_SetCursor(defaultCursor);
|
||||
|
||||
return next_SetCursor(cursor);
|
||||
}
|
||||
|
||||
// remap mouse events to touch events
|
||||
|
||||
static LRESULT hook_wndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
|
||||
if (hWnd == registered_hWnd && (Msg == WM_LBUTTONDOWN || Msg == WM_LBUTTONUP || (touch_held && Msg == WM_MOUSEMOVE))) {
|
||||
orig_wndProc(hWnd, WM_TOUCH, 1, 1);
|
||||
}
|
||||
|
||||
if (Msg == WM_SETCURSOR && touch_config.cursor) {
|
||||
SetCursor(defaultCursor);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return orig_wndProc(hWnd, Msg, wParam, lParam);
|
||||
}
|
||||
|
||||
static ATOM WINAPI hook_RegisterClassExA(
|
||||
WNDCLASSEXA* wndClass
|
||||
) {
|
||||
if (!touch_config.setwndptr && wndClass->lpfnWndProc) {
|
||||
orig_wndProc = wndClass->lpfnWndProc;
|
||||
wndClass->lpfnWndProc = (WNDPROC) hook_wndProc;
|
||||
}
|
||||
|
||||
return next_RegisterClassExA(wndClass);
|
||||
}
|
||||
|
||||
// Spicetools misc/wintouchemu.cpp
|
||||
|
||||
static int WINAPI hook_GetSystemMetrics(
|
||||
int nIndex
|
||||
)
|
||||
{
|
||||
if (nIndex == 94) return 0x01 | 0x02 | 0x40 | 0x80;
|
||||
|
||||
int orig = next_GetSystemMetrics(nIndex);
|
||||
|
||||
return orig;
|
||||
}
|
||||
|
||||
static BOOL WINAPI hook_RegisterTouchWindow(
|
||||
HWND hwnd,
|
||||
ULONG ulFlags
|
||||
)
|
||||
{
|
||||
registered_hWnd = hwnd;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Soul Reverse uses this to initialize wndprocs handling input
|
||||
|
||||
static LONG_PTR WINAPI hook_SetWindowLongPtrA(HWND hWnd, int nIndex, LONG_PTR dwNewLong) {
|
||||
if (touch_config.setwndptr && nIndex == -4) {
|
||||
orig_wndProc = (WNDPROC) dwNewLong;
|
||||
dwNewLong = (LONG_PTR) hook_wndProc;
|
||||
}
|
||||
|
||||
return next_SetWindowLongPtrA(hWnd, nIndex, dwNewLong);
|
||||
}
|
||||
|
||||
// Converting mouse event to touch event
|
||||
static BOOL WINAPI hook_GetTouchInputInfo(
|
||||
HANDLE hTouchInput,
|
||||
UINT cInputs,
|
||||
PTOUCHINPUT pInputs,
|
||||
int cbSize
|
||||
)
|
||||
{
|
||||
bool result = false;
|
||||
int sw, sh, cw, ch;
|
||||
RECT cRect;
|
||||
sw = GetSystemMetrics(SM_CXSCREEN);
|
||||
sh = GetSystemMetrics(SM_CYSCREEN);
|
||||
GetClientRect(registered_hWnd, &cRect);
|
||||
cw = cRect.right - cRect.left;
|
||||
ch = cRect.bottom - cRect.top;
|
||||
static bool mouse_state_old = false;
|
||||
|
||||
for (UINT input = 0; input < cInputs; input++) {
|
||||
TOUCHINPUT *touch_input = &pInputs[input];
|
||||
|
||||
touch_input->x = 0;
|
||||
touch_input->y = 0;
|
||||
touch_input->hSource = NULL;
|
||||
touch_input->dwID = 0;
|
||||
touch_input->dwFlags = 0;
|
||||
touch_input->dwMask = 0;
|
||||
touch_input->dwTime = 0;
|
||||
touch_input->dwExtraInfo = 0;
|
||||
touch_input->cxContact = 0;
|
||||
touch_input->cyContact = 0;
|
||||
|
||||
bool mouse_state = (GetKeyState(VK_LBUTTON) & 0x100) != 0;
|
||||
|
||||
if (mouse_state || mouse_state_old) {
|
||||
POINT cursorPos;
|
||||
|
||||
GetCursorPos(&cursorPos);
|
||||
|
||||
if (touch_config.remap) {
|
||||
ScreenToClient(registered_hWnd, &cursorPos);
|
||||
cursorPos.x = (long)(cursorPos.x * ((double)sw / cw));
|
||||
cursorPos.y = (long)(cursorPos.y * ((double)sh / ch));
|
||||
}
|
||||
|
||||
result = true;
|
||||
touch_input->x = cursorPos.x * 100;
|
||||
touch_input->y = cursorPos.y * 100;
|
||||
touch_input->hSource = hTouchInput;
|
||||
touch_input->dwID = 1;
|
||||
touch_input->dwFlags = 0;
|
||||
if (mouse_state && !mouse_state_old) {
|
||||
touch_input->dwFlags |= TOUCHEVENTF_DOWN;
|
||||
touch_held = true;
|
||||
} else if (mouse_state && mouse_state_old) {
|
||||
touch_input->dwFlags |= TOUCHEVENTF_MOVE;
|
||||
} else if (!mouse_state && mouse_state_old) {
|
||||
touch_input->dwFlags |= TOUCHEVENTF_UP;
|
||||
touch_held = false;
|
||||
}
|
||||
touch_input->dwMask = 0;
|
||||
touch_input->dwTime = 0;
|
||||
touch_input->dwExtraInfo = 0;
|
||||
touch_input->cxContact = 0;
|
||||
touch_input->cyContact = 0;
|
||||
}
|
||||
mouse_state_old = mouse_state;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct touch_screen_config {
|
||||
bool enable;
|
||||
bool remap;
|
||||
bool cursor;
|
||||
bool setwndptr;
|
||||
};
|
||||
|
||||
/* Init is not thread safe because API hook init is not thread safe blah
|
||||
blah blah you know the drill by now. */
|
||||
|
||||
void touch_screen_hook_init(const struct touch_screen_config *cfg, HINSTANCE self);
|
||||
void touch_hook_insert_hooks(HMODULE target);
|
||||
+3
-13
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "saohook/config.h"
|
||||
|
||||
#include "hooklib/config.h"
|
||||
|
||||
#include "platform/config.h"
|
||||
|
||||
void sao_dll_config_load(
|
||||
@@ -41,18 +43,6 @@ void systype_config_load(
|
||||
);
|
||||
}
|
||||
|
||||
void sao_touch_config_load(
|
||||
struct sao_touch_config *cfg,
|
||||
const wchar_t *filename)
|
||||
{
|
||||
cfg->enable = GetPrivateProfileIntW(
|
||||
L"touch",
|
||||
L"enable",
|
||||
1,
|
||||
filename
|
||||
);
|
||||
}
|
||||
|
||||
void sao_hook_config_load(
|
||||
struct sao_hook_config *cfg,
|
||||
const wchar_t *filename)
|
||||
@@ -67,6 +57,6 @@ void sao_hook_config_load(
|
||||
qr_config_load(&cfg->qr, filename);
|
||||
usio_config_load(&cfg->usio, filename);
|
||||
systype_config_load(&cfg->systype, filename);
|
||||
sao_touch_config_load(&cfg->touch, filename);
|
||||
touch_screen_config_load(&cfg->touch, filename);
|
||||
vfd_config_load(&cfg->vfd, filename);
|
||||
}
|
||||
|
||||
+2
-7
@@ -5,11 +5,11 @@
|
||||
#include "saohook/sao-dll.h"
|
||||
|
||||
#include "platform/config.h"
|
||||
#include "hooklib/touch.h"
|
||||
#include "gfxhook/config.h"
|
||||
#include "amcus/config.h"
|
||||
#include "board/config.h"
|
||||
#include "saohook/systype.h"
|
||||
#include "saohook/touch.h"
|
||||
|
||||
struct sao_hook_config {
|
||||
struct platform_config platform;
|
||||
@@ -20,7 +20,7 @@ struct sao_hook_config {
|
||||
struct qr_config qr;
|
||||
struct usio_config usio;
|
||||
struct systype_config systype;
|
||||
struct sao_touch_config touch;
|
||||
struct touch_screen_config touch;
|
||||
struct vfd_config vfd;
|
||||
};
|
||||
|
||||
@@ -39,8 +39,3 @@ void sao_hook_config_load(
|
||||
void systype_config_load(
|
||||
struct systype_config *cfg,
|
||||
const wchar_t *filename);
|
||||
|
||||
void sao_touch_config_load(
|
||||
struct sao_touch_config *cfg,
|
||||
const wchar_t *filename);
|
||||
|
||||
|
||||
+2
-7
@@ -6,13 +6,13 @@
|
||||
#include "saohook/usio.h"
|
||||
#include "saohook/unity.h"
|
||||
#include "saohook/systype.h"
|
||||
#include "saohook/touch.h"
|
||||
|
||||
#include "amcus/amcus.h"
|
||||
|
||||
#include "hook/process.h"
|
||||
|
||||
#include "hooklib/serial.h"
|
||||
#include "hooklib/touch.h"
|
||||
#include "board/sg-reader.h"
|
||||
#include "board/vfd.h"
|
||||
|
||||
@@ -35,6 +35,7 @@ static DWORD CALLBACK sao_pre_startup(void)
|
||||
|
||||
sao_hook_config_load(&sao_hook_cfg, L".\\bananatools.ini");
|
||||
|
||||
touch_screen_hook_init(&sao_hook_cfg.touch, sao_hook_mod);
|
||||
serial_hook_init();
|
||||
|
||||
struct dongle_info dinfo;
|
||||
@@ -79,12 +80,6 @@ static DWORD CALLBACK sao_pre_startup(void)
|
||||
|
||||
hr = systype_hook_init(&sao_hook_cfg.systype, &sao_hook_cfg.platform.dongle);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
ExitProcess(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
hr = sao_touch_hook_init(&sao_hook_cfg.touch);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
ExitProcess(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@@ -29,8 +29,6 @@ shared_library(
|
||||
'sao-dll.h',
|
||||
'systype.c',
|
||||
'systype.h',
|
||||
'touch.c',
|
||||
'touch.h',
|
||||
'usio.c',
|
||||
'usio.h',
|
||||
'unity.c',
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include <winuser.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "hook/table.h"
|
||||
#include "hooklib/reg.h"
|
||||
#include "util/dprintf.h"
|
||||
#include "saohook/touch.h"
|
||||
|
||||
static int WINAPI my_GetSystemMetrics(int nIndex);
|
||||
static int (WINAPI *next_GetSystemMetrics)(int nIndex);
|
||||
|
||||
static const struct hook_symbol touch_user32_syms[] = {
|
||||
{
|
||||
.name = "GetSystemMetrics",
|
||||
.patch = my_GetSystemMetrics,
|
||||
.link = (void **) &next_GetSystemMetrics,
|
||||
},
|
||||
};
|
||||
|
||||
HRESULT sao_touch_hook_init(const struct sao_touch_config *cfg)
|
||||
{
|
||||
if (!cfg->enable) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"User32.dll",
|
||||
touch_user32_syms,
|
||||
_countof(touch_user32_syms));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static int WINAPI my_GetSystemMetrics(int nIndex)
|
||||
{
|
||||
if (nIndex == SM_DIGITIZER) {
|
||||
return NID_MULTI_INPUT;
|
||||
}
|
||||
return next_GetSystemMetrics(nIndex);
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct sao_touch_config {
|
||||
bool enable;
|
||||
};
|
||||
|
||||
HRESULT sao_touch_hook_init(const struct sao_touch_config *cfg);
|
||||
Reference in New Issue
Block a user