From cd6bae96ff7a209883fc48715fb57d6f82dba302 Mon Sep 17 00:00:00 2001 From: CDarcey Date: Wed, 24 Jun 2026 20:15:42 -0500 Subject: [PATCH 1/3] feat(win32): implement cursor mode and raw input - implement PL_CURSOR_MODE_HIDDEN and PL_CURSOR_DISABLED in pl_set_cursor_mode - implement pl_set_raw_mouse_input using win32 RAWINPUTDEVICE - add WM_INPUT handler for raw mouse delta evvents - update pl_get_window_capabilities to advertise new supported modes - add set_mouse_pos to plWindowsI struct and pl.h declerations --- src/pl.c | 1 + src/pl.h | 2 ++ src/pl_internal.h | 1 + src/pl_main_win32.c | 85 +++++++++++++++++++++++++++++++++++++++------ 4 files changed, 79 insertions(+), 10 deletions(-) diff --git a/src/pl.c b/src/pl.c index 5210f775..6d0a83d3 100644 --- a/src/pl.c +++ b/src/pl.c @@ -1667,6 +1667,7 @@ pl__load_core_apis(void) tWindowApi.set_cursor_mode = pl_set_cursor_mode; tWindowApi.get_cursor_mode = pl_get_cursor_mode; tWindowApi.set_raw_mouse_input = pl_set_raw_mouse_input; + tWindowApi.set_mouse_pos = pl_set_mouse_pos; tWindowApi.set_fullscreen = pl_set_fullscreen; tWindowApi.get_capabilities = pl_get_window_capabilities; diff --git a/src/pl.h b/src/pl.h index e84d91cc..84d30321 100644 --- a/src/pl.h +++ b/src/pl.h @@ -197,6 +197,7 @@ PL_API bool pl_window_get_attribute (plWindow*, plWindowAttribute, plWindowAttri PL_API bool pl_window_set_cursor_mode (plWindow*, plCursorMode); PL_API plCursorMode pl_window_get_cursor_mode (plWindow*); PL_API bool pl_window_set_raw_mouse_input (plWindow*, bool); +PL_API bool pl_window_set_mouse_pos (plWindow*, plVec2); // full screen modes PL_API bool pl_window_set_fullscreen(plWindow*, const plFullScreenDesc*); @@ -328,6 +329,7 @@ typedef struct _plWindowI bool (*set_cursor_mode) (plWindow*, plCursorMode); plCursorMode (*get_cursor_mode) (plWindow*); bool (*set_raw_mouse_input) (plWindow*, bool); + bool (*set_mouse_pos) (plWindow*, plVec2); // full screen modes bool (*set_fullscreen)(plWindow*, const plFullScreenDesc*); diff --git a/src/pl_internal.h b/src/pl_internal.h index 9653dbe8..6c6b1a2c 100644 --- a/src/pl_internal.h +++ b/src/pl_internal.h @@ -71,6 +71,7 @@ bool pl_get_window_attribute(plWindow*, plWindowAttribute bool pl_set_cursor_mode(plWindow*, plCursorMode); plCursorMode pl_get_cursor_mode(plWindow*); bool pl_set_raw_mouse_input(plWindow*, bool); +bool pl_set_mouse_pos(plWindow*, plVec2); bool pl_set_fullscreen(plWindow*, const plFullScreenDesc*); const plWindowCapabilities* pl_get_window_capabilities(void); diff --git a/src/pl_main_win32.c b/src/pl_main_win32.c index 202cd00f..f41285db 100644 --- a/src/pl_main_win32.c +++ b/src/pl_main_win32.c @@ -428,6 +428,29 @@ pl__windows_procedure(HWND tHwnd, UINT tMsg, WPARAM tWParam, LPARAM tLParam) break; } + case WM_INPUT: + { + UINT uSize = 0; + GetRawInputData((HRAWINPUT)tLParam, RID_INPUT, NULL, &uSize, sizeof(RAWINPUTHEADER)); + if(uSize > 0) + { + RAWINPUT* ptRaw = (RAWINPUT*)malloc(uSize); + if(GetRawInputData((HRAWINPUT)tLParam, RID_INPUT, ptRaw, &uSize, sizeof(RAWINPUTHEADER)) == uSize) + { + if(ptRaw->header.dwType == RIM_TYPEMOUSE) + { + // get current cursor pos in client space and feed as mouse event + POINT tCurrent; + GetCursorPos(&tCurrent); + ScreenToClient(tHwnd, &tCurrent); + gptIOI->add_mouse_pos_event((float)tCurrent.x, (float)tCurrent.y); + } + } + free(ptRaw); + } + break; + } + case WM_MOUSEMOVE: { tMouseHandle = tHwnd; @@ -844,7 +867,31 @@ pl_get_window_attribute(plWindow* ptWindow, plWindowAttribute tAttribute, plWind bool pl_set_cursor_mode(plWindow* ptWindow, plCursorMode tMode) { - return tMode == PL_CURSOR_MODE_NORMAL; + HWND tHwnd = (HWND)ptWindow->_pBackendData; + + if(tMode == PL_CURSOR_MODE_NORMAL) + { + ShowCursor(true); + ClipCursor(NULL); + return true; + } + else if(tMode == PL_CURSOR_MODE_HIDDEN) + { + ShowCursor(false); + ClipCursor(NULL); + return true; + } + else if(tMode == PL_CURSOR_MODE_DISABLED) + { + ShowCursor(false); + RECT tRect; + GetClientRect(tHwnd, &tRect); + MapWindowPoints(tHwnd, NULL, (POINT*)&tRect, 2); + ClipCursor(&tRect); + return true; + } + + return false; } plCursorMode @@ -856,7 +903,23 @@ pl_get_cursor_mode(plWindow* ptWindow) bool pl_set_raw_mouse_input(plWindow* ptWindow, bool bValue) { - return !bValue; + HWND tHwnd = (HWND)ptWindow->_pBackendData; + RAWINPUTDEVICE tRid = { + .usUsagePage = 0x01, + .usUsage = 0x02, + .dwFlags = bValue ? 0 : RIDEV_REMOVE, + .hwndTarget = bValue ? tHwnd : NULL + }; + return RegisterRawInputDevices(&tRid, 1, sizeof(tRid)); +} + +bool +pl_set_mouse_pos(plWindow* ptWindow, plVec2 tPos) +{ + HWND tHwnd = (HWND)ptWindow->_pBackendData; + POINT tPoint = {(LONG)tPos.x, (LONG)tPos.y}; + ClientToScreen(tHwnd, &tPoint); + return SetCursorPos(tPoint.x, tPoint.y); } bool @@ -868,10 +931,10 @@ pl_set_fullscreen(plWindow* ptWindow, const plFullScreenDesc* tDesc) const plWindowCapabilities* pl_get_window_capabilities(void) { - static plWindowCapabilities tCapabilities = {}; + static plWindowCapabilities tCapabilities = {0}; - tCapabilities.uCursorModeCount = 1; - tCapabilities.uAttributeCount = 1; + tCapabilities.uCursorModeCount = 3; + tCapabilities.uAttributeCount = 1; tCapabilities.uFullScreenModeCount = 2; static const plWindowAttribute atSupportedAttributes[] = { @@ -879,7 +942,9 @@ pl_get_window_capabilities(void) }; static const plCursorMode atSupportedCursorModes[] = { - PL_CURSOR_MODE_NORMAL + PL_CURSOR_MODE_NORMAL, + PL_CURSOR_MODE_HIDDEN, + PL_CURSOR_MODE_DISABLED }; static const plFullScreenMode atSupportedScreenModes[] = { @@ -887,10 +952,10 @@ pl_get_window_capabilities(void) PL_FULLSCREEN_MODE_EXCLUSIVE }; - tCapabilities.atCursorModes = atSupportedCursorModes; - tCapabilities.atFullScreenModes = atSupportedScreenModes; - tCapabilities.atWindowAttributes = atSupportedAttributes; - tCapabilities.tFlags = PL_WINDOW_CAPABILITY_FLAGS_NONE; + tCapabilities.atCursorModes = atSupportedCursorModes; + tCapabilities.atFullScreenModes = atSupportedScreenModes; + tCapabilities.atWindowAttributes = atSupportedAttributes; + tCapabilities.tFlags = PL_WINDOW_CAPABILITY_FLAGS_RAW_MOUSE_INPUT; return &tCapabilities; } From 2e973f10e26de3a47388cf82dfd42b98efbcf087 Mon Sep 17 00:00:00 2001 From: CDarcey Date: Thu, 25 Jun 2026 07:42:51 -0500 Subject: [PATCH 2/3] fix: add pl_set_mouse_pos stub to non win32 platform backends --- src/pl_main_glfw.cpp | 6 ++++++ src/pl_main_macos.m | 6 ++++++ src/pl_main_x11.c | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/src/pl_main_glfw.cpp b/src/pl_main_glfw.cpp index b2c1b76b..e479bd3a 100644 --- a/src/pl_main_glfw.cpp +++ b/src/pl_main_glfw.cpp @@ -1706,6 +1706,12 @@ pl_glfw_cursor_enter_callback(GLFWwindow* window, int entered) } } +bool +pl_set_mouse_pos(plWindow* ptWindow, plVec2 tPos) +{ + return false; // not implemented on this platform +} + void pl_glfw_window_focus_callback(GLFWwindow* window, int focused) { diff --git a/src/pl_main_macos.m b/src/pl_main_macos.m index 9b0fefe9..0dcd2678 100644 --- a/src/pl_main_macos.m +++ b/src/pl_main_macos.m @@ -1159,6 +1159,12 @@ - (void)unmarkText return PL_CURSOR_MODE_NORMAL; } +bool +pl_set_mouse_pos(plWindow* ptWindow, plVec2 tPos) +{ + return false; // not implemented on this platform +} + bool pl_set_raw_mouse_input(plWindow* ptWindow, bool bValue) { diff --git a/src/pl_main_x11.c b/src/pl_main_x11.c index 90e30eb3..717fc33d 100644 --- a/src/pl_main_x11.c +++ b/src/pl_main_x11.c @@ -1013,6 +1013,12 @@ pl_get_cursor_mode(plWindow* ptWindow) return PL_CURSOR_MODE_NORMAL; } +bool +pl_set_mouse_pos(plWindow* ptWindow, plVec2 tPos) +{ + return false; // not implemented on this platform +} + bool pl_set_raw_mouse_input(plWindow* ptWindow, bool bValue) { From 89513e1ba7625ee388e2d275d5bd0944e07380d1 Mon Sep 17 00:00:00 2001 From: CDarcey Date: Thu, 25 Jun 2026 07:46:41 -0500 Subject: [PATCH 3/3] fix: add pl_set_mouse_pos stub to null platform backend --- src/pl_main_null.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/pl_main_null.c b/src/pl_main_null.c index cad36b85..29159ae3 100644 --- a/src/pl_main_null.c +++ b/src/pl_main_null.c @@ -314,6 +314,12 @@ pl_get_cursor_mode(plWindow* ptWindow) return PL_CURSOR_MODE_NORMAL; } +bool +pl_set_mouse_pos(plWindow* ptWindow, plVec2 tPos) +{ + return false; // not implemented on this platform +} + bool pl_set_raw_mouse_input(plWindow* ptWindow, bool bValue) {