Skip to content

Instantly share code, notes, and snippets.

@DennyLindberg
Created November 16, 2024 10:08
Show Gist options
  • Save DennyLindberg/5dfff8bd132ef3ed9fab71256f144fef to your computer and use it in GitHub Desktop.
Save DennyLindberg/5dfff8bd132ef3ed9fab71256f144fef to your computer and use it in GitHub Desktop.
Grabbing WM_POINTER events with SDL3 on Windows
// 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