Created
November 16, 2024 10:08
-
-
Save DennyLindberg/5dfff8bd132ef3ed9fab71256f144fef to your computer and use it in GitHub Desktop.
Grabbing WM_POINTER events with SDL3 on Windows
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This code does not work as-is. It is a work-in-progress in my application. You need to modify it for your application. | |
void handle_stylus_event(UINT uMsg, WPARAM wParam) | |
{ | |
// Wacom + [DriverSetting: Use Windows Ink] required for these events to happen at all. | |
// WinTab mandatory when Windows Ink is disabled in any way. | |
if (uMsg == WM_POINTERDEVICECHANGE) | |
{ | |
PRINT_INPUT("DEVICE CHANGE\n"); | |
return; | |
} | |
const WORD wid = GET_POINTERID_WPARAM(wParam); | |
POINTER_INFO info = {NULL}; | |
POINTER_PEN_INFO pen; | |
if (!GetPointerInfo(wid, &info)) | |
{ | |
return; // this happens at least with finger touches with no pointer info (just weird) | |
} | |
else if (info.pointerType == PT_PEN && GetPointerPenInfo(wid, &pen)) | |
{ | |
bool stylus_tip = info.ButtonChangeType == POINTER_CHANGE_FIRSTBUTTON_DOWN || info.ButtonChangeType == POINTER_CHANGE_FIRSTBUTTON_UP; | |
bool stylus_sidebutton_or_eraser = !stylus_tip && info.ButtonChangeType != POINTER_CHANGE_NONE; | |
switch (uMsg) | |
{ | |
case WM_POINTERDOWN: | |
{ | |
if (stylus_tip) | |
{ | |
PRINT_INPUT("WM_POINTERDOWN PEN %d\n", info.ButtonChangeType); | |
input_set_stylus_pressed(true); | |
} | |
break; | |
} | |
case WM_POINTERUP: | |
{ | |
if (stylus_tip) | |
{ | |
PRINT_INPUT("WM_POINTERUP PEN %d\n", info.ButtonChangeType); | |
input_set_stylus_pressed(false); | |
} | |
break; | |
} | |
case WM_POINTERUPDATE: | |
{ | |
//PRINT_INPUT("WM_POINTERUPDATE PEN %.2f\n", pen.pressure/1024.0f); | |
input_set_stylus_pressure(pen.pressure/1024.0f); | |
break; | |
} | |
case WM_POINTERDEVICEINRANGE: | |
case WM_POINTERENTER: | |
{ | |
PRINT_INPUT("WM_POINTERENTER/WM_POINTERDEVICEINRANGE PEN\n"); | |
input_set_stylus_inrange(true); | |
break; | |
} | |
case WM_POINTERDEVICEOUTOFRANGE: | |
case WM_POINTERLEAVE: | |
{ | |
PRINT_INPUT("WM_POINTERLEAVE/WM_POINTERDEVICEOUTOFRANGE PEN\n"); | |
input_set_stylus_inrange(false); | |
break; | |
} | |
default: {} | |
} | |
} | |
else | |
{ | |
// info.pointerType == PT_POINTER, PT_TOUCH, PT_MOUSE, PT_TOUCHPAD | |
} | |
} | |
// Use with SDL_SetWindowsMessageHook(&sdl_windowproc_callback, nullptr); | |
bool sdl_windowproc_callback(void *userdata, MSG *msg) | |
{ | |
MSG* sdl_msg = (MSG*)msg; | |
HWND hwnd = sdl_msg->hwnd; | |
UINT uMsg = sdl_msg->message; | |
WPARAM wParam = sdl_msg->wParam; | |
LPARAM lParam = sdl_msg->lParam; | |
if (EasyTab && EasyTab_HandleEvent(hwnd, uMsg, lParam, wParam) == EASYTAB_OK) | |
{ | |
input_set_stylus_pressed(EasyTab->Buttons & EasyTab_Buttons_Pen_Touch); | |
input_set_stylus_pressure(EasyTab->Pressure); | |
} | |
else | |
{ | |
switch (uMsg) | |
{ | |
case WM_POINTERENTER: | |
case WM_POINTERLEAVE: | |
case WM_POINTERDOWN: | |
case WM_POINTERUP: | |
case WM_POINTERUPDATE: | |
case WM_POINTERDEVICEINRANGE: | |
case WM_POINTERDEVICEOUTOFRANGE: | |
case WM_POINTERDEVICECHANGE: | |
{ | |
// pointer is triggered by both touch and pen input (we are only interested in pen here) | |
handle_stylus_event(uMsg, wParam); | |
break; | |
} | |
default: {} | |
} | |
} | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment