mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-04-21 23:05:49 +00:00
streamline cursor clipping logic on windows (#11237)
This commit does the following: - add logic in the `WM_MOUSEMOVE` case of the Window to conditionally call `WIN_UpdateClipCursor` upon receiving cursor motion if SDL is expecting the mouse to be clipped in some way (Fixes #7890) - remove Windows-specific periodic refresh of cursor clipping and its `SDL_HINT_MOUSE_RELATIVE_CLIP_INTERVAL` hint (superceded by the above bullet point) - streamline the processing logic within `WIN_UpdateClipCursor` for better readability of each branch, and avoid calling the Platform API until it is absolutely necessary. - move `relative_mouse_center` field from Windows-specific per-window `SDL_WindowData` to the global `SDL_Mouse` struct, and the corresponding hint callbacks to `SDL_mouse.c` instead of `SDL_windowswindow.c`
This commit is contained in:
@@ -2614,23 +2614,6 @@ extern "C" {
|
||||
*/
|
||||
#define SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE "SDL_MOUSE_RELATIVE_CURSOR_VISIBLE"
|
||||
|
||||
/**
|
||||
* Controls how often SDL issues cursor confinement commands to the operating
|
||||
* system while relative mode is active, in case the desired confinement state
|
||||
* became out-of-sync due to interference from other running programs.
|
||||
*
|
||||
* The variable can be integers representing milliseconds between each
|
||||
* refresh. A value of zero means SDL will not automatically refresh the
|
||||
* confinement. The default value varies depending on the operating system,
|
||||
* this variable might not have any effects on inapplicable platforms such as
|
||||
* those without a cursor.
|
||||
*
|
||||
* This hint can be set anytime.
|
||||
*
|
||||
* \since This hint is available since SDL 3.1.3.
|
||||
*/
|
||||
#define SDL_HINT_MOUSE_RELATIVE_CLIP_INTERVAL "SDL_MOUSE_RELATIVE_CLIP_INTERVAL"
|
||||
|
||||
/**
|
||||
* A variable controlling whether mouse events should generate synthetic touch
|
||||
* events.
|
||||
|
||||
@@ -65,17 +65,6 @@ static void SDLCALL SDL_MouseDoubleClickTimeChanged(void *userdata, const char *
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL SDL_MouseRelativeClipIntervalChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
SDL_Mouse *mouse = (SDL_Mouse *)userdata;
|
||||
|
||||
if (hint && *hint) {
|
||||
mouse->relative_mode_clip_interval = SDL_atoi(hint);
|
||||
} else {
|
||||
mouse->relative_mode_clip_interval = 3000;
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL SDL_MouseDoubleClickRadiusChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
SDL_Mouse *mouse = (SDL_Mouse *)userdata;
|
||||
@@ -113,6 +102,13 @@ static void SDLCALL SDL_MouseRelativeSpeedScaleChanged(void *userdata, const cha
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL SDL_MouseRelativeModeCenterChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
SDL_Mouse *mouse = (SDL_Mouse *)userdata;
|
||||
|
||||
mouse->relative_mode_center = SDL_GetStringBoolean(hint, true);
|
||||
}
|
||||
|
||||
static void SDLCALL SDL_MouseRelativeSystemScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
SDL_Mouse *mouse = (SDL_Mouse *)userdata;
|
||||
@@ -226,6 +222,9 @@ bool SDL_PreInitMouse(void)
|
||||
SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE,
|
||||
SDL_MouseRelativeSystemScaleChanged, mouse);
|
||||
|
||||
SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER,
|
||||
SDL_MouseRelativeModeCenterChanged, mouse);
|
||||
|
||||
SDL_AddHintCallback(SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE,
|
||||
SDL_MouseWarpEmulationChanged, mouse);
|
||||
|
||||
@@ -249,9 +248,6 @@ bool SDL_PreInitMouse(void)
|
||||
SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE,
|
||||
SDL_MouseRelativeCursorVisibleChanged, mouse);
|
||||
|
||||
SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_CLIP_INTERVAL,
|
||||
SDL_MouseRelativeClipIntervalChanged, mouse);
|
||||
|
||||
mouse->was_touch_mouse_events = false; // no touch to mouse movement event pending
|
||||
|
||||
mouse->cursor_shown = true;
|
||||
@@ -1055,6 +1051,9 @@ void SDL_QuitMouse(void)
|
||||
SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE,
|
||||
SDL_MouseRelativeSystemScaleChanged, mouse);
|
||||
|
||||
SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER,
|
||||
SDL_MouseRelativeModeCenterChanged, mouse);
|
||||
|
||||
SDL_RemoveHintCallback(SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE,
|
||||
SDL_MouseWarpEmulationChanged, mouse);
|
||||
|
||||
@@ -1073,9 +1072,6 @@ void SDL_QuitMouse(void)
|
||||
SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE,
|
||||
SDL_MouseRelativeCursorVisibleChanged, mouse);
|
||||
|
||||
SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_CLIP_INTERVAL,
|
||||
SDL_MouseRelativeClipIntervalChanged, mouse);
|
||||
|
||||
for (int i = SDL_mouse_count; i--; ) {
|
||||
SDL_RemoveMouse(SDL_mice[i].instance_id, false);
|
||||
}
|
||||
|
||||
@@ -98,11 +98,11 @@ typedef struct
|
||||
bool relative_mode_warp;
|
||||
bool relative_mode_warp_motion;
|
||||
bool relative_mode_cursor_visible;
|
||||
bool relative_mode_center;
|
||||
bool warp_emulation_hint;
|
||||
bool warp_emulation_active;
|
||||
bool warp_emulation_prohibited;
|
||||
Uint64 last_center_warp_time_ns;
|
||||
int relative_mode_clip_interval;
|
||||
bool enable_normal_speed_scale;
|
||||
float normal_speed_scale;
|
||||
bool enable_relative_speed_scale;
|
||||
|
||||
@@ -350,8 +350,6 @@ static void WIN_UpdateFocus(SDL_Window *window, bool expect_focus)
|
||||
|
||||
WIN_UpdateWindowICCProfile(data->window, true);
|
||||
} else {
|
||||
RECT rect;
|
||||
|
||||
data->in_window_deactivation = true;
|
||||
|
||||
SDL_SetKeyboardFocus(NULL);
|
||||
@@ -361,10 +359,7 @@ static void WIN_UpdateFocus(SDL_Window *window, bool expect_focus)
|
||||
}
|
||||
WIN_ResetDeadKeys();
|
||||
|
||||
if (GetClipCursor(&rect) && SDL_memcmp(&rect, &data->cursor_clipped_rect, sizeof(rect)) == 0) {
|
||||
ClipCursor(NULL);
|
||||
SDL_zero(data->cursor_clipped_rect);
|
||||
}
|
||||
WIN_UnclipCursorForWindow(window);
|
||||
|
||||
data->in_window_deactivation = false;
|
||||
}
|
||||
@@ -1078,6 +1073,10 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
||||
case WM_NCACTIVATE:
|
||||
{
|
||||
// Don't immediately clip the cursor in case we're clicking minimize/maximize buttons
|
||||
// This is the only place that this flag is set. This causes all subsequent calls to
|
||||
// WIN_UpdateClipCursor for this window to be no-ops in this frame's message-pumping.
|
||||
// This flag is unset at the end of message pumping each frame for every window, and
|
||||
// should never be carried over between frames.
|
||||
data->skip_update_clipcursor = true;
|
||||
|
||||
/* Update the focus here, since it's possible to get WM_ACTIVATE and WM_SETFOCUS without
|
||||
@@ -1120,7 +1119,18 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
{
|
||||
/* SDL_Mouse *mouse = SDL_GetMouse(); */
|
||||
SDL_Window *window = data->window;
|
||||
|
||||
if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
|
||||
bool wish_clip_cursor = (
|
||||
window->flags & (SDL_WINDOW_MOUSE_RELATIVE_MODE | SDL_WINDOW_MOUSE_GRABBED) ||
|
||||
(window->mouse_rect.w > 0 && window->mouse_rect.h > 0)
|
||||
);
|
||||
if (wish_clip_cursor) {
|
||||
data->skip_update_clipcursor = false;
|
||||
WIN_UpdateClipCursor(window);
|
||||
}
|
||||
}
|
||||
|
||||
if (!data->mouse_tracked) {
|
||||
TRACKMOUSEEVENT trackMouseEvent;
|
||||
@@ -1138,7 +1148,7 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
||||
// Only generate mouse events for real mouse
|
||||
if (GetMouseMessageSource((ULONG)GetMessageExtraInfo()) != SDL_MOUSE_EVENT_SOURCE_TOUCH &&
|
||||
lParam != data->last_pointer_update) {
|
||||
SDL_SendMouseMotion(WIN_GetEventTimestamp(), data->window, SDL_GLOBAL_MOUSE_ID, false, (float)GET_X_LPARAM(lParam), (float)GET_Y_LPARAM(lParam));
|
||||
SDL_SendMouseMotion(WIN_GetEventTimestamp(), window, SDL_GLOBAL_MOUSE_ID, false, (float)GET_X_LPARAM(lParam), (float)GET_Y_LPARAM(lParam));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@@ -2068,28 +2078,6 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
|
||||
}
|
||||
|
||||
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||
static void WIN_UpdateClipCursorForWindows(void)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
SDL_Window *window;
|
||||
Uint64 now = SDL_GetTicks();
|
||||
const int CLIPCURSOR_UPDATE_INTERVAL_MS = SDL_GetMouse()->relative_mode_clip_interval;
|
||||
|
||||
if (_this) {
|
||||
for (window = _this->windows; window; window = window->next) {
|
||||
SDL_WindowData *data = window->internal;
|
||||
if (data) {
|
||||
if (data->skip_update_clipcursor) {
|
||||
data->skip_update_clipcursor = false;
|
||||
WIN_UpdateClipCursor(window);
|
||||
} else if (CLIPCURSOR_UPDATE_INTERVAL_MS > 0 && now >= (data->last_updated_clipcursor + CLIPCURSOR_UPDATE_INTERVAL_MS)) {
|
||||
WIN_UpdateClipCursor(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void WIN_UpdateMouseCapture(void)
|
||||
{
|
||||
SDL_Window *focusWindow = SDL_GetKeyboardFocus();
|
||||
@@ -2284,7 +2272,17 @@ void WIN_PumpEvents(SDL_VideoDevice *_this)
|
||||
}
|
||||
|
||||
// Update the clipping rect in case someone else has stolen it
|
||||
WIN_UpdateClipCursorForWindows();
|
||||
if (_this) {
|
||||
SDL_Window *window = _this->windows;
|
||||
while (window) {
|
||||
SDL_WindowData *data = window->internal;
|
||||
if (data && data->skip_update_clipcursor) {
|
||||
data->skip_update_clipcursor = false;
|
||||
WIN_UpdateClipCursor(window);
|
||||
}
|
||||
window = window->next;
|
||||
}
|
||||
}
|
||||
|
||||
// Update mouse capture
|
||||
WIN_UpdateMouseCapture();
|
||||
|
||||
@@ -386,12 +386,6 @@ bool WIN_SetWindowPositionInternal(SDL_Window *window, UINT flags, SDL_WindowRec
|
||||
return result;
|
||||
}
|
||||
|
||||
static void SDLCALL WIN_MouseRelativeModeCenterChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
SDL_WindowData *data = (SDL_WindowData *)userdata;
|
||||
data->mouse_relative_mode_center = SDL_GetStringBoolean(hint, true);
|
||||
}
|
||||
|
||||
static SDL_WindowEraseBackgroundMode GetEraseBackgroundModeHint(void)
|
||||
{
|
||||
const char *hint = SDL_GetHint(SDL_HINT_WINDOWS_ERASE_BACKGROUND_MODE);
|
||||
@@ -443,6 +437,14 @@ static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwn
|
||||
data->dwma_border_color = DWMWA_COLOR_DEFAULT;
|
||||
data->hint_erase_background_mode = GetEraseBackgroundModeHint();
|
||||
|
||||
|
||||
// WIN_WarpCursor() jitters by +1, and remote desktop warp wobble is +/- 1
|
||||
LONG remote_desktop_adjustment = GetSystemMetrics(SM_REMOTESESSION) ? 2 : 0;
|
||||
data->cursor_ctrlock_rect.left = 0 - remote_desktop_adjustment;
|
||||
data->cursor_ctrlock_rect.top = 0;
|
||||
data->cursor_ctrlock_rect.right = 1 + remote_desktop_adjustment;
|
||||
data->cursor_ctrlock_rect.bottom = 1;
|
||||
|
||||
if (SDL_GetHintBoolean("SDL_WINDOW_RETAIN_CONTENT", false)) {
|
||||
data->copybits_flag = 0;
|
||||
} else {
|
||||
@@ -453,8 +455,6 @@ static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwn
|
||||
SDL_Log("SetupWindowData: initialized data->scaling_dpi to %d", data->scaling_dpi);
|
||||
#endif
|
||||
|
||||
SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, WIN_MouseRelativeModeCenterChanged, data);
|
||||
|
||||
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||
// Associate the data with the window
|
||||
if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
|
||||
@@ -626,7 +626,6 @@ static void CleanupWindowData(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
SDL_WindowData *data = window->internal;
|
||||
|
||||
if (data) {
|
||||
SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, WIN_MouseRelativeModeCenterChanged, data);
|
||||
|
||||
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||
if (data->drop_target) {
|
||||
@@ -1588,107 +1587,109 @@ static BOOL GetClientScreenRect(HWND hwnd, RECT *rect)
|
||||
ClientToScreen(hwnd, (LPPOINT)rect + 1); // POINT( right , bottom )
|
||||
}
|
||||
|
||||
void WIN_UnclipCursorForWindow(SDL_Window *window) {
|
||||
SDL_WindowData *data = window->internal;
|
||||
RECT rect;
|
||||
if (GetClipCursor(&rect) && SDL_memcmp(&rect, &data->cursor_clipped_rect, sizeof(rect)) == 0) {
|
||||
ClipCursor(NULL);
|
||||
SDL_zero(data->cursor_clipped_rect);
|
||||
}
|
||||
}
|
||||
|
||||
void WIN_UpdateClipCursor(SDL_Window *window)
|
||||
{
|
||||
SDL_VideoDevice *videodevice = SDL_GetVideoDevice();
|
||||
SDL_WindowData *data = window->internal;
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
RECT rect, clipped_rect;
|
||||
|
||||
if (data->in_title_click || data->focus_click_pending) {
|
||||
return;
|
||||
}
|
||||
if (data->skip_update_clipcursor) {
|
||||
return;
|
||||
}
|
||||
if (!GetClipCursor(&clipped_rect)) {
|
||||
if (data->in_title_click || data->focus_click_pending || data->skip_update_clipcursor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((mouse->relative_mode || (window->flags & SDL_WINDOW_MOUSE_GRABBED) ||
|
||||
(window->mouse_rect.w > 0 && window->mouse_rect.h > 0)) &&
|
||||
(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
|
||||
if (mouse->relative_mode && !mouse->relative_mode_warp && data->mouse_relative_mode_center) {
|
||||
if (GetClientScreenRect(data->hwnd, &rect)) {
|
||||
// WIN_WarpCursor() jitters by +1, and remote desktop warp wobble is +/- 1
|
||||
LONG remote_desktop_adjustment = GetSystemMetrics(SM_REMOTESESSION) ? 2 : 0;
|
||||
LONG cx, cy;
|
||||
SDL_Rect mouse_rect = window->mouse_rect;
|
||||
bool win_mouse_rect = (mouse_rect.w > 0 && mouse_rect.h > 0);
|
||||
bool win_have_focus = (window->flags & SDL_WINDOW_INPUT_FOCUS);
|
||||
bool win_is_grabbed = (window->flags & SDL_WINDOW_MOUSE_GRABBED);
|
||||
bool win_in_relmode = (window->flags & SDL_WINDOW_MOUSE_RELATIVE_MODE);
|
||||
bool cursor_confine = win_in_relmode || win_is_grabbed || win_mouse_rect;
|
||||
|
||||
cx = (rect.left + rect.right) / 2;
|
||||
cy = (rect.top + rect.bottom) / 2;
|
||||
|
||||
// Make an absurdly small clip rect
|
||||
rect.left = cx - remote_desktop_adjustment;
|
||||
rect.right = cx + 1 + remote_desktop_adjustment;
|
||||
rect.top = cy;
|
||||
rect.bottom = cy + 1;
|
||||
|
||||
if (SDL_memcmp(&rect, &clipped_rect, sizeof(rect)) != 0) {
|
||||
if (ClipCursor(&rect)) {
|
||||
data->cursor_clipped_rect = rect;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (GetClientScreenRect(data->hwnd, &rect)) {
|
||||
if (window->mouse_rect.w > 0 && window->mouse_rect.h > 0) {
|
||||
SDL_Rect mouse_rect_win_client;
|
||||
RECT mouse_rect, intersection;
|
||||
|
||||
// mouse_rect_win_client is the mouse rect in Windows client space
|
||||
mouse_rect_win_client = window->mouse_rect;
|
||||
|
||||
// mouse_rect is the rect in Windows screen space
|
||||
mouse_rect.left = rect.left + mouse_rect_win_client.x;
|
||||
mouse_rect.top = rect.top + mouse_rect_win_client.y;
|
||||
mouse_rect.right = mouse_rect.left + mouse_rect_win_client.w;
|
||||
mouse_rect.bottom = mouse_rect.top + mouse_rect_win_client.h;
|
||||
if (IntersectRect(&intersection, &rect, &mouse_rect)) {
|
||||
SDL_memcpy(&rect, &intersection, sizeof(rect));
|
||||
} else if (window->flags & SDL_WINDOW_MOUSE_GRABBED) {
|
||||
// Mouse rect was invalid, just do the normal grab
|
||||
} else {
|
||||
SDL_zero(rect);
|
||||
}
|
||||
}
|
||||
if (SDL_memcmp(&rect, &clipped_rect, sizeof(rect)) != 0) {
|
||||
if (!WIN_IsRectEmpty(&rect)) {
|
||||
if (ClipCursor(&rect)) {
|
||||
data->cursor_clipped_rect = rect;
|
||||
}
|
||||
} else {
|
||||
ClipCursor(NULL);
|
||||
SDL_zero(data->cursor_clipped_rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
// This is verbatim translation of the old logic,
|
||||
// but I don't quite get what it's trying to do.
|
||||
// A clean-room implementation according to MSDN
|
||||
// documentation of GetClipCursor is provided in
|
||||
// a commented-out block below.
|
||||
if (!win_have_focus || !cursor_confine) {
|
||||
SDL_VideoDevice *videodevice = SDL_GetVideoDevice();
|
||||
RECT current;
|
||||
if (!GetClipCursor(¤t)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
bool unclip_cursor = false;
|
||||
|
||||
// If the cursor is clipped to the screen, clear the clip state
|
||||
if (!videodevice ||
|
||||
(clipped_rect.left == videodevice->desktop_bounds.x &&
|
||||
clipped_rect.top == videodevice->desktop_bounds.y)) {
|
||||
unclip_cursor = true;
|
||||
} else {
|
||||
if (videodevice && (
|
||||
current.left != videodevice->desktop_bounds.x ||
|
||||
current.top != videodevice->desktop_bounds.y
|
||||
)) {
|
||||
POINT first, second;
|
||||
|
||||
first.x = clipped_rect.left;
|
||||
first.y = clipped_rect.top;
|
||||
second.x = clipped_rect.right - 1;
|
||||
second.y = clipped_rect.bottom - 1;
|
||||
if (PtInRect(&data->cursor_clipped_rect, first) &&
|
||||
PtInRect(&data->cursor_clipped_rect, second)) {
|
||||
unclip_cursor = true;
|
||||
first.x = current.left;
|
||||
first.y = current.top;
|
||||
second.x = current.right - 1;
|
||||
second.y = current.bottom - 1;
|
||||
if (!PtInRect(&data->cursor_clipped_rect, first) ||
|
||||
!PtInRect(&data->cursor_clipped_rect, second)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (unclip_cursor) {
|
||||
ClipCursor(NULL);
|
||||
SDL_zero(data->cursor_clipped_rect);
|
||||
ClipCursor(NULL);
|
||||
SDL_zero(data->cursor_clipped_rect);
|
||||
return;
|
||||
}
|
||||
|
||||
// if (!win_have_focus || !cursor_confine) {
|
||||
// RECT current;
|
||||
// SDL_VideoDevice *videodevice = SDL_GetVideoDevice();
|
||||
// if (GetClipCursor(¤t) && (!videodevice ||
|
||||
// current.left != videodevice->desktop_bounds.x ||
|
||||
// current.top != videodevice->desktop_bounds.y ||
|
||||
// current.right != videodevice->desktop_bounds.x + videodevice->desktop_bounds.w ||
|
||||
// current.bottom != videodevice->desktop_bounds.y + videodevice->desktop_bounds.h )) {
|
||||
// ClipCursor(NULL);
|
||||
// SDL_zero(data->cursor_clipped_rect);
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
bool lock_to_ctr = (mouse->relative_mode_center && mouse->relative_mode && !mouse->relative_mode_warp);
|
||||
|
||||
RECT client;
|
||||
if (!GetClientScreenRect(data->hwnd, &client)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RECT target = client;
|
||||
if (lock_to_ctr) {
|
||||
LONG cx = (client.left + client.right ) / 2;
|
||||
LONG cy = (client.top + client.bottom) / 2;
|
||||
target = data->cursor_ctrlock_rect;
|
||||
target.left += cx;
|
||||
target.right += cx;
|
||||
target.top += cy;
|
||||
target.bottom += cy;
|
||||
} else if (win_mouse_rect) {
|
||||
RECT custom, overlap;
|
||||
custom.left = client.left + mouse_rect.x;
|
||||
custom.top = client.top + mouse_rect.y;
|
||||
custom.right = client.left + mouse_rect.x + mouse_rect.w;
|
||||
custom.bottom = client.top + mouse_rect.y + mouse_rect.h;
|
||||
if (IntersectRect(&overlap, &client, &custom)) {
|
||||
target = overlap;
|
||||
} else if (!win_is_grabbed) {
|
||||
WIN_UnclipCursorForWindow(window);
|
||||
return;
|
||||
}
|
||||
}
|
||||
data->last_updated_clipcursor = SDL_GetTicks();
|
||||
|
||||
if (GetClipCursor(&client) &&
|
||||
0 != SDL_memcmp(&target, &client, sizeof(client)) &&
|
||||
ClipCursor(&target)) {
|
||||
data->cursor_clipped_rect = target; // ClipCursor may fail if rect beyond screen
|
||||
}
|
||||
}
|
||||
|
||||
bool WIN_SetWindowHitTest(SDL_Window *window, bool enabled)
|
||||
|
||||
@@ -79,11 +79,10 @@ struct SDL_WindowData
|
||||
bool in_title_click;
|
||||
Uint8 focus_click_pending;
|
||||
bool skip_update_clipcursor;
|
||||
Uint64 last_updated_clipcursor;
|
||||
bool mouse_relative_mode_center;
|
||||
bool windowed_mode_was_maximized;
|
||||
bool in_window_deactivation;
|
||||
RECT cursor_clipped_rect;
|
||||
RECT cursor_clipped_rect; // last successfully committed clipping rect for this window
|
||||
RECT cursor_ctrlock_rect; // this is Windows-specific, but probably does not need to be per-window
|
||||
UINT windowed_mode_corner_rounding;
|
||||
COLORREF dwma_border_color;
|
||||
bool mouse_tracked;
|
||||
@@ -128,6 +127,7 @@ extern bool WIN_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window
|
||||
extern void WIN_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void WIN_OnWindowEnter(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void WIN_UpdateClipCursor(SDL_Window *window);
|
||||
extern void WIN_UnclipCursorForWindow(SDL_Window *window);
|
||||
extern bool WIN_SetWindowHitTest(SDL_Window *window, bool enabled);
|
||||
extern void WIN_AcceptDragAndDrop(SDL_Window *window, bool accept);
|
||||
extern bool WIN_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation);
|
||||
|
||||
Reference in New Issue
Block a user