pen: Better pen position precision on Windows 8 and later.

Fixes #12084.
This commit is contained in:
Ryan C. Gordon
2025-11-07 10:34:17 -05:00
parent 704ac98d3f
commit 2f41dd7b5c
3 changed files with 28 additions and 5 deletions

View File

@@ -1334,12 +1334,33 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
SDL_SendPenTouch(timestamp, pen, window, (pen_info.penFlags & PEN_FLAG_INVERTED) != 0, false); SDL_SendPenTouch(timestamp, pen, window, (pen_info.penFlags & PEN_FLAG_INVERTED) != 0, false);
} }
POINT position; const POINTER_INFO *pointer_info = &pen_info.pointerInfo;
position.x = (LONG) GET_X_LPARAM(lParam); RECT tablet_bounds, tablet_mapping;
position.y = (LONG) GET_Y_LPARAM(lParam); float fx, fy;
ScreenToClient(data->hwnd, &position);
SDL_SendPenMotion(timestamp, pen, window, (float) position.x, (float) position.y); // try to get a more-precise position than is stored in lParam...GetPointerDeviceRects is available starting in Windows 8.
// we might need to cache this somewhere (and if we cache it, we will need to update it if the display changes)...for now we'll see if GetPointerDeviceRect is fast enough.
if (!data->videodata->GetPointerDeviceRects || !data->videodata->GetPointerDeviceRects(pointer_info->sourceDevice, &tablet_bounds, &tablet_mapping)) {
POINT position = { (LONG) GET_X_LPARAM(lParam), (LONG) GET_Y_LPARAM(lParam) };
ScreenToClient(data->hwnd, &position);
fx = (float) position.x;
fy = (float) position.y;
} else {
int ix, iy;
SDL_GetWindowPosition(window, &ix, &iy);
const SDL_FPoint window_pos = { (float) ix, (float) iy };
const float facX = pointer_info->ptHimetricLocationRaw.x / (float) (tablet_bounds.right );
const float facY = pointer_info->ptHimetricLocationRaw.y / (float) (tablet_bounds.bottom);
const float w = tablet_mapping.right - tablet_mapping.left;
const float h = tablet_mapping.bottom - tablet_mapping.top;
fx = (tablet_mapping.left + (facX * w)) - window_pos.x;
fy = (tablet_mapping.top + (facY * h)) - window_pos.y;
}
SDL_SendPenMotion(timestamp, pen, window, fx, fy);
SDL_SendPenButton(timestamp, pen, window, 1, (pen_info.penFlags & PEN_FLAG_BARREL) != 0); SDL_SendPenButton(timestamp, pen, window, 1, (pen_info.penFlags & PEN_FLAG_BARREL) != 0);
SDL_SendPenButton(timestamp, pen, window, 2, (pen_info.penFlags & PEN_FLAG_ERASER) != 0); SDL_SendPenButton(timestamp, pen, window, 2, (pen_info.penFlags & PEN_FLAG_ERASER) != 0);

View File

@@ -267,6 +267,7 @@ static SDL_VideoDevice *WIN_CreateDevice(void)
data->DisplayConfigGetDeviceInfo = (LONG (WINAPI *)(DISPLAYCONFIG_DEVICE_INFO_HEADER*))SDL_LoadFunction(data->userDLL, "DisplayConfigGetDeviceInfo"); data->DisplayConfigGetDeviceInfo = (LONG (WINAPI *)(DISPLAYCONFIG_DEVICE_INFO_HEADER*))SDL_LoadFunction(data->userDLL, "DisplayConfigGetDeviceInfo");
data->GetPointerType = (BOOL (WINAPI *)(UINT32, POINTER_INPUT_TYPE *))SDL_LoadFunction(data->userDLL, "GetPointerType"); data->GetPointerType = (BOOL (WINAPI *)(UINT32, POINTER_INPUT_TYPE *))SDL_LoadFunction(data->userDLL, "GetPointerType");
data->GetPointerPenInfo = (BOOL (WINAPI *)(UINT32, POINTER_PEN_INFO *))SDL_LoadFunction(data->userDLL, "GetPointerPenInfo"); data->GetPointerPenInfo = (BOOL (WINAPI *)(UINT32, POINTER_PEN_INFO *))SDL_LoadFunction(data->userDLL, "GetPointerPenInfo");
data->GetPointerDeviceRects = (BOOL (WINAPI *)(HANDLE, RECT *, RECT *))SDL_LoadFunction(data->userDLL, "GetPointerDeviceRects");
/* *INDENT-ON* */ // clang-format on /* *INDENT-ON* */ // clang-format on
} else { } else {
SDL_ClearError(); SDL_ClearError();

View File

@@ -552,6 +552,7 @@ struct SDL_VideoData
/* *INDENT-OFF* */ // clang-format off /* *INDENT-OFF* */ // clang-format off
BOOL (WINAPI *GetPointerType)(UINT32 pointerId, POINTER_INPUT_TYPE *pointerType); BOOL (WINAPI *GetPointerType)(UINT32 pointerId, POINTER_INPUT_TYPE *pointerType);
BOOL (WINAPI *GetPointerPenInfo)(UINT32 pointerId, POINTER_PEN_INFO *penInfo); BOOL (WINAPI *GetPointerPenInfo)(UINT32 pointerId, POINTER_PEN_INFO *penInfo);
BOOL (WINAPI *GetPointerDeviceRects)(HANDLE device, RECT *pointerDeviceRect, RECT *displayRect);
/* *INDENT-ON* */ // clang-format on /* *INDENT-ON* */ // clang-format on
// DPI functions // DPI functions